summaryrefslogtreecommitdiff
path: root/drivers/gpio
diff options
context:
space:
mode:
authorBai Ping <ping.bai@nxp.com>2018-11-09 17:11:52 +0800
committerJason Liu <jason.hui.liu@nxp.com>2019-02-12 10:35:22 +0800
commit20c3781a7fb9d8fa994b96b31c821e2f6312dd9b (patch)
treecf791b46654cf4160c0a5f572fa1c8a08db794aa /drivers/gpio
parent150d1ac2ef36d871103ce4ea9e33e1c595841f47 (diff)
MLK-20306 gpio: mxc: Skip GPIO_IMR restore in noirq resume
During the time window of noirq suspend and noirq resume, if a GPIO pin is enabled as system wakeup source, the corresponding GPIO line's IRQ will be unmasked, and GPIO bank will NOT lost power, when GPIO irq arrives, generic irq handler will mask it until GPIO driver is ready to handle it, but in GPIO noirq resume callback, current implementation will restore the IMR register using the value saved in previous noirq suspend callback which is unmasked, so this GPIO line with IRQ pending will be unmasked again after GPIO IMR regitster is restored, ARM will be triggered to handle this IRQ again, because of the change of commit bf22ff45bed6 ("genirq: Avoid unnecessary low level irq function calls"), the mask_irq function will check the status of irq_data to decide whether to mask the irq, in this scenario, since the GPIO IRQ is being masked before GPIO noirq resume, IRQD_IRQ_MASKED flag is set, so the second time GPIO IRQ triggered by restoring GPIO IMR register, the irq_mask callback will be skipped and cause ARM busy handling the GPIO IRQ come all the way and no response to user anymore. Signed-off-by: Bai Ping <ping.bai@nxp.com> Reviewed-by: Anson Huang <Anson.Huang@nxp.com>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/gpio-mxc.c2
1 files changed, 0 insertions, 2 deletions
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index d63064f10c0c..10d189072dd3 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -794,7 +794,6 @@ static int __maybe_unused mxc_gpio_noirq_suspend(struct device *dev)
spin_lock_irqsave(&port->gc.bgpio_lock, flags);
port->suspend_saved_reg[0] = readl(port->base + GPIO_ICR1);
port->suspend_saved_reg[1] = readl(port->base + GPIO_ICR2);
- port->suspend_saved_reg[2] = readl(port->base + GPIO_IMR);
port->suspend_saved_reg[3] = readl(port->base + GPIO_GDIR);
port->suspend_saved_reg[4] = readl(port->base + GPIO_EDGE_SEL);
port->suspend_saved_reg[5] = readl(port->base + GPIO_DR);
@@ -827,7 +826,6 @@ static int __maybe_unused mxc_gpio_noirq_resume(struct device *dev)
spin_lock_irqsave(&port->gc.bgpio_lock, flags);
writel(port->suspend_saved_reg[0], port->base + GPIO_ICR1);
writel(port->suspend_saved_reg[1], port->base + GPIO_ICR2);
- writel(port->suspend_saved_reg[2], port->base + GPIO_IMR);
writel(port->suspend_saved_reg[3], port->base + GPIO_GDIR);
writel(port->suspend_saved_reg[4], port->base + GPIO_EDGE_SEL);
writel(port->suspend_saved_reg[5], port->base + GPIO_DR);