diff options
Diffstat (limited to 'arch/arm/plat-omap/gpio.c')
-rw-r--r-- | arch/arm/plat-omap/gpio.c | 63 |
1 files changed, 61 insertions, 2 deletions
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index 04846811d0aa..d2422c766cca 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c | |||
@@ -192,6 +192,7 @@ struct gpio_bank { | |||
192 | u32 saved_risingdetect; | 192 | u32 saved_risingdetect; |
193 | #endif | 193 | #endif |
194 | u32 level_mask; | 194 | u32 level_mask; |
195 | u32 toggle_mask; | ||
195 | spinlock_t lock; | 196 | spinlock_t lock; |
196 | struct gpio_chip chip; | 197 | struct gpio_chip chip; |
197 | struct clk *dbck; | 198 | struct clk *dbck; |
@@ -749,6 +750,44 @@ static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio, | |||
749 | } | 750 | } |
750 | #endif | 751 | #endif |
751 | 752 | ||
753 | #ifdef CONFIG_ARCH_OMAP1 | ||
754 | /* | ||
755 | * This only applies to chips that can't do both rising and falling edge | ||
756 | * detection at once. For all other chips, this function is a noop. | ||
757 | */ | ||
758 | static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio) | ||
759 | { | ||
760 | void __iomem *reg = bank->base; | ||
761 | u32 l = 0; | ||
762 | |||
763 | switch (bank->method) { | ||
764 | case METHOD_MPUIO: | ||
765 | reg += OMAP_MPUIO_GPIO_INT_EDGE; | ||
766 | break; | ||
767 | #ifdef CONFIG_ARCH_OMAP15XX | ||
768 | case METHOD_GPIO_1510: | ||
769 | reg += OMAP1510_GPIO_INT_CONTROL; | ||
770 | break; | ||
771 | #endif | ||
772 | #if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) | ||
773 | case METHOD_GPIO_7XX: | ||
774 | reg += OMAP7XX_GPIO_INT_CONTROL; | ||
775 | break; | ||
776 | #endif | ||
777 | default: | ||
778 | return; | ||
779 | } | ||
780 | |||
781 | l = __raw_readl(reg); | ||
782 | if ((l >> gpio) & 1) | ||
783 | l &= ~(1 << gpio); | ||
784 | else | ||
785 | l |= 1 << gpio; | ||
786 | |||
787 | __raw_writel(l, reg); | ||
788 | } | ||
789 | #endif | ||
790 | |||
752 | static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger) | 791 | static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger) |
753 | { | 792 | { |
754 | void __iomem *reg = bank->base; | 793 | void __iomem *reg = bank->base; |
@@ -759,6 +798,8 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger) | |||
759 | case METHOD_MPUIO: | 798 | case METHOD_MPUIO: |
760 | reg += OMAP_MPUIO_GPIO_INT_EDGE; | 799 | reg += OMAP_MPUIO_GPIO_INT_EDGE; |
761 | l = __raw_readl(reg); | 800 | l = __raw_readl(reg); |
801 | if (trigger & IRQ_TYPE_EDGE_BOTH) | ||
802 | bank->toggle_mask |= 1 << gpio; | ||
762 | if (trigger & IRQ_TYPE_EDGE_RISING) | 803 | if (trigger & IRQ_TYPE_EDGE_RISING) |
763 | l |= 1 << gpio; | 804 | l |= 1 << gpio; |
764 | else if (trigger & IRQ_TYPE_EDGE_FALLING) | 805 | else if (trigger & IRQ_TYPE_EDGE_FALLING) |
@@ -771,6 +812,8 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger) | |||
771 | case METHOD_GPIO_1510: | 812 | case METHOD_GPIO_1510: |
772 | reg += OMAP1510_GPIO_INT_CONTROL; | 813 | reg += OMAP1510_GPIO_INT_CONTROL; |
773 | l = __raw_readl(reg); | 814 | l = __raw_readl(reg); |
815 | if (trigger & IRQ_TYPE_EDGE_BOTH) | ||
816 | bank->toggle_mask |= 1 << gpio; | ||
774 | if (trigger & IRQ_TYPE_EDGE_RISING) | 817 | if (trigger & IRQ_TYPE_EDGE_RISING) |
775 | l |= 1 << gpio; | 818 | l |= 1 << gpio; |
776 | else if (trigger & IRQ_TYPE_EDGE_FALLING) | 819 | else if (trigger & IRQ_TYPE_EDGE_FALLING) |
@@ -803,6 +846,8 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger) | |||
803 | case METHOD_GPIO_7XX: | 846 | case METHOD_GPIO_7XX: |
804 | reg += OMAP7XX_GPIO_INT_CONTROL; | 847 | reg += OMAP7XX_GPIO_INT_CONTROL; |
805 | l = __raw_readl(reg); | 848 | l = __raw_readl(reg); |
849 | if (trigger & IRQ_TYPE_EDGE_BOTH) | ||
850 | bank->toggle_mask |= 1 << gpio; | ||
806 | if (trigger & IRQ_TYPE_EDGE_RISING) | 851 | if (trigger & IRQ_TYPE_EDGE_RISING) |
807 | l |= 1 << gpio; | 852 | l |= 1 << gpio; |
808 | else if (trigger & IRQ_TYPE_EDGE_FALLING) | 853 | else if (trigger & IRQ_TYPE_EDGE_FALLING) |
@@ -1072,7 +1117,7 @@ static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int ena | |||
1072 | */ | 1117 | */ |
1073 | static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable) | 1118 | static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable) |
1074 | { | 1119 | { |
1075 | unsigned long flags; | 1120 | unsigned long uninitialized_var(flags); |
1076 | 1121 | ||
1077 | switch (bank->method) { | 1122 | switch (bank->method) { |
1078 | #ifdef CONFIG_ARCH_OMAP16XX | 1123 | #ifdef CONFIG_ARCH_OMAP16XX |
@@ -1217,7 +1262,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | |||
1217 | { | 1262 | { |
1218 | void __iomem *isr_reg = NULL; | 1263 | void __iomem *isr_reg = NULL; |
1219 | u32 isr; | 1264 | u32 isr; |
1220 | unsigned int gpio_irq; | 1265 | unsigned int gpio_irq, gpio_index; |
1221 | struct gpio_bank *bank; | 1266 | struct gpio_bank *bank; |
1222 | u32 retrigger = 0; | 1267 | u32 retrigger = 0; |
1223 | int unmasked = 0; | 1268 | int unmasked = 0; |
@@ -1284,9 +1329,23 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | |||
1284 | 1329 | ||
1285 | gpio_irq = bank->virtual_irq_start; | 1330 | gpio_irq = bank->virtual_irq_start; |
1286 | for (; isr != 0; isr >>= 1, gpio_irq++) { | 1331 | for (; isr != 0; isr >>= 1, gpio_irq++) { |
1332 | gpio_index = get_gpio_index(irq_to_gpio(gpio_irq)); | ||
1333 | |||
1287 | if (!(isr & 1)) | 1334 | if (!(isr & 1)) |
1288 | continue; | 1335 | continue; |
1289 | 1336 | ||
1337 | #ifdef CONFIG_ARCH_OMAP1 | ||
1338 | /* | ||
1339 | * Some chips can't respond to both rising and falling | ||
1340 | * at the same time. If this irq was requested with | ||
1341 | * both flags, we need to flip the ICR data for the IRQ | ||
1342 | * to respond to the IRQ for the opposite direction. | ||
1343 | * This will be indicated in the bank toggle_mask. | ||
1344 | */ | ||
1345 | if (bank->toggle_mask & (1 << gpio_index)) | ||
1346 | _toggle_gpio_edge_triggering(bank, gpio_index); | ||
1347 | #endif | ||
1348 | |||
1290 | generic_handle_irq(gpio_irq); | 1349 | generic_handle_irq(gpio_irq); |
1291 | } | 1350 | } |
1292 | } | 1351 | } |