brcm63xx: add linux 3.10 support
[openwrt.git] / target / linux / brcm63xx / patches-3.10 / 103-MIPS-bmips-change-compile-time-checks-to-runtime-che.patch
1 From 12594762fcbec024cb424c9b77efb28402651667 Mon Sep 17 00:00:00 2001
2 From: Jonas Gorski <jogo@openwrt.org>
3 Date: Thu, 27 Jun 2013 21:33:56 +0200
4 Subject: [PATCH 04/10] MIPS: bmips: change compile time checks to runtime
5  checks
6
7 Allow building for all bmips cpus at the same time by changing ifdefs
8 to checks for the cpu type, or adding appropriate checks to the
9 assembly.
10
11 Signed-off-by: Jonas Gorski <jogo@openwrt.org>
12 ---
13  arch/mips/kernel/bmips_vec.S |   55 +++++++---
14  arch/mips/kernel/smp-bmips.c |  241 ++++++++++++++++++++++--------------------
15  2 files changed, 172 insertions(+), 124 deletions(-)
16
17 --- a/arch/mips/kernel/bmips_vec.S
18 +++ b/arch/mips/kernel/bmips_vec.S
19 @@ -13,6 +13,7 @@
20  #include <asm/asm.h>
21  #include <asm/asmmacro.h>
22  #include <asm/cacheops.h>
23 +#include <asm/cpu.h>
24  #include <asm/regdef.h>
25  #include <asm/mipsregs.h>
26  #include <asm/stackframe.h>
27 @@ -89,12 +90,18 @@ NESTED(bmips_reset_nmi_vec, PT_SIZE, sp)
28         beqz    k0, bmips_smp_entry
29  
30  #if defined(CONFIG_CPU_BMIPS5000)
31 +       mfc0    k0, CP0_PRID
32 +       li      k1, PRID_IMP_BMIPS5000
33 +       andi    k0, 0xff00
34 +       bne     k0, k1, 1f
35 +
36         /* if we're not on core 0, this must be the SMP boot signal */
37         li      k1, (3 << 25)
38         mfc0    k0, $22
39         and     k0, k1
40         bnez    k0, bmips_smp_entry
41 -#endif
42 +1:
43 +#endif /* CONFIG_CPU_BMIPS5000 */
44  #endif /* CONFIG_SMP */
45  
46         /* nope, it's just a regular NMI */
47 @@ -137,7 +144,12 @@ bmips_smp_entry:
48         xori    k0, 0x04
49         mtc0    k0, CP0_CONFIG
50  
51 +       mfc0    k0, CP0_PRID
52 +       andi    k0, 0xff00
53  #if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380)
54 +       li      k1, PRID_IMP_BMIPS43XX
55 +       bne     k0, k1, 2f
56 +
57         /* initialize CPU1's local I-cache */
58         li      k0, 0x80000000
59         li      k1, 0x80010000
60 @@ -148,14 +160,21 @@ bmips_smp_entry:
61  1:     cache   Index_Store_Tag_I, 0(k0)
62         addiu   k0, 16
63         bne     k0, k1, 1b
64 -#elif defined(CONFIG_CPU_BMIPS5000)
65 +
66 +       b       3f
67 +2:
68 +#endif /* CONFIG_CPU_BMIPS4350 || CONFIG_CPU_BMIPS4380 */
69 +#if defined(CONFIG_CPU_BMIPS5000)
70         /* set exception vector base */
71 +       li      k1, PRID_IMP_BMIPS5000
72 +       bne     k0, k1, 3f
73 +
74         la      k0, ebase
75         lw      k0, 0(k0)
76         mtc0    k0, $15, 1
77         BARRIER
78 -#endif
79 -
80 +#endif /* CONFIG_CPU_BMIPS5000 */
81 +3:
82         /* jump back to kseg0 in case we need to remap the kseg1 area */
83         la      k0, 1f
84         jr      k0
85 @@ -221,8 +240,18 @@ END(bmips_smp_int_vec)
86  LEAF(bmips_enable_xks01)
87  
88  #if defined(CONFIG_XKS01)
89 -
90 +       mfc0    t0, CP0_PRID
91 +       andi    t2, t0, 0xff00
92  #if defined(CONFIG_CPU_BMIPS4380)
93 +       li      t1, PRID_IMP_BMIPS43XX
94 +       bne     t2, t1, 1f
95 +
96 +       andi    t0, 0xff
97 +       addiu   t1, t0, -PRID_REV_BMIPS4380_HI
98 +       bgtz    t1, 2f
99 +       addiu   t0, -PRID_REV_BMIPS4380_LO
100 +       bltz    t0, 2f
101 +
102         mfc0    t0, $22, 3
103         li      t1, 0x1ff0
104         li      t2, (1 << 12) | (1 << 9)
105 @@ -231,7 +260,13 @@ LEAF(bmips_enable_xks01)
106         or      t0, t2
107         mtc0    t0, $22, 3
108         BARRIER
109 -#elif defined(CONFIG_CPU_BMIPS5000)
110 +       b       2f
111 +1:
112 +#endif /* CONFIG_CPU_BMIPS4380 */
113 +#if defined(CONFIG_CPU_BMIPS5000)
114 +       li      t1, PRID_IMP_BMIPS5000
115 +       bne     t2, t1, 2f
116 +
117         mfc0    t0, $22, 5
118         li      t1, 0x01ff
119         li      t2, (1 << 8) | (1 << 5)
120 @@ -240,12 +275,8 @@ LEAF(bmips_enable_xks01)
121         or      t0, t2
122         mtc0    t0, $22, 5
123         BARRIER
124 -#else
125 -
126 -#error Missing XKS01 setup
127 -
128 -#endif
129 -
130 +#endif /* CONFIG_CPU_BMIPS5000 */
131 +2:
132  #endif /* defined(CONFIG_XKS01) */
133  
134         jr      ra
135 --- a/arch/mips/kernel/smp-bmips.c
136 +++ b/arch/mips/kernel/smp-bmips.c
137 @@ -49,8 +49,11 @@ cpumask_t bmips_booted_mask;
138  unsigned long bmips_smp_boot_sp;
139  unsigned long bmips_smp_boot_gp;
140  
141 +static void bmips43xx_send_ipi_single(int cpu, unsigned int action);
142 +static void bmips5000_send_ipi_single(int cpu, unsigned int action);
143  static void bmips_send_ipi_single(int cpu, unsigned int action);
144 -static irqreturn_t bmips_ipi_interrupt(int irq, void *dev_id);
145 +static irqreturn_t bmips43xx_ipi_interrupt(int irq, void *dev_id);
146 +static irqreturn_t bmips5000_ipi_interrupt(int irq, void *dev_id);
147  
148  /* SW interrupts 0,1 are used for interprocessor signaling */
149  #define IPI0_IRQ                       (MIPS_CPU_IRQ_BASE + 0)
150 @@ -65,48 +68,49 @@ static void __init bmips_smp_setup(void)
151  {
152         int i, cpu = 1, boot_cpu = 0;
153  
154 -#if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380)
155 -       /* arbitration priority */
156 -       clear_c0_brcm_cmt_ctrl(0x30);
157 -
158 -       /* NBK and weak order flags */
159 -       set_c0_brcm_config_0(0x30000);
160 -
161 -       /* Find out if we are running on TP0 or TP1 */
162 -       boot_cpu = !!(read_c0_brcm_cmt_local() & (1 << 31));
163 -
164 -       /*
165 -        * MIPS interrupts 0,1 (SW INT 0,1) cross over to the other thread
166 -        * MIPS interrupt 2 (HW INT 0) is the CPU0 L1 controller output
167 -        * MIPS interrupt 3 (HW INT 1) is the CPU1 L1 controller output
168 -        *
169 -        * If booting from TP1, leave the existing CMT interrupt routing
170 -        * such that TP0 responds to SW1 and TP1 responds to SW0.
171 -        */
172 -       if (boot_cpu == 0)
173 -               change_c0_brcm_cmt_intr(0xf8018000,
174 +       if (cpu_is_bmips4350() || cpu_is_bmips4380()) {
175 +               /* arbitration priority */
176 +               clear_c0_brcm_cmt_ctrl(0x30);
177 +
178 +               /* NBK and weak order flags */
179 +               set_c0_brcm_config_0(0x30000);
180 +
181 +               /* Find out if we are running on TP0 or TP1 */
182 +               boot_cpu = !!(read_c0_brcm_cmt_local() & (1 << 31));
183 +
184 +               /*
185 +                * MIPS interrupts 0,1 (SW INT 0,1) cross over to the other
186 +                * thread
187 +                * MIPS interrupt 2 (HW INT 0) is the CPU0 L1 controller output
188 +                * MIPS interrupt 3 (HW INT 1) is the CPU1 L1 controller output
189 +                *
190 +                * If booting from TP1, leave the existing CMT interrupt routing
191 +                * such that TP0 responds to SW1 and TP1 responds to SW0.
192 +                */
193 +               if (boot_cpu == 0)
194 +                       change_c0_brcm_cmt_intr(0xf8018000,
195                                         (0x02 << 27) | (0x03 << 15));
196 -       else
197 -               change_c0_brcm_cmt_intr(0xf8018000, (0x1d << 27));
198 -
199 -       /* single core, 2 threads (2 pipelines) */
200 -       max_cpus = 2;
201 -#elif defined(CONFIG_CPU_BMIPS5000)
202 -       /* enable raceless SW interrupts */
203 -       set_c0_brcm_config(0x03 << 22);
204 -
205 -       /* route HW interrupt 0 to CPU0, HW interrupt 1 to CPU1 */
206 -       change_c0_brcm_mode(0x1f << 27, 0x02 << 27);
207 +               else
208 +                       change_c0_brcm_cmt_intr(0xf8018000, (0x1d << 27));
209  
210 -       /* N cores, 2 threads per core */
211 -       max_cpus = (((read_c0_brcm_config() >> 6) & 0x03) + 1) << 1;
212 -
213 -       /* clear any pending SW interrupts */
214 -       for (i = 0; i < max_cpus; i++) {
215 -               write_c0_brcm_action(ACTION_CLR_IPI(i, 0));
216 -               write_c0_brcm_action(ACTION_CLR_IPI(i, 1));
217 +               /* single core, 2 threads (2 pipelines) */
218 +               max_cpus = 2;
219 +       } else if (cpu_is_bmips5000()) {
220 +               /* enable raceless SW interrupts */
221 +               set_c0_brcm_config(0x03 << 22);
222 +
223 +               /* route HW interrupt 0 to CPU0, HW interrupt 1 to CPU1 */
224 +               change_c0_brcm_mode(0x1f << 27, 0x02 << 27);
225 +
226 +               /* N cores, 2 threads per core */
227 +               max_cpus = (((read_c0_brcm_config() >> 6) & 0x03) + 1) << 1;
228 +
229 +               /* clear any pending SW interrupts */
230 +               for (i = 0; i < max_cpus; i++) {
231 +                       write_c0_brcm_action(ACTION_CLR_IPI(i, 0));
232 +                       write_c0_brcm_action(ACTION_CLR_IPI(i, 1));
233 +               }
234         }
235 -#endif
236  
237         if (!bmips_smp_enabled)
238                 max_cpus = 1;
239 @@ -134,6 +138,15 @@ static void __init bmips_smp_setup(void)
240   */
241  static void bmips_prepare_cpus(unsigned int max_cpus)
242  {
243 +       irqreturn_t (*bmips_ipi_interrupt)(int irq, void *dev_id);
244 +
245 +       if (cpu_is_bmips4350() || cpu_is_bmips4380())
246 +               bmips_ipi_interrupt = bmips43xx_ipi_interrupt;
247 +       else if (cpu_is_bmips5000())
248 +               bmips_ipi_interrupt = bmips5000_ipi_interrupt;
249 +       else
250 +               return;
251 +
252         if (request_irq(IPI0_IRQ, bmips_ipi_interrupt, IRQF_PERCPU,
253                         "smp_ipi0", NULL))
254                 panic("Can't request IPI0 interrupt\n");
255 @@ -168,26 +181,26 @@ static void bmips_boot_secondary(int cpu
256  
257         pr_info("SMP: Booting CPU%d...\n", cpu);
258  
259 -       if (cpumask_test_cpu(cpu, &bmips_booted_mask))
260 +       if (cpumask_test_cpu(cpu, &bmips_booted_mask)) {
261                 bmips_send_ipi_single(cpu, 0);
262 -       else {
263 -#if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380)
264 -               /* Reset slave TP1 if booting from TP0 */
265 -               if (cpu_logical_map(cpu) == 0)
266 -                       set_c0_brcm_cmt_ctrl(0x01);
267 -#elif defined(CONFIG_CPU_BMIPS5000)
268 -               if (cpu & 0x01)
269 -                       write_c0_brcm_action(ACTION_BOOT_THREAD(cpu));
270 -               else {
271 -                       /*
272 -                        * core N thread 0 was already booted; just
273 -                        * pulse the NMI line
274 -                        */
275 -                       bmips_write_zscm_reg(0x210, 0xc0000000);
276 -                       udelay(10);
277 -                       bmips_write_zscm_reg(0x210, 0x00);
278 +       } else {
279 +               if (cpu_is_bmips4350() || cpu_is_bmips4380()) {
280 +                       /* Reset slave TP1 if booting from TP0 */
281 +                       if (cpu_logical_map(cpu) == 0)
282 +                               set_c0_brcm_cmt_ctrl(0x01);
283 +               } else if (cpu_is_bmips5000()) {
284 +                       if (cpu & 0x01)
285 +                               write_c0_brcm_action(ACTION_BOOT_THREAD(cpu));
286 +                       else {
287 +                               /*
288 +                                * core N thread 0 was already booted; just
289 +                                * pulse the NMI line
290 +                                */
291 +                               bmips_write_zscm_reg(0x210, 0xc0000000);
292 +                               udelay(10);
293 +                               bmips_write_zscm_reg(0x210, 0x00);
294 +                       }
295                 }
296 -#endif
297                 cpumask_set_cpu(cpu, &bmips_booted_mask);
298         }
299  }
300 @@ -199,20 +212,21 @@ static void bmips_init_secondary(void)
301  {
302         /* move NMI vector to kseg0, in case XKS01 is enabled */
303  
304 -#if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380)
305 -       void __iomem *cbr = BMIPS_GET_CBR();
306 -       unsigned long old_vec;
307 -
308 -       old_vec = __raw_readl(cbr + BMIPS_RELO_VECTOR_CONTROL_1);
309 -       __raw_writel(old_vec & ~0x20000000, cbr + BMIPS_RELO_VECTOR_CONTROL_1);
310 -
311 -       clear_c0_cause(smp_processor_id() ? C_SW1 : C_SW0);
312 -#elif defined(CONFIG_CPU_BMIPS5000)
313 -       write_c0_brcm_bootvec(read_c0_brcm_bootvec() &
314 -               (smp_processor_id() & 0x01 ? ~0x20000000 : ~0x2000));
315 +       if (cpu_is_bmips4350() || cpu_is_bmips4380()) {
316 +               void __iomem *cbr = BMIPS_GET_CBR();
317 +               unsigned long old_vec;
318 +
319 +               old_vec = __raw_readl(cbr + BMIPS_RELO_VECTOR_CONTROL_1);
320 +               __raw_writel(old_vec & ~0x20000000,
321 +                       cbr + BMIPS_RELO_VECTOR_CONTROL_1);
322 +
323 +               clear_c0_cause(smp_processor_id() ? C_SW1 : C_SW0);
324 +       } else if (cpu_is_bmips5000()) {
325 +               write_c0_brcm_bootvec(read_c0_brcm_bootvec() &
326 +                       (smp_processor_id() & 0x01 ? ~0x20000000 : ~0x2000));
327  
328 -       write_c0_brcm_action(ACTION_CLR_IPI(smp_processor_id(), 0));
329 -#endif
330 +               write_c0_brcm_action(ACTION_CLR_IPI(smp_processor_id(), 0));
331 +       }
332  }
333  
334  /*
335 @@ -237,8 +251,6 @@ static void bmips_cpus_done(void)
336  {
337  }
338  
339 -#if defined(CONFIG_CPU_BMIPS5000)
340 -
341  /*
342   * BMIPS5000 raceless IPIs
343   *
344 @@ -247,12 +259,12 @@ static void bmips_cpus_done(void)
345   * IPI1 is used for SMP_CALL_FUNCTION
346   */
347  
348 -static void bmips_send_ipi_single(int cpu, unsigned int action)
349 +static void bmips5000_send_ipi_single(int cpu, unsigned int action)
350  {
351         write_c0_brcm_action(ACTION_SET_IPI(cpu, action == SMP_CALL_FUNCTION));
352  }
353  
354 -static irqreturn_t bmips_ipi_interrupt(int irq, void *dev_id)
355 +static irqreturn_t bmips5000_ipi_interrupt(int irq, void *dev_id)
356  {
357         int action = irq - IPI0_IRQ;
358  
359 @@ -266,8 +278,6 @@ static irqreturn_t bmips_ipi_interrupt(i
360         return IRQ_HANDLED;
361  }
362  
363 -#else
364 -
365  /*
366   * BMIPS43xx racey IPIs
367   *
368 @@ -281,7 +291,7 @@ static irqreturn_t bmips_ipi_interrupt(i
369  static DEFINE_SPINLOCK(ipi_lock);
370  static DEFINE_PER_CPU(int, ipi_action_mask);
371  
372 -static void bmips_send_ipi_single(int cpu, unsigned int action)
373 +static void bmips43xx_send_ipi_single(int cpu, unsigned int action)
374  {
375         unsigned long flags;
376  
377 @@ -292,7 +302,7 @@ static void bmips_send_ipi_single(int cp
378         spin_unlock_irqrestore(&ipi_lock, flags);
379  }
380  
381 -static irqreturn_t bmips_ipi_interrupt(int irq, void *dev_id)
382 +static irqreturn_t bmips43xx_ipi_interrupt(int irq, void *dev_id)
383  {
384         unsigned long flags;
385         int action, cpu = irq - IPI0_IRQ;
386 @@ -311,7 +321,13 @@ static irqreturn_t bmips_ipi_interrupt(i
387         return IRQ_HANDLED;
388  }
389  
390 -#endif /* BMIPS type */
391 +static void bmips_send_ipi_single(int cpu, unsigned int action)
392 +{
393 +       if (cpu_is_bmips4350() || cpu_is_bmips4380())
394 +               bmips43xx_send_ipi_single(cpu, action);
395 +       else if (cpu_is_bmips5000())
396 +               bmips5000_send_ipi_single(cpu, action);
397 +}
398  
399  static void bmips_send_ipi_mask(const struct cpumask *mask,
400         unsigned int action)
401 @@ -421,43 +437,44 @@ void __cpuinit bmips_ebase_setup(void)
402  
403         BUG_ON(ebase != CKSEG0);
404  
405 -#if defined(CONFIG_CPU_BMIPS4350)
406 -       /*
407 -        * BMIPS4350 cannot relocate the normal vectors, but it
408 -        * can relocate the BEV=1 vectors.  So CPU1 starts up at
409 -        * the relocated BEV=1, IV=0 general exception vector @
410 -        * 0xa000_0380.
411 -        *
412 -        * set_uncached_handler() is used here because:
413 -        *  - CPU1 will run this from uncached space
414 -        *  - None of the cacheflush functions are set up yet
415 -        */
416 -       set_uncached_handler(BMIPS_WARM_RESTART_VEC - CKSEG0,
417 -               &bmips_smp_int_vec, 0x80);
418 -       __sync();
419 -       return;
420 -#elif defined(CONFIG_CPU_BMIPS4380)
421 -       /*
422 -        * 0x8000_0000: reset/NMI (initially in kseg1)
423 -        * 0x8000_0400: normal vectors
424 -        */
425 -       new_ebase = 0x80000400;
426 -       cbr = BMIPS_GET_CBR();
427 -       __raw_writel(0x80080800, cbr + BMIPS_RELO_VECTOR_CONTROL_0);
428 -       __raw_writel(0xa0080800, cbr + BMIPS_RELO_VECTOR_CONTROL_1);
429 -#elif defined(CONFIG_CPU_BMIPS5000)
430 -       /*
431 -        * 0x8000_0000: reset/NMI (initially in kseg1)
432 -        * 0x8000_1000: normal vectors
433 -        */
434 -       new_ebase = 0x80001000;
435 -       write_c0_brcm_bootvec(0xa0088008);
436 -       write_c0_ebase(new_ebase);
437 -       if (max_cpus > 2)
438 -               bmips_write_zscm_reg(0xa0, 0xa008a008);
439 -#else
440 -       return;
441 -#endif
442 +       if (cpu_is_bmips4350()) {
443 +               /*
444 +                * BMIPS4350 cannot relocate the normal vectors, but it
445 +                * can relocate the BEV=1 vectors.  So CPU1 starts up at
446 +                * the relocated BEV=1, IV=0 general exception vector @
447 +                * 0xa000_0380.
448 +                *
449 +                * set_uncached_handler() is used here because:
450 +                *  - CPU1 will run this from uncached space
451 +                *  - None of the cacheflush functions are set up yet
452 +                */
453 +               set_uncached_handler(BMIPS_WARM_RESTART_VEC - CKSEG0,
454 +                       &bmips_smp_int_vec, 0x80);
455 +               __sync();
456 +               return;
457 +       } else if (cpu_is_bmips4380()) {
458 +               /*
459 +                * 0x8000_0000: reset/NMI (initially in kseg1)
460 +                * 0x8000_0400: normal vectors
461 +                */
462 +               new_ebase = 0x80000400;
463 +               cbr = BMIPS_GET_CBR();
464 +               __raw_writel(0x80080800, cbr + BMIPS_RELO_VECTOR_CONTROL_0);
465 +               __raw_writel(0xa0080800, cbr + BMIPS_RELO_VECTOR_CONTROL_1);
466 +       } else if (cpu_is_bmips5000()) {
467 +               /*
468 +                * 0x8000_0000: reset/NMI (initially in kseg1)
469 +                * 0x8000_1000: normal vectors
470 +                */
471 +               new_ebase = 0x80001000;
472 +               write_c0_brcm_bootvec(0xa0088008);
473 +               write_c0_ebase(new_ebase);
474 +               if (max_cpus > 2)
475 +                       bmips_write_zscm_reg(0xa0, 0xa008a008);
476 +       } else {
477 +               return;
478 +       }
479 +
480         board_nmi_handler_setup = &bmips_nmi_handler_setup;
481         ebase = new_ebase;
482  }