Merge branches 'iommu/fixes', 'x86/amd', 'groups', 'arm/tegra' and 'api/domain-attr...
[firefly-linux-kernel-4.4.55.git] / drivers / gpio / gpio-omap.c
index 4461540653a89526896d61adb0c364f2fa21d6fc..4fbc208c32cfa213812f6356323a36a51c37087c 100644 (file)
@@ -57,14 +57,10 @@ struct gpio_bank {
        u16 irq;
        int irq_base;
        struct irq_domain *domain;
-       u32 suspend_wakeup;
-       u32 saved_wakeup;
        u32 non_wakeup_gpios;
        u32 enabled_non_wakeup_gpios;
        struct gpio_regs context;
        u32 saved_datain;
-       u32 saved_fallingdetect;
-       u32 saved_risingdetect;
        u32 level_mask;
        u32 toggle_mask;
        spinlock_t lock;
@@ -178,12 +174,22 @@ static inline void _gpio_dbck_enable(struct gpio_bank *bank)
        if (bank->dbck_enable_mask && !bank->dbck_enabled) {
                clk_enable(bank->dbck);
                bank->dbck_enabled = true;
+
+               __raw_writel(bank->dbck_enable_mask,
+                            bank->base + bank->regs->debounce_en);
        }
 }
 
 static inline void _gpio_dbck_disable(struct gpio_bank *bank)
 {
        if (bank->dbck_enable_mask && bank->dbck_enabled) {
+               /*
+                * Disable debounce before cutting it's clock. If debounce is
+                * enabled but the clock is not, GPIO module seems to be unable
+                * to detect events and generate interrupts at least on OMAP3.
+                */
+               __raw_writel(0, bank->base + bank->regs->debounce_en);
+
                clk_disable(bank->dbck);
                bank->dbck_enabled = false;
        }
@@ -516,11 +522,11 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
 
        spin_lock_irqsave(&bank->lock, flags);
        if (enable)
-               bank->suspend_wakeup |= gpio_bit;
+               bank->context.wake_en |= gpio_bit;
        else
-               bank->suspend_wakeup &= ~gpio_bit;
+               bank->context.wake_en &= ~gpio_bit;
 
-       __raw_writel(bank->suspend_wakeup, bank->base + bank->regs->wkup_en);
+       __raw_writel(bank->context.wake_en, bank->base + bank->regs->wkup_en);
        spin_unlock_irqrestore(&bank->lock, flags);
 
        return 0;
@@ -640,7 +646,6 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
        u32 isr;
        unsigned int gpio_irq, gpio_index;
        struct gpio_bank *bank;
-       u32 retrigger = 0;
        int unmasked = 0;
        struct irq_chip *chip = irq_desc_get_chip(desc);
 
@@ -677,8 +682,6 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
                        chained_irq_exit(chip, desc);
                }
 
-               isr |= retrigger;
-               retrigger = 0;
                if (!isr)
                        break;
 
@@ -789,8 +792,7 @@ static int omap_mpuio_suspend_noirq(struct device *dev)
        unsigned long           flags;
 
        spin_lock_irqsave(&bank->lock, flags);
-       bank->saved_wakeup = __raw_readl(mask_reg);
-       __raw_writel(0xffff & ~bank->suspend_wakeup, mask_reg);
+       __raw_writel(0xffff & ~bank->context.wake_en, mask_reg);
        spin_unlock_irqrestore(&bank->lock, flags);
 
        return 0;
@@ -805,7 +807,7 @@ static int omap_mpuio_resume_noirq(struct device *dev)
        unsigned long           flags;
 
        spin_lock_irqsave(&bank->lock, flags);
-       __raw_writel(bank->saved_wakeup, mask_reg);
+       __raw_writel(bank->context.wake_en, mask_reg);
        spin_unlock_irqrestore(&bank->lock, flags);
 
        return 0;
@@ -1089,7 +1091,6 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)
        bank->is_mpuio = pdata->is_mpuio;
        bank->non_wakeup_gpios = pdata->non_wakeup_gpios;
        bank->loses_context = pdata->loses_context;
-       bank->get_context_loss_count = pdata->get_context_loss_count;
        bank->regs = pdata->regs;
 #ifdef CONFIG_OF_GPIO
        bank->chip.of_node = of_node_get(node);
@@ -1143,6 +1144,9 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)
        omap_gpio_chip_init(bank);
        omap_gpio_show_rev(bank);
 
+       if (bank->loses_context)
+               bank->get_context_loss_count = pdata->get_context_loss_count;
+
        pm_runtime_put(bank->dev);
 
        list_add_tail(&bank->node, &omap_gpio_list);
@@ -1152,54 +1156,6 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)
 
 #ifdef CONFIG_ARCH_OMAP2PLUS
 
