aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/brcm63xx/patches-3.13/009-MIPS-BMIPS-change-compile-time-checks-to-runtime-che.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/brcm63xx/patches-3.13/009-MIPS-BMIPS-change-compile-time-checks-to-runtime-che.patch')
-rw-r--r--target/linux/brcm63xx/patches-3.13/009-MIPS-BMIPS-change-compile-time-checks-to-runtime-che.patch602
1 files changed, 602 insertions, 0 deletions
diff --git a/target/linux/brcm63xx/patches-3.13/009-MIPS-BMIPS-change-compile-time-checks-to-runtime-che.patch b/target/linux/brcm63xx/patches-3.13/009-MIPS-BMIPS-change-compile-time-checks-to-ru
From 949b88531a779af4f6456ff43d3de2d4f74e44ee Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jogo@openwrt.org>
Date: Sun, 23 Jun 2013 12:25:49 +0200
Subject: [PATCH V2 10/13] MIPS: BCM63XX: let the individual SoCs select the
 appropriate CPUs

Let each supported chip select the appropirate SYS_HAS_CPU_BMIPS*
option for its embedded processor, so support will be conditionally
included.

Signed-off-by: Jonas Gorski <jogo@openwrt.org>
---
 arch/mips/Kconfig         | 1 -
 arch/mips/bcm63xx/Kconfig | 8 ++++++++
 2 files changed, 8 insertions(+), 1 deletion(-)

--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -133,7 +133,6 @@ config BCM63XX
 	select DMA_NONCOHERENT
 	select IRQ_CPU
 	select SYS_HAS_CPU_MIPS32_R1
-	select SYS_HAS_CPU_BMIPS4350 if !BCM63XX_CPU_6338 && !BCM63XX_CPU_6345 && !BCM63XX_CPU_6348
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_BIG_ENDIAN
 	select SYS_HAS_EARLY_PRINTK
--- a/arch/mips/bcm63xx/Kconfig
+++ b/arch/mips/bcm63xx/Kconfig
@@ -3,33 +3,41 @@ menu "CPU support"
 
 config BCM63XX_CPU_3368
 	bool "support 3368 CPU"
+	select SYS_HAS_CPU_BMIPS4350
 	select HW_HAS_PCI
 
 config BCM63XX_CPU_6328
 	bool "support 6328 CPU"
+	select SYS_HAS_CPU_BMIPS4350
 	select HW_HAS_PCI
 
 config BCM63XX_CPU_6338
 	bool "support 6338 CPU"
+	select SYS_HAS_CPU_BMIPS32_3300
 	select HW_HAS_PCI
 
 config BCM63XX_CPU_6345
 	bool "support 6345 CPU"
+	select SYS_HAS_CPU_BMIPS32_3300
 
 config BCM63XX_CPU_6348
 	bool "support 6348 CPU"
+	select SYS_HAS_CPU_BMIPS32_3300
 	select HW_HAS_PCI
 
 config BCM63XX_CPU_6358
 	bool "support 6358 CPU"
+	select SYS_HAS_CPU_BMIPS4350
 	select HW_HAS_PCI
 
 config BCM63XX_CPU_6362
 	bool "support 6362 CPU"
+	select SYS_HAS_CPU_BMIPS4350
 	select HW_HAS_PCI
 
 config BCM63XX_CPU_6368
 	bool "support 6368 CPU"
+	select SYS_HAS_CPU_BMIPS4350
 	select HW_HAS_PCI
 endmenu
 
