diff options
author | Jonathan Bell <jonathan@raspberrypi.org> | 2015-06-30 07:35:39 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2015-07-20 05:01:52 -0400 |
commit | 714b1dd8f72e39ef4bc0f38f7f341bb1d57d98bf (patch) | |
tree | d60063bd16f3e5d298b84925d26121ecb24aa691 | |
parent | c10372e615b8f790d30cbfcf59e43908ca42bf1a (diff) |
pinctrl: bcm2835: Clear the event latch register when disabling interrupts
It's possible to hit a race condition if interrupts are generated on a GPIO
pin when the IRQ line in question is being disabled.
If the interrupt is freed, bcm2835_gpio_irq_disable() is called which
disables the event generation sources (edge, level). If an event occurred
between the last disabling of hard IRQs and the write to the event
source registers, a bit would be set in the GPIO event detect register
(GPEDSn) which goes unacknowledged by bcm2835_gpio_irq_handler()
so Linux complains loudly.
There is no per-GPIO mask register, so when disabling GPIO interrupts
write 1 to the relevant bit in GPEDSn to clear out any stale events.
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
Acked-by: Stephen Warren <swarren@wwwdotorg.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r-- | drivers/pinctrl/bcm/pinctrl-bcm2835.c | 2 |
1 files changed, 2 insertions, 0 deletions
diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c index efcf2a2b3975..6177315ab74e 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c | |||
@@ -473,6 +473,8 @@ static void bcm2835_gpio_irq_disable(struct irq_data *data) | |||
473 | 473 | ||
474 | spin_lock_irqsave(&pc->irq_lock[bank], flags); | 474 | spin_lock_irqsave(&pc->irq_lock[bank], flags); |
475 | bcm2835_gpio_irq_config(pc, gpio, false); | 475 | bcm2835_gpio_irq_config(pc, gpio, false); |
476 | /* Clear events that were latched prior to clearing event sources */ | ||
477 | bcm2835_gpio_set_bit(pc, GPEDS0, gpio); | ||
476 | clear_bit(offset, &pc->enabled_irq_map[bank]); | 478 | clear_bit(offset, &pc->enabled_irq_map[bank]); |
477 | spin_unlock_irqrestore(&pc->irq_lock[bank], flags); | 479 | spin_unlock_irqrestore(&pc->irq_lock[bank], flags); |
478 | } | 480 | } |