Merge branch 'for-linus' of git://git.o-hand.com/linux-rpurdie-backlight
[pandora-kernel.git] / arch / arm / plat-omap / gpio.c
index 955597f..393e921 100644 (file)
 #define OMAP4_GPIO_IRQSTATUSCLR1       0x0040
 #define OMAP4_GPIO_IRQWAKEN0           0x0044
 #define OMAP4_GPIO_IRQWAKEN1           0x0048
-#define OMAP4_GPIO_SYSSTATUS           0x0104
+#define OMAP4_GPIO_SYSSTATUS           0x0114
+#define OMAP4_GPIO_IRQENABLE1          0x011c
+#define OMAP4_GPIO_WAKE_EN             0x0120
+#define OMAP4_GPIO_IRQSTATUS2          0x0128
+#define OMAP4_GPIO_IRQENABLE2          0x012c
 #define OMAP4_GPIO_CTRL                        0x0130
 #define OMAP4_GPIO_OE                  0x0134
 #define OMAP4_GPIO_DATAIN              0x0138
 #define OMAP4_GPIO_FALLINGDETECT       0x014c
 #define OMAP4_GPIO_DEBOUNCENABLE       0x0150
 #define OMAP4_GPIO_DEBOUNCINGTIME      0x0154
+#define OMAP4_GPIO_CLEARIRQENABLE1     0x0160
+#define OMAP4_GPIO_SETIRQENABLE1       0x0164
+#define OMAP4_GPIO_CLEARWKUENA         0x0180
+#define OMAP4_GPIO_SETWKUENA           0x0184
 #define OMAP4_GPIO_CLEARDATAOUT                0x0190
 #define OMAP4_GPIO_SETDATAOUT          0x0194
 /*
@@ -591,11 +599,15 @@ static int _get_gpio_dataout(struct gpio_bank *bank, int gpio)
                reg += OMAP7XX_GPIO_DATA_OUTPUT;
                break;
 #endif
-#ifdef CONFIG_ARCH_OMAP2PLUS
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
        case METHOD_GPIO_24XX:
-       case METHOD_GPIO_44XX:
                reg += OMAP24XX_GPIO_DATAOUT;
                break;
+#endif
+#ifdef CONFIG_ARCH_OMAP4
+       case METHOD_GPIO_44XX:
+               reg += OMAP4_GPIO_DATAOUT;
+               break;
 #endif
        default:
                return -EINVAL;
@@ -612,79 +624,58 @@ do {      \
        __raw_writel(l, base + reg); \
 } while(0)
 
-void omap_set_gpio_debounce(int gpio, int enable)
+/**
+ * _set_gpio_debounce - low level gpio debounce time
+ * @bank: the gpio bank we're acting upon
+ * @gpio: the gpio number on this @gpio
+ * @debounce: debounce time to use
+ *
+ * OMAP's debounce time is in 31us steps so we need
+ * to convert and round up to the closest unit.
+ */
+static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
+               unsigned debounce)
 {
-       struct gpio_bank *bank;
-       void __iomem *reg;
-       unsigned long flags;
-       u32 val, l = 1 << get_gpio_index(gpio);
+       void __iomem            *reg = bank->base;
+       u32                     val;
+       u32                     l;
+
+       if (debounce < 32)
+               debounce = 0x01;
+       else if (debounce > 7936)
+               debounce = 0xff;
+       else
+               debounce = (debounce / 0x1f) - 1;
 
-       if (cpu_class_is_omap1())
-               return;
+       l = 1 << get_gpio_index(gpio);
 
-       bank = get_gpio_bank(gpio);
-       reg = bank->base;
+       if (cpu_is_omap44xx())
+               reg += OMAP4_GPIO_DEBOUNCINGTIME;
+       else
+               reg += OMAP24XX_GPIO_DEBOUNCE_VAL;
+
+       __raw_writel(debounce, reg);
 
+       reg = bank->base;
        if (cpu_is_omap44xx())
                reg += OMAP4_GPIO_DEBOUNCENABLE;
        else
                reg += OMAP24XX_GPIO_DEBOUNCE_EN;
 
-       if (!(bank->mod_usage & l)) {
-               printk(KERN_ERR "GPIO %d not requested\n", gpio);
-               return;
-       }
-
-       spin_lock_irqsave(&bank->lock, flags);
        val = __raw_readl(reg);
 
-       if (enable && !(val & l))
+       if (debounce) {
                val |= l;
-       else if (!enable && (val & l))
-               val &= ~l;
-       else
-               goto done;
-
-       if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
-               bank->dbck_enable_mask = val;
-               if (enable)
+               if (cpu_is_omap34xx() || cpu_is_omap44xx())
                        clk_enable(bank->dbck);
-               else
+       } else {
+               val &= ~l;
+               if (cpu_is_omap34xx() || cpu_is_omap44xx())
                        clk_disable(bank->dbck);
        }
 
        __raw_writel(val, reg);
-done:
-       spin_unlock_irqrestore(&bank->lock, flags);
 }