2f
++
+ mfc0 t0, $22, 5
+ li t1, 0x01ff
+ li t2, (1 << 8) | (1 << 5)
+@@ -240,12 +275,8 @@ LEAF(bmips_enable_xks01)
+ or t0, t2
+ mtc0 t0, $22, 5
+ BARRIER
+-#else
+-
+-#error Missing XKS01 setup
+-
+-#endif
+-
++#endif /* CONFIG_CPU_BMIPS5000 */
++2:
+ #endif /* defined(CONFIG_XKS01) */
+
+ jr ra
+--- a/arch/mips/kernel/smp-bmips.c
++++ b/arch/mips/kernel/smp-bmips.c
+@@ -49,8 +49,10 @@ cpumask_t bmips_booted_mask;
+ unsigned long bmips_smp_boot_sp;
+ unsigned long bmips_smp_boot_gp;
+
+-static void bmips_send_ipi_single(int cpu, unsigned int action);
+-static irqreturn_t bmips_ipi_interrupt(int irq, void *dev_id);
++static void bmips43xx_send_ipi_single(int cpu, unsigned int action);
++static void bmips5000_send_ipi_single(int cpu, unsigned int action);
++static irqreturn_t bmips43xx_ipi_interrupt(int irq, void *dev_id);
++static irqreturn_t bmips5000_ipi_interrupt(int irq, void *dev_id);
+
+ /* SW interrupts 0,1 are used for interprocessor signaling */
+ #define IPI0_IRQ (MIPS_CPU_IRQ_BASE + 0)
+@@ -64,49 +66,58 @@ static irqreturn_t bmips_ipi_interrupt(i
+ static void __init bmips_smp_setup(void)
+ {
+ int i, cpu = 1, boot_cpu = 0;
+-
+-#if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380)
+ int cpu_hw_intr;
+
+- /* arbitration priority */
+- clear_c0_brcm_cmt_ctrl(0x30);
+-
+- /* NBK and weak order flags */
+- set_c0_brcm_config_0(0x30000);
+-
+- /* Find out if we are running on TP0 or TP1 */
+- boot_cpu = !!(read_c0_brcm_cmt_local() & (1 << 31));
+-
+- /*
+- * MIPS interrupts 0,1 (SW INT 0,1) cross over to the other thread
+- * MIPS interrupt 2 (HW INT 0) is the CPU0 L1 controller output
+- * MIPS interrupt 3 (HW INT 1) is the CPU1 L1 controller output
+- */
+- if (boot_cpu == 0)
+- cpu_hw_intr = 0x02;
+- else
+- cpu_hw_intr = 0x1d;
+-
+- change_c0_brcm_cmt_intr(0xf8018000, (cpu_hw_intr << 27) | (0x03 << 15));
+-
+- /* single core, 2 threads (2 pipelines) */
+- max_cpus = 2;
+-#elif defined(CONFIG_CPU_BMIPS5000)
+- /* enable raceless SW interrupts */
+- set_c0_brcm_config(0x03 << 22);
+-
+- /* route HW interrupt 0 to CPU0, HW interrupt 1 to CPU1 */
+- change_c0_brcm_mode(0x1f << 27, 0x02 << 27);
+-
+- /* N cores, 2 threads per core */
+- max_cpus = (((read_c0_brcm_config() >> 6) & 0x03) + 1) << 1;
++ switch (current_cpu_type()) {
++ case CPU_BMIPS4350:
++ case CPU_BMIPS4380:
++ /* arbitration priority */
++ clear_c0_brcm_cmt_ctrl(0x30);
++
++ /* NBK and weak order flags */
++ set_c0_brcm_config_0(0x30000);
++
++ /* Find out if we are running on TP0 or TP1 */
++ boot_cpu = !!(read_c0_brcm_cmt_local() & (1 << 31));
++
++ /*
++ * MIPS interrupts 0,1 (SW INT 0,1) cross over to the other
++ * thread
++ * MIPS interrupt 2 (HW INT 0) is the CPU0 L1 controller output
++ * MIPS interrupt 3 (HW INT 1) is the CPU1 L1 controller output
++ */
++ if (boot_cpu == 0)
++ cpu_hw_intr = 0x02;
++ else
++ cpu_hw_intr = 0x1d;
++
++ change_c0_brcm_cmt_intr(0xf8018000,
++ (cpu_hw_intr << 27) | (0x03 << 15));
++
++ /* single core, 2 threads (2 pipelines) */
++ max_cpus = 2;
++
++ break;
++ case CPU_BMIPS5000:
++ /* enable raceless SW interrupts */
++ set_c0_brcm_config(0x03 << 22);
++
++ /* route HW interrupt 0 to CPU0, HW interrupt 1 to CPU1 */
++ change_c0_brcm_mode(0x1f << 27, 0x02 << 27);
++
++ /* N cores, 2 threads per core */
++ max_cpus = (((read_c0_brcm_config() >> 6) & 0x03) + 1) << 1;
++
++ /* clear any pending SW interrupts */
++ for (i = 0; i < max_cpus; i++) {
++ write_c0_brcm_action(ACTION_CLR_IPI(i, 0));
++ write_c0_brcm_action(ACTION_CLR_IPI(i, 1));
++ }
+
+- /* clear any pending SW interrupts */
+- for (i = 0; i < max_cpus; i++) {
+- write_c0_brcm_action(ACTION_CLR_IPI(i, 0));
+- write_c0_brcm_action(ACTION_CLR_IPI(i, 1));
++ break;
++ default:
++ max_cpus = 1;
+ }
+-#endif
+
+ if (!bmips_smp_enabled)
+ max_cpus = 1;
+@@ -134,6 +145,20 @@ static void __init bmips_smp_setup(void)
+ */
+ static void bmips_prepare_cpus(unsigned int max_cpus)
+ {
++ irqreturn_t (*bmips_ipi_interrupt)(int irq, void *dev_id);
++
++ switch (current_cpu_type()) {
++ case CPU_BMIPS4350:
++ case CPU_BMIPS4380:
++ bmips_ipi_interrupt = bmips43xx_ipi_interrupt;
++ break;
++ case CPU_BMIPS5000:
++ bmips_ipi_interrupt = bmips5000_ipi_interrupt;
++ break;
++ default:
++ return;
++ }
++
+ if (request_irq(IPI0_IRQ, bmips_ipi_interrupt, IRQF_PERCPU,
+ "smp_ipi0", NULL))
+ panic("Can't request IPI0 interrupt");
+@@ -168,26 +193,39 @@ static void bmips_boot_secondary(int cpu
+
+ pr_info("SMP: Booting CPU%d...\n", cpu);
+
+- if (cpumask_test_cpu(cpu, &bmips_booted_mask))
+- bmips_send_ipi_single(cpu, 0);
++ if (cpumask_test_cpu(cpu, &bmips_booted_mask)) {
++ switch (current_cpu_type()) {
++ case CPU_BMIPS4350:
++ case CPU_BMIPS4380:
++ bmips43xx_send_ipi_single(cpu, 0);
++ break;
++ case CPU_BMIPS5000:
++ bmips5000_send_ipi_single(cpu, 0);
++ break;
++ }
++ }
+ else {
+-#if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380)
+- /* Reset slave TP1 if booting from TP0 */
+- if (cpu_logical_map(cpu) == 1)
+- set_c0_brcm_cmt_ctrl(0x01);
+-#elif defined(CONFIG_CPU_BMIPS5000)
+- if (cpu & 0x01)
+- write_c0_brcm_action(ACTION_BOOT_THREAD(cpu));
+- else {
+- /*
+- * core N thread 0 was already booted; just
+- * pulse the NMI line
+- */
+- bmips_write_zscm_reg(0x210, 0xc0000000);
+- udelay(10);
+- bmips_write_zscm_reg(0x210, 0x00);
++ switch (current_cpu_type()) {
++ case CPU_BMIPS4350:
++ case CPU_BMIPS4380:
++ /* Reset slave TP1 if booting from TP0 */
++ if (cpu_logical_map(cpu) == 1)
++ set_c0_brcm_cmt_ctrl(0x01);
++ break;
++ case CPU_BMIPS5000:
++ if (cpu & 0x01)
++ write_c0_brcm_action(ACTION_BOOT_THREAD(cpu));
++ else {
++ /*
++ * core N thread 0 was already booted; just
++ * pulse the NMI line
++ */
++ bmips_write_zscm_reg(0x210, 0xc0000000);
++ udelay(10);
++ bmips_write_zscm_reg(0x210, 0x00);
++ }
++ break;
+ }
+-#endif
+ cpumask_set_cpu(cpu, &bmips_booted_mask);
+ }
+ }
+@@ -199,26 +237,32 @@ static void bmips_init_secondary(void)
+ {
+ /* move NMI vector to kseg0, in case XKS01 is enabled */
+
+-#if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380)
+- void __iomem *cbr = BMIPS_GET_CBR();
++ void __iomem *cbr;
+ unsigned long old_vec;
+ unsigned long relo_vector;
+ int boot_cpu;
+
+- boot_cpu = !!(read_c0_brcm_cmt_local() & (1 << 31));
+- relo_vector = boot_cpu ? BMIPS_RELO_VECTOR_CONTROL_0 :
+- BMIPS_RELO_VECTOR_CONTROL_1;
+-
+- old_vec = __raw_readl(cbr + relo_vector);
+- __raw_writel(old_vec & ~0x20000000, cbr + relo_vector);
+-
+- clear_c0_cause(smp_processor_id() ? C_SW1 : C_SW0);
+-#elif defined(CONFIG_CPU_BMIPS5000)
+- write_c0_brcm_bootvec(read_c0_brcm_bootvec() &
+- (smp_processor_id() & 0x01 ? ~0x20000000 : ~0x2000));
++ switch (current_cpu_type()) {
++ case CPU_BMIPS4350:
++ case CPU_BMIPS4380:
++ cbr = BMIPS_GET_CBR();
++
++ boot_cpu = !!(read_c0_brcm_cmt_local() & (1 << 31));
++ relo_vector = boot_cpu ? BMIPS_RELO_VECTOR_CONTROL_0 :
++ BMIPS_RELO_VECTOR_CONTROL_1;
++
++ old_vec = __raw_readl(cbr + relo_vector);
++ __raw_writel(old_vec & ~0x20000000, cbr + relo_vector);
++
++ clear_c0_cause(smp_processor_id() ? C_SW1 : C_SW0);
++ break;
++ case CPU_BMIPS5000:
++ write_c0_brcm_bootvec(read_c0_brcm_bootvec() &
++ (smp_processor_id() & 0x01 ? ~0x20000000 : ~0x2000));
+
+- write_c0_brcm_action(ACTION_CLR_IPI(smp_processor_id(), 0));
+-#endif
++ write_c0_brcm_action(ACTION_CLR_IPI(smp_processor_id(), 0));
++ break;
++ }
+ }
+
+ /*
+@@ -243,8 +287,6 @@ static void bmips_cpus_done(void)
+ {
+ }
+
+-#if defined(CONFIG_CPU_BMIPS5000)
+-
+ /*
+ * BMIPS5000 raceless IPIs
+ *
+@@ -253,12 +295,12 @@ static void bmips_cpus_done(void)
+ * IPI1 is used for SMP_CALL_FUNCTION
+ */
+
+-static void bmips_send_ipi_single(int cpu, unsigned int action)
++static void bmips5000_send_ipi_single(int cpu, unsigned int action)
+ {
+ write_c0_brcm_action(ACTION_SET_IPI(cpu, action == SMP_CALL_FUNCTION));
+ }
+
+-static irqreturn_t bmips_ipi_interrupt(int irq, void *dev_id)
++static irqreturn_t bmips5000_ipi_interrupt(int irq, void *dev_id)
+ {
+ int action = irq - IPI0_IRQ;
+
+@@ -272,7 +314,14 @@ static irqreturn_t bmips_ipi_interrupt(i
+ return IRQ_HANDLED;
+ }
+
+-#else
++static void bmips5000_send_ipi_mask(const struct cpumask *mask,
++ unsigned int action)
++{
++ unsigned int i;
++
++ for_each_cpu(i, mask)
++ bmips5000_send_ipi_single(i, action);
++}
+
+ /*
+ * BMIPS43xx racey IPIs
+@@ -287,7 +336,7 @@ static irqreturn_t bmips_ipi_interrupt(i
+ static DEFINE_SPINLOCK(ipi_lock);
+ static DEFINE_PER_CPU(int, ipi_action_mask);
+
+-static void bmips_send_ipi_single(int cpu, unsigned int action)
++static void bmips43xx_send_ipi_single(int cpu, unsigned int action)
+ {
+ unsigned long flags;
+
+@@ -298,7 +347,7 @@ static void bmips_send_ipi_single(int cp
+ spin_unlock_irqrestore(&ipi_lock, flags);
+ }
+
+-static irqreturn_t bmips_ipi_interrupt(int irq, void *dev_id)
++static irqreturn_t bmips43xx_ipi_interrupt(int irq, void *dev_id)
+ {
+ unsigned long flags;
+ int action, cpu = irq - IPI0_IRQ;
+@@ -317,15 +366,13 @@ static irqreturn_t bmips_ipi_interrupt(i
+ return IRQ_HANDLED;
+ }
+
+-#endif /* BMIPS type */
+-
+-static void bmips_send_ipi_mask(const struct cpumask *mask,
++static void bmips43xx_send_ipi_mask(const struct cpumask *mask,
+ unsigned int action)
+ {
+ unsigned int i;
+
+ for_each_cpu(i, mask)
+- bmips_send_ipi_single(i, action);
++ bmips43xx_send_ipi_single(i, action);
+ }
+
+ #ifdef CONFIG_HOTPLUG_CPU
+@@ -381,15 +428,30 @@ void __ref play_dead(void)
+
+ #endif /* CONFIG_HOTPLUG_CPU */
+
+-struct plat_smp_ops bmips_smp_ops = {
++struct plat_smp_ops bmips43xx_smp_ops = {
++ .smp_setup = bmips_smp_setup,
++ .prepare_cpus = bmips_prepare_cpus,
++ .boot_secondary = bmips_boot_secondary,
++ .smp_finish = bmips_smp_finish,
++ .init_secondary = bmips_init_secondary,
++ .cpus_done = bmips_cpus_done,
++ .send_ipi_single = bmips43xx_send_ipi_single,
++ .send_ipi_mask = bmips43xx_send_ipi_mask,
++#ifdef CONFIG_HOTPLUG_CPU
++ .cpu_disable = bmips_cpu_disable,
++ .cpu_die = bmips_cpu_die,
++#endif
++};
++
++struct plat_smp_ops bmips5000_smp_ops = {
+ .smp_setup = bmips_smp_setup,
+ .prepare_cpus = bmips_prepare_cpus,
+ .boot_secondary = bmips_boot_secondary,
+ .smp_finish = bmips_smp_finish,
+ .init_secondary = bmips_init_secondary,
+ .cpus_done = bmips_cpus_done,
+- .send_ipi_single = bmips_send_ipi_single,
+- .send_ipi_mask = bmips_send_ipi_mask,
++ .send_ipi_single = bmips5000_send_ipi_single,
++ .send_ipi_mask = bmips5000_send_ipi_mask,
+ #ifdef CONFIG_HOTPLUG_CPU
+ .cpu_disable = bmips_cpu_disable,
+ .cpu_die = bmips_cpu_die,
+@@ -427,43 +489,47 @@ void bmips_ebase_setup(void)
+
+ BUG_ON(ebase != CKSEG0);
+
+-#if defined(CONFIG_CPU_BMIPS4350)
+- /*
+- * BMIPS4350 cannot relocate the normal vectors, but it
+- * can relocate the BEV=1 vectors. So CPU1 starts up at
+- * the relocated BEV=1, IV=0 general exception vector @
+- * 0xa000_0380.
+- *
+- * set_uncached_handler() is used here because:
+- * - CPU1 will run this from uncached space
+- * - None of the cacheflush functions are set up yet
+- */
+- set_uncached_handler(BMIPS_WARM_RESTART_VEC - CKSEG0,
+- &bmips_smp_int_vec, 0x80);
+- __sync();
+- return;
+-#elif defined(CONFIG_CPU_BMIPS4380)
+- /*
+- * 0x8000_0000: reset/NMI (initially in kseg1)
+- * 0x8000_0400: normal vectors
+- */
+- new_ebase = 0x80000400;
+- cbr = BMIPS_GET_CBR();
+- __raw_writel(0x80080800, cbr + BMIPS_RELO_VECTOR_CONTROL_0);
+- __raw_writel(0xa0080800, cbr + BMIPS_RELO_VECTOR_CONTROL_1);
+-#elif defined(CONFIG_CPU_BMIPS5000)
+- /*
+- * 0x8000_0000: reset/NMI (initially in kseg1)
+- * 0x8000_1000: normal vectors
+- */
+- new_ebase = 0x80001000;
+- write_c0_brcm_bootvec(0xa0088008);
+- write_c0_ebase(new_ebase);
+- if (max_cpus > 2)
+- bmips_write_zscm_reg(0xa0, 0xa008a008);
+-#else
+- return;
+-#endif
++ switch (current_cpu_type()) {
++ case CPU_BMIPS4350:
++ /*
++ * BMIPS4350 cannot relocate the normal vectors, but it
++ * can relocate the BEV=1 vectors. So CPU1 starts up at
++ * the relocated BEV=1, IV=0 general exception vector @
++ * 0xa000_0380.
++ *
++ * set_uncached_handler() is used here because:
++ * - CPU1 will run this from uncached space
++ * - None of the cacheflush functions are set up yet
++ */
++ set_uncached_handler(BMIPS_WARM_RESTART_VEC - CKSEG0,
++ &bmips_smp_int_vec, 0x80);
++ __sync();
++ return;
++ case CPU_BMIPS4380:
++ /*
++ * 0x8000_0000: reset/NMI (initially in kseg1)
++ * 0x8000_0400: normal vectors
++ */
++ new_ebase = 0x80000400;
++ cbr = BMIPS_GET_CBR();
++ __raw_writel(0x80080800, cbr + BMIPS_RELO_VECTOR_CONTROL_0);
++ __raw_writel(0xa0080800, cbr + BMIPS_RELO_VECTOR_CONTROL_1);
++ break;
++ case CPU_BMIPS5000:
++ /*
++ * 0x8000_0000: reset/NMI (initially in kseg1)
++ * 0x8000_1000: normal vectors
++ */
++ new_ebase = 0x80001000;
++ write_c0_brcm_bootvec(0xa0088008);
++ write_c0_ebase(new_ebase);
++ if (max_cpus > 2)
++ bmips_write_zscm_reg(0xa0, 0xa008a008);
++ break;
++ default:
++ return;
++ }
++
+ board_nmi_handler_setup = &bmips_nmi_handler_setup;
+ ebase = new_ebase;
+ }