diff --git a/target/linux/brcm63xx/patches-3.8/310-BCM63XX-Add-SMP-support-to-prom.c.patch b/target/linux/brcm63xx/patches-3.8/310-BCM63XX-Add-SMP-support-to-prom.c.patch
new file mode 100644
index 0000000000000000000000000000000000000000..7c9baf7e4e365337dbc3ccc779dd493828b2c16a
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.8/310-BCM63XX-Add-SMP-support-to-prom.c.patch
@@ -0,0 +1,71 @@
+From 10ea7fd6b854c3ecf745d053beba10c7e00c33c9 Mon Sep 17 00:00:00 2001
+From: Kevin Cernekee <cernekee@gmail.com>
+Date: Sat, 9 Jul 2011 12:15:06 -0700
+Subject: [PATCH 01/13] MIPS: BCM63XX: Add SMP support to prom.c
+
+This involves two changes to the BSP code:
+
+1) register_smp_ops() for BMIPS SMP
+
+2) The CPU1 boot vector on some of the BCM63xx platforms conflicts with
+the special interrupt vector (IV).  Move it to 0x8000_0380 at boot time,
+to resolve the conflict.
+
+Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
+[jogo@openwrt: move smp ops registration below #ifdef guard, don't enable
+ smp for 6328/6358]
+Signed-off-by: Jonas Gorski <jogo@openwrt.org>
+---
+ arch/mips/bcm63xx/prom.c |   33 +++++++++++++++++++++++++++++++++
+ 1 file changed, 33 insertions(+)
+
+--- a/arch/mips/bcm63xx/prom.c
++++ b/arch/mips/bcm63xx/prom.c
+@@ -8,7 +8,11 @@
+ 
+ #include <linux/init.h>
+ #include <linux/bootmem.h>
++#include <linux/smp.h>
+ #include <asm/bootinfo.h>
++#include <asm/bmips.h>
++#include <asm/smp-ops.h>
++#include <asm/mipsregs.h>
+ #include <bcm63xx_board.h>
+ #include <bcm63xx_cpu.h>
+ #include <bcm63xx_io.h>
+@@ -52,6 +56,35 @@ void __init prom_init(void)
+ 
+ 	/* do low level board init */
+ 	board_prom_init();
++
++#if defined(CONFIG_CPU_BMIPS4350) && defined(CONFIG_SMP)
++	/* set up SMP */
++	register_smp_ops(&bmips_smp_ops);
++
++	/*
++	 * BCM6328 does not have its second CPU enabled, while BCM6358
++	 * needs special handling for its shared TLB, so disable SMP for now.
++	 */
++	if (BCMCPU_IS_6328() || BCMCPU_IS_6358()) {
++		bmips_smp_enabled = 0;
++		return;
++	}
++
++	/*
++	 * The bootloader has set up the CPU1 reset vector at 0xa000_0200.
++	 * This conflicts with the special interrupt vector (IV).
++	 * The bootloader has also set up CPU1 to respond to the wrong
++	 * IPI interrupt.
++	 * Here we will start up CPU1 in the background and ask it to
++	 * reconfigure itself then go back to sleep.
++	 */
++	memcpy((void *)0xa0000200, &bmips_smp_movevec, 0x20);
++	__sync();
++	set_c0_cause(C_SW0);
++	cpumask_set_cpu(1, &bmips_booted_mask);
++
++	/* FIXME: we really should have some sort of hazard barrier here */
++#endif
+ }
+ 
+ void __init prom_free_prom_memory(void)
diff --git a/target/linux/brcm63xx/patches-3.8/311-MIPS-BCM63XX-Handle-SW-IRQs-0-1.patch b/target/linux/brcm63xx/patches-3.8/311-MIPS-BCM63XX-Handle-SW-IRQs-0-1.patch
new file mode 100644
index 0000000000000000000000000000000000000000..f08c7ef4fa887e4bf09a740f949d56ed80b8d6cf
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.8/311-MIPS-BCM63XX-Handle-SW-IRQs-0-1.patch
@@ -0,0 +1,28 @@
+From 8e0bd819cc0f8815cad99feea98664172c0b1fe4 Mon Sep 17 00:00:00 2001
+From: Kevin Cernekee <cernekee@gmail.com>
+Date: Mon, 31 Oct 2011 11:52:10 -0700
+Subject: [PATCH 02/13] MIPS: BCM63XX: Handle SW IRQs 0-1
+
+MIPS software IRQs 0 and 1 are used for interprocessor signaling (IPI)
+on BMIPS SMP.  Make the board support code aware of them.
+
+Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
+[jogo@openwrt.org: move sw irqs behind timer irq]
+Signed-off-by: Jonas Gorski <jogo@openwrt.org>
+---
+ arch/mips/bcm63xx/irq.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/arch/mips/bcm63xx/irq.c
++++ b/arch/mips/bcm63xx/irq.c
+@@ -294,6 +294,10 @@ asmlinkage void plat_irq_dispatch(void)
+ 
+ 		if (cause & CAUSEF_IP7)
+ 			do_IRQ(7);
++		if (cause & CAUSEF_IP0)
++			do_IRQ(0);
++		if (cause & CAUSEF_IP1)
++			do_IRQ(1);
+ 		if (cause & CAUSEF_IP2)
+ 			dispatch_internal();
+ 		if (!is_ext_irq_cascaded) {
diff --git a/target/linux/brcm63xx/patches-3.8/312-MIPS-BCM63XX-select-SYS_HAS_CPU_BMIPS4350-for-suppor.patch b/target/linux/brcm63xx/patches-3.8/312-MIPS-BCM63XX-select-SYS_HAS_CPU_BMIPS4350-for-suppor.patch
new file mode 100644
index 0000000000000000000000000000000000000000..ce0e769413d1e633bf88f2a20af8ccacc83e59f1
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.8/312-MIPS-BCM63XX-select-SYS_HAS_CPU_BMIPS4350-for-suppor.patch
@@ -0,0 +1,24 @@
+From 1923ce1435a5e89f9550e8c95db37a3ef1f92665 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jogo@openwrt.org>
+Date: Sun, 21 Apr 2013 14:44:00 +0200
+Subject: [PATCH 03/13] MIPS: BCM63XX: select SYS_HAS_CPU_BMIPS4350 for
+ supported SoCs
+
+BCM6338, BCM6345 and BCM6348 have a BMIPS3300, everything following
+has a BMIPS4350.
+
+Signed-off-by: Jonas Gorski <jogo@openwrt.org>
+---
+ arch/mips/Kconfig |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/mips/Kconfig
++++ b/arch/mips/Kconfig
+@@ -126,6 +126,7 @@ 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
diff --git a/target/linux/brcm63xx/patches-3.8/313-MIPS-BCM63XX-rename-__dispatch_internal-to-__dispatc.patch b/target/linux/brcm63xx/patches-3.8/313-MIPS-BCM63XX-rename-__dispatch_internal-to-__dispatc.patch
new file mode 100644
index 0000000000000000000000000000000000000000..f5b6071310e2340890725d31c2ac8bbb5f7dc910
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.8/313-MIPS-BCM63XX-rename-__dispatch_internal-to-__dispatc.patch
@@ -0,0 +1,51 @@
+From bb2774da9598f3ea38099d3dcf753b585824a011 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jogo@openwrt.org>
+Date: Thu, 21 Mar 2013 17:05:15 +0100
+Subject: [PATCH 04/13] MIPS: BCM63XX: rename __dispatch_internal to
+ __dispatch_internal_32
+
+Make it follow the same naming convention as the other functions.
+
+Signed-off-by: Jonas Gorski <jogo@openwrt.org>
+---
+ arch/mips/bcm63xx/irq.c |    8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/arch/mips/bcm63xx/irq.c
++++ b/arch/mips/bcm63xx/irq.c
+@@ -19,7 +19,7 @@
+ #include <bcm63xx_io.h>
+ #include <bcm63xx_irq.h>
+ 
+-static void __dispatch_internal(void) __maybe_unused;
++static void __dispatch_internal_32(void) __maybe_unused;
+ static void __dispatch_internal_64(void) __maybe_unused;
+ static void __internal_irq_mask_32(unsigned int irq) __maybe_unused;
+ static void __internal_irq_mask_64(unsigned int irq) __maybe_unused;
+@@ -106,7 +106,7 @@ static void __internal_irq_unmask_64(uns
+ #endif
+ 
+ #if irq_bits == 32
+-#define dispatch_internal			__dispatch_internal
++#define dispatch_internal			__dispatch_internal_32
+ #define internal_irq_mask			__internal_irq_mask_32
+ #define internal_irq_unmask			__internal_irq_unmask_32
+ #else
+@@ -207,7 +207,7 @@ static void bcm63xx_init_irq(void)
+ 	}
+ 
+ 	if (irq_bits == 32) {
+-		dispatch_internal = __dispatch_internal;
++		dispatch_internal = __dispatch_internal_32;
+ 		internal_irq_mask = __internal_irq_mask_32;
+ 		internal_irq_unmask = __internal_irq_unmask_32;
+ 	} else {
+@@ -240,7 +240,7 @@ static inline void handle_internal(int i
+  * will resume the loop where it ended the last time we left this
+  * function.
+  */
+-static void __dispatch_internal(void)
++static void __dispatch_internal_32(void)
+ {
+ 	u32 pending;
+ 	static int i;
diff --git a/target/linux/brcm63xx/patches-3.8/314-MIPS-BCM63XX-replace-irq-dispatch-code-with-a-generi.patch b/target/linux/brcm63xx/patches-3.8/314-MIPS-BCM63XX-replace-irq-dispatch-code-with-a-generi.patch
new file mode 100644
index 0000000000000000000000000000000000000000..5fabd0861d67a8e4b3f1e7612255f3cfdbb6ec0f
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.8/314-MIPS-BCM63XX-replace-irq-dispatch-code-with-a-generi.patch
@@ -0,0 +1,167 @@
+From 661e02b8e2b9a4b48a809bc82dfe8f7b20ca750f Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jogo@openwrt.org>
+Date: Thu, 18 Apr 2013 21:14:49 +0200
+Subject: [PATCH 05/13] MIPS: BCM63XX: replace irq dispatch code with a
+ generic version
+
+The generic version uses a variable length of u32 registers of u32/u64.
+This allows easier support for longer registers without having to rewrite
+verything.
+
+This "generic" version is not slower than the old version in the best case
+(= i == next set bit), and twice as fast in the worst case in 64 bits.
+
+Signed-off-by: Jonas Gorski <jogo@openwrt.org>
+---
+ arch/mips/bcm63xx/irq.c |  130 ++++++++++++++++++++---------------------------
+ 1 file changed, 56 insertions(+), 74 deletions(-)
+
+--- a/arch/mips/bcm63xx/irq.c
++++ b/arch/mips/bcm63xx/irq.c
+@@ -240,47 +240,65 @@ static inline void handle_internal(int i
+  * will resume the loop where it ended the last time we left this
+  * function.
+  */
+-static void __dispatch_internal_32(void)
+-{
+-	u32 pending;
+-	static int i;
+-
+-	pending = bcm_readl(irq_stat_addr) & bcm_readl(irq_mask_addr);
+-
+-	if (!pending)
+-		return ;
+-
+-	while (1) {
+-		int to_call = i;
+ 
+-		i = (i + 1) & 0x1f;
+-		if (pending & (1 << to_call)) {
+-			handle_internal(to_call);
+-			break;
+-		}
+-	}
++#define BUILD_IPIC_INTERNAL(width)					\
++void __dispatch_internal_##width(void)					\
++{									\
++	u32 pending[width / 32];					\
++	unsigned int src, tgt;						\
++	bool irqs_pending = false;					\
++	static int i;							\
++									\
++	/* read registers in reverse order */				\
++	for (src = 0, tgt = (width / 32); src < (width / 32); src++) {	\
++		u32 val;						\
++									\
++		val = bcm_readl(irq_stat_addr + src * sizeof(u32));	\
++		val &= bcm_readl(irq_mask_addr + src * sizeof(u32));	\
++		pending[--tgt] = val;					\
++									\
++		if (val)						\
++			irqs_pending = true;				\
++	}								\
++									\
++	if (!irqs_pending)						\
++		return;							\
++									\
++	while (1) {							\
++		int to_call = i;					\
++									\
++		i = (i + 1) & (width - 1);				\
++		if (pending[to_call / 32] & (1 << (to_call & 0x1f))) {	\
++			handle_internal(to_call);			\
++			break;						\
++		}							\
++	}								\
++}									\
++									\
++static void __internal_irq_mask_##width(unsigned int irq)		\
++{									\
++	u32 val;							\
++	unsigned reg = (irq / 32) ^ (width/32 - 1);			\
++	unsigned bit = irq & 0x1f;					\
++									\
++	val = bcm_readl(irq_mask_addr + reg * sizeof(u32));		\
++	val &= ~(1 << bit);						\
++	bcm_writel(val, irq_mask_addr + reg * sizeof(u32));		\
++}									\
++									\
++static void __internal_irq_unmask_##width(unsigned int irq)		\
++{ 									\
++	u32 val;							\
++	unsigned reg = (irq / 32) ^ (width/32 - 1);			\
++	unsigned bit = irq & 0x1f; 					\
++									\
++	val = bcm_readl(irq_mask_addr + reg * sizeof(u32));		\
++	val |= (1 << bit); 						\
++	bcm_writel(val, irq_mask_addr + reg * sizeof(u32));		\
+ }
+ 
+-static void __dispatch_internal_64(void)
+-{
+-	u64 pending;
+-	static int i;
+-
+-	pending = bcm_readq(irq_stat_addr) & bcm_readq(irq_mask_addr);
+-
+-	if (!pending)
+-		return ;
+-
+-	while (1) {
+-		int to_call = i;
+-
+-		i = (i + 1) & 0x3f;
+-		if (pending & (1ull << to_call)) {
+-			handle_internal(to_call);
+-			break;
+-		}
+-	}
+-}
++BUILD_IPIC_INTERNAL(32);
++BUILD_IPIC_INTERNAL(64);
+ 
+ asmlinkage void plat_irq_dispatch(void)
+ {
+@@ -317,42 +335,6 @@ asmlinkage void plat_irq_dispatch(void)
+  * internal IRQs operations: only mask/unmask on PERF irq mask
+  * register.
+  */
+-static void __internal_irq_mask_32(unsigned int irq)
+-{
+-	u32 mask;
+-
+-	mask = bcm_readl(irq_mask_addr);
+-	mask &= ~(1 << irq);
+-	bcm_writel(mask, irq_mask_addr);
+-}
+-
+-static void __internal_irq_mask_64(unsigned int irq)
+-{
+-	u64 mask;
+-
+-	mask = bcm_readq(irq_mask_addr);
+-	mask &= ~(1ull << irq);
+-	bcm_writeq(mask, irq_mask_addr);
+-}
+-
+-static void __internal_irq_unmask_32(unsigned int irq)
+-{
+-	u32 mask;
+-
+-	mask = bcm_readl(irq_mask_addr);
+-	mask |= (1 << irq);
+-	bcm_writel(mask, irq_mask_addr);
+-}
+-
+-static void __internal_irq_unmask_64(unsigned int irq)
+-{
+-	u64 mask;
+-
+-	mask = bcm_readq(irq_mask_addr);
+-	mask |= (1ull << irq);
+-	bcm_writeq(mask, irq_mask_addr);
+-}
+-
+ static void bcm63xx_internal_irq_mask(struct irq_data *d)
+ {
+ 	internal_irq_mask(d->irq - IRQ_INTERNAL_BASE);
diff --git a/target/linux/brcm63xx/patches-3.8/315-MIPS-BCM63XX-append-cpu-number-to-irq_-stat-mask.patch b/target/linux/brcm63xx/patches-3.8/315-MIPS-BCM63XX-append-cpu-number-to-irq_-stat-mask.patch
new file mode 100644
index 0000000000000000000000000000000000000000..98cd637a88a7d186a2cd9b89bcc4a6771092d741
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.8/315-MIPS-BCM63XX-append-cpu-number-to-irq_-stat-mask.patch
@@ -0,0 +1,258 @@
+From 6ec70ebfccd31ae3668d99b5703e5c9ce38384b4 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jogo@openwrt.org>
+Date: Thu, 25 Apr 2013 00:24:06 +0200
+Subject: [PATCH 06/13] MIPS: BCM63XX: append cpu number to irq_{stat,mask}*
+
+For SMP affinity support we need to discrimnate between the registers
+for both CPUs.
+
+Signed-off-by: Jonas Gorski <jogo@openwrt.org>
+---
+ arch/mips/bcm63xx/irq.c                           |   78 ++++++++++-----------
+ arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h |   16 ++---
+ 2 files changed, 47 insertions(+), 47 deletions(-)
+
+--- a/arch/mips/bcm63xx/irq.c
++++ b/arch/mips/bcm63xx/irq.c
+@@ -28,8 +28,8 @@ static void __internal_irq_unmask_64(uns
+ 
+ #ifndef BCMCPU_RUNTIME_DETECT
+ #ifdef CONFIG_BCM63XX_CPU_6328
+-#define irq_stat_reg		PERF_IRQSTAT_6328_REG
+-#define irq_mask_reg		PERF_IRQMASK_6328_REG
++#define irq_stat_reg0		PERF_IRQSTAT_6328_REG(0)
++#define irq_mask_reg0		PERF_IRQMASK_6328_REG(0)
+ #define irq_bits		64
+ #define is_ext_irq_cascaded	1
+ #define ext_irq_start		(BCM_6328_EXT_IRQ0 - IRQ_INTERNAL_BASE)
+@@ -39,8 +39,8 @@ static void __internal_irq_unmask_64(uns
+ #define ext_irq_cfg_reg2	0
+ #endif
+ #ifdef CONFIG_BCM63XX_CPU_6338
+-#define irq_stat_reg		PERF_IRQSTAT_6338_REG
+-#define irq_mask_reg		PERF_IRQMASK_6338_REG
++#define irq_stat_reg0		PERF_IRQSTAT_6338_REG
++#define irq_mask_reg0		PERF_IRQMASK_6338_REG
+ #define irq_bits		32
+ #define is_ext_irq_cascaded	0
+ #define ext_irq_start		0
+@@ -50,8 +50,8 @@ static void __internal_irq_unmask_64(uns
+ #define ext_irq_cfg_reg2	0
+ #endif
+ #ifdef CONFIG_BCM63XX_CPU_6345
+-#define irq_stat_reg		PERF_IRQSTAT_6345_REG
+-#define irq_mask_reg		PERF_IRQMASK_6345_REG
++#define irq_stat_reg0		PERF_IRQSTAT_6345_REG
++#define irq_mask_reg0		PERF_IRQMASK_6345_REG
+ #define irq_bits		32
+ #define is_ext_irq_cascaded	0
+ #define ext_irq_start		0
+@@ -61,8 +61,8 @@ static void __internal_irq_unmask_64(uns
+ #define ext_irq_cfg_reg2	0
+ #endif
+ #ifdef CONFIG_BCM63XX_CPU_6348
+-#define irq_stat_reg		PERF_IRQSTAT_6348_REG
+-#define irq_mask_reg		PERF_IRQMASK_6348_REG
++#define irq_stat_reg0		PERF_IRQSTAT_6348_REG
++#define irq_mask_reg0		PERF_IRQMASK_6348_REG
+ #define irq_bits		32
+ #define is_ext_irq_cascaded	0
+ #define ext_irq_start		0
+@@ -72,8 +72,8 @@ static void __internal_irq_unmask_64(uns
+ #define ext_irq_cfg_reg2	0
+ #endif
+ #ifdef CONFIG_BCM63XX_CPU_6358
+-#define irq_stat_reg		PERF_IRQSTAT_6358_REG
+-#define irq_mask_reg		PERF_IRQMASK_6358_REG
++#define irq_stat_reg0		PERF_IRQSTAT_6358_REG(0)
++#define irq_mask_reg0		PERF_IRQMASK_6358_REG(0)
+ #define irq_bits		32
+ #define is_ext_irq_cascaded	1
+ #define ext_irq_start		(BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE)
+@@ -83,8 +83,8 @@ static void __internal_irq_unmask_64(uns
+ #define ext_irq_cfg_reg2	0
+ #endif
+ #ifdef CONFIG_BCM63XX_CPU_6362
+-#define irq_stat_reg		PERF_IRQSTAT_6362_REG
+-#define irq_mask_reg		PERF_IRQMASK_6362_REG
++#define irq_stat_reg0		PERF_IRQSTAT_6362_REG(0)
++#define irq_mask_reg0		PERF_IRQMASK_6362_REG(0)
+ #define irq_bits		64
+ #define is_ext_irq_cascaded	1
+ #define ext_irq_start		(BCM_6362_EXT_IRQ0 - IRQ_INTERNAL_BASE)
+@@ -94,8 +94,8 @@ static void __internal_irq_unmask_64(uns
+ #define ext_irq_cfg_reg2	0
+ #endif
+ #ifdef CONFIG_BCM63XX_CPU_6368
+-#define irq_stat_reg		PERF_IRQSTAT_6368_REG
+-#define irq_mask_reg		PERF_IRQMASK_6368_REG
++#define irq_stat_reg0		PERF_IRQSTAT_6368_REG(0)
++#define irq_mask_reg0		PERF_IRQMASK_6368_REG(0)
+ #define irq_bits		64
+ #define is_ext_irq_cascaded	1
+ #define ext_irq_start		(BCM_6368_EXT_IRQ0 - IRQ_INTERNAL_BASE)
+@@ -115,15 +115,15 @@ static void __internal_irq_unmask_64(uns
+ #define internal_irq_unmask			__internal_irq_unmask_64
+ #endif
+ 
+-#define irq_stat_addr	(bcm63xx_regset_address(RSET_PERF) + irq_stat_reg)
+-#define irq_mask_addr	(bcm63xx_regset_address(RSET_PERF) + irq_mask_reg)
++#define irq_stat_addr0	(bcm63xx_regset_address(RSET_PERF) + irq_stat_reg0)
++#define irq_mask_addr0	(bcm63xx_regset_address(RSET_PERF) + irq_mask_reg0)
+ 
+ static inline void bcm63xx_init_irq(void)
+ {
+ }
+ #else /* ! BCMCPU_RUNTIME_DETECT */
+ 
+-static u32 irq_stat_addr, irq_mask_addr;
++static u32 irq_stat_addr0, irq_mask_addr0;
+ static void (*dispatch_internal)(void);
+ static int is_ext_irq_cascaded;
+ static unsigned int ext_irq_count;
+@@ -136,13 +136,13 @@ static void bcm63xx_init_irq(void)
+ {
+ 	int irq_bits;
+ 
+-	irq_stat_addr = bcm63xx_regset_address(RSET_PERF);
+-	irq_mask_addr = bcm63xx_regset_address(RSET_PERF);
++	irq_stat_addr0 = bcm63xx_regset_address(RSET_PERF);
++	irq_mask_addr0 = bcm63xx_regset_address(RSET_PERF);
+ 
+ 	switch (bcm63xx_get_cpu_id()) {
+ 	case BCM6328_CPU_ID:
+-		irq_stat_addr += PERF_IRQSTAT_6328_REG;
+-		irq_mask_addr += PERF_IRQMASK_6328_REG;
++		irq_stat_addr0 += PERF_IRQSTAT_6328_REG(0);
++		irq_mask_addr0 += PERF_IRQMASK_6328_REG(0);
+ 		irq_bits = 64;
+ 		ext_irq_count = 4;
+ 		is_ext_irq_cascaded = 1;
+@@ -151,29 +151,29 @@ static void bcm63xx_init_irq(void)
+ 		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6328;
+ 		break;
+ 	case BCM6338_CPU_ID:
+-		irq_stat_addr += PERF_IRQSTAT_6338_REG;
+-		irq_mask_addr += PERF_IRQMASK_6338_REG;
++		irq_stat_addr0 += PERF_IRQSTAT_6338_REG;
++		irq_mask_addr0 += PERF_IRQMASK_6338_REG;
+ 		irq_bits = 32;
+ 		ext_irq_count = 4;
+ 		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6338;
+ 		break;
+ 	case BCM6345_CPU_ID:
+-		irq_stat_addr += PERF_IRQSTAT_6345_REG;
+-		irq_mask_addr += PERF_IRQMASK_6345_REG;
++		irq_stat_addr0 += PERF_IRQSTAT_6345_REG;
++		irq_mask_addr0 += PERF_IRQMASK_6345_REG;
+ 		irq_bits = 32;
+ 		ext_irq_count = 4;
+ 		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6345;
+ 		break;
+ 	case BCM6348_CPU_ID:
+-		irq_stat_addr += PERF_IRQSTAT_6348_REG;
+-		irq_mask_addr += PERF_IRQMASK_6348_REG;
++		irq_stat_addr0 += PERF_IRQSTAT_6348_REG;
++		irq_mask_addr0 += PERF_IRQMASK_6348_REG;
+ 		irq_bits = 32;
+ 		ext_irq_count = 4;
+ 		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6348;
+ 		break;
+ 	case BCM6358_CPU_ID:
+-		irq_stat_addr += PERF_IRQSTAT_6358_REG;
+-		irq_mask_addr += PERF_IRQMASK_6358_REG;
++		irq_stat_addr0 += PERF_IRQSTAT_6358_REG(0);
++		irq_mask_addr0 += PERF_IRQMASK_6358_REG(0);
+ 		irq_bits = 32;
+ 		ext_irq_count = 4;
+ 		is_ext_irq_cascaded = 1;
+@@ -182,8 +182,8 @@ static void bcm63xx_init_irq(void)
+ 		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6358;
+ 		break;
+ 	case BCM6362_CPU_ID:
+-		irq_stat_addr += PERF_IRQSTAT_6362_REG;
+-		irq_mask_addr += PERF_IRQMASK_6362_REG;
++		irq_stat_addr0 += PERF_IRQSTAT_6362_REG(0);
++		irq_mask_addr0 += PERF_IRQMASK_6362_REG(0);
+ 		irq_bits = 64;
+ 		ext_irq_count = 4;
+ 		is_ext_irq_cascaded = 1;
+@@ -192,8 +192,8 @@ static void bcm63xx_init_irq(void)
+ 		ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6362;
+ 		break;
+ 	case BCM6368_CPU_ID:
+-		irq_stat_addr += PERF_IRQSTAT_6368_REG;
+-		irq_mask_addr += PERF_IRQMASK_6368_REG;
++		irq_stat_addr0 += PERF_IRQSTAT_6368_REG(0);
++		irq_mask_addr0 += PERF_IRQMASK_6368_REG(0);
+ 		irq_bits = 64;
+ 		ext_irq_count = 6;
+ 		is_ext_irq_cascaded = 1;
+@@ -253,8 +253,8 @@ void __dispatch_internal_##width(void)
+ 	for (src = 0, tgt = (width / 32); src < (width / 32); src++) {	\
+ 		u32 val;						\
+ 									\
+-		val = bcm_readl(irq_stat_addr + src * sizeof(u32));	\
+-		val &= bcm_readl(irq_mask_addr + src * sizeof(u32));	\
++		val = bcm_readl(irq_stat_addr0 + src * sizeof(u32));	\
++		val &= bcm_readl(irq_mask_addr0 + src * sizeof(u32));	\
+ 		pending[--tgt] = val;					\
+ 									\
+ 		if (val)						\
+@@ -281,9 +281,9 @@ static void __internal_irq_mask_##width(
+ 	unsigned reg = (irq / 32) ^ (width/32 - 1);			\
+ 	unsigned bit = irq & 0x1f;					\
+ 									\
+-	val = bcm_readl(irq_mask_addr + reg * sizeof(u32));		\
++	val = bcm_readl(irq_mask_addr0 + reg * sizeof(u32));		\
+ 	val &= ~(1 << bit);						\
+-	bcm_writel(val, irq_mask_addr + reg * sizeof(u32));		\
++	bcm_writel(val, irq_mask_addr0 + reg * sizeof(u32));		\
+ }									\
+ 									\
+ static void __internal_irq_unmask_##width(unsigned int irq)		\
+@@ -292,9 +292,9 @@ static void __internal_irq_unmask_##widt
+ 	unsigned reg = (irq / 32) ^ (width/32 - 1);			\
+ 	unsigned bit = irq & 0x1f; 					\
+ 									\
+-	val = bcm_readl(irq_mask_addr + reg * sizeof(u32));		\
++	val = bcm_readl(irq_mask_addr0 + reg * sizeof(u32));		\
+ 	val |= (1 << bit); 						\
+-	bcm_writel(val, irq_mask_addr + reg * sizeof(u32));		\
++	bcm_writel(val, irq_mask_addr0 + reg * sizeof(u32));		\
+ }
+ 
+ BUILD_IPIC_INTERNAL(32);
+--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
++++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+@@ -181,22 +181,22 @@
+ #define SYS_PLL_SOFT_RESET		0x1
+ 
+ /* Interrupt Mask register */
+-#define PERF_IRQMASK_6328_REG		0x20
++#define PERF_IRQMASK_6328_REG(x)	(0x20 + (x) * 0x10)
+ #define PERF_IRQMASK_6338_REG		0xc
+ #define PERF_IRQMASK_6345_REG		0xc
+ #define PERF_IRQMASK_6348_REG		0xc
+-#define PERF_IRQMASK_6358_REG		0xc
+-#define PERF_IRQMASK_6362_REG		0x20
+-#define PERF_IRQMASK_6368_REG		0x20
++#define PERF_IRQMASK_6358_REG(x)	(0xc + (x) * 0x2c)
++#define PERF_IRQMASK_6362_REG(x)	(0x20 + (x) * 0x10)
++#define PERF_IRQMASK_6368_REG(x)	(0x20 + (x) * 0x10)
+ 
+ /* Interrupt Status register */
+-#define PERF_IRQSTAT_6328_REG		0x28
++#define PERF_IRQSTAT_6328_REG(x)	(0x28 + (x) * 0x10)
+ #define PERF_IRQSTAT_6338_REG		0x10
+ #define PERF_IRQSTAT_6345_REG		0x10
+ #define PERF_IRQSTAT_6348_REG		0x10
+-#define PERF_IRQSTAT_6358_REG		0x10
+-#define PERF_IRQSTAT_6362_REG		0x28
+-#define PERF_IRQSTAT_6368_REG		0x28
++#define PERF_IRQSTAT_6358_REG(x)	(0x10 + (x) * 0x2c)
++#define PERF_IRQSTAT_6362_REG(x)	(0x28 + (x) * 0x10)
++#define PERF_IRQSTAT_6368_REG(x)	(0x28 + (x) * 0x10)
+ 
+ /* External Interrupt Configuration register */
+ #define PERF_EXTIRQ_CFG_REG_6328	0x18
diff --git a/target/linux/brcm63xx/patches-3.8/316-MIPS-BCM63XX-populate-irq_-stat-mask-_addr-for-secon.patch b/target/linux/brcm63xx/patches-3.8/316-MIPS-BCM63XX-populate-irq_-stat-mask-_addr-for-secon.patch
new file mode 100644
index 0000000000000000000000000000000000000000..094eaa88ccdadb952c053922a51e649294da31ac
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.8/316-MIPS-BCM63XX-populate-irq_-stat-mask-_addr-for-secon.patch
@@ -0,0 +1,138 @@
+From b14de5c78d32f8f98535a99ea56bb924beb66810 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jogo@openwrt.org>
+Date: Thu, 25 Apr 2013 00:31:29 +0200
+Subject: [PATCH 07/13] MIPS: BCM63XX: populate irq_{stat,mask}_addr for
+ second CPU
+
+Populate it for all platforms with a BMIPS4350.
+
+Signed-off-by: Jonas Gorski <jogo@openwrt.org>
+---
+ arch/mips/bcm63xx/irq.c |   28 +++++++++++++++++++++++++++-
+ 1 file changed, 27 insertions(+), 1 deletion(-)
+
+--- a/arch/mips/bcm63xx/irq.c
++++ b/arch/mips/bcm63xx/irq.c
+@@ -30,6 +30,8 @@ static void __internal_irq_unmask_64(uns
+ #ifdef CONFIG_BCM63XX_CPU_6328
+ #define irq_stat_reg0		PERF_IRQSTAT_6328_REG(0)
+ #define irq_mask_reg0		PERF_IRQMASK_6328_REG(0)
++#define irq_stat_reg1		PERF_IRQSTAT_6328_REG(1)
++#define irq_mask_reg1		PERF_IRQMASK_6328_REG(1)
+ #define irq_bits		64
+ #define is_ext_irq_cascaded	1
+ #define ext_irq_start		(BCM_6328_EXT_IRQ0 - IRQ_INTERNAL_BASE)
+@@ -41,6 +43,8 @@ static void __internal_irq_unmask_64(uns
+ #ifdef CONFIG_BCM63XX_CPU_6338
+ #define irq_stat_reg0		PERF_IRQSTAT_6338_REG
+ #define irq_mask_reg0		PERF_IRQMASK_6338_REG
++#define irq_stat_reg1		0
++#define irq_mask_reg1		0
+ #define irq_bits		32
+ #define is_ext_irq_cascaded	0
+ #define ext_irq_start		0
+@@ -52,6 +56,8 @@ static void __internal_irq_unmask_64(uns
+ #ifdef CONFIG_BCM63XX_CPU_6345
+ #define irq_stat_reg0		PERF_IRQSTAT_6345_REG
+ #define irq_mask_reg0		PERF_IRQMASK_6345_REG
++#define irq_stat_reg1		0
++#define irq_mask_reg1		0
+ #define irq_bits		32
+ #define is_ext_irq_cascaded	0
+ #define ext_irq_start		0
+@@ -63,6 +69,8 @@ static void __internal_irq_unmask_64(uns
+ #ifdef CONFIG_BCM63XX_CPU_6348
+ #define irq_stat_reg0		PERF_IRQSTAT_6348_REG
+ #define irq_mask_reg0		PERF_IRQMASK_6348_REG
++#define irq_stat_reg1		0
++#define irq_mask_reg1		0
+ #define irq_bits		32
+ #define is_ext_irq_cascaded	0
+ #define ext_irq_start		0
+@@ -74,6 +82,8 @@ static void __internal_irq_unmask_64(uns
+ #ifdef CONFIG_BCM63XX_CPU_6358
+ #define irq_stat_reg0		PERF_IRQSTAT_6358_REG(0)
+ #define irq_mask_reg0		PERF_IRQMASK_6358_REG(0)
++#define irq_stat_reg1		PERF_IRQSTAT_6358_REG(1)
++#define irq_mask_reg1		PERF_IRQMASK_6358_REG(1)
+ #define irq_bits		32
+ #define is_ext_irq_cascaded	1
+ #define ext_irq_start		(BCM_6358_EXT_IRQ0 - IRQ_INTERNAL_BASE)
+@@ -85,6 +95,8 @@ static void __internal_irq_unmask_64(uns
+ #ifdef CONFIG_BCM63XX_CPU_6362
+ #define irq_stat_reg0		PERF_IRQSTAT_6362_REG(0)
+ #define irq_mask_reg0		PERF_IRQMASK_6362_REG(0)
++#define irq_stat_reg1		PERF_IRQSTAT_6362_REG(1)
++#define irq_mask_reg1		PERF_IRQMASK_6362_REG(1)
+ #define irq_bits		64
+ #define is_ext_irq_cascaded	1
+ #define ext_irq_start		(BCM_6362_EXT_IRQ0 - IRQ_INTERNAL_BASE)
+@@ -96,6 +108,8 @@ static void __internal_irq_unmask_64(uns
+ #ifdef CONFIG_BCM63XX_CPU_6368
+ #define irq_stat_reg0		PERF_IRQSTAT_6368_REG(0)
+ #define irq_mask_reg0		PERF_IRQMASK_6368_REG(0)
++#define irq_stat_reg1		PERF_IRQSTAT_6368_REG(1)
++#define irq_mask_reg1		PERF_IRQMASK_6368_REG(1)
+ #define irq_bits		64
+ #define is_ext_irq_cascaded	1
+ #define ext_irq_start		(BCM_6368_EXT_IRQ0 - IRQ_INTERNAL_BASE)
+@@ -117,13 +131,15 @@ static void __internal_irq_unmask_64(uns
+ 
+ #define irq_stat_addr0	(bcm63xx_regset_address(RSET_PERF) + irq_stat_reg0)
+ #define irq_mask_addr0	(bcm63xx_regset_address(RSET_PERF) + irq_mask_reg0)
++#define irq_stat_addr1	(bcm63xx_regset_address(RSET_PERF) + irq_stat_reg1)
++#define irq_mask_addr1	(bcm63xx_regset_address(RSET_PERF) + irq_mask_reg1)
+ 
+ static inline void bcm63xx_init_irq(void)
+ {
+ }
+ #else /* ! BCMCPU_RUNTIME_DETECT */
+ 
+-static u32 irq_stat_addr0, irq_mask_addr0;
++static u32 irq_stat_addr0, irq_mask_addr0, irq_stat_addr1, irq_mask_addr1;
+ static void (*dispatch_internal)(void);
+ static int is_ext_irq_cascaded;
+ static unsigned int ext_irq_count;
+@@ -138,11 +154,15 @@ static void bcm63xx_init_irq(void)
+ 
+ 	irq_stat_addr0 = bcm63xx_regset_address(RSET_PERF);
+ 	irq_mask_addr0 = bcm63xx_regset_address(RSET_PERF);
++	irq_stat_addr1 = bcm63xx_regset_address(RSET_PERF);
++	irq_mask_addr1 = bcm63xx_regset_address(RSET_PERF);
+ 
+ 	switch (bcm63xx_get_cpu_id()) {
+ 	case BCM6328_CPU_ID:
+ 		irq_stat_addr0 += PERF_IRQSTAT_6328_REG(0);
+ 		irq_mask_addr0 += PERF_IRQMASK_6328_REG(0);
++		irq_stat_addr1 += PERF_IRQSTAT_6328_REG(1);
++		irq_stat_addr1 += PERF_IRQMASK_6328_REG(1);
+ 		irq_bits = 64;
+ 		ext_irq_count = 4;
+ 		is_ext_irq_cascaded = 1;
+@@ -174,6 +194,8 @@ static void bcm63xx_init_irq(void)
+ 	case BCM6358_CPU_ID:
+ 		irq_stat_addr0 += PERF_IRQSTAT_6358_REG(0);
+ 		irq_mask_addr0 += PERF_IRQMASK_6358_REG(0);
++		irq_stat_addr1 += PERF_IRQSTAT_6358_REG(1);
++		irq_mask_addr1 += PERF_IRQMASK_6358_REG(1);
+ 		irq_bits = 32;
+ 		ext_irq_count = 4;
+ 		is_ext_irq_cascaded = 1;
+@@ -184,6 +206,8 @@ static void bcm63xx_init_irq(void)
+ 	case BCM6362_CPU_ID:
+ 		irq_stat_addr0 += PERF_IRQSTAT_6362_REG(0);
+ 		irq_mask_addr0 += PERF_IRQMASK_6362_REG(0);
++		irq_stat_addr1 += PERF_IRQSTAT_6362_REG(1);
++		irq_mask_addr1 += PERF_IRQMASK_6362_REG(1);
+ 		irq_bits = 64;
+ 		ext_irq_count = 4;
+ 		is_ext_irq_cascaded = 1;
+@@ -194,6 +218,8 @@ static void bcm63xx_init_irq(void)
+ 	case BCM6368_CPU_ID:
+ 		irq_stat_addr0 += PERF_IRQSTAT_6368_REG(0);
+ 		irq_mask_addr0 += PERF_IRQMASK_6368_REG(0);
++		irq_stat_addr1 += PERF_IRQSTAT_6368_REG(1);
++		irq_mask_addr1 += PERF_IRQMASK_6368_REG(1);
+ 		irq_bits = 64;
+ 		ext_irq_count = 6;
+ 		is_ext_irq_cascaded = 1;
diff --git a/target/linux/brcm63xx/patches-3.8/317-MIPS-BCM63XX-use-a-helper-for-getting-the-right-regi.patch b/target/linux/brcm63xx/patches-3.8/317-MIPS-BCM63XX-use-a-helper-for-getting-the-right-regi.patch
new file mode 100644
index 0000000000000000000000000000000000000000..3931b218c9524f1f515b25912234beba87af5b46
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.8/317-MIPS-BCM63XX-use-a-helper-for-getting-the-right-regi.patch
@@ -0,0 +1,80 @@
+From 7c9d3fe01034adbb890aab7c44534658f89c211b Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jogo@openwrt.org>
+Date: Thu, 25 Apr 2013 15:35:12 +0200
+Subject: [PATCH 08/13] MIPS: BCM63XX: use a helper for getting the right
+ register address
+
+Signed-off-by: Jonas Gorski <jogo@openwrt.org>
+---
+ arch/mips/bcm63xx/irq.c |   30 ++++++++++++++++++++++++------
+ 1 file changed, 24 insertions(+), 6 deletions(-)
+
+--- a/arch/mips/bcm63xx/irq.c
++++ b/arch/mips/bcm63xx/irq.c
+@@ -251,6 +251,20 @@ static inline u32 get_ext_irq_perf_reg(i
+ 	return ext_irq_cfg_reg2;
+ }
+ 
++static inline u32 get_irq_stat_addr(int cpu)
++{
++	if (cpu == 0)
++		return irq_stat_addr0;
++	return irq_stat_addr1;
++}
++
++static inline u32 get_irq_mask_addr(int cpu)
++{
++	if (cpu == 0)
++		return irq_mask_addr0;
++	return irq_mask_addr1;
++}
++
+ static inline void handle_internal(int intbit)
+ {
+ 	if (is_ext_irq_cascaded &&
+@@ -274,13 +288,15 @@ void __dispatch_internal_##width(void)
+ 	unsigned int src, tgt;						\
+ 	bool irqs_pending = false;					\
+ 	static int i;							\
++	u32 irq_stat_addr = get_irq_stat_addr(0);			\
++	u32 irq_mask_addr = get_irq_mask_addr(0);			\
+ 									\
+ 	/* read registers in reverse order */				\
+ 	for (src = 0, tgt = (width / 32); src < (width / 32); src++) {	\
+ 		u32 val;						\
+ 									\
+-		val = bcm_readl(irq_stat_addr0 + src * sizeof(u32));	\
+-		val &= bcm_readl(irq_mask_addr0 + src * sizeof(u32));	\
++		val = bcm_readl(irq_stat_addr + src * sizeof(u32));	\
++		val &= bcm_readl(irq_mask_addr + src * sizeof(u32));	\
+ 		pending[--tgt] = val;					\
+ 									\
+ 		if (val)						\
+@@ -306,10 +322,11 @@ static void __internal_irq_mask_##width(
+ 	u32 val;							\
+ 	unsigned reg = (irq / 32) ^ (width/32 - 1);			\
+ 	unsigned bit = irq & 0x1f;					\
++	u32 irq_mask_addr = get_irq_mask_addr(0);			\
+ 									\
+-	val = bcm_readl(irq_mask_addr0 + reg * sizeof(u32));		\
++	val = bcm_readl(irq_mask_addr + reg * sizeof(u32));		\
+ 	val &= ~(1 << bit);						\
+-	bcm_writel(val, irq_mask_addr0 + reg * sizeof(u32));		\
++	bcm_writel(val, irq_mask_addr + reg * sizeof(u32));		\
+ }									\
+ 									\
+ static void __internal_irq_unmask_##width(unsigned int irq)		\
+@@ -317,10 +334,11 @@ static void __internal_irq_unmask_##widt
+ 	u32 val;							\
+ 	unsigned reg = (irq / 32) ^ (width/32 - 1);			\
+ 	unsigned bit = irq & 0x1f; 					\
++	u32 irq_mask_addr = get_irq_mask_addr(0);			\
+ 									\
+-	val = bcm_readl(irq_mask_addr0 + reg * sizeof(u32));		\
++	val = bcm_readl(irq_mask_addr + reg * sizeof(u32));		\
+ 	val |= (1 << bit); 						\
+-	bcm_writel(val, irq_mask_addr0 + reg * sizeof(u32));		\
++	bcm_writel(val, irq_mask_addr + reg * sizeof(u32));		\
+ }
+ 
+ BUILD_IPIC_INTERNAL(32);
diff --git a/target/linux/brcm63xx/patches-3.8/318-MIPS-BCM63XX-add-cpu-argument-to-dispatch-internal.patch b/target/linux/brcm63xx/patches-3.8/318-MIPS-BCM63XX-add-cpu-argument-to-dispatch-internal.patch
new file mode 100644
index 0000000000000000000000000000000000000000..081ec18b3d66448108cb552860bc9e9d3fcb70fd
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.8/318-MIPS-BCM63XX-add-cpu-argument-to-dispatch-internal.patch
@@ -0,0 +1,59 @@
+From 398337c57ebe3c704e0df5f569e6bd860ffe8914 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jogo@openwrt.org>
+Date: Fri, 26 Apr 2013 11:21:16 +0200
+Subject: [PATCH 09/13] MIPS: BCM63XX: add cpu argument to dispatch internal
+
+Signed-off-by: Jonas Gorski <jogo@openwrt.org>
+---
+ arch/mips/bcm63xx/irq.c |   14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+--- a/arch/mips/bcm63xx/irq.c
++++ b/arch/mips/bcm63xx/irq.c
+@@ -19,8 +19,8 @@
+ #include <bcm63xx_io.h>
+ #include <bcm63xx_irq.h>
+ 
+-static void __dispatch_internal_32(void) __maybe_unused;
+-static void __dispatch_internal_64(void) __maybe_unused;
++static void __dispatch_internal_32(int cpu) __maybe_unused;
++static void __dispatch_internal_64(int cpu) __maybe_unused;
+ static void __internal_irq_mask_32(unsigned int irq) __maybe_unused;
+ static void __internal_irq_mask_64(unsigned int irq) __maybe_unused;
+ static void __internal_irq_unmask_32(unsigned int irq) __maybe_unused;
+@@ -140,7 +140,7 @@ static inline void bcm63xx_init_irq(void
+ #else /* ! BCMCPU_RUNTIME_DETECT */
+ 
+ static u32 irq_stat_addr0, irq_mask_addr0, irq_stat_addr1, irq_mask_addr1;
+-static void (*dispatch_internal)(void);
++static void (*dispatch_internal)(int cpu);
+ static int is_ext_irq_cascaded;
+ static unsigned int ext_irq_count;
+ static unsigned int ext_irq_start, ext_irq_end;
+@@ -282,14 +282,14 @@ static inline void handle_internal(int i
+  */
+ 
+ #define BUILD_IPIC_INTERNAL(width)					\
+-void __dispatch_internal_##width(void)					\
++void __dispatch_internal_##width(int cpu)				\
+ {									\
+ 	u32 pending[width / 32];					\
+ 	unsigned int src, tgt;						\
+ 	bool irqs_pending = false;					\
+ 	static int i;							\
+-	u32 irq_stat_addr = get_irq_stat_addr(0);			\
+-	u32 irq_mask_addr = get_irq_mask_addr(0);			\
++	u32 irq_stat_addr = get_irq_stat_addr(cpu);			\
++	u32 irq_mask_addr = get_irq_mask_addr(cpu);			\
+ 									\
+ 	/* read registers in reverse order */				\
+ 	for (src = 0, tgt = (width / 32); src < (width / 32); src++) {	\
+@@ -361,7 +361,7 @@ asmlinkage void plat_irq_dispatch(void)
+ 		if (cause & CAUSEF_IP1)
+ 			do_IRQ(1);
+ 		if (cause & CAUSEF_IP2)
+-			dispatch_internal();
++			dispatch_internal(0);
+ 		if (!is_ext_irq_cascaded) {
+ 			if (cause & CAUSEF_IP3)
+ 				do_IRQ(IRQ_EXT_0);
diff --git a/target/linux/brcm63xx/patches-3.8/319-MIPS-BCM63XX-protect-irq-register-accesses-with-a-sp.patch b/target/linux/brcm63xx/patches-3.8/319-MIPS-BCM63XX-protect-irq-register-accesses-with-a-sp.patch
new file mode 100644
index 0000000000000000000000000000000000000000..76e8c32670d7cc76009c3a2b75d5f1c7de8f13af
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.8/319-MIPS-BCM63XX-protect-irq-register-accesses-with-a-sp.patch
@@ -0,0 +1,174 @@
+From 7b8e7bc9806b61be2f07bf2bbb5e3ee6e0f333e9 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jogo@openwrt.org>
+Date: Sun, 21 Apr 2013 15:38:56 +0200
+Subject: [PATCH 10/13] MIPS: BCM63XX: protect irq register accesses with a
+ spinlock
+
+Since IRQs can be handled on both CPUs, we need to ensure that we
+don't try to modify the IRQ registers at the same time.
+
+Signed-off-by: Jonas Gorski <jogo@openwrt.org>
+---
+ arch/mips/bcm63xx/irq.c |   47 ++++++++++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 42 insertions(+), 5 deletions(-)
+
+--- a/arch/mips/bcm63xx/irq.c
++++ b/arch/mips/bcm63xx/irq.c
+@@ -12,6 +12,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/module.h>
+ #include <linux/irq.h>
++#include <linux/spinlock.h>
+ #include <asm/irq_cpu.h>
+ #include <asm/mipsregs.h>
+ #include <bcm63xx_cpu.h>
+@@ -26,6 +27,9 @@ static void __internal_irq_mask_64(unsig
+ static void __internal_irq_unmask_32(unsigned int irq) __maybe_unused;
+ static void __internal_irq_unmask_64(unsigned int irq) __maybe_unused;
+ 
++static DEFINE_SPINLOCK(ipic_lock);
++static DEFINE_SPINLOCK(epic_lock);
++
+ #ifndef BCMCPU_RUNTIME_DETECT
+ #ifdef CONFIG_BCM63XX_CPU_6328
+ #define irq_stat_reg0		PERF_IRQSTAT_6328_REG(0)
+@@ -290,7 +294,9 @@ void __dispatch_internal_##width(int cpu
+ 	static int i;							\
+ 	u32 irq_stat_addr = get_irq_stat_addr(cpu);			\
+ 	u32 irq_mask_addr = get_irq_mask_addr(cpu);			\
++	unsigned long flags;						\
+ 									\
++	spin_lock_irqsave(&ipic_lock, flags);				\
+ 	/* read registers in reverse order */				\
+ 	for (src = 0, tgt = (width / 32); src < (width / 32); src++) {	\
+ 		u32 val;						\
+@@ -302,6 +308,7 @@ void __dispatch_internal_##width(int cpu
+ 		if (val)						\
+ 			irqs_pending = true;				\
+ 	}								\
++	spin_unlock_irqrestore(&ipic_lock, flags);			\
+ 									\
+ 	if (!irqs_pending)						\
+ 		return;							\
+@@ -381,12 +388,20 @@ asmlinkage void plat_irq_dispatch(void)
+  */
+ static void bcm63xx_internal_irq_mask(struct irq_data *d)
+ {
++	unsigned long flags;
++
++	spin_lock_irqsave(&ipic_lock, flags);
+ 	internal_irq_mask(d->irq - IRQ_INTERNAL_BASE);
++	spin_unlock_irqrestore(&ipic_lock, flags);
+ }
+ 
+ static void bcm63xx_internal_irq_unmask(struct irq_data *d)
+ {
++	unsigned long flags;
++
++	spin_lock_irqsave(&ipic_lock, flags);
+ 	internal_irq_unmask(d->irq - IRQ_INTERNAL_BASE);
++	spin_unlock_irqrestore(&ipic_lock, flags);
+ }
+ 
+ /*
+@@ -397,8 +412,11 @@ static void bcm63xx_external_irq_mask(st
+ {
+ 	unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
+ 	u32 reg, regaddr;
++	unsigned long flags;
+ 
+ 	regaddr = get_ext_irq_perf_reg(irq);
++
++	spin_lock_irqsave(&epic_lock, flags);
+ 	reg = bcm_perf_readl(regaddr);
+ 
+ 	if (BCMCPU_IS_6348())
+@@ -407,16 +425,24 @@ static void bcm63xx_external_irq_mask(st
+ 		reg &= ~EXTIRQ_CFG_MASK(irq % 4);
+ 
+ 	bcm_perf_writel(reg, regaddr);
+-	if (is_ext_irq_cascaded)
+-		internal_irq_mask(irq + ext_irq_start);
++	spin_unlock_irqrestore(&epic_lock, flags);
++
++	if (is_ext_irq_cascaded) {
++		struct irq_data *cd = irq_get_irq_data(irq + ext_irq_start);
++
++		bcm63xx_internal_irq_mask(cd);
++	}
+ }
+ 
+ static void bcm63xx_external_irq_unmask(struct irq_data *d)
+ {
+ 	unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
+ 	u32 reg, regaddr;
++	unsigned long flags;
+ 
+ 	regaddr = get_ext_irq_perf_reg(irq);
++
++	spin_lock_irqsave(&epic_lock, flags);
+ 	reg = bcm_perf_readl(regaddr);
+ 
+ 	if (BCMCPU_IS_6348())
+@@ -425,16 +451,22 @@ static void bcm63xx_external_irq_unmask(
+ 		reg |= EXTIRQ_CFG_MASK(irq % 4);
+ 
+ 	bcm_perf_writel(reg, regaddr);
++	spin_unlock_irqrestore(&epic_lock, flags);
++
++	if (is_ext_irq_cascaded) {
++		struct irq_data *cd = irq_get_irq_data(irq + ext_irq_start);
+ 
+-	if (is_ext_irq_cascaded)
+-		internal_irq_unmask(irq + ext_irq_start);
++		bcm63xx_internal_irq_unmask(cd);
++	}
+ }
+ 
+ static void bcm63xx_external_irq_clear(struct irq_data *d)
+ {
+ 	unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
+ 	u32 reg, regaddr;
++	unsigned long flags;
+ 
++	spin_lock_irqsave(&epic_lock, flags);
+ 	regaddr = get_ext_irq_perf_reg(irq);
+ 	reg = bcm_perf_readl(regaddr);
+ 
+@@ -444,6 +476,7 @@ static void bcm63xx_external_irq_clear(s
+ 		reg |= EXTIRQ_CFG_CLEAR(irq % 4);
+ 
+ 	bcm_perf_writel(reg, regaddr);
++	spin_unlock_irqrestore(&epic_lock, flags);
+ }
+ 
+ static int bcm63xx_external_irq_set_type(struct irq_data *d,
+@@ -452,6 +485,7 @@ static int bcm63xx_external_irq_set_type
+ 	unsigned int irq = d->irq - IRQ_EXTERNAL_BASE;
+ 	u32 reg, regaddr;
+ 	int levelsense, sense, bothedge;
++	unsigned long flags;
+ 
+ 	flow_type &= IRQ_TYPE_SENSE_MASK;
+ 
+@@ -486,9 +520,11 @@ static int bcm63xx_external_irq_set_type
+ 	}
+ 
+ 	regaddr = get_ext_irq_perf_reg(irq);
+-	reg = bcm_perf_readl(regaddr);
+ 	irq %= 4;
+ 
++	spin_lock_irqsave(&epic_lock, flags);
++	reg = bcm_perf_readl(regaddr);
++
+ 	switch (bcm63xx_get_cpu_id()) {
+ 	case BCM6348_CPU_ID:
+ 		if (levelsense)
+@@ -529,6 +565,7 @@ static int bcm63xx_external_irq_set_type
+ 	}
+ 
+ 	bcm_perf_writel(reg, regaddr);
++	spin_unlock_irqrestore(&epic_lock, flags);
+ 
+ 	irqd_set_trigger_type(d, flow_type);
+ 	if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
diff --git a/target/linux/brcm63xx/patches-3.8/320-MIPS-BCM63XX-wire-up-the-second-CPU-s-irq-line.patch b/target/linux/brcm63xx/patches-3.8/320-MIPS-BCM63XX-wire-up-the-second-CPU-s-irq-line.patch
new file mode 100644
index 0000000000000000000000000000000000000000..2acbf30b0d79b04d9e3acf90668a4e3a5a0896bd
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.8/320-MIPS-BCM63XX-wire-up-the-second-CPU-s-irq-line.patch
@@ -0,0 +1,96 @@
+From 1baec3216529f795905b6376f9c8e4f14b114ba2 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jogo@openwrt.org>
+Date: Fri, 26 Apr 2013 12:03:15 +0200
+Subject: [PATCH 11/13] MIPS: BCM63XX: wire up the second CPU's irq line
+
+It's hardwired to IRQ3, so we don't need to actually check the CPU id.
+
+Signed-off-by: Jonas Gorski <jogo@openwrt.org>
+---
+ arch/mips/bcm63xx/irq.c |   40 ++++++++++++++++++++++++++++++++--------
+ 1 file changed, 32 insertions(+), 8 deletions(-)
+
+--- a/arch/mips/bcm63xx/irq.c
++++ b/arch/mips/bcm63xx/irq.c
+@@ -329,11 +329,15 @@ static void __internal_irq_mask_##width(
+ 	u32 val;							\
+ 	unsigned reg = (irq / 32) ^ (width/32 - 1);			\
+ 	unsigned bit = irq & 0x1f;					\
+-	u32 irq_mask_addr = get_irq_mask_addr(0);			\
++	int cpu;							\
+ 									\
+-	val = bcm_readl(irq_mask_addr + reg * sizeof(u32));		\
+-	val &= ~(1 << bit);						\
+-	bcm_writel(val, irq_mask_addr + reg * sizeof(u32));		\
++	for_each_online_cpu(cpu) {					\
++		u32 irq_mask_addr = get_irq_mask_addr(cpu);		\
++									\
++		val = bcm_readl(irq_mask_addr + reg * sizeof(u32));	\
++		val &= ~(1 << bit);					\
++		bcm_writel(val, irq_mask_addr + reg * sizeof(u32));	\
++	}								\
+ }									\
+ 									\
+ static void __internal_irq_unmask_##width(unsigned int irq)		\
+@@ -341,11 +345,15 @@ static void __internal_irq_unmask_##widt
+ 	u32 val;							\
+ 	unsigned reg = (irq / 32) ^ (width/32 - 1);			\
+ 	unsigned bit = irq & 0x1f; 					\
+-	u32 irq_mask_addr = get_irq_mask_addr(0);			\
++	int cpu;							\
++									\
++	for_each_online_cpu(cpu) {					\
++		u32 irq_mask_addr = get_irq_mask_addr(cpu);		\
+ 									\
+-	val = bcm_readl(irq_mask_addr + reg * sizeof(u32));		\
+-	val |= (1 << bit); 						\
+-	bcm_writel(val, irq_mask_addr + reg * sizeof(u32));		\
++		val = bcm_readl(irq_mask_addr + reg * sizeof(u32));	\
++		val |= (1 << bit); 					\
++		bcm_writel(val, irq_mask_addr + reg * sizeof(u32));	\
++	}								\
+ }
+ 
+ BUILD_IPIC_INTERNAL(32);
+@@ -369,6 +377,10 @@ asmlinkage void plat_irq_dispatch(void)
+ 			do_IRQ(1);
+ 		if (cause & CAUSEF_IP2)
+ 			dispatch_internal(0);
++#ifdef CONFIG_SMP
++		if (cause & CAUSEF_IP3)
++			dispatch_internal(1);
++#else
+ 		if (!is_ext_irq_cascaded) {
+ 			if (cause & CAUSEF_IP3)
+ 				do_IRQ(IRQ_EXT_0);
+@@ -379,6 +391,7 @@ asmlinkage void plat_irq_dispatch(void)
+ 			if (cause & CAUSEF_IP6)
+ 				do_IRQ(IRQ_EXT_3);
+ 		}
++#endif
+ 	} while (1);
+ }
+ 
+@@ -598,6 +611,14 @@ static struct irqaction cpu_ip2_cascade_
+ 	.flags		= IRQF_NO_THREAD,
+ };
+ 
++#ifdef CONFIG_SMP
++static struct irqaction cpu_ip3_cascade_action = {
++	.handler	= no_action,
++	.name		= "cascade_ip3",
++	.flags		= IRQF_NO_THREAD,
++};
++#endif
++
+ static struct irqaction cpu_ext_cascade_action = {
+ 	.handler	= no_action,
+ 	.name		= "cascade_extirq",
+@@ -624,4 +645,7 @@ void __init arch_init_irq(void)
+ 	}
+ 
+ 	setup_irq(MIPS_CPU_IRQ_BASE + 2, &cpu_ip2_cascade_action);
++#ifdef CONFIG_SMP
++	setup_irq(MIPS_CPU_IRQ_BASE + 3, &cpu_ip3_cascade_action);
++#endif
+ }
diff --git a/target/linux/brcm63xx/patches-3.8/321-MIPS-BCM63XX-add-cpumask-argument-to-unmask.patch b/target/linux/brcm63xx/patches-3.8/321-MIPS-BCM63XX-add-cpumask-argument-to-unmask.patch
new file mode 100644
index 0000000000000000000000000000000000000000..1047de39ebf20b35165d1341fc092f4ac4141c21
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.8/321-MIPS-BCM63XX-add-cpumask-argument-to-unmask.patch
@@ -0,0 +1,68 @@
+From 8679976d2ec08db4e4a14ecdd1ee022b70e51fc6 Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jogo@openwrt.org>
+Date: Tue, 30 Apr 2013 11:26:53 +0200
+Subject: [PATCH 12/13] MIPS: BCM63XX: add cpumask argument to unmask
+
+Allow selective unmasking of IPIC irqs.
+
+Signed-off-by: Jonas Gorski <jogo@openwrt.org>
+---
+ arch/mips/bcm63xx/irq.c |   19 +++++++++++++------
+ 1 file changed, 13 insertions(+), 6 deletions(-)
+
+--- a/arch/mips/bcm63xx/irq.c
++++ b/arch/mips/bcm63xx/irq.c
+@@ -24,8 +24,10 @@ static void __dispatch_internal_32(int c
+ static void __dispatch_internal_64(int cpu) __maybe_unused;
+ static void __internal_irq_mask_32(unsigned int irq) __maybe_unused;
+ static void __internal_irq_mask_64(unsigned int irq) __maybe_unused;
+-static void __internal_irq_unmask_32(unsigned int irq) __maybe_unused;
+-static void __internal_irq_unmask_64(unsigned int irq) __maybe_unused;
++static void __internal_irq_unmask_32(unsigned int irq,
++				     const struct cpumask *dest) __maybe_unused;
++static void __internal_irq_unmask_64(unsigned int irq,
++				     const struct cpumask *dest) __maybe_unused;
+ 
+ static DEFINE_SPINLOCK(ipic_lock);
+ static DEFINE_SPINLOCK(epic_lock);
+@@ -150,7 +152,8 @@ static unsigned int ext_irq_count;
+ static unsigned int ext_irq_start, ext_irq_end;
+ static unsigned int ext_irq_cfg_reg1, ext_irq_cfg_reg2;
+ static void (*internal_irq_mask)(unsigned int irq);
+-static void (*internal_irq_unmask)(unsigned int irq);
++static void (*internal_irq_unmask)(unsigned int irq,
++				   const struct cpumask *dest);
+ 
+ static void bcm63xx_init_irq(void)
+ {
+@@ -340,7 +343,8 @@ static void __internal_irq_mask_##width(
+ 	}								\
+ }									\
+ 									\
+-static void __internal_irq_unmask_##width(unsigned int irq)		\
++static void __internal_irq_unmask_##width(unsigned int irq,		\
++					const struct cpumask *dest)	\
+ { 									\
+ 	u32 val;							\
+ 	unsigned reg = (irq / 32) ^ (width/32 - 1);			\
+@@ -351,7 +355,10 @@ static void __internal_irq_unmask_##widt
+ 		u32 irq_mask_addr = get_irq_mask_addr(cpu);		\
+ 									\
+ 		val = bcm_readl(irq_mask_addr + reg * sizeof(u32));	\
+-		val |= (1 << bit); 					\
++		if (cpu_isset(cpu, *dest))				\
++			val |= (1 << bit); 				\
++		else							\
++			val &= ~(1 << bit);				\
+ 		bcm_writel(val, irq_mask_addr + reg * sizeof(u32));	\
+ 	}								\
+ }
+@@ -413,7 +420,7 @@ static void bcm63xx_internal_irq_unmask(
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&ipic_lock, flags);
+-	internal_irq_unmask(d->irq - IRQ_INTERNAL_BASE);
++	internal_irq_unmask(d->irq - IRQ_INTERNAL_BASE, cpu_online_mask);
+ 	spin_unlock_irqrestore(&ipic_lock, flags);
+ }
+ 
diff --git a/target/linux/brcm63xx/patches-3.8/322-MIPS-BCM63XX-allow-setting-affinity-for-IPIC.patch b/target/linux/brcm63xx/patches-3.8/322-MIPS-BCM63XX-allow-setting-affinity-for-IPIC.patch
new file mode 100644
index 0000000000000000000000000000000000000000..d976903d2fed7d55d21106620f20e7e0b4fa8b1a
--- /dev/null
+++ b/target/linux/brcm63xx/patches-3.8/322-MIPS-BCM63XX-allow-setting-affinity-for-IPIC.patch
@@ -0,0 +1,61 @@
+From a8bb19e5ba9a3a73fe6a761295b67b641a7bc9df Mon Sep 17 00:00:00 2001
+From: Jonas Gorski <jogo@openwrt.org>
+Date: Fri, 26 Apr 2013 12:06:03 +0200
+Subject: [PATCH 13/13] MIPS: BCM63XX: allow setting affinity for IPIC
+
+Add support for setting the SMP affinity for the IPIC IRQs.
+
+Signed-off-by: Jonas Gorski <jogo@openwrt.org>
+---
+ arch/mips/bcm63xx/irq.c |   27 ++++++++++++++++++++++++++-
+ 1 file changed, 26 insertions(+), 1 deletion(-)
+
+--- a/arch/mips/bcm63xx/irq.c
++++ b/arch/mips/bcm63xx/irq.c
+@@ -418,9 +418,14 @@ static void bcm63xx_internal_irq_mask(st
+ static void bcm63xx_internal_irq_unmask(struct irq_data *d)
+ {
+ 	unsigned long flags;
++	const struct cpumask *dest = cpu_online_mask;
+ 
+ 	spin_lock_irqsave(&ipic_lock, flags);
+-	internal_irq_unmask(d->irq - IRQ_INTERNAL_BASE, cpu_online_mask);
++#ifdef CONFIG_SMP
++	if (irqd_affinity_was_set(d))
++		dest = d->affinity;
++#endif
++	internal_irq_unmask(d->irq - IRQ_INTERNAL_BASE, dest);
+ 	spin_unlock_irqrestore(&ipic_lock, flags);
+ }
+ 
+@@ -596,10 +601,30 @@ static int bcm63xx_external_irq_set_type
+ 	return IRQ_SET_MASK_OK_NOCOPY;
+ }
+ 
++#ifdef CONFIG_SMP
++static int bcm63xx_internal_set_affinity(struct irq_data *data,
++					 const struct cpumask *dest,
++					 bool force)
++{
++	unsigned int irq = data->irq - IRQ_INTERNAL_BASE;
++	unsigned long flags;
++
++	spin_lock_irqsave(&ipic_lock, flags);
++	if (!irqd_irq_disabled(data))
++		internal_irq_unmask(irq, dest);
++	spin_unlock_irqrestore(&ipic_lock, flags);
++
++	return 0;
++}
++#endif
++
+ static struct irq_chip bcm63xx_internal_irq_chip = {
+ 	.name		= "bcm63xx_ipic",
+ 	.irq_mask	= bcm63xx_internal_irq_mask,
+ 	.irq_unmask	= bcm63xx_internal_irq_unmask,
++#ifdef CONFIG_SMP
++	.irq_set_affinity = bcm63xx_internal_set_affinity,
++#endif
+ };
+ 
+ static struct irq_chip bcm63xx_external_irq_chip = {