-EXPORT_SYMBOL(omap_set_gpio_debounce);
-
-void omap_set_gpio_debounce_time(int gpio, int enc_time)
-{
-       struct gpio_bank *bank;
-       void __iomem *reg;
-
-       if (cpu_class_is_omap1())
-               return;
-
-       bank = get_gpio_bank(gpio);
-       reg = bank->base;
-
-       if (!bank->mod_usage) {
-               printk(KERN_ERR "GPIO not requested\n");
-               return;
-       }
-
-       enc_time &= 0xff;
-
-       if (cpu_is_omap44xx())
-               reg += OMAP4_GPIO_DEBOUNCINGTIME;
-       else
-               reg += OMAP24XX_GPIO_DEBOUNCE_VAL;
-
-       __raw_writel(enc_time, reg);
-}
-EXPORT_SYMBOL(omap_set_gpio_debounce_time);
 
 #ifdef CONFIG_ARCH_OMAP2PLUS
 static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio,
@@ -1213,11 +1204,17 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
 #endif
        if (!cpu_class_is_omap1()) {
                if (!bank->mod_usage) {
+                       void __iomem *reg = bank->base;
                        u32 ctrl;
-                       ctrl = __raw_readl(bank->base + OMAP24XX_GPIO_CTRL);
-                       ctrl &= 0xFFFFFFFE;
+
+                       if (cpu_is_omap24xx() || cpu_is_omap34xx())
+                               reg += OMAP24XX_GPIO_CTRL;
+                       else if (cpu_is_omap44xx())
+                               reg += OMAP4_GPIO_CTRL;
+                       ctrl = __raw_readl(reg);
                        /* Module is enabled, clocks are not gated */
-                       __raw_writel(ctrl, bank->base + OMAP24XX_GPIO_CTRL);
+                       ctrl &= 0xFFFFFFFE;
+                       __raw_writel(ctrl, reg);
                }
                bank->mod_usage |= 1 << offset;
        }
@@ -1239,22 +1236,34 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)
                __raw_writel(1 << offset, reg);
        }
 #endif
-#ifdef CONFIG_ARCH_OMAP2PLUS
-       if ((bank->method == METHOD_GPIO_24XX) ||
-                       (bank->method == METHOD_GPIO_44XX)) {
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+       if (bank->method == METHOD_GPIO_24XX) {
                /* Disable wake-up during idle for dynamic tick */
                void __iomem *reg = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
                __raw_writel(1 << offset, reg);
        }
+#endif
+#ifdef CONFIG_ARCH_OMAP4
+       if (bank->method == METHOD_GPIO_44XX) {
+               /* Disable wake-up during idle for dynamic tick */
+               void __iomem *reg = bank->base + OMAP4_GPIO_IRQWAKEN0;
+               __raw_writel(1 << offset, reg);
+       }
 #endif
        if (!cpu_class_is_omap1()) {
                bank->mod_usage &= ~(1 << offset);
                if (!bank->mod_usage) {
+                       void __iomem *reg = bank->base;
                        u32 ctrl;
-                       ctrl = __raw_readl(bank->base + OMAP24XX_GPIO_CTRL);
+
+                       if (cpu_is_omap24xx() || cpu_is_omap34xx())
+                               reg += OMAP24XX_GPIO_CTRL;
+                       else if (cpu_is_omap44xx())
+                               reg += OMAP4_GPIO_CTRL;
+                       ctrl = __raw_readl(reg);
                        /* Module is disabled, clocks are gated */
                        ctrl |= 1;
-                       __raw_writel(ctrl, bank->base + OMAP24XX_GPIO_CTRL);
+                       __raw_writel(ctrl, reg);
                }
        }
        _reset_gpio(bank, bank->chip.base + offset);
@@ -1583,9 +1592,14 @@ static int gpio_is_input(struct gpio_bank *bank, int mask)
                reg += OMAP7XX_GPIO_DIR_CONTROL;
                break;
        case METHOD_GPIO_24XX:
-       case METHOD_GPIO_44XX:
                reg += OMAP24XX_GPIO_OE;
                break;
+       case METHOD_GPIO_44XX:
+               reg += OMAP4_GPIO_OE;
+               break;
+       default:
+               WARN_ONCE(1, "gpio_is_input: incorrect OMAP GPIO method");
+               return -EINVAL;
        }
        return __raw_readl(reg) & mask;
 }
@@ -1621,6 +1635,20 @@ static int gpio_output(struct gpio_chip *chip, unsigned offset, int value)
        return 0;
 }
 
+static int gpio_debounce(struct gpio_chip *chip, unsigned offset,
+               unsigned debounce)
+{
+       struct gpio_bank *bank;
+       unsigned long flags;
+
+       bank = container_of(chip, struct gpio_bank, chip);
+       spin_lock_irqsave(&bank->lock, flags);
+       _set_gpio_debounce(bank, offset, debounce);
+       spin_unlock_irqrestore(&bank->lock, flags);
+
+       return 0;
+}
+
 static void gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
        struct gpio_bank *bank;
@@ -1874,6 +1902,7 @@ static int __init _omap_gpio_init(void)
                bank->chip.direction_input = gpio_input;
                bank->chip.get = gpio_get;
                bank->chip.direction_output = gpio_output;
+               bank->chip.set_debounce = gpio_debounce;
                bank->chip.set = gpio_set;
                bank->chip.to_irq = gpio_2irq;
                if (bank_is_mpuio(bank)) {