Commit 00ded24c authored by Tony Lindgren's avatar Tony Lindgren Committed by Linus Walleij

gpio: gpio-omap: Revert deferred wakeup quirk handling for regressions

Commit ec0daae6 ("gpio: omap: Add level wakeup handling for omap4
based SoCs") attempted to fix omap4 GPIO wakeup handling as it was
blocking deeper SoC idle states. However this caused a regression for
GPIOs during runtime having over second long latencies for Ethernet
GPIO interrupt as reportedy by Russell King <>.

Let's fix this issue by doing a partial revert of the breaking commit.
We still want to keep the quirk handling around as it is also used for

The real fix for omap4 GPIO wakeup handling involves fixes for
omap_set_gpio_trigger() and omap_gpio_unmask_irq() and will be posted
separately. And we must keep the wakeup bit enabled during runtime
because of module doing clock autogating with autoidle configured.
Reported-by: default avatarRussell King <>
Fixes: ec0daae6 ("gpio: omap: Add level wakeup handling for omap4
based SoCs")
Cc: Aaro Koskinen <>
Cc: Grygorii Strashko <>
Cc: Keerthy <>
Cc: Ladislav Michl <>
Cc: Russell King <>
Cc: Tero Kristo <>
Signed-off-by: default avatarTony Lindgren <>
Signed-off-by: default avatarLinus Walleij <>
parent e59f5e08
......@@ -32,7 +32,6 @@
struct gpio_regs {
u32 irqenable1;
......@@ -379,18 +378,9 @@ static inline void omap_set_gpio_trigger(struct gpio_bank *bank, int gpio,
readl_relaxed(bank->base + bank->regs->fallingdetect);
if (likely(!(bank->non_wakeup_gpios & gpio_bit))) {
/* Defer wkup_en register update until we idle? */
if (bank->quirks & OMAP_GPIO_QUIRK_DEFERRED_WKUP_EN) {
if (trigger)
bank->context.wake_en |= gpio_bit;
bank->context.wake_en &= ~gpio_bit;
} else {
omap_gpio_rmw(base, bank->regs->wkup_en, gpio_bit,
trigger != 0);
bank->context.wake_en =
readl_relaxed(bank->base + bank->regs->wkup_en);
omap_gpio_rmw(base, bank->regs->wkup_en, gpio_bit, trigger != 0);
bank->context.wake_en =
readl_relaxed(bank->base + bank->regs->wkup_en);
/* This part needs to be executed always for OMAP{34xx, 44xx} */
......@@ -942,44 +932,6 @@ omap2_gpio_disable_level_quirk(struct gpio_bank *bank)
bank->base + bank->regs->risingdetect);
* On omap4 and later SoC variants a level interrupt with wkup_en
* enabled blocks the GPIO functional clock from idling until the GPIO
* instance has been reset. To avoid that, we must set wkup_en only for
* idle for level interrupts, and clear level registers for the duration
* of idle. The level interrupts will be still there on wakeup by their
* nature.
static void __maybe_unused
omap4_gpio_enable_level_quirk(struct gpio_bank *bank)
/* Update wake register for idle, edge bits might be already set */
bank->base + bank->regs->wkup_en);
/* Clear level registers for idle */
writel_relaxed(0, bank->base + bank->regs->leveldetect0);
writel_relaxed(0, bank->base + bank->regs->leveldetect1);
static void __maybe_unused
omap4_gpio_disable_level_quirk(struct gpio_bank *bank)
/* Restore level registers after idle */
bank->base + bank->regs->leveldetect0);
bank->base + bank->regs->leveldetect1);
/* Clear saved wkup_en for level, it will be set for next idle again */
bank->context.wake_en &= ~(bank->context.leveldetect0 |
/* Update wake with only edge configuration */
bank->base + bank->regs->wkup_en);
static int omap_mpuio_suspend_noirq(struct device *dev)
......@@ -1412,12 +1364,7 @@ static int omap_gpio_probe(struct platform_device *pdev)
if (bank->quirks & OMAP_GPIO_QUIRK_DEFERRED_WKUP_EN) {
bank->funcs.idle_enable_level_quirk =
bank->funcs.idle_disable_level_quirk =
} else if (bank->quirks & OMAP_GPIO_QUIRK_IDLE_REMOVE_TRIGGER) {
bank->funcs.idle_enable_level_quirk =
bank->funcs.idle_disable_level_quirk =
......@@ -1806,8 +1753,7 @@ static const struct omap_gpio_platform_data omap4_pdata = {
.regs = &omap4_gpio_regs,
.bank_width = 32,
.dbck_flag = true,
static const struct of_device_id omap_gpio_match[] = {
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