aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpio/gpio-omap.c53
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)
};