sh: intc - convert voyagergx code
authorMagnus Damm <damm@igel.co.jp>
Fri, 3 Aug 2007 05:27:20 +0000 (14:27 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Fri, 21 Sep 2007 02:57:48 +0000 (11:57 +0900)
This patch converts the sh-specific voyagergx interrupt code to make use
of intc. A lot of "interesting" old cruft gets replaced with intc tables
and some simple demux code.

- All interrupt sources in the sm501 data sheet are now in the header.
- The number and order of IRQ values are disconnected from register bits.
- Interrupt sources now start from IRQ 200.
- set_irq_chained_handler() is now used to hook up the demux function.

In the future it would probably make sense to move the interrupt demuxer
into into the mfd driver, but this is probably a nice step in the right
direction until that happens.

Tested on a R2D-1 board using the serial port hooked up to the sm501.

Signed-off-by: Magnus Damm <damm@igel.co.jp>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
arch/sh/boards/renesas/rts7751r2d/irq.c
arch/sh/boards/renesas/rts7751r2d/setup.c
arch/sh/cchips/voyagergx/irq.c
include/asm-sh/voyagergx.h

index 0bae9041acebaa04e9a9dede1593096267bb2750..b97c25de3a4124bddb95261c82ead13fc52b8dd1 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <asm/voyagergx.h>
 #include <asm/rts7751r2d.h>
 
 #if defined(CONFIG_RTS7751R2D_REV11)
@@ -21,9 +22,6 @@ static int mask_pos[] = {11, 9, 8, 12, 10, 6, 5, 4, 7, 14, 13, 0, 0, 0, 0};
 static int mask_pos[] = {6, 11, 9, 8, 12, 10, 5, 4, 7, 14, 13, 0, 0, 0, 0};
 #endif
 
-extern int voyagergx_irq_demux(int irq);
-extern void setup_voyagergx_irq(void);
-
 static void enable_rts7751r2d_irq(unsigned int irq)
 {
        /* Set priority in IPR back to original value */
@@ -39,7 +37,7 @@ static void disable_rts7751r2d_irq(unsigned int irq)
 
 int rts7751r2d_irq_demux(int irq)
 {
-       return voyagergx_irq_demux(irq);
+       return irq;
 }
 
 static struct irq_chip rts7751r2d_irq_chip __read_mostly = {
index 6f7029d33241db4beeb46395968c24b81e0403e0..4d1bbd30e52bd23830647fa481d370f75e207c7a 100644 (file)
@@ -82,7 +82,7 @@ static struct plat_serial8250_port uart_platform_data[] = {
                .membase        = (void __iomem *)VOYAGER_UART_BASE,
                .mapbase        = VOYAGER_UART_BASE,
                .iotype         = UPIO_MEM,
-               .irq            = VOYAGER_UART0_IRQ,
+               .irq            = IRQ_SM501_U0,
                .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
                .regshift       = 2,
                .uartclk        = (9600 * 16),
@@ -125,7 +125,7 @@ static struct resource sm501_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [2]     = {
-               .start  = 32,
+               .start  = IRQ_SM501_CV,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -187,7 +187,6 @@ static void __init rts7751r2d_setup(char **cmdline_p)
 static struct sh_machine_vector mv_rts7751r2d __initmv = {
        .mv_name                = "RTS7751R2D",
        .mv_setup               = rts7751r2d_setup,
-       .mv_nr_irqs             = 72,
 
        .mv_init_irq            = init_rts7751r2d_IRQ,
        .mv_irq_demux           = rts7751r2d_irq_demux,
index d70e5c8461b56e4b60c72c43ae9204c4b0637a8e..0ca405a46a5bd3ec6d7d7ae754a7a8f5d48a7c33 100644 (file)
 #include <asm/voyagergx.h>
 #include <asm/rts7751r2d.h>
 
-static void disable_voyagergx_irq(unsigned int irq)
-{
-       unsigned long val;
-       unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE);
-
-       pr_debug("disable_voyagergx_irq(%d): mask=%lx\n", irq, mask);
-       val = readl((void __iomem *)VOYAGER_INT_MASK);
-       val &= ~mask;
-       writel(val, (void __iomem *)VOYAGER_INT_MASK);
-}
-
-static void enable_voyagergx_irq(unsigned int irq)
-{
-       unsigned long val;
-       unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE);
-
-       pr_debug("disable_voyagergx_irq(%d): mask=%lx\n", irq, mask);
-       val = readl((void __iomem *)VOYAGER_INT_MASK);
-       val |= mask;
-       writel(val, (void __iomem *)VOYAGER_INT_MASK);
-}
-
-static void mask_and_ack_voyagergx(unsigned int irq)
-{
-       disable_voyagergx_irq(irq);
-}
-
-static void end_voyagergx_irq(unsigned int irq)
-{
-       if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-               enable_voyagergx_irq(irq);
-}
-
-static unsigned int startup_voyagergx_irq(unsigned int irq)
-{
-       enable_voyagergx_irq(irq);
-       return 0;
-}
-
-static void shutdown_voyagergx_irq(unsigned int irq)
-{
-       disable_voyagergx_irq(irq);
-}
-
-static struct hw_interrupt_type voyagergx_irq_type = {
-       .typename       = "VOYAGERGX-IRQ",
-       .startup        = startup_voyagergx_irq,
-       .shutdown       = shutdown_voyagergx_irq,
-       .enable         = enable_voyagergx_irq,
-       .disable        = disable_voyagergx_irq,
-       .ack            = mask_and_ack_voyagergx,
-       .end            = end_voyagergx_irq,
+enum {
+       UNUSED = 0,
+
+       /* voyager specific interrupt sources */
+       UP, G54, G53, G52, G51, G50, G49, G48,
+       I2C, PW, DMA, PCI, I2S, AC, US,
+       U1, U0, CV, MC, S1, S0,
+       UH, TWOD, ZD, PV, CI,
 };
 
-static irqreturn_t voyagergx_interrupt(int irq, void *dev_id)
-{
-       printk(KERN_INFO
-              "VoyagerGX: spurious interrupt, status: 0x%x\n",
-                       (unsigned int)readl((void __iomem *)INT_STATUS));
-       return IRQ_HANDLED;
-}
-
-static struct {
-       int (*func)(int, void *);
-       void *dev;
-} voyagergx_demux[VOYAGER_IRQ_NUM];
+static struct intc_vect vectors[] = {
+       INTC_IRQ(UP, IRQ_SM501_UP), INTC_IRQ(G54, IRQ_SM501_G54),
+       INTC_IRQ(G53, IRQ_SM501_G53), INTC_IRQ(G52, IRQ_SM501_G52),
+       INTC_IRQ(G51, IRQ_SM501_G51), INTC_IRQ(G50, IRQ_SM501_G50),
+       INTC_IRQ(G49, IRQ_SM501_G49), INTC_IRQ(G48, IRQ_SM501_G48),
+       INTC_IRQ(I2C, IRQ_SM501_I2C), INTC_IRQ(PW, IRQ_SM501_PW),
+       INTC_IRQ(DMA, IRQ_SM501_DMA), INTC_IRQ(PCI, IRQ_SM501_PCI),
+       INTC_IRQ(I2S, IRQ_SM501_I2S), INTC_IRQ(AC, IRQ_SM501_AC),
+       INTC_IRQ(US, IRQ_SM501_US), INTC_IRQ(U1, IRQ_SM501_U1),
+       INTC_IRQ(U0, IRQ_SM501_U0), INTC_IRQ(CV, IRQ_SM501_CV),
+       INTC_IRQ(MC, IRQ_SM501_MC), INTC_IRQ(S1, IRQ_SM501_S1),
+       INTC_IRQ(S0, IRQ_SM501_S0), INTC_IRQ(UH, IRQ_SM501_UH),
+       INTC_IRQ(TWOD, IRQ_SM501_2D), INTC_IRQ(ZD, IRQ_SM501_ZD),
+       INTC_IRQ(PV, IRQ_SM501_PV), INTC_IRQ(CI, IRQ_SM501_CI),
+};
 
-void voyagergx_register_irq_demux(int irq,
-               int (*demux)(int irq, void *dev), void *dev)
-{
-       voyagergx_demux[irq - VOYAGER_IRQ_BASE].func = demux;
-       voyagergx_demux[irq - VOYAGER_IRQ_BASE].dev = dev;
-}
+static struct intc_mask_reg mask_registers[] = {
+       { VOYAGER_INT_MASK, 1, 32, /* "Interrupt Mask", MMIO_base + 0x30 */
+         { UP, G54, G53, G52, G51, G50, G49, G48,
+           I2C, PW, 0, DMA, PCI, I2S, AC, US,
+           0, 0, U1, U0, CV, MC, S1, S0,
+           0, UH, 0, 0, TWOD, ZD, PV, CI } },
+};
 
-void voyagergx_unregister_irq_demux(int irq)
-{
-       voyagergx_demux[irq - VOYAGER_IRQ_BASE].func = 0;
-}
+static DECLARE_INTC_DESC(intc_desc, "voyagergx", vectors,
+                        NULL, NULL, mask_registers, NULL, NULL);
+
+static unsigned int voyagergx_stat2irq[32] = {
+       IRQ_SM501_CI, IRQ_SM501_PV, IRQ_SM501_ZD, IRQ_SM501_2D,
+       0, 0, IRQ_SM501_UH, 0,
+       IRQ_SM501_S0, IRQ_SM501_S1, IRQ_SM501_MC, IRQ_SM501_CV,
+       IRQ_SM501_U0, IRQ_SM501_U1, 0, 0,
+       IRQ_SM501_US, IRQ_SM501_AC, IRQ_SM501_I2S, IRQ_SM501_PCI,
+       IRQ_SM501_DMA, 0, IRQ_SM501_PW, IRQ_SM501_I2C,
+       IRQ_SM501_G48, IRQ_SM501_G49, IRQ_SM501_G50, IRQ_SM501_G51,
+       IRQ_SM501_G52, IRQ_SM501_G53, IRQ_SM501_G54, IRQ_SM501_UP
+};
 
-int voyagergx_irq_demux(int irq)
+static void voyagergx_irq_demux(unsigned int irq, struct irq_desc *desc)
 {
-
-       if (irq == IRQ_VOYAGER ) {
-               unsigned long i = 0, bit __attribute__ ((unused));
-               unsigned long val  = readl((void __iomem *)INT_STATUS);
-
-               if (val & (1 << 1))
-                       i = 1;
-               else if (val & (1 << 2))
-                       i = 2;
-               else if (val & (1 << 6))
-                       i = 6;
-               else if (val & (1 << 10))
-                       i = 10;
-               else if (val & (1 << 11))
-                       i = 11;
-               else if (val & (1 << 12))
-                       i = 12;
-               else if (val & (1 << 17))
-                       i = 17;
-               else
-                       printk("Unexpected IRQ irq = %d status = 0x%08lx\n", irq, val);
-               pr_debug("voyagergx_irq_demux %ld \n", i);
-               if (i < VOYAGER_IRQ_NUM) {
-                       irq = VOYAGER_IRQ_BASE + i;
-                       if (voyagergx_demux[i].func != 0)
-                               irq = voyagergx_demux[i].func(irq,
-                                               voyagergx_demux[i].dev);
+       unsigned long intv = ctrl_inl(INT_STATUS);
+       struct irq_desc *ext_desc;
+       unsigned int ext_irq;
+       unsigned int k = 0;
+
+       while (intv) {
+               ext_irq = voyagergx_stat2irq[k];
+               if (ext_irq && (intv & 1)) {
+                       ext_desc = irq_desc + ext_irq;
+                       handle_level_irq(ext_irq, ext_desc);
                }
+               intv >>= 1;
+               k++;
        }
-       return irq;
 }
 
-static struct irqaction irq0  = {
-       .name           = "voyagergx",
-       .handler        = voyagergx_interrupt,
-       .flags          = IRQF_DISABLED,
-       .mask           = CPU_MASK_NONE,
-};
-
 void __init setup_voyagergx_irq(void)
 {
-       int i, flag;
-
-       printk(KERN_INFO "VoyagerGX configured at 0x%x on irq %d(mapped into %d to %d)\n",
-              VOYAGER_BASE,
+       printk(KERN_INFO "VoyagerGX on irq %d (mapped into %d to %d)\n",
               IRQ_VOYAGER,
               VOYAGER_IRQ_BASE,
               VOYAGER_IRQ_BASE + VOYAGER_IRQ_NUM - 1);
 
-       for (i=0; i<VOYAGER_IRQ_NUM; i++) {
-               flag = 0;
-               switch (VOYAGER_IRQ_BASE + i) {
-               case VOYAGER_USBH_IRQ:
-               case VOYAGER_8051_IRQ:
-               case VOYAGER_UART0_IRQ:
-               case VOYAGER_UART1_IRQ:
-               case VOYAGER_AC97_IRQ:
-                       flag = 1;
-               }
-               if (flag == 1)
-                       irq_desc[VOYAGER_IRQ_BASE + i].chip = &voyagergx_irq_type;
-       }
-
-       setup_irq(IRQ_VOYAGER, &irq0);
+       register_intc_controller(&intc_desc);
+       set_irq_chained_handler(IRQ_VOYAGER, voyagergx_irq_demux);
 }
index 64c936b22715e89283213cf6b9058117b3fdc3a2..d825596562dfa92017469e4da171e530bac7cdd1 100644 (file)
 #define VOYAGER_UART_BASE              (0x30000 + VOYAGER_BASE)
 #define        VOYAGER_AC97_BASE               (0xa0000 + VOYAGER_BASE)
 
-#define VOYAGER_IRQ_NUM                        32
-#define VOYAGER_IRQ_BASE               50
-#define VOYAGER_USBH_IRQ               VOYAGER_IRQ_BASE + 6
-#define VOYAGER_8051_IRQ               VOYAGER_IRQ_BASE + 10
-#define VOYAGER_UART0_IRQ              VOYAGER_IRQ_BASE + 12
-#define VOYAGER_UART1_IRQ              VOYAGER_IRQ_BASE + 13
-#define        VOYAGER_AC97_IRQ                VOYAGER_IRQ_BASE + 17
+#define VOYAGER_IRQ_NUM                        26
+#define VOYAGER_IRQ_BASE               200
+
+#define IRQ_SM501_UP                   (VOYAGER_IRQ_BASE + 0)
+#define IRQ_SM501_G54                  (VOYAGER_IRQ_BASE + 1)
+#define IRQ_SM501_G53                  (VOYAGER_IRQ_BASE + 2)
+#define IRQ_SM501_G52                  (VOYAGER_IRQ_BASE + 3)
+#define IRQ_SM501_G51                  (VOYAGER_IRQ_BASE + 4)
+#define IRQ_SM501_G50                  (VOYAGER_IRQ_BASE + 5)
+#define IRQ_SM501_G49                  (VOYAGER_IRQ_BASE + 6)
+#define IRQ_SM501_G48                  (VOYAGER_IRQ_BASE + 7)
+#define IRQ_SM501_I2C                  (VOYAGER_IRQ_BASE + 8)
+#define IRQ_SM501_PW                   (VOYAGER_IRQ_BASE + 9)
+#define IRQ_SM501_DMA                  (VOYAGER_IRQ_BASE + 10)
+#define IRQ_SM501_PCI                  (VOYAGER_IRQ_BASE + 11)
+#define IRQ_SM501_I2S                  (VOYAGER_IRQ_BASE + 12)
+#define IRQ_SM501_AC                   (VOYAGER_IRQ_BASE + 13)
+#define IRQ_SM501_US                   (VOYAGER_IRQ_BASE + 14)
+#define IRQ_SM501_U1                   (VOYAGER_IRQ_BASE + 15)
+#define IRQ_SM501_U0                   (VOYAGER_IRQ_BASE + 16)
+#define IRQ_SM501_CV                   (VOYAGER_IRQ_BASE + 17)
+#define IRQ_SM501_MC                   (VOYAGER_IRQ_BASE + 18)
+#define IRQ_SM501_S1                   (VOYAGER_IRQ_BASE + 19)
+#define IRQ_SM501_S0                   (VOYAGER_IRQ_BASE + 20)
+#define IRQ_SM501_UH                   (VOYAGER_IRQ_BASE + 21)
+#define IRQ_SM501_2D                   (VOYAGER_IRQ_BASE + 22)
+#define IRQ_SM501_ZD                   (VOYAGER_IRQ_BASE + 23)
+#define IRQ_SM501_PV                   (VOYAGER_IRQ_BASE + 24)
+#define IRQ_SM501_CI                   (VOYAGER_IRQ_BASE + 25)
 
 /* ----- MISC controle  register ------------------------------ */
 #define MISC_CTRL                      (0x000004 + VOYAGER_BASE)
 void *voyagergx_consistent_alloc(struct device *, size_t, dma_addr_t *, gfp_t);
 int voyagergx_consistent_free(struct device *, size_t, void *, dma_addr_t);
 
+/* arch/sh/cchips/voyagergx/irq.c */
+void setup_voyagergx_irq(void);
+
 #endif /* _VOYAGER_GX_REG_H */