diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-10-23 08:45:05 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-10-23 08:45:05 +0100 |
commit | 114b5f8f7efc036dd7dd16efb0f218a88e6c6c02 (patch) | |
tree | ac02a222661b8b0bfb87f15773dc1d23220edfd9 /drivers/gpio/gpio-omap.c | |
parent | b0b6a28bc4b265aa56cbf4fa8fd27c0a4fa3a49c (diff) | |
parent | 40f5ff4f9f23a849ad135cb736d4d448d810ac17 (diff) |
Merge tag 'gpio-v4.20-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio
Pull GPIO updates from Linus Walleij:
"This is the bulk of GPIO changes for the v4.20 series:
Core changes:
- A patch series from Hans Verkuil to make it possible to
enable/disable IRQs on a GPIO line at runtime and drive GPIO lines
as output without having to put/get them from scratch.
The irqchip callbacks have been improved so that they can use only
the fastpatch callbacks to enable/disable irqs like any normal
irqchip, especially the gpiod_lock_as_irq() has been improved to be
callable in fastpath context.
A bunch of rework had to be done to achieve this but it is a big
win since I never liked to restrict this to slowpath. The only call
requireing slowpath was try_module_get() and this is kept at the
.request_resources() slowpath callback. In the GPIO CEC driver this
is a big win sine a single line is used for both outgoing and
incoming traffic, and this needs to use IRQs for incoming traffic
while actively driving the line for outgoing traffic.
- Janusz Krzysztofik improved the GPIO array API to pass a "cookie"
(struct gpio_array) and a bitmap for setting or getting multiple
GPIO lines at once.
This improvement orginated in a specific need to speed up an OMAP1
driver and has led to a much better API and real performance gains
when the state of the array can be used to bypass a lot of checks
and code when we want things to go really fast.
The previous code would minimize the number of calls down to the
driver callbacks assuming the CPU speed was orders of magnitude
faster than the I/O latency, but this assumption was wrong on
several platforms: what we needed to do was to profile and improve
the speed on the hot path of the array functions and this change is
now completed.
- Clean out the painful and hard to grasp BNF experiments from the
device tree bindings. Future approaches are looking into using JSON
schema for this purpose. (Rob Herring is floating a patch series.)
New drivers:
- The RCAR driver now supports r8a774a1 (RZ/G2M).
- Synopsys GPIO via CREGs driver.
Major improvements:
- Modernization of the EP93xx driver to use irqdomain and other
contemporary concepts.
- The ingenic driver has been merged into the Ingenic pin control
driver and removed from the GPIO subsystem.
- Debounce support in the ftgpio010 driver"
* tag 'gpio-v4.20-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (116 commits)
gpio: Clarify kerneldoc on gpiochip_set_chained_irqchip()
gpio: Remove unused 'irqchip' argument to gpiochip_set_cascaded_irqchip()
gpio: Drop parent irq assignment during cascade setup
mmc: pwrseq_simple: Fix incorrect handling of GPIO bitmap
gpio: fix SNPS_CREG kconfig dependency warning
gpiolib: Initialize gdev field before is used
gpio: fix kernel-doc after devres.c file rename
gpio: fix doc string for devm_gpiochip_add_data() to not talk about irq_chip
gpio: syscon: Fix possible NULL ptr usage
gpiolib: Show correct direction from the beginning
pinctrl: msm: Use init_valid_mask exported function
gpiolib: Add init_valid_mask exported function
GPIO: add single-register GPIO via CREG driver
dt-bindings: Document the Synopsys GPIO via CREG bindings
gpio: mockup: use device properties instead of platform_data
gpio: Slightly more helpful debugfs
gpio: omap: Remove set but not used variable 'dev'
gpio: omap: drop omap_gpio_list
Accept partial 'gpio-line-names' property.
gpio: omap: get rid of the conditional PM runtime calls
...
Diffstat (limited to 'drivers/gpio/gpio-omap.c')
-rw-r--r-- | drivers/gpio/gpio-omap.c | 356 |
1 files changed, 229 insertions, 127 deletions
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index e81008678a38..9887c3db6e16 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -19,6 +19,7 @@ #include <linux/err.h> #include <linux/clk.h> #include <linux/io.h> +#include <linux/cpu_pm.h> #include <linux/device.h> #include <linux/pm_runtime.h> #include <linux/pm.h> @@ -28,10 +29,10 @@ #include <linux/bitops.h> #include <linux/platform_data/gpio-omap.h> -#define OFF_MODE 1 #define OMAP4_GPIO_DEBOUNCINGTIME_MASK 0xFF -static LIST_HEAD(omap_gpio_list); +#define OMAP_GPIO_QUIRK_IDLE_REMOVE_TRIGGER BIT(2) +#define OMAP_GPIO_QUIRK_DEFERRED_WKUP_EN BIT(1) struct gpio_regs { u32 irqenable1; @@ -48,6 +49,13 @@ struct gpio_regs { u32 debounce_en; }; +struct gpio_bank; + +struct gpio_omap_funcs { + void (*idle_enable_level_quirk)(struct gpio_bank *bank); + void (*idle_disable_level_quirk)(struct gpio_bank *bank); +}; + struct gpio_bank { struct list_head node; void __iomem *base; @@ -55,6 +63,7 @@ struct gpio_bank { u32 non_wakeup_gpios; u32 enabled_non_wakeup_gpios; struct gpio_regs context; + struct gpio_omap_funcs funcs; u32 saved_datain; u32 level_mask; u32 toggle_mask; @@ -62,6 +71,8 @@ struct gpio_bank { raw_spinlock_t wa_lock; struct gpio_chip chip; struct clk *dbck; + struct notifier_block nb; + unsigned int is_suspended:1; u32 mod_usage; u32 irq_usage; u32 dbck_enable_mask; @@ -73,8 +84,8 @@ struct gpio_bank { int stride; u32 width; int context_loss_count; - int power_mode; bool workaround_enabled; + u32 quirks; void (*set_dataout)(struct gpio_bank *bank, unsigned gpio, int enable); void (*set_dataout_multiple)(struct gpio_bank *bank, @@ -368,9 +379,18 @@ 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))) { - omap_gpio_rmw(base, bank->regs->wkup_en, gpio_bit, trigger != 0); - bank->context.wake_en = - readl_relaxed(bank->base + bank->regs->wkup_en); + /* 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; + else + 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); + } } /* This part needs to be executed always for OMAP{34xx, 44xx} */ @@ -682,12 +702,7 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset) struct gpio_bank *bank = gpiochip_get_data(chip); unsigned long flags; - /* - * If this is the first gpio_request for the bank, - * enable the bank module. - */ - if (!BANK_USED(bank)) - pm_runtime_get_sync(chip->parent); + pm_runtime_get_sync(chip->parent); raw_spin_lock_irqsave(&bank->lock, flags); omap_enable_gpio_module(bank, offset); @@ -711,12 +726,7 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset) omap_disable_gpio_module(bank, offset); raw_spin_unlock_irqrestore(&bank->lock, flags); - /* - * If this is the last gpio to be freed in the bank, - * disable the bank module. - */ - if (!BANK_USED(bank)) - pm_runtime_put(chip->parent); + pm_runtime_put(chip->parent); } /* @@ -741,7 +751,9 @@ static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank) if (WARN_ON(!isr_reg)) goto exit; - pm_runtime_get_sync(bank->chip.parent); + if (WARN_ONCE(!pm_runtime_active(bank->chip.parent), + "gpio irq%i while runtime suspended?\n", irq)) + return IRQ_NONE; while (1) { raw_spin_lock_irqsave(&bank->lock, lock_flags); @@ -792,7 +804,6 @@ static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank) } } exit: - pm_runtime_put(bank->chip.parent); return IRQ_HANDLED; } @@ -841,20 +852,14 @@ static void omap_gpio_irq_bus_lock(struct irq_data *data) { struct gpio_bank *bank = omap_irq_data_get_bank(data); - if (!BANK_USED(bank)) - pm_runtime_get_sync(bank->chip.parent); + pm_runtime_get_sync(bank->chip.parent); } static void gpio_irq_bus_sync_unlock(struct irq_data *data) { struct gpio_bank *bank = omap_irq_data_get_bank(data); - /* - * If this is the last IRQ to be freed in the bank, - * disable the bank module. - */ - if (!BANK_USED(bank)) - pm_runtime_put(bank->chip.parent); + pm_runtime_put(bank->chip.parent); } static void omap_gpio_ack_irq(struct irq_data *d) @@ -899,6 +904,82 @@ static void omap_gpio_unmask_irq(struct irq_data *d) raw_spin_unlock_irqrestore(&bank->lock, flags); } +/* + * Only edges can generate a wakeup event to the PRCM. + * + * Therefore, ensure any wake-up capable GPIOs have + * edge-detection enabled before going idle to ensure a wakeup + * to the PRCM is generated on a GPIO transition. (c.f. 34xx + * NDA TRM 25.5.3.1) + * + * The normal values will be restored upon ->runtime_resume() + * by writing back the values saved in bank->context. + */ +static void __maybe_unused +omap2_gpio_enable_level_quirk(struct gpio_bank *bank) +{ + u32 wake_low, wake_hi; + + /* Enable additional edge detection for level gpios for idle */ + wake_low = bank->context.leveldetect0 & bank->context.wake_en; + if (wake_low) + writel_relaxed(wake_low | bank->context.fallingdetect, + bank->base + bank->regs->fallingdetect); + + wake_hi = bank->context.leveldetect1 & bank->context.wake_en; + if (wake_hi) + writel_relaxed(wake_hi | bank->context.risingdetect, + bank->base + bank->regs->risingdetect); +} + +static void __maybe_unused +omap2_gpio_disable_level_quirk(struct gpio_bank *bank) +{ + /* Disable edge detection for level gpios after idle */ + writel_relaxed(bank->context.fallingdetect, + bank->base + bank->regs->fallingdetect); + writel_relaxed(bank->context.risingdetect, + 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 */ + writel_relaxed(bank->context.wake_en, + 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 */ + writel_relaxed(bank->context.leveldetect0, + bank->base + bank->regs->leveldetect0); + writel_relaxed(bank->context.leveldetect1, + 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 | + bank->context.leveldetect1); + + /* Update wake with only edge configuration */ + writel_relaxed(bank->context.wake_en, + bank->base + bank->regs->wkup_en); +} + /*---------------------------------------------------------------------*/ static int omap_mpuio_suspend_noirq(struct device *dev) @@ -1218,6 +1299,36 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc) return ret; } +static void omap_gpio_idle(struct gpio_bank *bank, bool may_lose_context); +static void omap_gpio_unidle(struct gpio_bank *bank); + +static int gpio_omap_cpu_notifier(struct notifier_block *nb, + unsigned long cmd, void *v) +{ + struct gpio_bank *bank; + unsigned long flags; + + bank = container_of(nb, struct gpio_bank, nb); + + raw_spin_lock_irqsave(&bank->lock, flags); + switch (cmd) { + case CPU_CLUSTER_PM_ENTER: + if (bank->is_suspended) + 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; + } + raw_spin_unlock_irqrestore(&bank->lock, flags); + + return NOTIFY_OK; +} + static const struct of_device_id omap_gpio_match[]; static int omap_gpio_probe(struct platform_device *pdev) @@ -1256,6 +1367,7 @@ static int omap_gpio_probe(struct platform_device *pdev) irqc->irq_bus_sync_unlock = gpio_irq_bus_sync_unlock, irqc->name = dev_name(&pdev->dev); irqc->flags = IRQCHIP_MASK_ON_SUSPEND; + irqc->parent_device = dev; bank->irq = platform_get_irq(pdev, 0); if (bank->irq <= 0) { @@ -1270,6 +1382,7 @@ static int omap_gpio_probe(struct platform_device *pdev) bank->chip.parent = dev; bank->chip.owner = THIS_MODULE; bank->dbck_flag = pdata->dbck_flag; + bank->quirks = pdata->quirks; bank->stride = pdata->bank_stride; bank->width = pdata->bank_width; bank->is_mpuio = pdata->is_mpuio; @@ -1278,6 +1391,7 @@ static int omap_gpio_probe(struct platform_device *pdev) #ifdef CONFIG_OF_GPIO bank->chip.of_node = of_node_get(node); #endif + if (node) { if (!of_property_read_bool(node, "ti,gpio-always-on")) bank->loses_context = true; @@ -1298,6 +1412,18 @@ static int omap_gpio_probe(struct platform_device *pdev) omap_set_gpio_dataout_mask_multiple; } + if (bank->quirks & OMAP_GPIO_QUIRK_DEFERRED_WKUP_EN) { + bank->funcs.idle_enable_level_quirk = + omap4_gpio_enable_level_quirk; + bank->funcs.idle_disable_level_quirk = + omap4_gpio_disable_level_quirk; + } else if (bank->quirks & OMAP_GPIO_QUIRK_IDLE_REMOVE_TRIGGER) { + bank->funcs.idle_enable_level_quirk = + omap2_gpio_enable_level_quirk; + bank->funcs.idle_disable_level_quirk = + omap2_gpio_disable_level_quirk; + } + raw_spin_lock_init(&bank->lock); raw_spin_lock_init(&bank->wa_lock); @@ -1322,7 +1448,6 @@ static int omap_gpio_probe(struct platform_device *pdev) platform_set_drvdata(pdev, bank); pm_runtime_enable(dev); - pm_runtime_irq_safe(dev); pm_runtime_get_sync(dev); if (bank->is_mpuio) @@ -1341,9 +1466,13 @@ static int omap_gpio_probe(struct platform_device *pdev) omap_gpio_show_rev(bank); - pm_runtime_put(dev); + if (bank->funcs.idle_enable_level_quirk && + bank->funcs.idle_disable_level_quirk) { + bank->nb.notifier_call = gpio_omap_cpu_notifier; + cpu_pm_register_notifier(&bank->nb); + } - list_add_tail(&bank->node, &omap_gpio_list); + pm_runtime_put(dev); return 0; } @@ -1352,6 +1481,8 @@ static int omap_gpio_remove(struct platform_device *pdev) { struct gpio_bank *bank = platform_get_drvdata(pdev); + if (bank->nb.notifier_call) + cpu_pm_unregister_notifier(&bank->nb); list_del(&bank->node); gpiochip_remove(&bank->chip); pm_runtime_disable(&pdev->dev); @@ -1361,48 +1492,22 @@ static int omap_gpio_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_ARCH_OMAP2PLUS - -#if defined(CONFIG_PM) static void omap_gpio_restore_context(struct gpio_bank *bank); -static int omap_gpio_runtime_suspend(struct device *dev) +static void omap_gpio_idle(struct gpio_bank *bank, bool may_lose_context) { - struct platform_device *pdev = to_platform_device(dev); - struct gpio_bank *bank = platform_get_drvdata(pdev); + struct device *dev = bank->chip.parent; u32 l1 = 0, l2 = 0; - unsigned long flags; - u32 wake_low, wake_hi; - raw_spin_lock_irqsave(&bank->lock, flags); - - /* - * Only edges can generate a wakeup event to the PRCM. - * - * Therefore, ensure any wake-up capable GPIOs have - * edge-detection enabled before going idle to ensure a wakeup - * to the PRCM is generated on a GPIO transition. (c.f. 34xx - * NDA TRM 25.5.3.1) - * - * The normal values will be restored upon ->runtime_resume() - * by writing back the values saved in bank->context. - */ - wake_low = bank->context.leveldetect0 & bank->context.wake_en; - if (wake_low) - writel_relaxed(wake_low | bank->context.fallingdetect, - bank->base + bank->regs->fallingdetect); - wake_hi = bank->context.leveldetect1 & bank->context.wake_en; - if (wake_hi) - writel_relaxed(wake_hi | bank->context.risingdetect, - bank->base + bank->regs->risingdetect); + if (bank->funcs.idle_enable_level_quirk) + bank->funcs.idle_enable_level_quirk(bank); if (!bank->enabled_non_wakeup_gpios) goto update_gpio_context_count; - if (bank->power_mode != OFF_MODE) { - bank->power_mode = 0; + if (!may_lose_context) goto update_gpio_context_count; - } + /* * If going to OFF, remove triggering for all * non-wakeup GPIOs. Otherwise spurious IRQs will be @@ -1427,23 +1532,16 @@ update_gpio_context_count: bank->get_context_loss_count(dev); omap_gpio_dbck_disable(bank); - raw_spin_unlock_irqrestore(&bank->lock, flags); - - return 0; } static void omap_gpio_init_context(struct gpio_bank *p); -static int omap_gpio_runtime_resume(struct device *dev) +static void omap_gpio_unidle(struct gpio_bank *bank) { - struct platform_device *pdev = to_platform_device(dev); - struct gpio_bank *bank = platform_get_drvdata(pdev); + struct device *dev = bank->chip.parent; u32 l = 0, gen, gen0, gen1; - unsigned long flags; int c; - raw_spin_lock_irqsave(&bank->lock, flags); - /* * On the first resume during the probe, the context has not * been initialised and so initialise it now. Also initialise @@ -1459,16 +1557,8 @@ static int omap_gpio_runtime_resume(struct device *dev) omap_gpio_dbck_enable(bank); - /* - * In ->runtime_suspend(), level-triggered, wakeup-enabled - * GPIOs were set to edge trigger also in order to be able to - * generate a PRCM wakeup. Here we restore the - * pre-runtime_suspend() values for edge triggering. - */ - writel_relaxed(bank->context.fallingdetect, - bank->base + bank->regs->fallingdetect); - writel_relaxed(bank->context.risingdetect, - bank->base + bank->regs->risingdetect); + if (bank->funcs.idle_disable_level_quirk) + bank->funcs.idle_disable_level_quirk(bank); if (bank->loses_context) { if (!bank->get_context_loss_count) { @@ -1478,16 +1568,13 @@ static int omap_gpio_runtime_resume(struct device *dev) if (c != bank->context_loss_count) { omap_gpio_restore_context(bank); } else { - raw_spin_unlock_irqrestore(&bank->lock, flags); - return 0; + return; } } } - if (!bank->workaround_enabled) { - raw_spin_unlock_irqrestore(&bank->lock, flags); - return 0; - } + if (!bank->workaround_enabled) + return; l = readl_relaxed(bank->base + bank->regs->datain); @@ -1540,41 +1627,8 @@ static int omap_gpio_runtime_resume(struct device *dev) } bank->workaround_enabled = false; - raw_spin_unlock_irqrestore(&bank->lock, flags); - - return 0; -} -#endif /* CONFIG_PM */ - -#if IS_BUILTIN(CONFIG_GPIO_OMAP) -void omap2_gpio_prepare_for_idle(int pwr_mode) -{ - struct gpio_bank *bank; - - list_for_each_entry(bank, &omap_gpio_list, node) { - if (!BANK_USED(bank) || !bank->loses_context) - continue; - - bank->power_mode = pwr_mode; - - pm_runtime_put_sync_suspend(bank->chip.parent); - } -} - -void omap2_gpio_resume_after_idle(void) -{ - struct gpio_bank *bank; - - list_for_each_entry(bank, &omap_gpio_list, node) { - if (!BANK_USED(bank) || !bank->loses_context) - continue; - - pm_runtime_get_sync(bank->chip.parent); - } } -#endif -#if defined(CONFIG_PM) static void omap_gpio_init_context(struct gpio_bank *p) { struct omap_gpio_reg_offs *regs = p->regs; @@ -1631,17 +1685,57 @@ static void omap_gpio_restore_context(struct gpio_bank *bank) writel_relaxed(bank->context.irqenable2, bank->base + bank->regs->irqenable2); } -#endif /* CONFIG_PM */ -#else -#define omap_gpio_runtime_suspend NULL -#define omap_gpio_runtime_resume NULL -static inline void omap_gpio_init_context(struct gpio_bank *p) {} -#endif +static int __maybe_unused omap_gpio_runtime_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct gpio_bank *bank = platform_get_drvdata(pdev); + unsigned long flags; + int error = 0; + + raw_spin_lock_irqsave(&bank->lock, flags); + /* Must be idled only by CPU_CLUSTER_PM_ENTER? */ + if (bank->irq_usage) { + error = -EBUSY; + goto unlock; + } + omap_gpio_idle(bank, true); + bank->is_suspended = true; +unlock: + raw_spin_unlock_irqrestore(&bank->lock, flags); + + return error; +} + +static int __maybe_unused omap_gpio_runtime_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct gpio_bank *bank = platform_get_drvdata(pdev); + unsigned long flags; + int error = 0; + + raw_spin_lock_irqsave(&bank->lock, flags); + /* Must be unidled only by CPU_CLUSTER_PM_ENTER? */ + if (bank->irq_usage) { + error = -EBUSY; + goto unlock; + } + omap_gpio_unidle(bank); + bank->is_suspended = false; +unlock: + raw_spin_unlock_irqrestore(&bank->lock, flags); + + return error; +} + +#ifdef CONFIG_ARCH_OMAP2PLUS static const struct dev_pm_ops gpio_pm_ops = { SET_RUNTIME_PM_OPS(omap_gpio_runtime_suspend, omap_gpio_runtime_resume, NULL) }; +#else +static const struct dev_pm_ops gpio_pm_ops; +#endif /* CONFIG_ARCH_OMAP2PLUS */ #if defined(CONFIG_OF) static struct omap_gpio_reg_offs omap2_gpio_regs = { @@ -1690,6 +1784,11 @@ static struct omap_gpio_reg_offs omap4_gpio_regs = { .fallingdetect = OMAP4_GPIO_FALLINGDETECT, }; +/* + * Note that omap2 does not currently support idle modes with context loss so + * no need to add OMAP_GPIO_QUIRK_IDLE_REMOVE_TRIGGER quirk flag to save + * and restore context. + */ static const struct omap_gpio_platform_data omap2_pdata = { .regs = &omap2_gpio_regs, .bank_width = 32, @@ -1700,12 +1799,15 @@ static const struct omap_gpio_platform_data omap3_pdata = { .regs = &omap2_gpio_regs, .bank_width = 32, .dbck_flag = true, + .quirks = OMAP_GPIO_QUIRK_IDLE_REMOVE_TRIGGER, }; static const struct omap_gpio_platform_data omap4_pdata = { .regs = &omap4_gpio_regs, .bank_width = 32, .dbck_flag = true, + .quirks = OMAP_GPIO_QUIRK_IDLE_REMOVE_TRIGGER | + OMAP_GPIO_QUIRK_DEFERRED_WKUP_EN, }; static const struct of_device_id omap_gpio_match[] = { |