diff options
13 files changed, 1275 insertions, 0 deletions
| 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 000000000..7c9baf7e4 --- /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 000000000..f08c7ef4f --- /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 000000000..ce0e76941 --- /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 000000000..f5b607131 --- /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 000000000..5fabd0861 --- /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 000000000..98cd637a8 --- /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 000000000..094eaa88c --- /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 000000000..3931b218c --- /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 000000000..081ec18b3 --- /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 000000000..76e8c3267 --- /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 000000000..2acbf30b0 --- /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 000000000..1047de39e --- /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 000000000..d976903d2 --- /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 = { | 
