Commit 5ff56b01 authored by Rushikesh S Kadam's avatar Rushikesh S Kadam Committed by Linus Walleij

pinctrl: intel: Disable GPIO pin interrupts in suspend

The fix prevents unintended wakes from second level GPIO pin interrupts.

On some Intel Kabylake platforms, it is observed that GPIO pin interrupts
can wake the platform from suspend-to-idle, even though the IRQ is not
configured as IRQF_NO_SUSPEND or enable_irq_wake().

This can cause undesired wakes on Mobile devices such as Laptops and
Chromebook devices. For example a headset jack insertion is not a desired
wake source on Chromebook devices.

The pinctrl-intel (GPIO controller) driver implements a "Shared IRQ" model.
All GPIO pin interrupts are OR'ed and mapped to a first level IRQ14 (or
IRQ15). The driver registers an irq_chip struct and maps an irq_domain for
the GPIO pin interrupts. The IRQ14 handler demuxes and calls the second
level IRQ for the respective pin.

In the suspend entry flow, at suspend_noirq stage, the kernel disables IRQs
that are not marked for wake. The pinctrl-intel driver does not implement a
irq_disable()  callback (to take advantage of lazy disabling). The
pinctrl-intel GPIO interrupts are not disabled in hardware during suspend
entry, and thus are able to wake the SoC out of suspend-to-idle.

This patch sets the IRQCHIP_MASK_ON_SUSPEND flag for the GPIO irq_chip, to
disable the second level interrupts at suspend_noirq stage via the irq_mask
callbacks. The irq_mask callback disables the IRQs in hardware by
programming the corresponding GPIO pad registers. Only IRQs that are not
marked for wake are disabled.
Signed-off-by: default avatarRushikesh S Kadam <rushikesh.s.kadam@intel.com>
Acked-by: default avatarMika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: default avatarAndy Shevchenko <andy.shevchenko@gmail.com>
Reviewed-and-tested-by: default avatarRajneesh Bhardwaj <rajneesh.bhardwaj@intel.com>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent a228d74f
...@@ -1035,6 +1035,7 @@ static struct irq_chip intel_gpio_irqchip = { ...@@ -1035,6 +1035,7 @@ static struct irq_chip intel_gpio_irqchip = {
.irq_unmask = intel_gpio_irq_unmask, .irq_unmask = intel_gpio_irq_unmask,
.irq_set_type = intel_gpio_irq_type, .irq_set_type = intel_gpio_irq_type,
.irq_set_wake = intel_gpio_irq_wake, .irq_set_wake = intel_gpio_irq_wake,
.flags = IRQCHIP_MASK_ON_SUSPEND,
}; };
static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq) static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment