Commit e8189af4 authored by Kevin Hilman's avatar Kevin Hilman Committed by Tony Lindgren

ARM: OMAP: Clear level-triggered GPIO interrupts in unmask hook

The clearing was moved to the unmask hook because it is known to run
after the interrupt handler has actually run.  Before this patch, if
interrupts are threaded, the clearing/unmasking of level triggered
interrupts would be done before the threaded handler actually ran.
Signed-off-by: default avatarKevin Hilman <khilman@mvista.com>
Signed-off-by: default avatarTony Lindgren <tony@atomide.com>
parent 58beff48
...@@ -149,6 +149,7 @@ struct gpio_bank { ...@@ -149,6 +149,7 @@ struct gpio_bank {
u32 saved_fallingdetect; u32 saved_fallingdetect;
u32 saved_risingdetect; u32 saved_risingdetect;
#endif #endif
u32 level_mask;
spinlock_t lock; spinlock_t lock;
}; };
...@@ -536,6 +537,9 @@ static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio, ...@@ -536,6 +537,9 @@ static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio,
bank->enabled_non_wakeup_gpios &= ~gpio_bit; bank->enabled_non_wakeup_gpios &= ~gpio_bit;
} }
bank->level_mask =
__raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0) |
__raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1);
/* /*
* FIXME: Possibly do 'set_irq_handler(j, handle_level_irq)' if only * FIXME: Possibly do 'set_irq_handler(j, handle_level_irq)' if only
* level triggering requested. * level triggering requested.
...@@ -1015,12 +1019,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) ...@@ -1015,12 +1019,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
isr &= 0x0000ffff; isr &= 0x0000ffff;
if (cpu_class_is_omap2()) { if (cpu_class_is_omap2()) {
level_mask = level_mask = bank->level_mask & enabled;
__raw_readl(bank->base +
OMAP24XX_GPIO_LEVELDETECT0) |
__raw_readl(bank->base +
OMAP24XX_GPIO_LEVELDETECT1);
level_mask &= enabled;
} }
/* clear edge sensitive interrupts before handler(s) are /* clear edge sensitive interrupts before handler(s) are
...@@ -1082,14 +1081,6 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) ...@@ -1082,14 +1081,6 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
retrigger |= irq_mask; retrigger |= irq_mask;
} }
} }
if (cpu_class_is_omap2()) {
/* clear level sensitive interrupts after handler(s) */
_enable_gpio_irqbank(bank, isr_saved & level_mask, 0);
_clear_gpio_irqbank(bank, isr_saved & level_mask);
_enable_gpio_irqbank(bank, isr_saved & level_mask, 1);
}
} }
/* if bank has any level sensitive GPIO pin interrupt /* if bank has any level sensitive GPIO pin interrupt
configured, we must unmask the bank interrupt only after configured, we must unmask the bank interrupt only after
...@@ -1128,6 +1119,14 @@ static void gpio_unmask_irq(unsigned int irq) ...@@ -1128,6 +1119,14 @@ static void gpio_unmask_irq(unsigned int irq)
{ {
unsigned int gpio = irq - IH_GPIO_BASE; unsigned int gpio = irq - IH_GPIO_BASE;
struct gpio_bank *bank = get_irq_chip_data(irq); struct gpio_bank *bank = get_irq_chip_data(irq);
unsigned int irq_mask = 1 << get_gpio_index(gpio);
/* For level-triggered GPIOs, the clearing must be done after
* the HW source is cleared, thus after the handler has run */
if (bank->level_mask & irq_mask) {
_set_gpio_irqenable(bank, gpio, 0);
_clear_gpio_irqstatus(bank, gpio);
}
_set_gpio_irqenable(bank, gpio, 1); _set_gpio_irqenable(bank, gpio, 1);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment