summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@armlinux.org.uk>2019-06-10 20:10:44 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-07-26 09:14:06 +0200
commit544cd592ca72785c4a9132536b715de8ad6242b3 (patch)
treeae90fe21080da1a9106c906d6a2ad5cee24fa5e3 /drivers
parentddeef7a00050bcd9ff285a3c20709cbea9132c04 (diff)
downloadlinux-stable-544cd592ca72785c4a9132536b715de8ad6242b3.tar.gz
linux-stable-544cd592ca72785c4a9132536b715de8ad6242b3.tar.bz2
linux-stable-544cd592ca72785c4a9132536b715de8ad6242b3.zip
gpio: omap: ensure irq is enabled before wakeup
[ Upstream commit c859e0d479b3b4f6132fc12637c51e01492f31f6 ] Documentation states: NOTE: There must be a correlation between the wake-up enable and interrupt-enable registers. If a GPIO pin has a wake-up configured on it, it must also have the corresponding interrupt enabled (on one of the two interrupt lines). Ensure that this condition is always satisfied by enabling the detection events after enabling the interrupt, and disabling the detection before disabling the interrupt. This ensures interrupt/wakeup events can not happen until both the wakeup and interrupt enables correlate. If we do any clearing, clear between the interrupt enable/disable and trigger setting. Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com> Tested-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpio/gpio-omap.c15
1 files changed, 8 insertions, 7 deletions
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index 9254bcf7f647..feabac40743e 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -837,9 +837,9 @@ static void omap_gpio_irq_shutdown(struct irq_data *d)
raw_spin_lock_irqsave(&bank->lock, flags);
bank->irq_usage &= ~(BIT(offset));
- omap_set_gpio_irqenable(bank, offset, 0);
- omap_clear_gpio_irqstatus(bank, offset);
omap_set_gpio_triggering(bank, offset, IRQ_TYPE_NONE);
+ omap_clear_gpio_irqstatus(bank, offset);
+ omap_set_gpio_irqenable(bank, offset, 0);
if (!LINE_USED(bank->mod_usage, offset))
omap_clear_gpio_debounce(bank, offset);
omap_disable_gpio_module(bank, offset);
@@ -881,8 +881,8 @@ static void omap_gpio_mask_irq(struct irq_data *d)
unsigned long flags;
raw_spin_lock_irqsave(&bank->lock, flags);
- omap_set_gpio_irqenable(bank, offset, 0);
omap_set_gpio_triggering(bank, offset, IRQ_TYPE_NONE);
+ omap_set_gpio_irqenable(bank, offset, 0);
raw_spin_unlock_irqrestore(&bank->lock, flags);
}
@@ -894,9 +894,6 @@ static void omap_gpio_unmask_irq(struct irq_data *d)
unsigned long flags;
raw_spin_lock_irqsave(&bank->lock, flags);
- if (trigger)
- omap_set_gpio_triggering(bank, offset, trigger);
-
omap_set_gpio_irqenable(bank, offset, 1);
/*
@@ -904,9 +901,13 @@ static void omap_gpio_unmask_irq(struct irq_data *d)
* is cleared, thus after the handler has run. OMAP4 needs this done
* after enabing the interrupt to clear the wakeup status.
*/
- if (bank->level_mask & BIT(offset))
+ if (bank->regs->leveldetect0 && bank->regs->wkup_en &&
+ trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
omap_clear_gpio_irqstatus(bank, offset);
+ if (trigger)
+ omap_set_gpio_triggering(bank, offset, trigger);
+
raw_spin_unlock_irqrestore(&bank->lock, flags);
}