mirror of
https://github.com/torvalds/linux.git
synced 2024-12-18 17:12:55 +00:00
pinctrl: exynos: ack level-triggered interrupts before unmasking
A level-triggered interrupt should be acked after the interrupt line becomes inactive and before it is unmasked, or else another interrupt will be immediately triggered. Acking before or after calling the handler is not enough. Signed-off-by: Luigi Semenzato <semenzato@chromium.org> Signed-off-by: Doug Anderson <dianders@chromium.org> Acked-by: Tomasz Figa <t.figa@samsung.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
parent
b75e60d615
commit
5a68e7a748
@ -84,6 +84,17 @@ static void exynos_gpio_irq_unmask(struct irq_data *irqd)
|
||||
unsigned long mask;
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* Ack level interrupts right before unmask
|
||||
*
|
||||
* If we don't do this we'll get a double-interrupt. Level triggered
|
||||
* interrupts must not fire an interrupt if the level is not
|
||||
* _currently_ active, even if it was active while the interrupt was
|
||||
* masked.
|
||||
*/
|
||||
if (irqd_get_trigger_type(irqd) & IRQ_TYPE_LEVEL_MASK)
|
||||
exynos_gpio_irq_ack(irqd);
|
||||
|
||||
spin_lock_irqsave(&bank->slock, flags);
|
||||
|
||||
mask = readl(d->virt_base + reg_mask);
|
||||
@ -302,6 +313,17 @@ static void exynos_wkup_irq_unmask(struct irq_data *irqd)
|
||||
unsigned long mask;
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* Ack level interrupts right before unmask
|
||||
*
|
||||
* If we don't do this we'll get a double-interrupt. Level triggered
|
||||
* interrupts must not fire an interrupt if the level is not
|
||||
* _currently_ active, even if it was active while the interrupt was
|
||||
* masked.
|
||||
*/
|
||||
if (irqd_get_trigger_type(irqd) & IRQ_TYPE_LEVEL_MASK)
|
||||
exynos_wkup_irq_ack(irqd);
|
||||
|
||||
spin_lock_irqsave(&b->slock, flags);
|
||||
|
||||
mask = readl(d->virt_base + reg_mask);
|
||||
|
Loading…
Reference in New Issue
Block a user