diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpio/langwell_gpio.c | 13 |
1 files changed, 7 insertions, 6 deletions
diff --git a/drivers/gpio/langwell_gpio.c b/drivers/gpio/langwell_gpio.c index 6efc4e60aca7..f658af016f44 100644 --- a/drivers/gpio/langwell_gpio.c +++ b/drivers/gpio/langwell_gpio.c | |||
@@ -191,19 +191,20 @@ static void lnw_irq_handler(unsigned irq, struct irq_desc *desc) | |||
191 | struct lnw_gpio *lnw = irq_data_get_irq_handler_data(data); | 191 | struct lnw_gpio *lnw = irq_data_get_irq_handler_data(data); |
192 | struct irq_chip *chip = irq_data_get_irq_chip(data); | 192 | struct irq_chip *chip = irq_data_get_irq_chip(data); |
193 | u32 base, gpio, gedr_v; | 193 | u32 base, gpio, gedr_v; |
194 | unsigned long pending; | ||
194 | void __iomem *gedr; | 195 | void __iomem *gedr; |
195 | 196 | ||
196 | /* check GPIO controller to check which pin triggered the interrupt */ | 197 | /* check GPIO controller to check which pin triggered the interrupt */ |
197 | for (base = 0; base < lnw->chip.ngpio; base += 32) { | 198 | for (base = 0; base < lnw->chip.ngpio; base += 32) { |
198 | gedr = gpio_reg(&lnw->chip, base, GEDR); | 199 | gedr = gpio_reg(&lnw->chip, base, GEDR); |
199 | gedr_v = readl(gedr); | 200 | gedr_v = pending = readl(gedr); |
200 | if (!gedr_v) | 201 | if (!gedr_v) |
201 | continue; | 202 | continue; |
202 | for (gpio = base; gpio < base + 32; gpio++) | 203 | while (pending) { |
203 | if (gedr_v & BIT(gpio % 32)) { | 204 | gpio = __ffs(pending) - 1; |
204 | pr_debug("pin %d triggered\n", gpio); | 205 | pending &= ~BIT(gpio); |
205 | generic_handle_irq(lnw->irq_base + gpio); | 206 | generic_handle_irq(lnw->irq_base + base + gpio); |
206 | } | 207 | } |
207 | /* clear the edge detect status bit */ | 208 | /* clear the edge detect status bit */ |
208 | writel(gedr_v, gedr); | 209 | writel(gedr_v, gedr); |
209 | } | 210 | } |