aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2011-03-17 15:32:58 -0400
committerGrant Likely <grant.likely@secretlab.ca>2011-03-18 01:07:44 -0400
commit84bead6c38b0374e6e7db06b3097f0e700b8f148 (patch)
treed2570d9265aaea5f2b4df6b7bba44f390687f031 /drivers
parent732063b92bb727b27e61580ce278dddefe31c6ad (diff)
gpio/langwell: Clear edge bit before handling
I don't have the specs for this beast, but it looks a lot like the PXA GPIO block. Though I bet it's the same IP and the driver should have reused the PXA code. Acknowleding the edge detect status after handling one or more gpio interrupts looks wrong. We might lose an edge which came in while we handled the previous one. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: Alek Du <alek.du@intel.com> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpio/langwell_gpio.c13
1 files changed, 6 insertions, 7 deletions
diff --git a/drivers/gpio/langwell_gpio.c b/drivers/gpio/langwell_gpio.c
index f658af016f44..560ab648cf18 100644
--- a/drivers/gpio/langwell_gpio.c
+++ b/drivers/gpio/langwell_gpio.c
@@ -190,23 +190,22 @@ static void lnw_irq_handler(unsigned irq, struct irq_desc *desc)
190 struct irq_data *data = irq_desc_get_irq_data(desc); 190 struct irq_data *data = irq_desc_get_irq_data(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, mask;
194 unsigned long pending; 194 unsigned long pending;
195 void __iomem *gedr; 195 void __iomem *gedr;
196 196
197 /* check GPIO controller to check which pin triggered the interrupt */ 197 /* check GPIO controller to check which pin triggered the interrupt */
198 for (base = 0; base < lnw->chip.ngpio; base += 32) { 198 for (base = 0; base < lnw->chip.ngpio; base += 32) {
199 gedr = gpio_reg(&lnw->chip, base, GEDR); 199 gedr = gpio_reg(&lnw->chip, base, GEDR);
200 gedr_v = pending = readl(gedr); 200 pending = readl(gedr);
201 if (!gedr_v)
202 continue;
203 while (pending) { 201 while (pending) {
204 gpio = __ffs(pending) - 1; 202 gpio = __ffs(pending) - 1;
205 pending &= ~BIT(gpio); 203 mask = BIT(gpio);
204 pending &= ~mask;
205 /* Clear before handling so we can't lose an edge */
206 writel(mask, gedr);
206 generic_handle_irq(lnw->irq_base + base + gpio); 207 generic_handle_irq(lnw->irq_base + base + gpio);
207 } 208 }
208 /* clear the edge detect status bit */
209 writel(gedr_v, gedr);
210 } 209 }
211 210
212 chip->irq_eoi(data); 211 chip->irq_eoi(data);