Merge branch 'stable-3.2' into pandora-3.2
[pandora-kernel.git] / drivers / gpio / gpio-omap.c
index 0b05629..4390dd7 100644 (file)
@@ -44,6 +44,7 @@ struct gpio_bank {
        u32 saved_datain;
        u32 saved_fallingdetect;
        u32 saved_risingdetect;
+       u32 saved_irqstatus;
        u32 level_mask;
        u32 toggle_mask;
        spinlock_t lock;
@@ -508,7 +509,10 @@ static void _disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
 
 static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable)
 {
-       _enable_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
+       if (enable)
+               _enable_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
+       else
+               _disable_gpio_irqbank(bank, GPIO_BIT(bank, gpio));
 }
 
 /*
@@ -1347,9 +1351,23 @@ void omap2_gpio_prepare_for_idle(int off_mode)
 
        for (i = min; i < gpio_bank_count; i++) {
                struct gpio_bank *bank = &gpio_bank[i];
+               void __iomem *reg;
                u32 l1 = 0, l2 = 0;
                int j;
 
+               /*
+                * Disable debounce since clock disable below will cause
+                * problems if GPIO module doesn't go idle for some reason.
+                */
+               if (bank->dbck_enable_mask != 0) {
+                       reg = bank->base + bank->regs->datain;
+                       bank->saved_datain = __raw_readl(reg);
+                       reg = bank->base + bank->regs->irqstatus;
+                       bank->saved_irqstatus = __raw_readl(reg);
+                       reg = bank->base + bank->regs->debounce_en;
+                       __raw_writel(0, reg);
+               }
+
                for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
                        clk_disable(bank->dbck);
 
@@ -1415,12 +1433,28 @@ void omap2_gpio_resume_after_idle(void)
                min = 1;
        for (i = min; i < gpio_bank_count; i++) {
                struct gpio_bank *bank = &gpio_bank[i];
+               void __iomem *reg;
                u32 l = 0, gen, gen0, gen1;
                int j;
 
                for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
                        clk_enable(bank->dbck);
 
+               if (bank->dbck_enable_mask != 0) {
+                       reg = bank->base + bank->regs->debounce_en;
+                       __raw_writel(bank->dbck_enable_mask, reg);
+                       /* clear irqs that could come from glitches
+                        * because debounce was disabled */
+                       reg = bank->base + bank->regs->irqstatus;
+                       gen = __raw_readl(reg) & ~bank->saved_irqstatus;
+                       reg = bank->base + bank->regs->datain;
+                       l = __raw_readl(reg) ^ bank->saved_datain;
+                       l = gen & ~l;
+                       l = l & bank->dbck_enable_mask & ~bank->level_mask;
+                       if (l)
+                               _clear_gpio_irqbank(bank, l);
+               }
+
                if (!workaround_enabled)
                        continue;