gpio: omap: Block idle on pending gpio interrupts
authorTony Lindgren <tony@atomide.com>
Wed, 4 Mar 2020 22:54:31 +0000 (14:54 -0800)
committerLinus Walleij <linus.walleij@linaro.org>
Mon, 9 Mar 2020 09:24:23 +0000 (10:24 +0100)
With the SoC cpuidle handling fixed for cpu_pm, we can now start to
return NOTIFY_BAD if there there are pending gpio interrupts.

This way the deeper SoC idle states can get blocked, and gpio latency
is improved in some cases. Note that this will not help with the
latency if the SoC has already entered a deeper idle state.

Note that this patch depends on cpu_pm properly handling the errors
returned by notifiers. For omap variants, this is fixed with patch
"ARM: OMAP2+: Handle errors for cpu_pm".

Cc: Dave Gerlach <d-gerlach@ti.com>
Cc: Grygorii Strashko <grygorii.strashko@ti.com>
Cc: Keerthy <j-keerthy@ti.com>
Cc: Ladislav Michl <ladis@linux-mips.org>
Cc: Russell King <rmk+kernel@armlinux.org.uk>
Cc: Tero Kristo <t-kristo@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Link: https://lore.kernel.org/r/20200304225433.37336-3-tony@atomide.com
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
drivers/gpio/gpio-omap.c

index 3bd8ada..3d50cb2 100644 (file)
@@ -1237,26 +1237,35 @@ static int gpio_omap_cpu_notifier(struct notifier_block *nb,
 {
        struct gpio_bank *bank;
        unsigned long flags;
+       int ret = NOTIFY_OK;
+       u32 isr, mask;
 
        bank = container_of(nb, struct gpio_bank, nb);
 
        raw_spin_lock_irqsave(&bank->lock, flags);
+       if (bank->is_suspended)
+               goto out_unlock;
+
        switch (cmd) {
        case CPU_CLUSTER_PM_ENTER:
-               if (bank->is_suspended)
+               mask = omap_get_gpio_irqbank_mask(bank);
+               isr = readl_relaxed(bank->base + bank->regs->irqstatus) & mask;
+               if (isr) {
+                       ret = NOTIFY_BAD;
                        break;
+               }
                omap_gpio_idle(bank, true);
                break;
        case CPU_CLUSTER_PM_ENTER_FAILED:
        case CPU_CLUSTER_PM_EXIT:
-               if (bank->is_suspended)
-                       break;
                omap_gpio_unidle(bank);
                break;
        }
+
+out_unlock:
        raw_spin_unlock_irqrestore(&bank->lock, flags);
 
-       return NOTIFY_OK;
+       return ret;
 }
 
 static const struct omap_gpio_reg_offs omap2_gpio_regs = {