diff options
Diffstat (limited to 'drivers/gpio/langwell_gpio.c')
-rw-r--r-- | drivers/gpio/langwell_gpio.c | 43 |
1 files changed, 20 insertions, 23 deletions
diff --git a/drivers/gpio/langwell_gpio.c b/drivers/gpio/langwell_gpio.c index 54d70a47afc1..560ab648cf18 100644 --- a/drivers/gpio/langwell_gpio.c +++ b/drivers/gpio/langwell_gpio.c | |||
@@ -187,31 +187,28 @@ MODULE_DEVICE_TABLE(pci, lnw_gpio_ids); | |||
187 | 187 | ||
188 | static void lnw_irq_handler(unsigned irq, struct irq_desc *desc) | 188 | static void lnw_irq_handler(unsigned irq, struct irq_desc *desc) |
189 | { | 189 | { |
190 | struct lnw_gpio *lnw = get_irq_data(irq); | 190 | struct irq_data *data = irq_desc_get_irq_data(desc); |
191 | u32 base, gpio; | 191 | struct lnw_gpio *lnw = irq_data_get_irq_handler_data(data); |
192 | struct irq_chip *chip = irq_data_get_irq_chip(data); | ||
193 | u32 base, gpio, mask; | ||
194 | unsigned long pending; | ||
192 | void __iomem *gedr; | 195 | void __iomem *gedr; |
193 | u32 gedr_v; | ||
194 | 196 | ||
195 | /* check GPIO controller to check which pin triggered the interrupt */ | 197 | /* check GPIO controller to check which pin triggered the interrupt */ |
196 | for (base = 0; base < lnw->chip.ngpio; base += 32) { | 198 | for (base = 0; base < lnw->chip.ngpio; base += 32) { |
197 | gedr = gpio_reg(&lnw->chip, base, GEDR); | 199 | gedr = gpio_reg(&lnw->chip, base, GEDR); |
198 | gedr_v = readl(gedr); | 200 | pending = readl(gedr); |
199 | if (!gedr_v) | 201 | while (pending) { |
200 | continue; | 202 | gpio = __ffs(pending) - 1; |
201 | for (gpio = base; gpio < base + 32; gpio++) | 203 | mask = BIT(gpio); |
202 | if (gedr_v & BIT(gpio % 32)) { | 204 | pending &= ~mask; |
203 | pr_debug("pin %d triggered\n", gpio); | 205 | /* Clear before handling so we can't lose an edge */ |
204 | generic_handle_irq(lnw->irq_base + gpio); | 206 | writel(mask, gedr); |
205 | } | 207 | generic_handle_irq(lnw->irq_base + base + gpio); |
206 | /* clear the edge detect status bit */ | 208 | } |
207 | writel(gedr_v, gedr); | ||
208 | } | 209 | } |
209 | 210 | ||
210 | if (desc->chip->irq_eoi) | 211 | chip->irq_eoi(data); |
211 | desc->chip->irq_eoi(irq_get_irq_data(irq)); | ||
212 | else | ||
213 | dev_warn(lnw->chip.dev, "missing EOI handler for irq %d\n", irq); | ||
214 | |||
215 | } | 212 | } |
216 | 213 | ||
217 | static int __devinit lnw_gpio_probe(struct pci_dev *pdev, | 214 | static int __devinit lnw_gpio_probe(struct pci_dev *pdev, |
@@ -279,12 +276,12 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev, | |||
279 | dev_err(&pdev->dev, "langwell gpiochip_add error %d\n", retval); | 276 | dev_err(&pdev->dev, "langwell gpiochip_add error %d\n", retval); |
280 | goto err5; | 277 | goto err5; |
281 | } | 278 | } |
282 | set_irq_data(pdev->irq, lnw); | 279 | irq_set_handler_data(pdev->irq, lnw); |
283 | set_irq_chained_handler(pdev->irq, lnw_irq_handler); | 280 | irq_set_chained_handler(pdev->irq, lnw_irq_handler); |
284 | for (i = 0; i < lnw->chip.ngpio; i++) { | 281 | for (i = 0; i < lnw->chip.ngpio; i++) { |
285 | set_irq_chip_and_handler_name(i + lnw->irq_base, &lnw_irqchip, | 282 | irq_set_chip_and_handler_name(i + lnw->irq_base, &lnw_irqchip, |
286 | handle_simple_irq, "demux"); | 283 | handle_simple_irq, "demux"); |
287 | set_irq_chip_data(i + lnw->irq_base, lnw); | 284 | irq_set_chip_data(i + lnw->irq_base, lnw); |
288 | } | 285 | } |
289 | 286 | ||
290 | spin_lock_init(&lnw->lock); | 287 | spin_lock_init(&lnw->lock); |