-#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;
-       void __iomem *wakeup_enable;
-       unsigned long flags;
-
-       if (!bank->mod_usage || !bank->loses_context)
-               return 0;
-
-       if (!bank->regs->wkup_en || !bank->suspend_wakeup)
-               return 0;
-
-       wakeup_enable = bank->base + bank->regs->wkup_en;
-
-       spin_lock_irqsave(&bank->lock, flags);
-       bank->saved_wakeup = __raw_readl(wakeup_enable);
-       _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->loses_context)
-               return 0;
-
-       if (!bank->regs->wkup_en || !bank->saved_wakeup)
-               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->saved_wakeup, 1);
-       spin_unlock_irqrestore(&bank->lock, flags);
-
-       return 0;
-}
-#endif /* CONFIG_PM_SLEEP */
-
 #if defined(CONFIG_PM_RUNTIME)
 static void omap_gpio_restore_context(struct gpio_bank *bank);
 
@@ -1233,6 +1189,9 @@ static int omap_gpio_runtime_suspend(struct device *dev)
                __raw_writel(wake_hi | bank->context.risingdetect,
                             bank->base + bank->regs->risingdetect);
 
+       if (!bank->enabled_non_wakeup_gpios)
+               goto update_gpio_context_count;
+
        if (bank->power_mode != OFF_MODE) {
                bank->power_mode = 0;
                goto update_gpio_context_count;
@@ -1244,11 +1203,9 @@ static int omap_gpio_runtime_suspend(struct device *dev)
         */
        bank->saved_datain = __raw_readl(bank->base +
                                                bank->regs->datain);
-       l1 = __raw_readl(bank->base + bank->regs->fallingdetect);
-       l2 = __raw_readl(bank->base + bank->regs->risingdetect);
+       l1 = bank->context.fallingdetect;
+       l2 = bank->context.risingdetect;
 
-       bank->saved_fallingdetect = l1;
-       bank->saved_risingdetect = l2;
        l1 &= ~bank->enabled_non_wakeup_gpios;
        l2 &= ~bank->enabled_non_wakeup_gpios;
 
@@ -1290,16 +1247,10 @@ static int omap_gpio_runtime_resume(struct device *dev)
        __raw_writel(bank->context.risingdetect,
                     bank->base + bank->regs->risingdetect);
 
-       if (!bank->workaround_enabled) {
-               spin_unlock_irqrestore(&bank->lock, flags);
-               return 0;
-       }
-
        if (bank->get_context_loss_count) {
                context_lost_cnt_after =
                        bank->get_context_loss_count(bank->dev);
-               if (context_lost_cnt_after != bank->context_loss_count ||
-                                               !context_lost_cnt_after) {
+               if (context_lost_cnt_after != bank->context_loss_count) {
                        omap_gpio_restore_context(bank);
                } else {
                        spin_unlock_irqrestore(&bank->lock, flags);
@@ -1307,9 +1258,14 @@ static int omap_gpio_runtime_resume(struct device *dev)
                }
        }
 
-       __raw_writel(bank->saved_fallingdetect,
+       if (!bank->workaround_enabled) {
+               spin_unlock_irqrestore(&bank->lock, flags);
+               return 0;
+       }
+
+       __raw_writel(bank->context.fallingdetect,
                        bank->base + bank->regs->fallingdetect);
-       __raw_writel(bank->saved_risingdetect,
+       __raw_writel(bank->context.risingdetect,
                        bank->base + bank->regs->risingdetect);
        l = __raw_readl(bank->base + bank->regs->datain);
 
@@ -1326,14 +1282,15 @@ static int omap_gpio_runtime_resume(struct device *dev)
         * No need to generate IRQs for the rising edge for gpio IRQs
         * configured with falling edge only; and vice versa.
         */
-       gen0 = l & bank->saved_fallingdetect;
+       gen0 = l & bank->context.fallingdetect;
        gen0 &= bank->saved_datain;
 
-       gen1 = l & bank->saved_risingdetect;
+       gen1 = l & bank->context.risingdetect;
        gen1 &= ~(bank->saved_datain);
 
        /* FIXME: Consider GPIO IRQs with level detections properly! */
-       gen = l & (~(bank->saved_fallingdetect) & ~(bank->saved_risingdetect));
+       gen = l & (~(bank->context.fallingdetect) &
+                                        ~(bank->context.risingdetect));
        /* Consider all GPIO IRQs needed to be updated */
        gen |= gen0 | gen1;
 
@@ -1343,14 +1300,14 @@ static int omap_gpio_runtime_resume(struct device *dev)
                old0 = __raw_readl(bank->base + bank->regs->leveldetect0);
                old1 = __raw_readl(bank->base + bank->regs->leveldetect1);
 
-               if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
+               if (!bank->regs->irqstatus_raw0) {
                        __raw_writel(old0 | gen, bank->base +
                                                bank->regs->leveldetect0);
                        __raw_writel(old1 | gen, bank->base +
                                                bank->regs->leveldetect1);
                }
 
-               if (cpu_is_omap44xx()) {
+               if (bank->regs->irqstatus_raw0) {
                        __raw_writel(old0 | l, bank->base +
                                                bank->regs->leveldetect0);
                        __raw_writel(old1 | l, bank->base +
@@ -1429,14 +1386,11 @@ 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)
 };