]> Pileus Git - ~andy/linux/blobdiff - drivers/gpio/langwell_gpio.c
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab...
[~andy/linux] / drivers / gpio / langwell_gpio.c
index 6efc4e60aca7bf4964c903ba9ad634da669784b5..560ab648cf1861dc7cae22e85306b5d87c7fbcde 100644 (file)
@@ -190,22 +190,22 @@ static void lnw_irq_handler(unsigned irq, struct irq_desc *desc)
        struct irq_data *data = irq_desc_get_irq_data(desc);
        struct lnw_gpio *lnw = irq_data_get_irq_handler_data(data);
        struct irq_chip *chip = irq_data_get_irq_chip(data);
-       u32 base, gpio, gedr_v;
+       u32 base, gpio, mask;
+       unsigned long pending;
        void __iomem *gedr;
 
        /* check GPIO controller to check which pin triggered the interrupt */
        for (base = 0; base < lnw->chip.ngpio; base += 32) {
                gedr = gpio_reg(&lnw->chip, base, GEDR);
-               gedr_v = readl(gedr);
-               if (!gedr_v)
-                       continue;
-               for (gpio = base; gpio < base + 32; gpio++)
-                       if (gedr_v & BIT(gpio % 32)) {
-                               pr_debug("pin %d triggered\n", gpio);
-                               generic_handle_irq(lnw->irq_base + gpio);
-                       }
-               /* clear the edge detect status bit */
-               writel(gedr_v, gedr);
+               pending = readl(gedr);
+               while (pending) {
+                       gpio = __ffs(pending) - 1;
+                       mask = BIT(gpio);
+                       pending &= ~mask;
+                       /* Clear before handling so we can't lose an edge */
+                       writel(mask, gedr);
+                       generic_handle_irq(lnw->irq_base + base + gpio);
+               }
        }
 
        chip->irq_eoi(data);