1
0
Fork 0

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 bf22ff45be ("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>
(cherry picked from commit c03d9ec1f861ff7cd04637ef01aa7e14388277b6)
pull/10/head
Bai Ping 2018-11-09 17:11:52 +08:00
parent 3a30144862
commit cf3ac97055
1 changed files with 0 additions and 2 deletions

View File

@ -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);