aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl/bcm/pinctrl-bcm2835.c
diff options
context:
space:
mode:
authorJonathan Bell <jonathan@raspberrypi.org>2015-06-30 12:35:39 +0100
committerLinus Walleij <linus.walleij@linaro.org>2015-07-20 11:01:52 +0200
commit714b1dd8f72e39ef4bc0f38f7f341bb1d57d98bf (patch)
treed60063bd16f3e5d298b84925d26121ecb24aa691 /drivers/pinctrl/bcm/pinctrl-bcm2835.c
parentpinctrl: single: ensure pcs irq will not be forced threaded (diff)
downloadlinux-dev-714b1dd8f72e39ef4bc0f38f7f341bb1d57d98bf.tar.xz
linux-dev-714b1dd8f72e39ef4bc0f38f7f341bb1d57d98bf.zip
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>
Diffstat (limited to 'drivers/pinctrl/bcm/pinctrl-bcm2835.c')
-rw-r--r--drivers/pinctrl/bcm/pinctrl-bcm2835.c2
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)
spin_lock_irqsave(&pc->irq_lock[bank], flags);
bcm2835_gpio_irq_config(pc, gpio, false);
+ /* Clear events that were latched prior to clearing event sources */
+ bcm2835_gpio_set_bit(pc, GPEDS0, gpio);
clear_bit(offset, &pc->enabled_irq_map[bank]);
spin_unlock_irqrestore(&pc->irq_lock[bank], flags);
}