kernel: backport MIPS changes introducing a separate IRQ stack
[lede.git] / target / linux / lantiq / patches-4.4 / 0152-lantiq-VPE.patch
1 --- a/arch/mips/Kconfig
2 +++ b/arch/mips/Kconfig
3 @@ -2221,6 +2221,12 @@ config MIPS_VPE_LOADER
4           Includes a loader for loading an elf relocatable object
5           onto another VPE and running it.
6  
7 +config IFX_VPE_EXT
8 +       bool "IFX APRP Extensions"
9 +       depends on MIPS_VPE_LOADER
10 +       help
11 +         IFX included extensions in APRP
12 +
13  config MIPS_VPE_LOADER_CMP
14         bool
15         default "y"
16 --- a/arch/mips/include/asm/vpe.h
17 +++ b/arch/mips/include/asm/vpe.h
18 @@ -127,4 +127,23 @@ void cleanup_tc(struct tc *tc);
19  
20  int __init vpe_module_init(void);
21  void __exit vpe_module_exit(void);
22 +
23 +/* For the explanation of the APIs please refer the section "MT APRP Kernel
24 + * Programming" in AR9 SW Architecture Specification
25 + */
26 +int32_t vpe1_sw_start(void *sw_start_addr, uint32_t tcmask, uint32_t flags);
27 +int32_t vpe1_sw_stop(uint32_t flags);
28 +uint32_t vpe1_get_load_addr(uint32_t flags);
29 +uint32_t vpe1_get_max_mem(uint32_t flags);
30 +
31 +/* Watchdog APIs */
32 +extern uint32_t vpe1_wdog_ctr;
33 +extern uint32_t vpe1_wdog_timeout;
34 +
35 +unsigned long vpe1_sw_wdog_start(unsigned long);
36 +unsigned long vpe1_sw_wdog_stop(unsigned long);
37 +
38 +typedef int (*VPE_SW_WDOG_RESET)(unsigned long wdog_cleared_ok_count);
39 +int32_t vpe1_sw_wdog_register_reset_handler(VPE_SW_WDOG_RESET reset_fn);
40 +
41  #endif /* _ASM_VPE_H */
42 --- a/arch/mips/kernel/vpe-mt.c
43 +++ b/arch/mips/kernel/vpe-mt.c
44 @@ -29,6 +29,7 @@ int vpe_run(struct vpe *v)
45         struct vpe_notifications *notifier;
46         unsigned int vpeflags;
47         struct tc *t;
48 +       unsigned long physical_memsize = 0L;
49  
50         /* check we are the Master VPE */
51         local_irq_save(flags);
52 @@ -417,6 +418,8 @@ int __init vpe_module_init(void)
53                         }
54  
55                         v->ntcs = hw_tcs - aprp_cpu_index();
56 +                       write_tc_c0_tcbind((read_tc_c0_tcbind() &
57 +                                               ~TCBIND_CURVPE) | 1);
58  
59                         /* add the tc to the list of this vpe's tc's. */
60                         list_add(&t->tc, &v->tc);
61 @@ -519,3 +522,47 @@ void __exit vpe_module_exit(void)
62                         release_vpe(v);
63         }
64  }
65 +
66 +#ifdef CONFIG_IFX_VPE_EXT
67 +int32_t vpe1_sw_start(void *sw_start_addr, uint32_t tcmask, uint32_t flags)
68 +{
69 +       enum vpe_state state;
70 +       struct vpe *v = get_vpe(tclimit);
71 +       struct vpe_notifications *not;
72 +
73 +       if (tcmask || flags) {
74 +               pr_warn("Currently tcmask and flags should be 0. Other values are not supported\n");
75 +               return -1;
76 +       }
77 +
78 +       state = xchg(&v->state, VPE_STATE_INUSE);
79 +       if (state != VPE_STATE_UNUSED) {
80 +               vpe_stop(v);
81 +
82 +               list_for_each_entry(not, &v->notify, list) {
83 +                       not->stop(tclimit);
84 +               }
85 +       }
86 +
87 +       v->__start = (unsigned long)sw_start_addr;
88 +
89 +       if (!vpe_run(v)) {
90 +               pr_debug("VPE loader: VPE1 running successfully\n");
91 +               return 0;
92 +       }
93 +       return -1;
94 +}
95 +EXPORT_SYMBOL(vpe1_sw_start);
96 +
97 +int32_t vpe1_sw_stop(uint32_t flags)
98 +{
99 +       struct vpe *v = get_vpe(tclimit);
100 +
101 +       if (!vpe_free(v)) {
102 +               pr_debug("RP Stopped\n");
103 +               return 0;
104 +       } else
105 +               return -1;
106 +}
107 +EXPORT_SYMBOL(vpe1_sw_stop);
108 +#endif
109 --- a/arch/mips/kernel/vpe.c
110 +++ b/arch/mips/kernel/vpe.c
111 @@ -49,6 +49,59 @@ struct vpe_control vpecontrol = {
112         .tc_list        = LIST_HEAD_INIT(vpecontrol.tc_list)
113  };
114  
115 +#ifdef CONFIG_IFX_VPE_EXT
116 +unsigned int vpe1_load_addr;
117 +
118 +static int __init load_address(char *str)
119 +{
120 +       get_option(&str, &vpe1_load_addr);
121 +       return 1;
122 +}
123 +__setup("vpe1_load_addr=", load_address);
124 +
125 +static unsigned int vpe1_mem;
126 +static int __init vpe1mem(char *str)
127 +{
128 +       vpe1_mem = memparse(str, &str);
129 +       return 1;
130 +}
131 +__setup("vpe1_mem=", vpe1mem);
132 +
133 +uint32_t vpe1_wdog_ctr;
134 +static int __init wdog_ctr(char *str)
135 +{
136 +       get_option(&str, &vpe1_wdog_ctr);
137 +       return 1;
138 +}
139 +EXPORT_SYMBOL(vpe1_wdog_ctr);
140 +__setup("vpe1_wdog_ctr_addr=", wdog_ctr);
141 +
142 +uint32_t vpe1_wdog_timeout;
143 +static int __init wdog_timeout(char *str)
144 +{
145 +       get_option(&str, &vpe1_wdog_timeout);
146 +       return 1;
147 +}
148 +EXPORT_SYMBOL(vpe1_wdog_timeout);
149 +__setup("vpe1_wdog_timeout=", wdog_timeout);
150 +
151 +uint32_t vpe1_get_load_addr(uint32_t flags)
152 +{
153 +       return vpe1_load_addr;
154 +}
155 +EXPORT_SYMBOL(vpe1_get_load_addr);
156 +
157 +uint32_t vpe1_get_max_mem(uint32_t flags)
158 +{
159 +       if (!vpe1_mem)
160 +               return P_SIZE;
161 +       else
162 +               return vpe1_mem;
163 +}
164 +EXPORT_SYMBOL(vpe1_get_max_mem);
165 +
166 +#endif
167 +
168  /* get the vpe associated with this minor */
169  struct vpe *get_vpe(int minor)
170  {
171 --- a/arch/mips/lantiq/prom.c
172 +++ b/arch/mips/lantiq/prom.c
173 @@ -31,10 +31,14 @@ EXPORT_SYMBOL_GPL(ebu_lock);
174   */
175  static struct ltq_soc_info soc_info;
176  
177 +/* for Multithreading (APRP), vpe.c will use it */
178 +unsigned long cp0_memsize;
179 +
180  const char *get_system_type(void)
181  {
182         return soc_info.sys_type;
183  }
184 +EXPORT_SYMBOL(ltq_soc_type);
185  
186  int ltq_soc_type(void)
187  {
188 --- a/arch/mips/include/asm/mipsmtregs.h
189 +++ b/arch/mips/include/asm/mipsmtregs.h
190 @@ -31,6 +31,9 @@
191  #define read_c0_vpeconf1()             __read_32bit_c0_register($1, 3)
192  #define write_c0_vpeconf1(val)         __write_32bit_c0_register($1, 3, val)
193  
194 +#define read_c0_vpeopt()               __read_32bit_c0_register($1, 7)
195 +#define write_c0_vpeopt(val)           __write_32bit_c0_register($1, 7, val)
196 +
197  #define read_c0_tcstatus()             __read_32bit_c0_register($2, 1)
198  #define write_c0_tcstatus(val)         __write_32bit_c0_register($2, 1, val)
199  
200 @@ -376,6 +379,8 @@ do {                                                                        \
201  #define write_vpe_c0_vpeconf0(val)     mttc0(1, 2, val)
202  #define read_vpe_c0_vpeconf1()         mftc0(1, 3)
203  #define write_vpe_c0_vpeconf1(val)     mttc0(1, 3, val)
204 +#define read_vpe_c0_vpeopt()           mftc0(1, 7)
205 +#define write_vpe_c0_vpeopt(val)       mttc0(1, 7, val)
206  #define read_vpe_c0_count()            mftc0(9, 0)
207  #define write_vpe_c0_count(val)                mttc0(9, 0, val)
208  #define read_vpe_c0_status()           mftc0(12, 0)