Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gpio: omap: fix irq triggering in smart-idle wakeup mode

Now GPIO IRQ loss is observed on dra7-evm after suspend/resume cycle
in the following case:
extcon_usb1(id_irq) -> pcf8575.gpio1 -> omapgpio6.gpio11 -> gic

the extcon_usb1 is wake up source and it enables IRQ wake up for
id_irq by calling enable/disable_irq_wake() during suspend/resume
which, in turn, causes execution of omap_gpio_wake_enable(). And
omap_gpio_wake_enable() will set/clear corresponding bit in
GPIO_IRQWAKEN_x register.

omapgpio6 configuration after boot - wakeup is enabled for GPIO IRQs
by default from omap_gpio_irq_type:
GPIO_IRQSTATUS_SET_0 | 0x00000400
GPIO_IRQSTATUS_CLR_0 | 0x00000400
GPIO_IRQWAKEN_0 | 0x00000400
GPIO_RISINGDETECT | 0x00000000
GPIO_FALLINGDETECT | 0x00000400

omapgpio6 configuration after after suspend/resume cycle:
GPIO_IRQSTATUS_SET_0 | 0x00000400
GPIO_IRQSTATUS_CLR_0 | 0x00000400
GPIO_IRQWAKEN_0 | 0x00000000 <---
GPIO_RISINGDETECT | 0x00000000
GPIO_FALLINGDETECT | 0x00000400

As result, system will start to lose interrupts from pcf8575 GPIO
expander, because when OMAP GPIO IP is in smart-idle wakeup mode, there
is no guarantee that transition(s) on input non wake up GPIO pin will
trigger asynchronous wake-up request to PRCM and then IRQ generation.
IRQ will be generated when GPIO is in active mode - for example, some
time after accessing GPIO bank registers IRQs will be generated
normally, but issue will happen again once PRCM will put GPIO in low
power smart-idle wakeup mode.

Note 1. Issue is not reproduced if debounce clk is enabled for GPIO
bank.

Note 2. Issue hardly reproducible if GPIO pins group contains both
wakeup/non-wakeup gpios - for example, it will be hard to reproduce
issue with pin2 if GPIO_IRQWAKEN_0=0x1 GPIO_IRQSTATUS_SET_0=0x3
GPIO_FALLINGDETECT = 0x3 (TRM "Power Saving by Grouping the Edge/Level
Detection").

Note 3. There nothing common bitween System wake up and OMAP GPIO bank
IP wake up logic - the last one defines how the GPIO bank ON-IDLE-ON
transition will happen inside SoC under control of PRCM.

Hence, fix the problem by removing omap_set_gpio_wakeup() function
completely and so keeping always in sync GPIO IRQ mask/unmask
(IRQSTATUS_SET) and wake up enable (GPIO_IRQWAKEN) bits; and adding
IRQCHIP_MASK_ON_SUSPEND flag in OMAP GPIO irqchip. That way non wakeup
GPIO IRQs will be properly masked/unmask by IRQ PM core during
suspend/resume cycle.

Cc: Roger Quadros <rogerq@ti.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Acked-by: Tony Lindgren <tony@atomide.com>
Acked-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

authored by

Grygorii Strashko and committed by
Linus Walleij
0c0451e7 f7cb5120

+2 -40
+2 -40
drivers/gpio/gpio-omap.c
··· 611 611 omap_disable_gpio_irqbank(bank, BIT(offset)); 612 612 } 613 613 614 - /* 615 - * Note that ENAWAKEUP needs to be enabled in GPIO_SYSCONFIG register. 616 - * 1510 does not seem to have a wake-up register. If JTAG is connected 617 - * to the target, system will wake up always on GPIO events. While 618 - * system is running all registered GPIO interrupts need to have wake-up 619 - * enabled. When system is suspended, only selected GPIO interrupts need 620 - * to have wake-up enabled. 621 - */ 622 - static int omap_set_gpio_wakeup(struct gpio_bank *bank, unsigned offset, 623 - int enable) 624 - { 625 - u32 gpio_bit = BIT(offset); 626 - unsigned long flags; 627 - 628 - if (bank->non_wakeup_gpios & gpio_bit) { 629 - dev_err(bank->chip.parent, 630 - "Unable to modify wakeup on non-wakeup GPIO%d\n", 631 - offset); 632 - return -EINVAL; 633 - } 634 - 635 - raw_spin_lock_irqsave(&bank->lock, flags); 636 - if (enable) 637 - bank->context.wake_en |= gpio_bit; 638 - else 639 - bank->context.wake_en &= ~gpio_bit; 640 - 641 - writel_relaxed(bank->context.wake_en, bank->base + bank->regs->wkup_en); 642 - raw_spin_unlock_irqrestore(&bank->lock, flags); 643 - 644 - return 0; 645 - } 646 - 647 614 /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */ 648 615 static int omap_gpio_wake_enable(struct irq_data *d, unsigned int enable) 649 616 { 650 617 struct gpio_bank *bank = omap_irq_data_get_bank(d); 651 - unsigned offset = d->hwirq; 652 - int ret; 653 618 654 - ret = omap_set_gpio_wakeup(bank, offset, enable); 655 - if (!ret) 656 - ret = irq_set_irq_wake(bank->irq, enable); 657 - 658 - return ret; 619 + return irq_set_irq_wake(bank->irq, enable); 659 620 } 660 621 661 622 static int omap_gpio_request(struct gpio_chip *chip, unsigned offset) ··· 1148 1187 irqc->irq_bus_lock = omap_gpio_irq_bus_lock, 1149 1188 irqc->irq_bus_sync_unlock = gpio_irq_bus_sync_unlock, 1150 1189 irqc->name = dev_name(&pdev->dev); 1190 + irqc->flags = IRQCHIP_MASK_ON_SUSPEND; 1151 1191 1152 1192 bank->irq = platform_get_irq(pdev, 0); 1153 1193 if (bank->irq <= 0) {