Merge branch 'gpio-2.6.35' of git://git.kernel.org/pub/scm/linux/kernel/git/khilman...
authorTony Lindgren <tony@atomide.com>
Thu, 20 May 2010 18:07:34 +0000 (11:07 -0700)
committerTony Lindgren <tony@atomide.com>
Thu, 20 May 2010 18:07:34 +0000 (11:07 -0700)
arch/arm/mach-omap2/pm24xx.c
arch/arm/mach-omap2/pm34xx.c
arch/arm/plat-omap/gpio.c
arch/arm/plat-omap/include/plat/gpio.h

index 374299e..7816c4e 100644 (file)
@@ -107,7 +107,7 @@ static void omap2_enter_full_retention(void)
        l = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0) | OMAP24XX_USBSTANDBYCTRL;
        omap_ctrl_writel(l, OMAP2_CONTROL_DEVCONF0);
 
-       omap2_gpio_prepare_for_retention();
+       omap2_gpio_prepare_for_idle(PWRDM_POWER_RET);
 
        if (omap2_pm_debug) {
                omap2_pm_dump(0, 0, 0);
@@ -141,7 +141,7 @@ no_sleep:
                tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC;
                omap2_pm_dump(0, 1, tmp);
        }
-       omap2_gpio_resume_after_retention();
+       omap2_gpio_resume_after_idle();
 
        clk_enable(osc_ck);
 
