1 From 7d790bd6cab314462a29ba194e243b8b1d529524 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 V2 03/13] MIPS: BMIPS: change compile time checks to runtime
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
11 Since BMIPS43XX and BMIPS5000 require different IPI implementations,
12 split the SMP ops into one for each, so the runtime overhead is only
13 at registration time for them.
15 Signed-off-by: Jonas Gorski <jogo@openwrt.org>
18 * use switch (cpu_type()) instead of if () else if () ...
19 * split the smp ops into bmips43xx and bmips5000
21 arch/mips/bcm63xx/prom.c | 2 +-
22 arch/mips/include/asm/bmips.h | 3 +-
23 arch/mips/kernel/bmips_vec.S | 55 ++++++--
24 arch/mips/kernel/smp-bmips.c | 312 +++++++++++++++++++++++++-----------------
25 4 files changed, 235 insertions(+), 137 deletions(-)
27 --- a/arch/mips/bcm63xx/prom.c
28 +++ b/arch/mips/bcm63xx/prom.c
29 @@ -61,7 +61,7 @@ void __init prom_init(void)
31 if (IS_ENABLED(CONFIG_CPU_BMIPS4350) && IS_ENABLED(CONFIG_SMP)) {
33 - register_smp_ops(&bmips_smp_ops);
34 + register_smp_ops(&bmips43xx_smp_ops);
37 * BCM6328 might not have its second CPU enabled, while BCM3368
38 --- a/arch/mips/include/asm/bmips.h
39 +++ b/arch/mips/include/asm/bmips.h
41 #include <linux/cpumask.h>
42 #include <asm/r4kcache.h>
44 -extern struct plat_smp_ops bmips_smp_ops;
45 +extern struct plat_smp_ops bmips43xx_smp_ops;
46 +extern struct plat_smp_ops bmips5000_smp_ops;
47 extern char bmips_reset_nmi_vec;
48 extern char bmips_reset_nmi_vec_end;
49 extern char bmips_smp_movevec;
50 --- a/arch/mips/kernel/bmips_vec.S
51 +++ b/arch/mips/kernel/bmips_vec.S
54 #include <asm/asmmacro.h>
55 #include <asm/cacheops.h>
57 #include <asm/regdef.h>
58 #include <asm/mipsregs.h>
59 #include <asm/stackframe.h>
60 @@ -91,12 +92,18 @@ NESTED(bmips_reset_nmi_vec, PT_SIZE, sp)
61 beqz k0, bmips_smp_entry
63 #if defined(CONFIG_CPU_BMIPS5000)
65 + li k1, PRID_IMP_BMIPS5000
69 /* if we're not on core 0, this must be the SMP boot signal */
73 bnez k0, bmips_smp_entry
76 +#endif /* CONFIG_CPU_BMIPS5000 */
77 #endif /* CONFIG_SMP */
79 /* nope, it's just a regular NMI */
80 @@ -139,7 +146,12 @@ bmips_smp_entry:
86 #if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380)
87 + li k1, PRID_IMP_BMIPS43XX
90 /* initialize CPU1's local I-cache */
93 @@ -150,14 +162,21 @@ bmips_smp_entry:
94 1: cache Index_Store_Tag_I, 0(k0)
97 -#elif defined(CONFIG_CPU_BMIPS5000)
101 +#endif /* CONFIG_CPU_BMIPS4350 || CONFIG_CPU_BMIPS4380 */
102 +#if defined(CONFIG_CPU_BMIPS5000)
103 /* set exception vector base */
104 + li k1, PRID_IMP_BMIPS5000
113 +#endif /* CONFIG_CPU_BMIPS5000 */
115 /* jump back to kseg0 in case we need to remap the kseg1 area */
118 @@ -221,8 +240,18 @@ END(bmips_smp_int_vec)
119 LEAF(bmips_enable_xks01)
121 #if defined(CONFIG_XKS01)
124 + andi t2, t0, 0xff00
125 #if defined(CONFIG_CPU_BMIPS4380)
126 + li t1, PRID_IMP_BMIPS43XX
130 + addiu t1, t0, -PRID_REV_BMIPS4380_HI
132 + addiu t0, -PRID_REV_BMIPS4380_LO
137 li t2, (1 << 12) | (1 << 9)
138 @@ -231,7 +260,13 @@ LEAF(bmips_enable_xks01)
142 -#elif defined(CONFIG_CPU_BMIPS5000)
145 +#endif /* CONFIG_CPU_BMIPS4380 */
146 +#if defined(CONFIG_CPU_BMIPS5000)
147 + li t1, PRID_IMP_BMIPS5000
152 li t2, (1 << 8) | (1 << 5)
153 @@ -240,12 +275,8 @@ LEAF(bmips_enable_xks01)
159 -#error Missing XKS01 setup
163 +#endif /* CONFIG_CPU_BMIPS5000 */
165 #endif /* defined(CONFIG_XKS01) */
168 --- a/arch/mips/kernel/smp-bmips.c
169 +++ b/arch/mips/kernel/smp-bmips.c
170 @@ -49,8 +49,10 @@ cpumask_t bmips_booted_mask;
171 unsigned long bmips_smp_boot_sp;
172 unsigned long bmips_smp_boot_gp;
174 -static void bmips_send_ipi_single(int cpu, unsigned int action);
175 -static irqreturn_t bmips_ipi_interrupt(int irq, void *dev_id);
176 +static void bmips43xx_send_ipi_single(int cpu, unsigned int action);
177 +static void bmips5000_send_ipi_single(int cpu, unsigned int action);
178 +static irqreturn_t bmips43xx_ipi_interrupt(int irq, void *dev_id);
179 +static irqreturn_t bmips5000_ipi_interrupt(int irq, void *dev_id);
181 /* SW interrupts 0,1 are used for interprocessor signaling */
182 #define IPI0_IRQ (MIPS_CPU_IRQ_BASE + 0)
183 @@ -64,49 +66,58 @@ static irqreturn_t bmips_ipi_interrupt(i
184 static void __init bmips_smp_setup(void)
186 int i, cpu = 1, boot_cpu = 0;
188 -#if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380)
191 - /* arbitration priority */
192 - clear_c0_brcm_cmt_ctrl(0x30);
194 - /* NBK and weak order flags */
195 - set_c0_brcm_config_0(0x30000);
197 - /* Find out if we are running on TP0 or TP1 */
198 - boot_cpu = !!(read_c0_brcm_cmt_local() & (1 << 31));
201 - * MIPS interrupts 0,1 (SW INT 0,1) cross over to the other thread
202 - * MIPS interrupt 2 (HW INT 0) is the CPU0 L1 controller output
203 - * MIPS interrupt 3 (HW INT 1) is the CPU1 L1 controller output
206 - cpu_hw_intr = 0x02;
208 - cpu_hw_intr = 0x1d;
210 - change_c0_brcm_cmt_intr(0xf8018000, (cpu_hw_intr << 27) | (0x03 << 15));
212 - /* single core, 2 threads (2 pipelines) */
214 -#elif defined(CONFIG_CPU_BMIPS5000)
215 - /* enable raceless SW interrupts */
216 - set_c0_brcm_config(0x03 << 22);
218 - /* route HW interrupt 0 to CPU0, HW interrupt 1 to CPU1 */
219 - change_c0_brcm_mode(0x1f << 27, 0x02 << 27);
221 - /* N cores, 2 threads per core */
222 - max_cpus = (((read_c0_brcm_config() >> 6) & 0x03) + 1) << 1;
223 + switch (current_cpu_type()) {
224 + case CPU_BMIPS4350:
225 + case CPU_BMIPS4380:
226 + /* arbitration priority */
227 + clear_c0_brcm_cmt_ctrl(0x30);
229 + /* NBK and weak order flags */
230 + set_c0_brcm_config_0(0x30000);
232 + /* Find out if we are running on TP0 or TP1 */
233 + boot_cpu = !!(read_c0_brcm_cmt_local() & (1 << 31));
236 + * MIPS interrupts 0,1 (SW INT 0,1) cross over to the other
238 + * MIPS interrupt 2 (HW INT 0) is the CPU0 L1 controller output
239 + * MIPS interrupt 3 (HW INT 1) is the CPU1 L1 controller output
242 + cpu_hw_intr = 0x02;
244 + cpu_hw_intr = 0x1d;
246 + change_c0_brcm_cmt_intr(0xf8018000,
247 + (cpu_hw_intr << 27) | (0x03 << 15));
249 + /* single core, 2 threads (2 pipelines) */
253 + case CPU_BMIPS5000:
254 + /* enable raceless SW interrupts */
255 + set_c0_brcm_config(0x03 << 22);
257 + /* route HW interrupt 0 to CPU0, HW interrupt 1 to CPU1 */
258 + change_c0_brcm_mode(0x1f << 27, 0x02 << 27);
260 + /* N cores, 2 threads per core */
261 + max_cpus = (((read_c0_brcm_config() >> 6) & 0x03) + 1) << 1;
263 + /* clear any pending SW interrupts */
264 + for (i = 0; i < max_cpus; i++) {
265 + write_c0_brcm_action(ACTION_CLR_IPI(i, 0));
266 + write_c0_brcm_action(ACTION_CLR_IPI(i, 1));
269 - /* clear any pending SW interrupts */
270 - for (i = 0; i < max_cpus; i++) {
271 - write_c0_brcm_action(ACTION_CLR_IPI(i, 0));
272 - write_c0_brcm_action(ACTION_CLR_IPI(i, 1));
279 if (!bmips_smp_enabled)
281 @@ -134,6 +145,20 @@ static void __init bmips_smp_setup(void)
283 static void bmips_prepare_cpus(unsigned int max_cpus)
285 + irqreturn_t (*bmips_ipi_interrupt)(int irq, void *dev_id);
287 + switch (current_cpu_type()) {
288 + case CPU_BMIPS4350:
289 + case CPU_BMIPS4380:
290 + bmips_ipi_interrupt = bmips43xx_ipi_interrupt;
292 + case CPU_BMIPS5000:
293 + bmips_ipi_interrupt = bmips5000_ipi_interrupt;
299 if (request_irq(IPI0_IRQ, bmips_ipi_interrupt, IRQF_PERCPU,
301 panic("Can't request IPI0 interrupt");
302 @@ -168,26 +193,39 @@ static void bmips_boot_secondary(int cpu
304 pr_info("SMP: Booting CPU%d...\n", cpu);
306 - if (cpumask_test_cpu(cpu, &bmips_booted_mask))
307 - bmips_send_ipi_single(cpu, 0);
308 + if (cpumask_test_cpu(cpu, &bmips_booted_mask)) {
309 + switch (current_cpu_type()) {
310 + case CPU_BMIPS4350:
311 + case CPU_BMIPS4380:
312 + bmips43xx_send_ipi_single(cpu, 0);
314 + case CPU_BMIPS5000:
315 + bmips5000_send_ipi_single(cpu, 0);
320 -#if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380)
321 - /* Reset slave TP1 if booting from TP0 */
322 - if (cpu_logical_map(cpu) == 1)
323 - set_c0_brcm_cmt_ctrl(0x01);
324 -#elif defined(CONFIG_CPU_BMIPS5000)
326 - write_c0_brcm_action(ACTION_BOOT_THREAD(cpu));
329 - * core N thread 0 was already booted; just
330 - * pulse the NMI line
332 - bmips_write_zscm_reg(0x210, 0xc0000000);
334 - bmips_write_zscm_reg(0x210, 0x00);
335 + switch (current_cpu_type()) {
336 + case CPU_BMIPS4350:
337 + case CPU_BMIPS4380:
338 + /* Reset slave TP1 if booting from TP0 */
339 + if (cpu_logical_map(cpu) == 1)
340 + set_c0_brcm_cmt_ctrl(0x01);
342 + case CPU_BMIPS5000:
344 + write_c0_brcm_action(ACTION_BOOT_THREAD(cpu));
347 + * core N thread 0 was already booted; just
348 + * pulse the NMI line
350 + bmips_write_zscm_reg(0x210, 0xc0000000);
352 + bmips_write_zscm_reg(0x210, 0x00);
357 cpumask_set_cpu(cpu, &bmips_booted_mask);
360 @@ -199,26 +237,32 @@ static void bmips_init_secondary(void)
362 /* move NMI vector to kseg0, in case XKS01 is enabled */
364 -#if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380)
365 - void __iomem *cbr = BMIPS_GET_CBR();
367 unsigned long old_vec;
368 unsigned long relo_vector;
371 - boot_cpu = !!(read_c0_brcm_cmt_local() & (1 << 31));
372 - relo_vector = boot_cpu ? BMIPS_RELO_VECTOR_CONTROL_0 :
373 - BMIPS_RELO_VECTOR_CONTROL_1;
375 - old_vec = __raw_readl(cbr + relo_vector);
376 - __raw_writel(old_vec & ~0x20000000, cbr + relo_vector);
378 - clear_c0_cause(smp_processor_id() ? C_SW1 : C_SW0);
379 -#elif defined(CONFIG_CPU_BMIPS5000)
380 - write_c0_brcm_bootvec(read_c0_brcm_bootvec() &
381 - (smp_processor_id() & 0x01 ? ~0x20000000 : ~0x2000));
382 + switch (current_cpu_type()) {
383 + case CPU_BMIPS4350:
384 + case CPU_BMIPS4380:
385 + cbr = BMIPS_GET_CBR();
387 + boot_cpu = !!(read_c0_brcm_cmt_local() & (1 << 31));
388 + relo_vector = boot_cpu ? BMIPS_RELO_VECTOR_CONTROL_0 :
389 + BMIPS_RELO_VECTOR_CONTROL_1;
391 + old_vec = __raw_readl(cbr + relo_vector);
392 + __raw_writel(old_vec & ~0x20000000, cbr + relo_vector);
394 + clear_c0_cause(smp_processor_id() ? C_SW1 : C_SW0);
396 + case CPU_BMIPS5000:
397 + write_c0_brcm_bootvec(read_c0_brcm_bootvec() &
398 + (smp_processor_id() & 0x01 ? ~0x20000000 : ~0x2000));
400 - write_c0_brcm_action(ACTION_CLR_IPI(smp_processor_id(), 0));
402 + write_c0_brcm_action(ACTION_CLR_IPI(smp_processor_id(), 0));
408 @@ -243,8 +287,6 @@ static void bmips_cpus_done(void)
412 -#if defined(CONFIG_CPU_BMIPS5000)
415 * BMIPS5000 raceless IPIs
417 @@ -253,12 +295,12 @@ static void bmips_cpus_done(void)
418 * IPI1 is used for SMP_CALL_FUNCTION
421 -static void bmips_send_ipi_single(int cpu, unsigned int action)
422 +static void bmips5000_send_ipi_single(int cpu, unsigned int action)
424 write_c0_brcm_action(ACTION_SET_IPI(cpu, action == SMP_CALL_FUNCTION));
427 -static irqreturn_t bmips_ipi_interrupt(int irq, void *dev_id)
428 +static irqreturn_t bmips5000_ipi_interrupt(int irq, void *dev_id)
430 int action = irq - IPI0_IRQ;
432 @@ -272,7 +314,14 @@ static irqreturn_t bmips_ipi_interrupt(i
437 +static void bmips5000_send_ipi_mask(const struct cpumask *mask,
438 + unsigned int action)
442 + for_each_cpu(i, mask)
443 + bmips5000_send_ipi_single(i, action);
447 * BMIPS43xx racey IPIs
448 @@ -287,7 +336,7 @@ static irqreturn_t bmips_ipi_interrupt(i
449 static DEFINE_SPINLOCK(ipi_lock);
450 static DEFINE_PER_CPU(int, ipi_action_mask);
452 -static void bmips_send_ipi_single(int cpu, unsigned int action)
453 +static void bmips43xx_send_ipi_single(int cpu, unsigned int action)
457 @@ -298,7 +347,7 @@ static void bmips_send_ipi_single(int cp
458 spin_unlock_irqrestore(&ipi_lock, flags);
461 -static irqreturn_t bmips_ipi_interrupt(int irq, void *dev_id)
462 +static irqreturn_t bmips43xx_ipi_interrupt(int irq, void *dev_id)
465 int action, cpu = irq - IPI0_IRQ;
466 @@ -317,15 +366,13 @@ static irqreturn_t bmips_ipi_interrupt(i
470 -#endif /* BMIPS type */
472 -static void bmips_send_ipi_mask(const struct cpumask *mask,
473 +static void bmips43xx_send_ipi_mask(const struct cpumask *mask,
478 for_each_cpu(i, mask)
479 - bmips_send_ipi_single(i, action);
480 + bmips43xx_send_ipi_single(i, action);
483 #ifdef CONFIG_HOTPLUG_CPU
484 @@ -381,15 +428,30 @@ void __ref play_dead(void)
486 #endif /* CONFIG_HOTPLUG_CPU */
488 -struct plat_smp_ops bmips_smp_ops = {
489 +struct plat_smp_ops bmips43xx_smp_ops = {
490 + .smp_setup = bmips_smp_setup,
491 + .prepare_cpus = bmips_prepare_cpus,
492 + .boot_secondary = bmips_boot_secondary,
493 + .smp_finish = bmips_smp_finish,
494 + .init_secondary = bmips_init_secondary,
495 + .cpus_done = bmips_cpus_done,
496 + .send_ipi_single = bmips43xx_send_ipi_single,
497 + .send_ipi_mask = bmips43xx_send_ipi_mask,
498 +#ifdef CONFIG_HOTPLUG_CPU
499 + .cpu_disable = bmips_cpu_disable,
500 + .cpu_die = bmips_cpu_die,
504 +struct plat_smp_ops bmips5000_smp_ops = {
505 .smp_setup = bmips_smp_setup,
506 .prepare_cpus = bmips_prepare_cpus,
507 .boot_secondary = bmips_boot_secondary,
508 .smp_finish = bmips_smp_finish,
509 .init_secondary = bmips_init_secondary,
510 .cpus_done = bmips_cpus_done,
511 - .send_ipi_single = bmips_send_ipi_single,
512 - .send_ipi_mask = bmips_send_ipi_mask,
513 + .send_ipi_single = bmips5000_send_ipi_single,
514 + .send_ipi_mask = bmips5000_send_ipi_mask,
515 #ifdef CONFIG_HOTPLUG_CPU
516 .cpu_disable = bmips_cpu_disable,
517 .cpu_die = bmips_cpu_die,
518 @@ -427,43 +489,47 @@ void bmips_ebase_setup(void)
520 BUG_ON(ebase != CKSEG0);
522 -#if defined(CONFIG_CPU_BMIPS4350)
524 - * BMIPS4350 cannot relocate the normal vectors, but it
525 - * can relocate the BEV=1 vectors. So CPU1 starts up at
526 - * the relocated BEV=1, IV=0 general exception vector @
529 - * set_uncached_handler() is used here because:
530 - * - CPU1 will run this from uncached space
531 - * - None of the cacheflush functions are set up yet
533 - set_uncached_handler(BMIPS_WARM_RESTART_VEC - CKSEG0,
534 - &bmips_smp_int_vec, 0x80);
537 -#elif defined(CONFIG_CPU_BMIPS4380)
539 - * 0x8000_0000: reset/NMI (initially in kseg1)
540 - * 0x8000_0400: normal vectors
542 - new_ebase = 0x80000400;
543 - cbr = BMIPS_GET_CBR();
544 - __raw_writel(0x80080800, cbr + BMIPS_RELO_VECTOR_CONTROL_0);
545 - __raw_writel(0xa0080800, cbr + BMIPS_RELO_VECTOR_CONTROL_1);
546 -#elif defined(CONFIG_CPU_BMIPS5000)
548 - * 0x8000_0000: reset/NMI (initially in kseg1)
549 - * 0x8000_1000: normal vectors
551 - new_ebase = 0x80001000;
552 - write_c0_brcm_bootvec(0xa0088008);
553 - write_c0_ebase(new_ebase);
555 - bmips_write_zscm_reg(0xa0, 0xa008a008);
559 + switch (current_cpu_type()) {
560 + case CPU_BMIPS4350:
562 + * BMIPS4350 cannot relocate the normal vectors, but it
563 + * can relocate the BEV=1 vectors. So CPU1 starts up at
564 + * the relocated BEV=1, IV=0 general exception vector @
567 + * set_uncached_handler() is used here because:
568 + * - CPU1 will run this from uncached space
569 + * - None of the cacheflush functions are set up yet
571 + set_uncached_handler(BMIPS_WARM_RESTART_VEC - CKSEG0,
572 + &bmips_smp_int_vec, 0x80);
575 + case CPU_BMIPS4380:
577 + * 0x8000_0000: reset/NMI (initially in kseg1)
578 + * 0x8000_0400: normal vectors
580 + new_ebase = 0x80000400;
581 + cbr = BMIPS_GET_CBR();
582 + __raw_writel(0x80080800, cbr + BMIPS_RELO_VECTOR_CONTROL_0);
583 + __raw_writel(0xa0080800, cbr + BMIPS_RELO_VECTOR_CONTROL_1);
585 + case CPU_BMIPS5000:
587 + * 0x8000_0000: reset/NMI (initially in kseg1)
588 + * 0x8000_1000: normal vectors
590 + new_ebase = 0x80001000;
591 + write_c0_brcm_bootvec(0xa0088008);
592 + write_c0_ebase(new_ebase);
594 + bmips_write_zscm_reg(0xa0, 0xa008a008);
600 board_nmi_handler_setup = &bmips_nmi_handler_setup;