linux-mips
[Top] [All Lists]

[PATCH 10/11] MIPS: BCM63XX: add external irq support for non 6348 CPUs.

To: ralf@linux-mips.org
Subject: [PATCH 10/11] MIPS: BCM63XX: add external irq support for non 6348 CPUs.
From: Maxime Bizon <mbizon@freebox.fr>
Date: Fri, 10 Jun 2011 23:47:20 +0200
Cc: linux-mips@linux-mips.org, florian@openwrt.org, Maxime Bizon <mbizon@freebox.fr>
In-reply-to: <1307742441-28284-1-git-send-email-mbizon@freebox.fr>
References: <1307742441-28284-1-git-send-email-mbizon@freebox.fr>
Sender: linux-mips-bounce@linux-mips.org
Signed-off-by: Maxime Bizon <mbizon@freebox.fr>
---
 arch/mips/bcm63xx/irq.c                           |   74 ++++++++++++++++-----
 arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h |   20 ++++--
 2 files changed, 73 insertions(+), 21 deletions(-)

diff --git a/arch/mips/bcm63xx/irq.c b/arch/mips/bcm63xx/irq.c
index 07909a9..f2d5e30 100644
--- a/arch/mips/bcm63xx/irq.c
+++ b/arch/mips/bcm63xx/irq.c
@@ -276,7 +276,12 @@ static void bcm63xx_external_irq_mask(struct irq_data *d)
        u32 reg;
 
        reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG);
-       reg &= ~EXTIRQ_CFG_MASK(irq);
+
+       if (BCMCPU_IS_6348())
+               reg &= ~EXTIRQ_CFG_MASK_6348(irq);
+       else
+               reg &= ~EXTIRQ_CFG_MASK(irq);
+
        bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG);
        if (is_ext_irq_cascaded)
                internal_irq_mask(irq + ext_irq_start);
@@ -288,7 +293,12 @@ static void bcm63xx_external_irq_unmask(struct irq_data *d)
        u32 reg;
 
        reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG);
-       reg |= EXTIRQ_CFG_MASK(irq);
+
+       if (BCMCPU_IS_6348())
+               reg |= EXTIRQ_CFG_MASK_6348(irq);
+       else
+               reg |= EXTIRQ_CFG_MASK(irq);
+
        bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG);
        if (is_ext_irq_cascaded)
                internal_irq_unmask(irq + ext_irq_start);
@@ -300,7 +310,12 @@ static void bcm63xx_external_irq_clear(struct irq_data *d)
        u32 reg;
 
        reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG);
-       reg |= EXTIRQ_CFG_CLEAR(irq);
+
+       if (BCMCPU_IS_6348())
+               reg |= EXTIRQ_CFG_CLEAR_6348(irq);
+       else
+               reg |= EXTIRQ_CFG_CLEAR(irq);
+
        bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG);
        if (is_ext_irq_cascaded)
                internal_irq_mask(irq + ext_irq_start);
