sh: mach-se: Convert SE7722 FPGA to dynamic IRQ allocation.
Paul Mundt [Wed, 4 Nov 2009 02:44:21 +0000 (11:44 +0900)]
This gets rid of the arbitrary set of vectors used by the SE7722 FPGA
interrupt controller and witches over to a completely dynamic set.
No assumptions regarding a contiguous range are made, and the platform
resources themselves need to be filled in lazily.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>

arch/sh/boards/mach-se/7722/irq.c
arch/sh/boards/mach-se/7722/setup.c
arch/sh/include/mach-se/mach/se7722.h

index 02d21a3..4eb31ac 100644 (file)
 #include <asm/io.h>
 #include <mach-se/mach/se7722.h>
 
+unsigned int se7722_fpga_irq[SE7722_FPGA_IRQ_NR] = { 0, };
+
 static void disable_se7722_irq(unsigned int irq)
 {
-       unsigned int bit = irq - SE7722_FPGA_IRQ_BASE;
+       unsigned int bit = (unsigned int)get_irq_chip_data(irq);
        ctrl_outw(ctrl_inw(IRQ01_MASK) | 1 << bit, IRQ01_MASK);
 }
 
 static void enable_se7722_irq(unsigned int irq)
 {
-       unsigned int bit = irq - SE7722_FPGA_IRQ_BASE;
+       unsigned int bit = (unsigned int)get_irq_chip_data(irq);
        ctrl_outw(ctrl_inw(IRQ01_MASK) & ~(1 << bit), IRQ01_MASK);
 }
 
@@ -38,18 +40,15 @@ static struct irq_chip se7722_irq_chip __read_mostly = {
 static void se7722_irq_demux(unsigned int irq, struct irq_desc *desc)
 {
        unsigned short intv = ctrl_inw(IRQ01_STS);
-       struct irq_desc *ext_desc;
-       unsigned int ext_irq = SE7722_FPGA_IRQ_BASE;
+       unsigned int ext_irq = 0;
 
        intv &= (1 << SE7722_FPGA_IRQ_NR) - 1;
 
-       while (intv) {
-               if (intv & 1) {
-                       ext_desc = irq_desc + ext_irq;
-                       handle_level_irq(ext_irq, ext_desc);
-               }
-               intv >>= 1;
-               ext_irq++;
+       for (; intv; intv >>= 1, ext_irq++) {
+               if (!(intv & 1))
+                       continue;
+
+               generic_handle_irq(se7722_fpga_irq[ext_irq]);
        }
 }
 
@@ -63,11 +62,18 @@ void __init init_se7722_IRQ(void)
        ctrl_outw(0, IRQ01_MASK);       /* disable all irqs */
        ctrl_outw(0x2000, 0xb03fffec);  /* mrshpc irq enable */
 
-       for (i = 0; i < SE7722_FPGA_IRQ_NR; i++)
-               set_irq_chip_and_handler_name(SE7722_FPGA_IRQ_BASE + i,
+       for (i = 0; i < SE7722_FPGA_IRQ_NR; i++) {
+               se7722_fpga_irq[i] = create_irq();
+               if (se7722_fpga_irq[i] < 0)
+                       return;
+
+               set_irq_chip_and_handler_name(se7722_fpga_irq[i],
                                              &se7722_irq_chip,
                                              handle_level_irq, "level");
 
+               set_irq_chip_data(se7722_fpga_irq[i], (void *)i);
+       }
+
        set_irq_chained_handler(IRQ0_IRQ, se7722_irq_demux);
        set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW);
 
index 3637407..d05f34f 100644 (file)
@@ -60,8 +60,7 @@ static struct resource smc91x_eth_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = SMC_IRQ,
-               .end    = SMC_IRQ,
+               /* Filled in later */
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -90,8 +89,7 @@ static struct resource cf_ide_resources[] = {
                .flags  = IORESOURCE_IO,
        },
        [2] = {
-               .start  = MRSHPC_IRQ0,
-               .end    = MRSHPC_IRQ0,
+               /* Filled in later */
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -153,6 +151,14 @@ static struct platform_device *se7722_devices[] __initdata = {
 static int __init se7722_devices_setup(void)
 {
        mrshpc_setup_windows();
+
+       /* Wire-up dynamic vectors */
+       cf_ide_resources[2].start = cf_ide_resources[2].end =
+               se7722_fpga_irq[SE7722_FPGA_IRQ_MRSHPC0];
+
+       smc91x_eth_resources[1].start = smc91x_eth_resources[1].end =
+               se7722_fpga_irq[SE7722_FPGA_IRQ_SMC];
+
        return platform_add_devices(se7722_devices, ARRAY_SIZE(se7722_devices));
 }
 device_initcall(se7722_devices_setup);
@@ -193,6 +199,5 @@ static void __init se7722_setup(char **cmdline_p)
 static struct sh_machine_vector mv_se7722 __initmv = {
        .mv_name                = "Solution Engine 7722" ,
        .mv_setup               = se7722_setup ,
-       .mv_nr_irqs             = SE7722_FPGA_IRQ_BASE + SE7722_FPGA_IRQ_NR,
        .mv_init_irq            = init_se7722_IRQ,
 };
index e971d9a..16505bf 100644 (file)
 #define SE7722_FPGA_IRQ_MRSHPC1        3 /* IRQ1 */
 #define SE7722_FPGA_IRQ_MRSHPC2        4 /* IRQ1 */
 #define SE7722_FPGA_IRQ_MRSHPC3        5 /* IRQ1 */
-
 #define SE7722_FPGA_IRQ_NR     6
-#define SE7722_FPGA_IRQ_BASE   110
-
-#define MRSHPC_IRQ3            (SE7722_FPGA_IRQ_BASE + SE7722_FPGA_IRQ_MRSHPC3)
-#define MRSHPC_IRQ2            (SE7722_FPGA_IRQ_BASE + SE7722_FPGA_IRQ_MRSHPC2)
-#define MRSHPC_IRQ1            (SE7722_FPGA_IRQ_BASE + SE7722_FPGA_IRQ_MRSHPC1)
-#define MRSHPC_IRQ0            (SE7722_FPGA_IRQ_BASE + SE7722_FPGA_IRQ_MRSHPC0)
-#define SMC_IRQ                (SE7722_FPGA_IRQ_BASE + SE7722_FPGA_IRQ_SMC)
-#define USB_IRQ                (SE7722_FPGA_IRQ_BASE + SE7722_FPGA_IRQ_USB)
 
 /* arch/sh/boards/se/7722/irq.c */
+extern unsigned int se7722_fpga_irq[];
+
 void init_se7722_IRQ(void);
 
 #define __IO_PREFIX            se7722