diff options
-rw-r--r-- | drivers/gpio/gpio-omap.c | 53 |
1 files changed, 49 insertions, 4 deletions
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index d335af1..fd22d77 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -55,6 +55,7 @@ struct gpio_bank { u16 irq; int irq_base; struct irq_domain *domain; + u32 suspend_wakeup; u32 non_wakeup_gpios; u32 enabled_non_wakeup_gpios; struct gpio_regs context; @@ -557,11 +558,9 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable) spin_lock_irqsave(&bank->lock, flags); if (enable) - bank->context.wake_en |= gpio_bit; + bank->suspend_wakeup |= gpio_bit; else - bank->context.wake_en &= ~gpio_bit; - - __raw_writel(bank->context.wake_en, bank->base + bank->regs->wkup_en); + bank->suspend_wakeup &= ~gpio_bit; spin_unlock_irqrestore(&bank->lock, flags); return 0; @@ -1191,6 +1190,49 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev) #ifdef CONFIG_ARCH_OMAP2PLUS #if defined(CONFIG_PM_RUNTIME) + +#if defined(CONFIG_PM_SLEEP) +static int omap_gpio_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct gpio_bank *bank = platform_get_drvdata(pdev); + void __iomem *base = bank->base; + unsigned long flags; + + if (!bank->mod_usage || + !bank->regs->wkup_en || + !bank->context.wake_en) + return 0; + + spin_lock_irqsave(&bank->lock, flags); + _gpio_rmw(base, bank->regs->wkup_en, 0xffffffff, 0); + _gpio_rmw(base, bank->regs->wkup_en, bank->suspend_wakeup, 1); + spin_unlock_irqrestore(&bank->lock, flags); + + return 0; +} + +static int omap_gpio_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct gpio_bank *bank = platform_get_drvdata(pdev); + void __iomem *base = bank->base; + unsigned long flags; + + if (!bank->mod_usage || + !bank->regs->wkup_en || + !bank->context.wake_en) + return 0; + + spin_lock_irqsave(&bank->lock, flags); + _gpio_rmw(base, bank->regs->wkup_en, 0xffffffff, 0); + _gpio_rmw(base, bank->regs->wkup_en, bank->context.wake_en, 1); + spin_unlock_irqrestore(&bank->lock, flags); + + return 0; +} +#endif /* CONFIG_PM_SLEEP */ + static void omap_gpio_restore_context(struct gpio_bank *bank); static int omap_gpio_runtime_suspend(struct device *dev) @@ -1420,11 +1462,14 @@ static void omap_gpio_restore_context(struct gpio_bank *bank) } #endif /* CONFIG_PM_RUNTIME */ #else +#define omap_gpio_suspend NULL +#define omap_gpio_resume NULL #define omap_gpio_runtime_suspend NULL #define omap_gpio_runtime_resume NULL #endif static const struct dev_pm_ops gpio_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(omap_gpio_suspend, omap_gpio_resume) SET_RUNTIME_PM_OPS(omap_gpio_runtime_suspend, omap_gpio_runtime_resume, NULL) }; |