@@ -330,45 +345,72 @@ static int bcm63xx_external_irq_set_type(struct irq_data 
*d,
 {
        unsigned int irq = d->irq - IRQ_EXT_BASE;
        u32 reg;
+       int levelsense, sense, bothedge;
 
        flow_type &= IRQ_TYPE_SENSE_MASK;
 
        if (flow_type == IRQ_TYPE_NONE)
                flow_type = IRQ_TYPE_LEVEL_LOW;
 
-       reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG);
+       levelsense = sense = bothedge = 0;
        switch (flow_type) {
        case IRQ_TYPE_EDGE_BOTH:
-               reg &= ~EXTIRQ_CFG_LEVELSENSE(irq);
-               reg |= EXTIRQ_CFG_BOTHEDGE(irq);
+               bothedge = 1;
                break;
 
        case IRQ_TYPE_EDGE_RISING:
-               reg &= ~EXTIRQ_CFG_LEVELSENSE(irq);
-               reg |= EXTIRQ_CFG_SENSE(irq);
-               reg &= ~EXTIRQ_CFG_BOTHEDGE(irq);
+               sense = 1;
                break;
 
        case IRQ_TYPE_EDGE_FALLING:
-               reg &= ~EXTIRQ_CFG_LEVELSENSE(irq);
-               reg &= ~EXTIRQ_CFG_SENSE(irq);
-               reg &= ~EXTIRQ_CFG_BOTHEDGE(irq);
                break;
 
        case IRQ_TYPE_LEVEL_HIGH:
-               reg |= EXTIRQ_CFG_LEVELSENSE(irq);
-               reg |= EXTIRQ_CFG_SENSE(irq);
+               levelsense = 1;
+               sense = 1;
                break;
 
        case IRQ_TYPE_LEVEL_LOW:
-               reg |= EXTIRQ_CFG_LEVELSENSE(irq);
-               reg &= ~EXTIRQ_CFG_SENSE(irq);
+               levelsense = 1;
                break;
 
        default:
                printk(KERN_ERR "bogus flow type combination given !\n");
                return -EINVAL;
        }
+
+       reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG);
+
+       if (BCMCPU_IS_6348()) {
+               if (levelsense)
+                       reg |= EXTIRQ_CFG_LEVELSENSE_6348(irq);
+               else
+                       reg &= ~EXTIRQ_CFG_LEVELSENSE_6348(irq);
+               if (sense)
+                       reg |= EXTIRQ_CFG_SENSE_6348(irq);
+               else
+                       reg &= ~EXTIRQ_CFG_SENSE_6348(irq);
+               if (bothedge)
+                       reg |= EXTIRQ_CFG_BOTHEDGE_6348(irq);
+               else
+                       reg &= ~EXTIRQ_CFG_BOTHEDGE_6348(irq);
+       }
+
+       if (BCMCPU_IS_6338() || BCMCPU_IS_6358() || BCMCPU_IS_6368()) {
+               if (levelsense)
+                       reg |= EXTIRQ_CFG_LEVELSENSE(irq);
+               else
+                       reg &= ~EXTIRQ_CFG_LEVELSENSE(irq);
+               if (sense)
+                       reg |= EXTIRQ_CFG_SENSE(irq);
+               else
+                       reg &= ~EXTIRQ_CFG_SENSE(irq);
+               if (bothedge)
+                       reg |= EXTIRQ_CFG_BOTHEDGE(irq);
+               else
+                       reg &= ~EXTIRQ_CFG_BOTHEDGE(irq);
+       }
+
        bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG);
 
        irqd_set_trigger_type(d, flow_type);
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h 
b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
index 4354be1..0fa613c 100644
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
@@ -104,12 +104,22 @@
 
 /* External Interrupt Configuration register */
 #define PERF_EXTIRQ_CFG_REG            0x14
+
+/* for 6348 only */
+#define EXTIRQ_CFG_SENSE_6348(x)       (1 << (x))
+#define EXTIRQ_CFG_STAT_6348(x)                (1 << (x + 5))
+#define EXTIRQ_CFG_CLEAR_6348(x)       (1 << (x + 10))
+#define EXTIRQ_CFG_MASK_6348(x)                (1 << (x + 15))
+#define EXTIRQ_CFG_BOTHEDGE_6348(x)    (1 << (x + 20))
+#define EXTIRQ_CFG_LEVELSENSE_6348(x)  (1 << (x + 25))
+
+/* for all others */
 #define EXTIRQ_CFG_SENSE(x)            (1 << (x))
-#define EXTIRQ_CFG_STAT(x)             (1 << (x + 5))
-#define EXTIRQ_CFG_CLEAR(x)            (1 << (x + 10))
-#define EXTIRQ_CFG_MASK(x)             (1 << (x + 15))
-#define EXTIRQ_CFG_BOTHEDGE(x)         (1 << (x + 20))
-#define EXTIRQ_CFG_LEVELSENSE(x)       (1 << (x + 25))
+#define EXTIRQ_CFG_STAT(x)             (1 << (x + 4))
+#define EXTIRQ_CFG_CLEAR(x)            (1 << (x + 8))
+#define EXTIRQ_CFG_MASK(x)             (1 << (x + 12))
+#define EXTIRQ_CFG_BOTHEDGE(x)         (1 << (x + 16))
+#define EXTIRQ_CFG_LEVELSENSE(x)       (1 << (x + 20))
 
 #define EXTIRQ_CFG_CLEAR_ALL           (0xf << 10)
 #define EXTIRQ_CFG_MASK_ALL            (0xf << 15)
-- 
1.7.1.1


<Prev in Thread] Current Thread [Next in Thread>