mirror of https://github.com/hak5/openwrt.git
bcm63xx: add SMP support for BCM6362 and BCM6368
BCM6358 requires further work due to its shared TLB. Signed-off-by: Jonas Gorski <jogo@openwrt.org> SVN-Revision: 36526lede-17.01
parent
8f15326acc
commit
d11efa1428
|
@ -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)
|
|
@ -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) {
|
|
@ -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
|
|
@ -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;
|
|
@ -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);
|
|
@ -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
|
|
@ -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;
|
|
@ -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);
|
|
@ -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);
|
|
@ -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))
|
|
@ -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
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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 = {
|
Loading…
Reference in New Issue