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:
authorJonas Gorski <jogo@openwrt.org>2014-02-24 15:54:12 +0000
committerJonas Gorski <jogo@openwrt.org>2014-02-24 15:54:12 +0000
commit0d120f42daa76a299219ce56ac8c3b273d59840c (patch)
tree52d739635e27535ccd5f4b7784dd718f28a59a52 /target/linux/brcm63xx/patches-3.13/009-MIPS-BMIPS-change-compile-time-checks-to-runtime-che.patch
parent8ffe7e9d41f86a4a941292bb8d3e637e6ae03be9 (diff)
downloadupstream-0d120f42daa76a299219ce56ac8c3b273d59840c.tar.gz
upstream-0d120f42daa76a299219ce56ac8c3b273d59840c.tar.bz2
upstream-0d120f42daa76a299219ce56ac8c3b273d59840c.zip
brcm63xx: add preliminary support for 3.13
Add support for 3.13 as a development kernel. Mostly untested, only net booted. If flashed may brick your router or kill your cat. Signed-off-by: Jonas Gorski <jogo@openwrt.org> SVN-Revision: 39746
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-runtime-che.patch
new file mode 100644
index 0000000000..2f56f15e76
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.13/009-MIPS-BMIPS-change-compile-time-checks-to-runtime-che.patch
@@ -0,0 +1,602 @@
+From 7d790bd6cab314462a29ba194e243b8b1d529524 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jogo@openwrt.org>
+Date: Thu, 27 Jun 2013 21:33:56 +0200
+Subject: [PATCH V2 03/13] MIPS: BMIPS: change compile time checks to runtime
+ checks
+
+Allow building for all bmips cpus at the same time by changing ifdefs
+to checks for the cpu type, or adding appropriate checks to the
+assembly.
+
+Since BMIPS43XX and BMIPS5000 require different IPI implementations,
+split the SMP ops into one for each, so the runtime overhead is only
+at registration time for them.
+
+Signed-off-by: Jonas Gorski <jogo@openwrt.org>
+---
+V1 -> V2:
+ * use switch (cpu_type()) instead of if () else if () ...
+ * split the smp ops into bmips43xx and bmips5000
+
+ arch/mips/bcm63xx/prom.c | 2 +-
+ arch/mips/include/asm/bmips.h | 3 +-
+ arch/mips/kernel/bmips_vec.S | 55 ++++++--
+ arch/mips/kernel/smp-bmips.c | 312 +++++++++++++++++++++++++-----------------
+ 4 files changed, 235 insertions(+), 137 deletions(-)
+
+--- a/arch/mips/bcm63xx/prom.c
++++ b/arch/mips/bcm63xx/prom.c
+@@ -61,7 +61,7 @@ void __init prom_init(void)
+
+ if (IS_ENABLED(CONFIG_CPU_BMIPS4350) && IS_ENABLED(CONFIG_SMP)) {
+ /* set up SMP */
+- register_smp_ops(&bmips_smp_ops);
++ register_smp_ops(&bmips43xx_smp_ops);
+
+ /*
+ * BCM6328 might not have its second CPU enabled, while BCM3368
+--- a/arch/mips/include/asm/bmips.h
++++ b/arch/mips/include/asm/bmips.h
+@@ -47,7 +47,8 @@
+ #include <linux/cpumask.h>
+ #include <asm/r4kcache.h>
+
+-extern struct plat_smp_ops bmips_smp_ops;
++extern struct plat_smp_ops bmips43xx_smp_ops;
++extern struct plat_smp_ops bmips5000_smp_ops;
+ extern char bmips_reset_nmi_vec;
+ extern char bmips_reset_nmi_vec_end;
+ extern char bmips_smp_movevec;
+--- a/arch/mips/kernel/bmips_vec.S
++++ b/arch/mips/kernel/bmips_vec.S
+@@ -13,6 +13,7 @@
+ #include <asm/asm.h>
+ #include <asm/asmmacro.h>
+ #include <asm/cacheops.h>
++#include <asm/cpu.h>
+ #include <asm/regdef.h>
+ #include <asm/mipsregs.h>
+ #include <asm/stackframe.h>
+@@ -91,12 +92,18 @@ NESTED(bmips_reset_nmi_vec, PT_SIZE, sp)
+ beqz k0, bmips_smp_entry
+
+ #if defined(CONFIG_CPU_BMIPS5000)
++ mfc0 k0, CP0_PRID
++ li k1, PRID_IMP_BMIPS5000
++ andi k0, 0xff00
++ bne k0, k1, 1f
++
+ /* if we're not on core 0, this must be the SMP boot signal */
+ li k1, (3 << 25)
+ mfc0 k0, $22
+ and k0, k1
+ bnez k0, bmips_smp_entry
+-#endif
++1:
++#endif /* CONFIG_CPU_BMIPS5000 */
+ #endif /* CONFIG_SMP */
+
+ /* nope, it's just a regular NMI */
+@@ -139,7 +146,12 @@ bmips_smp_entry:
+ xori k0, 0x04
+ mtc0 k0, CP0_CONFIG
+
++ mfc0 k0, CP0_PRID
++ andi k0, 0xff00
+ #if defined(CONFIG_CPU_BMIPS4350) || defined(CONFIG_CPU_BMIPS4380)
++ li k1, PRID_IMP_BMIPS43XX
++ bne k0, k1, 2f
++
+ /* initialize CPU1's local I-cache */
+ li k0, 0x80000000
+ li k1, 0x80010000
+@@ -150,14 +162,21 @@ bmips_smp_entry:
+ 1: cache Index_Store_Tag_I, 0(k0)
+ addiu k0, 16
+ bne k0, k1, 1b
+-#elif defined(CONFIG_CPU_BMIPS5000)
++
++ b 3f
++2:
++#endif /* CONFIG_CPU_BMIPS4350 || CONFIG_CPU_BMIPS4380 */
++#if defined(CONFIG_CPU_BMIPS5000)
+ /* set exception vector base */
++ li k1, PRID_IMP_BMIPS5000
++ bne k0, k1, 3f
++
+ la k0, ebase
+ lw k0, 0(k0)
+ mtc0 k0, $15, 1
+ BARRIER
+-#endif
+-
++#endif /* CONFIG_CPU_BMIPS5000 */
++3:
+ /* jump back to kseg0 in case we need to remap the kseg1 area */
+ la k0, 1f
+ jr k0
+@@ -221,8 +240,18 @@ END(bmips_smp_int_vec)
+ LEAF(bmips_enable_xks01)
+
+ #if defined(CONFIG_XKS01)
+-
++ mfc0 t0, CP0_PRID
++ andi t2, t0, 0xff00
+ #if defined(CONFIG_CPU_BMIPS4380)
++ li t1, PRID_IMP_BMIPS43XX
++ bne t2, t1, 1f
++
++ andi t0, 0xff
++ addiu t1, t0, -PRID_REV_BMIPS4380_HI
++ bgtz t1, 2f
++ addiu t0, -PRID_REV_BMIPS4380_LO
++ bltz t0, 2f
++
+ mfc0 t0, $22, 3
+ li t1, 0x1ff0
+ li t2, (1 << 12) | (1 << 9)
+@@ -231,7 +260,13 @@ LEAF(bmips_enable_xks01)
+ or t0, t2
+ mtc0 t0, $22, 3
+ BARRIER
+-#elif defined(CONFIG_CPU_BMIPS5000)
++ b 2f
++1:
++#endif /* CONFIG_CPU_BMIPS4380 */
++#if defined(CONFIG_CPU_BMIPS5000)
++ li t1, PRID_IMP_BMIPS5000
++ bne t2, t1, 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;
+ }