]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/arm/plat-omap/gpio.c
ARM: OMAP: TUSB EVM init
[linux-2.6-omap-h63xx.git] / arch / arm / plat-omap / gpio.c
index eb9245b2a92805b6aeebebe26cc8c9fbe017b858..7e90cea37a4251a5f08dfb919bacdeaad0f2a4b3 100644 (file)
@@ -584,7 +584,7 @@ static int gpio_irq_type(unsigned irq, unsigned type)
                        && (type & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH)))
                return -EINVAL;
 
-       bank = get_gpio_bank(gpio);
+       bank = get_irq_chip_data(irq);
        spin_lock(&bank->lock);
        retval = _set_gpio_triggering(bank, get_gpio_index(gpio), type);
        if (retval == 0) {
@@ -773,29 +773,35 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
 {
        switch (bank->method) {
 #ifdef CONFIG_ARCH_OMAP16XX
+       case METHOD_MPUIO:
        case METHOD_GPIO_1610:
                spin_lock(&bank->lock);
-               if (enable)
+               if (enable) {
                        bank->suspend_wakeup |= (1 << gpio);
-               else
+                       enable_irq_wake(bank->irq);
+               } else {
+                       disable_irq_wake(bank->irq);
                        bank->suspend_wakeup &= ~(1 << gpio);
+               }
                spin_unlock(&bank->lock);
                return 0;
 #endif
 #ifdef CONFIG_ARCH_OMAP24XX
        case METHOD_GPIO_24XX:
+               if (bank->non_wakeup_gpios & (1 << gpio)) {
+                       printk(KERN_ERR "Unable to modify wakeup on "
+                                       "non-wakeup GPIO%d\n",
+                                       (bank - gpio_bank) * 32 + gpio);
+                       return -EINVAL;
+               }
                spin_lock(&bank->lock);
                if (enable) {
-                       if (bank->non_wakeup_gpios & (1 << gpio)) {
-                               printk(KERN_ERR "Unable to enable wakeup on "
-                                               "non-wakeup GPIO%d\n",
-                                               (bank - gpio_bank) * 32 + gpio);
-                               spin_unlock(&bank->lock);
-                               return -EINVAL;
-                       }
                        bank->suspend_wakeup |= (1 << gpio);
-               } else
+                       enable_irq_wake(bank->irq);
+               } else {
+                       disable_irq_wake(bank->irq);
                        bank->suspend_wakeup &= ~(1 << gpio);
+               }
                spin_unlock(&bank->lock);
                return 0;
 #endif
@@ -823,7 +829,7 @@ static int gpio_wake_enable(unsigned int irq, unsigned int enable)
 
        if (check_gpio(gpio) < 0)
                return -ENODEV;
-       bank = get_gpio_bank(gpio);
+       bank = get_irq_chip_data(irq);
        retval = _set_gpio_wakeup(bank, get_gpio_index(gpio), enable);
 
        return retval;
@@ -1038,7 +1044,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 static void gpio_irq_shutdown(unsigned int irq)
 {
        unsigned int gpio = irq - IH_GPIO_BASE;
-       struct gpio_bank *bank = get_gpio_bank(gpio);
+       struct gpio_bank *bank = get_irq_chip_data(irq);
 
        _reset_gpio(bank, gpio);
 }
@@ -1046,7 +1052,7 @@ static void gpio_irq_shutdown(unsigned int irq)
 static void gpio_ack_irq(unsigned int irq)
 {
        unsigned int gpio = irq - IH_GPIO_BASE;
-       struct gpio_bank *bank = get_gpio_bank(gpio);
+       struct gpio_bank *bank = get_irq_chip_data(irq);
 
        _clear_gpio_irqstatus(bank, gpio);
 }
@@ -1054,7 +1060,7 @@ static void gpio_ack_irq(unsigned int irq)
 static void gpio_mask_irq(unsigned int irq)
 {
        unsigned int gpio = irq - IH_GPIO_BASE;
-       struct gpio_bank *bank = get_gpio_bank(gpio);
+       struct gpio_bank *bank = get_irq_chip_data(irq);
 
        _set_gpio_irqenable(bank, gpio, 0);
 }
@@ -1063,7 +1069,7 @@ static void gpio_unmask_irq(unsigned int irq)
 {
        unsigned int gpio = irq - IH_GPIO_BASE;
        unsigned int gpio_idx = get_gpio_index(gpio);
-       struct gpio_bank *bank = get_gpio_bank(gpio);
+       struct gpio_bank *bank = get_irq_chip_data(irq);
 
        _set_gpio_irqenable(bank, gpio_idx, 1);
 }
@@ -1092,7 +1098,7 @@ static void mpuio_ack_irq(unsigned int irq)
 static void mpuio_mask_irq(unsigned int irq)
 {
        unsigned int gpio = OMAP_MPUIO(irq - IH_MPUIO_BASE);
-       struct gpio_bank *bank = get_gpio_bank(gpio);
+       struct gpio_bank *bank = get_irq_chip_data(irq);
 
        _set_gpio_irqenable(bank, gpio, 0);
 }
@@ -1100,7 +1106,7 @@ static void mpuio_mask_irq(unsigned int irq)
 static void mpuio_unmask_irq(unsigned int irq)
 {
        unsigned int gpio = OMAP_MPUIO(irq - IH_MPUIO_BASE);
-       struct gpio_bank *bank = get_gpio_bank(gpio);
+       struct gpio_bank *bank = get_irq_chip_data(irq);
 
        _set_gpio_irqenable(bank, gpio, 1);
 }
@@ -1111,16 +1117,81 @@ static struct irq_chip mpuio_irq_chip = {
        .mask           = mpuio_mask_irq,
        .unmask         = mpuio_unmask_irq,
        .set_type       = gpio_irq_type,
+#ifdef CONFIG_ARCH_OMAP16XX
+       /* REVISIT: assuming only 16xx supports MPUIO wake events */
+       .set_wake       = gpio_wake_enable,
+#endif
 };
 
 
 #define bank_is_mpuio(bank)    ((bank)->method == METHOD_MPUIO)
 
+
+#ifdef CONFIG_ARCH_OMAP16XX
+
+#include <linux/platform_device.h>
+
+static int omap_mpuio_suspend_late(struct platform_device *pdev, pm_message_t mesg)
+{
+       struct gpio_bank        *bank = platform_get_drvdata(pdev);
+       void __iomem            *mask_reg = bank->base + OMAP_MPUIO_GPIO_MASKIT;
+
+       spin_lock(&bank->lock);
+       bank->saved_wakeup = __raw_readl(mask_reg);
+       __raw_writel(0xffff & ~bank->suspend_wakeup, mask_reg);
+       spin_unlock(&bank->lock);
+
+       return 0;
+}
+
+static int omap_mpuio_resume_early(struct platform_device *pdev)
+{
+       struct gpio_bank        *bank = platform_get_drvdata(pdev);
+       void __iomem            *mask_reg = bank->base + OMAP_MPUIO_GPIO_MASKIT;
+
+       spin_lock(&bank->lock);
+       __raw_writel(bank->saved_wakeup, mask_reg);
+       spin_unlock(&bank->lock);
+
+       return 0;
+}
+
+/* use platform_driver for this, now that there's no longer any
+ * point to sys_device (other than not disturbing old code).
+ */
+static struct platform_driver omap_mpuio_driver = {
+       .suspend_late   = omap_mpuio_suspend_late,
+       .resume_early   = omap_mpuio_resume_early,
+       .driver         = {
+               .name   = "mpuio",
+       },
+};
+
+static struct platform_device omap_mpuio_device = {
+       .name           = "mpuio",
+       .id             = -1,
+       .dev = {
+               .driver = &omap_mpuio_driver.driver,
+       }
+       /* could list the /proc/iomem resources */
+};
+
+static inline void mpuio_init(void)
+{
+       if (platform_driver_register(&omap_mpuio_driver) == 0)
+               (void) platform_device_register(&omap_mpuio_device);
+}
+
+#else
+static inline void mpuio_init(void) {}
+#endif /* 16xx */
+
 #else
 
 extern struct irq_chip mpuio_irq_chip;
 
 #define bank_is_mpuio(bank)    0
+static inline void mpuio_init(void) {}
 
 #endif
 
@@ -1275,6 +1346,7 @@ static int __init _omap_gpio_init(void)
 #endif
                for (j = bank->virtual_irq_start;
                     j < bank->virtual_irq_start + gpio_count; j++) {
+                       set_irq_chip_data(j, bank);
                        if (bank_is_mpuio(bank))
                                set_irq_chip(j, &mpuio_irq_chip);
                        else
@@ -1486,6 +1558,8 @@ static int __init omap_gpio_sysinit(void)
        if (!initialized)
                ret = _omap_gpio_init();
 
+       mpuio_init();
+
 #if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX)
        if (cpu_is_omap16xx() || cpu_is_omap24xx()) {
                if (ret == 0) {