index ea0000b..468e1e3 100644 (file)
@@ -376,7 +376,7 @@ void omap_sram_idle(void)
        core_next_state = pwrdm_read_next_pwrst(core_pwrdm);
        if (per_next_state < PWRDM_POWER_ON) {
                omap_uart_prepare_idle(2);
-               omap2_gpio_prepare_for_retention();
+               omap2_gpio_prepare_for_idle(per_next_state);
                if (per_next_state == PWRDM_POWER_OFF) {
                        if (core_next_state == PWRDM_POWER_ON) {
                                per_next_state = PWRDM_POWER_RET;
@@ -454,9 +454,9 @@ void omap_sram_idle(void)
        /* PER */
        if (per_next_state < PWRDM_POWER_ON) {
                per_prev_state = pwrdm_read_prev_pwrst(per_pwrdm);
+               omap2_gpio_resume_after_idle();
                if (per_prev_state == PWRDM_POWER_OFF)
                        omap3_per_restore_context();
-               omap2_gpio_resume_after_retention();
                omap_uart_resume_idle(2);
                if (per_state_modified)
                        pwrdm_set_next_pwrst(per_pwrdm, PWRDM_POWER_OFF);
index 45a225d..955597f 100644 (file)
@@ -27,6 +27,7 @@
 #include <mach/irqs.h>
 #include <mach/gpio.h>
 #include <asm/mach/irq.h>
+#include <plat/powerdomain.h>
 
 /*
  * OMAP1510 GPIO registers
@@ -195,6 +196,7 @@ struct gpio_bank {
        struct gpio_chip chip;
        struct clk *dbck;
        u32 mod_usage;
+       u32 dbck_enable_mask;
 };
 
 #define METHOD_MPUIO           0
@@ -303,8 +305,6 @@ struct omap3_gpio_regs {
        u32 risingdetect;
        u32 fallingdetect;
        u32 dataout;
-       u32 setwkuena;
-       u32 setdataout;
 };
 
 static struct omap3_gpio_regs gpio_context[OMAP34XX_NR_GPIOS];
@@ -646,6 +646,7 @@ void omap_set_gpio_debounce(int gpio, int enable)
                goto done;
 
        if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
+               bank->dbck_enable_mask = val;
                if (enable)
                        clk_enable(bank->dbck);
                else
@@ -724,15 +725,27 @@ static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio,
                                                         OMAP4_GPIO_IRQWAKEN0);
                        }
                } else {
-                       if (trigger != 0)
+                       /*
+                        * GPIO wakeup request can only be generated on edge
+                        * transitions
+                        */
+                       if (trigger & IRQ_TYPE_EDGE_BOTH)
                                __raw_writel(1 << gpio, bank->base
                                        + OMAP24XX_GPIO_SETWKUENA);
                        else
                                __raw_writel(1 << gpio, bank->base
                                        + OMAP24XX_GPIO_CLEARWKUENA);
                }
-       } else {
-               if (trigger != 0)
+       }
+       /* This part needs to be executed always for OMAP34xx */
+       if (cpu_is_omap34xx() || (bank->non_wakeup_gpios & gpio_bit)) {
+               /*
+                * Log the edge gpio and manually trigger the IRQ
+                * after resume if the input level changes
+                * to avoid irq lost during PER RET/OFF mode
+                * Applies for omap2 non-wakeup gpio and all omap3 gpios
+                */
+               if (trigger & IRQ_TYPE_EDGE_BOTH)
                        bank->enabled_non_wakeup_gpios |= gpio_bit;
                else
                        bank->enabled_non_wakeup_gpios &= ~gpio_bit;
@@ -1845,7 +1858,8 @@ static int __init _omap_gpio_init(void)
                                __raw_writel(0, bank->base +
                                                OMAP24XX_GPIO_CTRL);
                        }
-                       if (i < ARRAY_SIZE(non_wakeup_gpios))
+                       if (cpu_is_omap24xx() &&
+                           i < ARRAY_SIZE(non_wakeup_gpios))
                                bank->non_wakeup_gpios = non_wakeup_gpios[i];
                        gpio_count = 32;
                }
@@ -2028,16 +2042,27 @@ static struct sys_device omap_gpio_device = {
 
 static int workaround_enabled;
 
-void omap2_gpio_prepare_for_retention(void)
+void omap2_gpio_prepare_for_idle(int power_state)
 {
        int i, c = 0;
+       int min = 0;
 
-       /* Remove triggering for all non-wakeup GPIOs.  Otherwise spurious
-        * IRQs will be generated.  See OMAP2420 Errata item 1.101. */
-       for (i = 0; i < gpio_bank_count; i++) {
+       if (cpu_is_omap34xx())
+               min = 1;
+
+       for (i = min; i < gpio_bank_count; i++) {
                struct gpio_bank *bank = &gpio_bank[i];
                u32 l1, l2;
 
+               if (bank->dbck_enable_mask)
+                       clk_disable(bank->dbck);
+
+               if (power_state > PWRDM_POWER_OFF)
+                       continue;
+
+               /* If going to OFF, remove triggering for all
+                * non-wakeup GPIOs.  Otherwise spurious IRQs will be
+                * generated.  See OMAP2420 Errata item 1.101. */
                if (!(bank->enabled_non_wakeup_gpios))
                        continue;
 
@@ -2085,16 +2110,23 @@ void omap2_gpio_prepare_for_retention(void)
        workaround_enabled = 1;
 }
 
-void omap2_gpio_resume_after_retention(void)
+void omap2_gpio_resume_after_idle(void)
 {
        int i;
+       int min = 0;
 
-       if (!workaround_enabled)
-               return;
-       for (i = 0; i < gpio_bank_count; i++) {
+       if (cpu_is_omap34xx())
+               min = 1;
+       for (i = min; i < gpio_bank_count; i++) {
                struct gpio_bank *bank = &gpio_bank[i];
                u32 l, gen, gen0, gen1;
 
+               if (bank->dbck_enable_mask)
+                       clk_enable(bank->dbck);
+
+               if (!workaround_enabled)
+                       continue;
+
                if (!(bank->enabled_non_wakeup_gpios))
                        continue;
 
@@ -2119,7 +2151,7 @@ void omap2_gpio_resume_after_retention(void)
                 * horribly racy, but it's the best we can do to work around
                 * this silicon bug. */
                l ^= bank->saved_datain;
-               l &= bank->non_wakeup_gpios;
+               l &= bank->enabled_non_wakeup_gpios;
 
                /*
                 * No need to generate IRQs for the rising edge for gpio IRQs
@@ -2207,10 +2239,6 @@ void omap_gpio_save_context(void)
                        __raw_readl(bank->base + OMAP24XX_GPIO_FALLINGDETECT);
                gpio_context[i].dataout =
                        __raw_readl(bank->base + OMAP24XX_GPIO_DATAOUT);
-               gpio_context[i].setwkuena =
-                       __raw_readl(bank->base + OMAP24XX_GPIO_SETWKUENA);
-               gpio_context[i].setdataout =
-                       __raw_readl(bank->base + OMAP24XX_GPIO_SETDATAOUT);
        }
 }
 
@@ -2243,10 +2271,6 @@ void omap_gpio_restore_context(void)
                                bank->base + OMAP24XX_GPIO_FALLINGDETECT);
                __raw_writel(gpio_context[i].dataout,
                                bank->base + OMAP24XX_GPIO_DATAOUT);
-               __raw_writel(gpio_context[i].setwkuena,
-                               bank->base + OMAP24XX_GPIO_SETWKUENA);
-               __raw_writel(gpio_context[i].setdataout,
-                               bank->base + OMAP24XX_GPIO_SETDATAOUT);
        }
 }
 #endif
@@ -2286,110 +2310,3 @@ static int __init omap_gpio_sysinit(void)
 }
 
 arch_initcall(omap_gpio_sysinit);
-
-
-#ifdef CONFIG_DEBUG_FS
-
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-
-static int dbg_gpio_show(struct seq_file *s, void *unused)
-{
-       unsigned        i, j, gpio;
-
-       for (i = 0, gpio = 0; i < gpio_bank_count; i++) {
-               struct gpio_bank        *bank = gpio_bank + i;
-               unsigned                bankwidth = 16;
-               u32                     mask = 1;
-
-               if (bank_is_mpuio(bank))
-                       gpio = OMAP_MPUIO(0);
-               else if (cpu_class_is_omap2() || cpu_is_omap7xx())
-                       bankwidth = 32;
-
-               for (j = 0; j < bankwidth; j++, gpio++, mask <<= 1) {
-                       unsigned        irq, value, is_in, irqstat;
-                       const char      *label;
-
-                       label = gpiochip_is_requested(&bank->chip, j);
-                       if (!label)
-                               continue;
-
-                       irq = bank->virtual_irq_start + j;
-                       value = gpio_get_value(gpio);
-                       is_in = gpio_is_input(bank, mask);
-
-                       if (bank_is_mpuio(bank))
-                               seq_printf(s, "MPUIO %2d ", j);
-                       else
-                               seq_printf(s, "GPIO %3d ", gpio);
-                       seq_printf(s, "(%-20.20s): %s %s",
-                                       label,
-                                       is_in ? "in " : "out",
-                                       value ? "hi"  : "lo");
-
-/* FIXME for at least omap2, show pullup/pulldown state */
-
-                       irqstat = irq_desc[irq].status;
-#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS)
-                       if (is_in && ((bank->suspend_wakeup & mask)
-                                       || irqstat & IRQ_TYPE_SENSE_MASK)) {
-                               char    *trigger = NULL;
-
-                               switch (irqstat & IRQ_TYPE_SENSE_MASK) {
-                               case IRQ_TYPE_EDGE_FALLING:
-                                       trigger = "falling";
-                                       break;
-                               case IRQ_TYPE_EDGE_RISING:
-                                       trigger = "rising";
-                                       break;
-                               case IRQ_TYPE_EDGE_BOTH:
-                                       trigger = "bothedge";
-                                       break;
-                               case IRQ_TYPE_LEVEL_LOW:
-                                       trigger = "low";
-                                       break;
-                               case IRQ_TYPE_LEVEL_HIGH:
-                                       trigger = "high";
-                                       break;
-                               case IRQ_TYPE_NONE:
-                                       trigger = "(?)";
-                                       break;
-                               }
-                               seq_printf(s, ", irq-%d %-8s%s",
-                                               irq, trigger,
-                                               (bank->suspend_wakeup & mask)
-                                                       ? " wakeup" : "");
-                       }
-#endif
-                       seq_printf(s, "\n");
-               }
-
-               if (bank_is_mpuio(bank)) {
-                       seq_printf(s, "\n");
-                       gpio = 0;
-               }
-       }
-       return 0;
-}
-
-static int dbg_gpio_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, dbg_gpio_show, &inode->i_private);
-}
-
-static const struct file_operations debug_fops = {
-       .open           = dbg_gpio_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-
-static int __init omap_gpio_debuginit(void)
-{
-       (void) debugfs_create_file("omap_gpio", S_IRUGO,
-                                       NULL, NULL, &debug_fops);
-       return 0;
-}
-late_initcall(omap_gpio_debuginit);
-#endif
index de7c547..de1c604 100644 (file)
@@ -72,8 +72,8 @@
                                 IH_GPIO_BASE + (nr))
 
 extern int omap_gpio_init(void);       /* Call from board init only */
-extern void omap2_gpio_prepare_for_retention(void);
-extern void omap2_gpio_resume_after_retention(void);
+extern void omap2_gpio_prepare_for_idle(int power_state);
+extern void omap2_gpio_resume_after_idle(void);
 extern void omap_set_gpio_debounce(int gpio, int enable);
 extern void omap_set_gpio_debounce_time(int gpio, int enable);
 extern void omap_gpio_save_context(void);