diff options
Diffstat (limited to 'arch/arm/plat-omap/gpio.c')
-rw-r--r-- | arch/arm/plat-omap/gpio.c | 93 |
1 files changed, 83 insertions, 10 deletions
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index 14a3f7118c73..df0ff0fd881a 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c | |||
@@ -773,29 +773,35 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable) | |||
773 | { | 773 | { |
774 | switch (bank->method) { | 774 | switch (bank->method) { |
775 | #ifdef CONFIG_ARCH_OMAP16XX | 775 | #ifdef CONFIG_ARCH_OMAP16XX |
776 | case METHOD_MPUIO: | ||
776 | case METHOD_GPIO_1610: | 777 | case METHOD_GPIO_1610: |
777 | spin_lock(&bank->lock); | 778 | spin_lock(&bank->lock); |
778 | if (enable) | 779 | if (enable) { |
779 | bank->suspend_wakeup |= (1 << gpio); | 780 | bank->suspend_wakeup |= (1 << gpio); |
780 | else | 781 | enable_irq_wake(bank->irq); |
782 | } else { | ||
783 | disable_irq_wake(bank->irq); | ||
781 | bank->suspend_wakeup &= ~(1 << gpio); | 784 | bank->suspend_wakeup &= ~(1 << gpio); |
785 | } | ||
782 | spin_unlock(&bank->lock); | 786 | spin_unlock(&bank->lock); |
783 | return 0; | 787 | return 0; |
784 | #endif | 788 | #endif |
785 | #ifdef CONFIG_ARCH_OMAP24XX | 789 | #ifdef CONFIG_ARCH_OMAP24XX |
786 | case METHOD_GPIO_24XX: | 790 | case METHOD_GPIO_24XX: |
791 | if (bank->non_wakeup_gpios & (1 << gpio)) { | ||
792 | printk(KERN_ERR "Unable to modify wakeup on " | ||
793 | "non-wakeup GPIO%d\n", | ||
794 | (bank - gpio_bank) * 32 + gpio); | ||
795 | return -EINVAL; | ||
796 | } | ||
787 | spin_lock(&bank->lock); | 797 | spin_lock(&bank->lock); |
788 | if (enable) { | 798 | if (enable) { |
789 | if (bank->non_wakeup_gpios & (1 << gpio)) { | ||
790 | printk(KERN_ERR "Unable to enable wakeup on " | ||
791 | "non-wakeup GPIO%d\n", | ||
792 | (bank - gpio_bank) * 32 + gpio); | ||
793 | spin_unlock(&bank->lock); | ||
794 | return -EINVAL; | ||
795 | } | ||
796 | bank->suspend_wakeup |= (1 << gpio); | 799 | bank->suspend_wakeup |= (1 << gpio); |
797 | } else | 800 | enable_irq_wake(bank->irq); |
801 | } else { | ||
802 | disable_irq_wake(bank->irq); | ||
798 | bank->suspend_wakeup &= ~(1 << gpio); | 803 | bank->suspend_wakeup &= ~(1 << gpio); |
804 | } | ||
799 | spin_unlock(&bank->lock); | 805 | spin_unlock(&bank->lock); |
800 | return 0; | 806 | return 0; |
801 | #endif | 807 | #endif |
@@ -1111,16 +1117,81 @@ static struct irq_chip mpuio_irq_chip = { | |||
1111 | .mask = mpuio_mask_irq, | 1117 | .mask = mpuio_mask_irq, |
1112 | .unmask = mpuio_unmask_irq, | 1118 | .unmask = mpuio_unmask_irq, |
1113 | .set_type = gpio_irq_type, | 1119 | .set_type = gpio_irq_type, |
1120 | #ifdef CONFIG_ARCH_OMAP16XX | ||
1121 | /* REVISIT: assuming only 16xx supports MPUIO wake events */ | ||
1122 | .set_wake = gpio_wake_enable, | ||
1123 | #endif | ||
1114 | }; | 1124 | }; |
1115 | 1125 | ||
1116 | 1126 | ||
1117 | #define bank_is_mpuio(bank) ((bank)->method == METHOD_MPUIO) | 1127 | #define bank_is_mpuio(bank) ((bank)->method == METHOD_MPUIO) |
1118 | 1128 | ||
1129 | |||
1130 | #ifdef CONFIG_ARCH_OMAP16XX | ||
1131 | |||
1132 | #include <linux/platform_device.h> | ||
1133 | |||
1134 | static int omap_mpuio_suspend_late(struct platform_device *pdev, pm_message_t mesg) | ||
1135 | { | ||
1136 | struct gpio_bank *bank = platform_get_drvdata(pdev); | ||
1137 | void __iomem *mask_reg = bank->base + OMAP_MPUIO_GPIO_MASKIT; | ||
1138 | |||
1139 | spin_lock(&bank->lock); | ||
1140 | bank->saved_wakeup = __raw_readl(mask_reg); | ||
1141 | __raw_writel(0xffff & ~bank->suspend_wakeup, mask_reg); | ||
1142 | spin_unlock(&bank->lock); | ||
1143 | |||
1144 | return 0; | ||
1145 | } | ||
1146 | |||
1147 | static int omap_mpuio_resume_early(struct platform_device *pdev) | ||
1148 | { | ||
1149 | struct gpio_bank *bank = platform_get_drvdata(pdev); | ||
1150 | void __iomem *mask_reg = bank->base + OMAP_MPUIO_GPIO_MASKIT; | ||
1151 | |||
1152 | spin_lock(&bank->lock); | ||
1153 | __raw_writel(bank->saved_wakeup, mask_reg); | ||
1154 | spin_unlock(&bank->lock); | ||
1155 | |||
1156 | return 0; | ||
1157 | } | ||
1158 | |||
1159 | /* use platform_driver for this, now that there's no longer any | ||
1160 | * point to sys_device (other than not disturbing old code). | ||
1161 | */ | ||
1162 | static struct platform_driver omap_mpuio_driver = { | ||
1163 | .suspend_late = omap_mpuio_suspend_late, | ||
1164 | .resume_early = omap_mpuio_resume_early, | ||
1165 | .driver = { | ||
1166 | .name = "mpuio", | ||
1167 | }, | ||
1168 | }; | ||
1169 | |||
1170 | static struct platform_device omap_mpuio_device = { | ||
1171 | .name = "mpuio", | ||
1172 | .id = -1, | ||
1173 | .dev = { | ||
1174 | .driver = &omap_mpuio_driver.driver, | ||
1175 | } | ||
1176 | /* could list the /proc/iomem resources */ | ||
1177 | }; | ||
1178 | |||
1179 | static inline void mpuio_init(void) | ||
1180 | { | ||
1181 | if (platform_driver_register(&omap_mpuio_driver) == 0) | ||
1182 | (void) platform_device_register(&omap_mpuio_device); | ||
1183 | } | ||
1184 | |||
1185 | #else | ||
1186 | static inline void mpuio_init(void) {} | ||
1187 | #endif /* 16xx */ | ||
1188 | |||
1119 | #else | 1189 | #else |
1120 | 1190 | ||
1121 | extern struct irq_chip mpuio_irq_chip; | 1191 | extern struct irq_chip mpuio_irq_chip; |
1122 | 1192 | ||
1123 | #define bank_is_mpuio(bank) 0 | 1193 | #define bank_is_mpuio(bank) 0 |
1194 | static inline void mpuio_init(void) {} | ||
1124 | 1195 | ||
1125 | #endif | 1196 | #endif |
1126 | 1197 | ||
@@ -1487,6 +1558,8 @@ static int __init omap_gpio_sysinit(void) | |||
1487 | if (!initialized) | 1558 | if (!initialized) |
1488 | ret = _omap_gpio_init(); | 1559 | ret = _omap_gpio_init(); |
1489 | 1560 | ||
1561 | mpuio_init(); | ||
1562 | |||
1490 | #if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX) | 1563 | #if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX) |
1491 | if (cpu_is_omap16xx() || cpu_is_omap24xx()) { | 1564 | if (cpu_is_omap16xx() || cpu_is_omap24xx()) { |
1492 | if (ret == 0) { | 1565 | if (ret == 0) { |