]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
sh: fix the HD64461 level-triggered interrupts handling
authorRafael Ignacio Zurita <rizurita@yahoo.com>
Fri, 20 Mar 2009 02:08:22 +0000 (02:08 +0000)
committerPaul Mundt <lethal@linux-sh.org>
Fri, 20 Mar 2009 09:57:48 +0000 (18:57 +0900)
Rework the hd64461 demuxer code to fix the HD64461 level-triggered
interrupts handling, using handle_level_irq() as needed.

Signed-off-by: Rafael Ignacio Zurita <rizurita@yahoo.com>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
arch/sh/boards/mach-hp6xx/setup.c
arch/sh/cchips/hd6446x/hd64461.c
arch/sh/include/asm/hd64461.h

index 746742bdc0142d6d45be6c55bbe38970be3324d1..8f305b36358ba4912ea6c9bf2deb2fd017969421 100644 (file)
@@ -115,7 +115,6 @@ static struct sh_machine_vector mv_hp6xx __initmv = {
        .mv_setup = hp6xx_setup,
        /* IRQ's : CPU(64) + CCHIP(16) + FREE_TO_USE(6) */
        .mv_nr_irqs = HD64461_IRQBASE + HD64461_IRQ_NUM + 6,
-       .mv_irq_demux = hd64461_irq_demux,
        /* Enable IRQ0 -> IRQ3 in IRQ_MODE */
        .mv_init_irq = hp6xx_init_irq,
 };
index 27ceeb948bb1059a142f627c540d07848993e52b..25ef910615217a5c7115d19e77d9008c68085b67 100644 (file)
@@ -53,21 +53,22 @@ static struct irq_chip hd64461_irq_chip = {
        .unmask         = hd64461_unmask_irq,
 };
 
-int hd64461_irq_demux(int irq)
+static void hd64461_irq_demux(unsigned int irq, struct irq_desc *desc)
 {
-       if (irq == CONFIG_HD64461_IRQ) {
-               unsigned short bit;
-               unsigned short nirr = inw(HD64461_NIRR);
-               unsigned short nimr = inw(HD64461_NIMR);
-               int i;
-
-               nirr &= ~nimr;
-               for (bit = 1, i = 0; i < 16; bit <<= 1, i++)
-                       if (nirr & bit)
-                               break;
-               irq = HD64461_IRQBASE + i;
+       unsigned short intv = ctrl_inw(HD64461_NIRR);
+       struct irq_desc *ext_desc;
+       unsigned int ext_irq = HD64461_IRQBASE;
+
+       intv &= (1 << HD64461_IRQ_NUM) - 1;
+
+       while (intv) {
+               if (intv & 1) {
+                       ext_desc = irq_desc + ext_irq;
+                       handle_level_irq(ext_irq, ext_desc);
+               }
+               intv >>= 1;
+               ext_irq++;
        }
-       return irq;
 }
 
 int __init setup_hd64461(void)
@@ -93,6 +94,9 @@ int __init setup_hd64461(void)
                set_irq_chip_and_handler(i, &hd64461_irq_chip,
                                         handle_level_irq);
 
+       set_irq_chained_handler(CONFIG_HD64461_IRQ, hd64461_irq_demux);
+       set_irq_type(CONFIG_HD64461_IRQ, IRQ_TYPE_LEVEL_LOW);
+
 #ifdef CONFIG_HD64461_ENABLER
        printk(KERN_INFO "HD64461: enabling PCMCIA devices\n");
        __raw_writeb(0x4c, HD64461_PCC1CSCIER);
index 8c1353baf00f8e5e1676d0e5940304e3fdfa9b62..52b4b62382777a3d03ff41c62441d0102521be61 100644 (file)
 #include <asm/io_generic.h>
 
 /* arch/sh/cchips/hd6446x/hd64461/setup.c */
-int hd64461_irq_demux(int irq);
 void hd64461_register_irq_demux(int irq,
                                int (*demux) (int irq, void *dev), void *dev);
 void hd64461_unregister_irq_demux(int irq);