summaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpio-omap.c
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2020-03-04 14:54:31 -0800
committerLinus Walleij <linus.walleij@linaro.org>2020-03-09 10:24:23 +0100
commit43582265be8c5c29f4f420ce08a29d48f560c86e (patch)
tree9ef0170d001afabe66a0285f5af25410a72b7c0d /drivers/gpio/gpio-omap.c
parent55be2f50336f67800513b46c5ba6270e4ed0e784 (diff)
downloadlinux-43582265be8c5c29f4f420ce08a29d48f560c86e.tar.gz
linux-43582265be8c5c29f4f420ce08a29d48f560c86e.tar.bz2
linux-43582265be8c5c29f4f420ce08a29d48f560c86e.zip
gpio: omap: Block idle on pending gpio interrupts
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>
Diffstat (limited to 'drivers/gpio/gpio-omap.c')
-rw-r--r--drivers/gpio/gpio-omap.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index 3bd8adaeed9e..3d50cb25aa24 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -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 = {