diff options
Diffstat (limited to 'arch/arm/plat-omap/gpio.c')
-rw-r--r-- | arch/arm/plat-omap/gpio.c | 176 |
1 files changed, 109 insertions, 67 deletions
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index 8c78e4e57b5c..1903a3491ee9 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c | |||
@@ -136,7 +136,6 @@ struct gpio_bank { | |||
136 | u16 irq; | 136 | u16 irq; |
137 | u16 virtual_irq_start; | 137 | u16 virtual_irq_start; |
138 | int method; | 138 | int method; |
139 | u32 reserved_map; | ||
140 | #if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) | 139 | #if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) |
141 | u32 suspend_wakeup; | 140 | u32 suspend_wakeup; |
142 | u32 saved_wakeup; | 141 | u32 saved_wakeup; |
@@ -149,7 +148,9 @@ struct gpio_bank { | |||
149 | u32 saved_fallingdetect; | 148 | u32 saved_fallingdetect; |
150 | u32 saved_risingdetect; | 149 | u32 saved_risingdetect; |
151 | #endif | 150 | #endif |
151 | u32 level_mask; | ||
152 | spinlock_t lock; | 152 | spinlock_t lock; |
153 | struct gpio_chip chip; | ||
153 | }; | 154 | }; |
154 | 155 | ||
155 | #define METHOD_MPUIO 0 | 156 | #define METHOD_MPUIO 0 |
@@ -538,10 +539,9 @@ static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio, | |||
538 | bank->enabled_non_wakeup_gpios &= ~gpio_bit; | 539 | bank->enabled_non_wakeup_gpios &= ~gpio_bit; |
539 | } | 540 | } |
540 | 541 | ||
541 | /* | 542 | bank->level_mask = |
542 | * FIXME: Possibly do 'set_irq_handler(j, handle_level_irq)' if only | 543 | __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0) | |
543 | * level triggering requested. | 544 | __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1); |
544 | */ | ||
545 | } | 545 | } |
546 | #endif | 546 | #endif |
547 | 547 | ||
@@ -652,6 +652,12 @@ static int gpio_irq_type(unsigned irq, unsigned type) | |||
652 | irq_desc[irq].status |= type; | 652 | irq_desc[irq].status |= type; |
653 | } | 653 | } |
654 | spin_unlock_irqrestore(&bank->lock, flags); | 654 | spin_unlock_irqrestore(&bank->lock, flags); |
655 | |||
656 | if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) | ||
657 | __set_irq_handler_unlocked(irq, handle_level_irq); | ||
658 | else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) | ||
659 | __set_irq_handler_unlocked(irq, handle_edge_irq); | ||
660 | |||
655 | return retval; | 661 | return retval; |
656 | } | 662 | } |
657 | 663 | ||
@@ -903,19 +909,17 @@ int omap_request_gpio(int gpio) | |||
903 | { | 909 | { |
904 | struct gpio_bank *bank; | 910 | struct gpio_bank *bank; |
905 | unsigned long flags; | 911 | unsigned long flags; |
912 | int status; | ||
906 | 913 | ||
907 | if (check_gpio(gpio) < 0) | 914 | if (check_gpio(gpio) < 0) |
908 | return -EINVAL; | 915 | return -EINVAL; |
909 | 916 | ||
917 | status = gpio_request(gpio, NULL); | ||
918 | if (status < 0) | ||
919 | return status; | ||
920 | |||
910 | bank = get_gpio_bank(gpio); | 921 | bank = get_gpio_bank(gpio); |
911 | spin_lock_irqsave(&bank->lock, flags); | 922 | spin_lock_irqsave(&bank->lock, flags); |
912 | if (unlikely(bank->reserved_map & (1 << get_gpio_index(gpio)))) { | ||
913 | printk(KERN_ERR "omap-gpio: GPIO %d is already reserved!\n", gpio); | ||
914 | dump_stack(); | ||
915 | spin_unlock_irqrestore(&bank->lock, flags); | ||
916 | return -1; | ||
917 | } | ||
918 | bank->reserved_map |= (1 << get_gpio_index(gpio)); | ||
919 | 923 | ||
920 | /* Set trigger to none. You need to enable the desired trigger with | 924 | /* Set trigger to none. You need to enable the desired trigger with |
921 | * request_irq() or set_irq_type(). | 925 | * request_irq() or set_irq_type(). |
@@ -945,10 +949,11 @@ void omap_free_gpio(int gpio) | |||
945 | return; | 949 | return; |
946 | bank = get_gpio_bank(gpio); | 950 | bank = get_gpio_bank(gpio); |
947 | spin_lock_irqsave(&bank->lock, flags); | 951 | spin_lock_irqsave(&bank->lock, flags); |
948 | if (unlikely(!(bank->reserved_map & (1 << get_gpio_index(gpio))))) { | 952 | if (unlikely(!gpiochip_is_requested(&bank->chip, |
953 | get_gpio_index(gpio)))) { | ||
954 | spin_unlock_irqrestore(&bank->lock, flags); | ||
949 | printk(KERN_ERR "omap-gpio: GPIO %d wasn't reserved!\n", gpio); | 955 | printk(KERN_ERR "omap-gpio: GPIO %d wasn't reserved!\n", gpio); |
950 | dump_stack(); | 956 | dump_stack(); |
951 | spin_unlock_irqrestore(&bank->lock, flags); | ||
952 | return; | 957 | return; |
953 | } | 958 | } |
954 | #ifdef CONFIG_ARCH_OMAP16XX | 959 | #ifdef CONFIG_ARCH_OMAP16XX |
@@ -965,9 +970,9 @@ void omap_free_gpio(int gpio) | |||
965 | __raw_writel(1 << get_gpio_index(gpio), reg); | 970 | __raw_writel(1 << get_gpio_index(gpio), reg); |
966 | } | 971 | } |
967 | #endif | 972 | #endif |
968 | bank->reserved_map &= ~(1 << get_gpio_index(gpio)); | ||
969 | _reset_gpio(bank, gpio); | 973 | _reset_gpio(bank, gpio); |
970 | spin_unlock_irqrestore(&bank->lock, flags); | 974 | spin_unlock_irqrestore(&bank->lock, flags); |
975 | gpio_free(gpio); | ||
971 | } | 976 | } |
972 | 977 | ||
973 | /* | 978 | /* |
@@ -1022,12 +1027,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | |||
1022 | isr &= 0x0000ffff; | 1027 | isr &= 0x0000ffff; |
1023 | 1028 | ||
1024 | if (cpu_class_is_omap2()) { | 1029 | if (cpu_class_is_omap2()) { |
1025 | level_mask = | 1030 | level_mask = bank->level_mask & enabled; |
1026 | __raw_readl(bank->base + | ||
1027 | OMAP24XX_GPIO_LEVELDETECT0) | | ||
1028 | __raw_readl(bank->base + | ||
1029 | OMAP24XX_GPIO_LEVELDETECT1); | ||
1030 | level_mask &= enabled; | ||
1031 | } | 1031 | } |
1032 | 1032 | ||
1033 | /* clear edge sensitive interrupts before handler(s) are | 1033 | /* clear edge sensitive interrupts before handler(s) are |
@@ -1052,51 +1052,13 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | |||
1052 | gpio_irq = bank->virtual_irq_start; | 1052 | gpio_irq = bank->virtual_irq_start; |
1053 | for (; isr != 0; isr >>= 1, gpio_irq++) { | 1053 | for (; isr != 0; isr >>= 1, gpio_irq++) { |
1054 | struct irq_desc *d; | 1054 | struct irq_desc *d; |
1055 | int irq_mask; | 1055 | |
1056 | if (!(isr & 1)) | 1056 | if (!(isr & 1)) |
1057 | continue; | 1057 | continue; |
1058 | d = irq_desc + gpio_irq; | 1058 | d = irq_desc + gpio_irq; |
1059 | /* Don't run the handler if it's already running | ||
1060 | * or was disabled lazely. | ||
1061 | */ | ||
1062 | if (unlikely((d->depth || | ||
1063 | (d->status & IRQ_INPROGRESS)))) { | ||
1064 | irq_mask = 1 << | ||
1065 | (gpio_irq - bank->virtual_irq_start); | ||
1066 | /* The unmasking will be done by | ||
1067 | * enable_irq in case it is disabled or | ||
1068 | * after returning from the handler if | ||
1069 | * it's already running. | ||
1070 | */ | ||
1071 | _enable_gpio_irqbank(bank, irq_mask, 0); | ||
1072 | if (!d->depth) { | ||
1073 | /* Level triggered interrupts | ||
1074 | * won't ever be reentered | ||
1075 | */ | ||
1076 | BUG_ON(level_mask & irq_mask); | ||
1077 | d->status |= IRQ_PENDING; | ||
1078 | } | ||
1079 | continue; | ||
1080 | } | ||
1081 | 1059 | ||
1082 | desc_handle_irq(gpio_irq, d); | 1060 | desc_handle_irq(gpio_irq, d); |
1083 | |||
1084 | if (unlikely((d->status & IRQ_PENDING) && !d->depth)) { | ||
1085 | irq_mask = 1 << | ||
1086 | (gpio_irq - bank->virtual_irq_start); | ||
1087 | d->status &= ~IRQ_PENDING; | ||
1088 | _enable_gpio_irqbank(bank, irq_mask, 1); | ||
1089 | retrigger |= irq_mask; | ||
1090 | } | ||
1091 | } | 1061 | } |
1092 | |||
1093 | if (cpu_class_is_omap2()) { | ||
1094 | /* clear level sensitive interrupts after handler(s) */ | ||
1095 | _enable_gpio_irqbank(bank, isr_saved & level_mask, 0); | ||
1096 | _clear_gpio_irqbank(bank, isr_saved & level_mask); | ||
1097 | _enable_gpio_irqbank(bank, isr_saved & level_mask, 1); | ||
1098 | } | ||
1099 | |||
1100 | } | 1062 | } |
1101 | /* if bank has any level sensitive GPIO pin interrupt | 1063 | /* if bank has any level sensitive GPIO pin interrupt |
1102 | configured, we must unmask the bank interrupt only after | 1064 | configured, we must unmask the bank interrupt only after |
@@ -1135,6 +1097,14 @@ static void gpio_unmask_irq(unsigned int irq) | |||
1135 | { | 1097 | { |
1136 | unsigned int gpio = irq - IH_GPIO_BASE; | 1098 | unsigned int gpio = irq - IH_GPIO_BASE; |
1137 | struct gpio_bank *bank = get_irq_chip_data(irq); | 1099 | struct gpio_bank *bank = get_irq_chip_data(irq); |
1100 | unsigned int irq_mask = 1 << get_gpio_index(gpio); | ||
1101 | |||
1102 | /* For level-triggered GPIOs, the clearing must be done after | ||
1103 | * the HW source is cleared, thus after the handler has run */ | ||
1104 | if (bank->level_mask & irq_mask) { | ||
1105 | _set_gpio_irqenable(bank, gpio, 0); | ||
1106 | _clear_gpio_irqstatus(bank, gpio); | ||
1107 | } | ||
1138 | 1108 | ||
1139 | _set_gpio_irqenable(bank, gpio, 1); | 1109 | _set_gpio_irqenable(bank, gpio, 1); |
1140 | } | 1110 | } |
@@ -1266,6 +1236,53 @@ static inline void mpuio_init(void) {} | |||
1266 | 1236 | ||
1267 | /*---------------------------------------------------------------------*/ | 1237 | /*---------------------------------------------------------------------*/ |
1268 | 1238 | ||
1239 | /* REVISIT these are stupid implementations! replace by ones that | ||
1240 | * don't switch on METHOD_* and which mostly avoid spinlocks | ||
1241 | */ | ||
1242 | |||
1243 | static int gpio_input(struct gpio_chip *chip, unsigned offset) | ||
1244 | { | ||
1245 | struct gpio_bank *bank; | ||
1246 | unsigned long flags; | ||
1247 | |||
1248 | bank = container_of(chip, struct gpio_bank, chip); | ||
1249 | spin_lock_irqsave(&bank->lock, flags); | ||
1250 | _set_gpio_direction(bank, offset, 1); | ||
1251 | spin_unlock_irqrestore(&bank->lock, flags); | ||
1252 | return 0; | ||
1253 | } | ||
1254 | |||
1255 | static int gpio_get(struct gpio_chip *chip, unsigned offset) | ||
1256 | { | ||
1257 | return omap_get_gpio_datain(chip->base + offset); | ||
1258 | } | ||
1259 | |||
1260 | static int gpio_output(struct gpio_chip *chip, unsigned offset, int value) | ||
1261 | { | ||
1262 | struct gpio_bank *bank; | ||
1263 | unsigned long flags; | ||
1264 | |||
1265 | bank = container_of(chip, struct gpio_bank, chip); | ||
1266 | spin_lock_irqsave(&bank->lock, flags); | ||
1267 | _set_gpio_dataout(bank, offset, value); | ||
1268 | _set_gpio_direction(bank, offset, 0); | ||
1269 | spin_unlock_irqrestore(&bank->lock, flags); | ||
1270 | return 0; | ||
1271 | } | ||
1272 | |||
1273 | static void gpio_set(struct gpio_chip *chip, unsigned offset, int value) | ||
1274 | { | ||
1275 | struct gpio_bank *bank; | ||
1276 | unsigned long flags; | ||
1277 | |||
1278 | bank = container_of(chip, struct gpio_bank, chip); | ||
1279 | spin_lock_irqsave(&bank->lock, flags); | ||
1280 | _set_gpio_dataout(bank, offset, value); | ||
1281 | spin_unlock_irqrestore(&bank->lock, flags); | ||
1282 | } | ||
1283 | |||
1284 | /*---------------------------------------------------------------------*/ | ||
1285 | |||
1269 | static int initialized; | 1286 | static int initialized; |
1270 | #if !defined(CONFIG_ARCH_OMAP3) | 1287 | #if !defined(CONFIG_ARCH_OMAP3) |
1271 | static struct clk * gpio_ick; | 1288 | static struct clk * gpio_ick; |
@@ -1293,6 +1310,7 @@ static struct lock_class_key gpio_lock_class; | |||
1293 | static int __init _omap_gpio_init(void) | 1310 | static int __init _omap_gpio_init(void) |
1294 | { | 1311 | { |
1295 | int i; | 1312 | int i; |
1313 | int gpio = 0; | ||
1296 | struct gpio_bank *bank; | 1314 | struct gpio_bank *bank; |
1297 | #if defined(CONFIG_ARCH_OMAP3) | 1315 | #if defined(CONFIG_ARCH_OMAP3) |
1298 | char clk_name[11]; | 1316 | char clk_name[11]; |
@@ -1423,7 +1441,6 @@ static int __init _omap_gpio_init(void) | |||
1423 | int j, gpio_count = 16; | 1441 | int j, gpio_count = 16; |
1424 | 1442 | ||
1425 | bank = &gpio_bank[i]; | 1443 | bank = &gpio_bank[i]; |
1426 | bank->reserved_map = 0; | ||
1427 | bank->base = IO_ADDRESS(bank->base); | 1444 | bank->base = IO_ADDRESS(bank->base); |
1428 | spin_lock_init(&bank->lock); | 1445 | spin_lock_init(&bank->lock); |
1429 | if (bank_is_mpuio(bank)) | 1446 | if (bank_is_mpuio(bank)) |
@@ -1461,6 +1478,26 @@ static int __init _omap_gpio_init(void) | |||
1461 | gpio_count = 32; | 1478 | gpio_count = 32; |
1462 | } | 1479 | } |
1463 | #endif | 1480 | #endif |
1481 | |||
1482 | /* REVISIT eventually switch from OMAP-specific gpio structs | ||
1483 | * over to the generic ones | ||
1484 | */ | ||
1485 | bank->chip.direction_input = gpio_input; | ||
1486 | bank->chip.get = gpio_get; | ||
1487 | bank->chip.direction_output = gpio_output; | ||
1488 | bank->chip.set = gpio_set; | ||
1489 | if (bank_is_mpuio(bank)) { | ||
1490 | bank->chip.label = "mpuio"; | ||
1491 | bank->chip.base = OMAP_MPUIO(0); | ||
1492 | } else { | ||
1493 | bank->chip.label = "gpio"; | ||
1494 | bank->chip.base = gpio; | ||
1495 | gpio += gpio_count; | ||
1496 | } | ||
1497 | bank->chip.ngpio = gpio_count; | ||
1498 | |||
1499 | gpiochip_add(&bank->chip); | ||
1500 | |||
1464 | for (j = bank->virtual_irq_start; | 1501 | for (j = bank->virtual_irq_start; |
1465 | j < bank->virtual_irq_start + gpio_count; j++) { | 1502 | j < bank->virtual_irq_start + gpio_count; j++) { |
1466 | lockdep_set_class(&irq_desc[j].lock, &gpio_lock_class); | 1503 | lockdep_set_class(&irq_desc[j].lock, &gpio_lock_class); |
@@ -1757,8 +1794,10 @@ static int dbg_gpio_show(struct seq_file *s, void *unused) | |||
1757 | 1794 | ||
1758 | for (j = 0; j < bankwidth; j++, gpio++, mask <<= 1) { | 1795 | for (j = 0; j < bankwidth; j++, gpio++, mask <<= 1) { |
1759 | unsigned irq, value, is_in, irqstat; | 1796 | unsigned irq, value, is_in, irqstat; |
1797 | const char *label; | ||
1760 | 1798 | ||
1761 | if (!(bank->reserved_map & mask)) | 1799 | label = gpiochip_is_requested(&bank->chip, j); |
1800 | if (!label) | ||
1762 | continue; | 1801 | continue; |
1763 | 1802 | ||
1764 | irq = bank->virtual_irq_start + j; | 1803 | irq = bank->virtual_irq_start + j; |
@@ -1766,13 +1805,16 @@ static int dbg_gpio_show(struct seq_file *s, void *unused) | |||
1766 | is_in = gpio_is_input(bank, mask); | 1805 | is_in = gpio_is_input(bank, mask); |
1767 | 1806 | ||
1768 | if (bank_is_mpuio(bank)) | 1807 | if (bank_is_mpuio(bank)) |
1769 | seq_printf(s, "MPUIO %2d: ", j); | 1808 | seq_printf(s, "MPUIO %2d ", j); |
1770 | else | 1809 | else |
1771 | seq_printf(s, "GPIO %3d: ", gpio); | 1810 | seq_printf(s, "GPIO %3d ", gpio); |
1772 | seq_printf(s, "%s %s", | 1811 | seq_printf(s, "(%10s): %s %s", |
1812 | label, | ||
1773 | is_in ? "in " : "out", | 1813 | is_in ? "in " : "out", |
1774 | value ? "hi" : "lo"); | 1814 | value ? "hi" : "lo"); |
1775 | 1815 | ||
1816 | /* FIXME for at least omap2, show pullup/pulldown state */ | ||
1817 | |||
1776 | irqstat = irq_desc[irq].status; | 1818 | irqstat = irq_desc[irq].status; |
1777 | if (is_in && ((bank->suspend_wakeup & mask) | 1819 | if (is_in && ((bank->suspend_wakeup & mask) |
1778 | || irqstat & IRQ_TYPE_SENSE_MASK)) { | 1820 | || irqstat & IRQ_TYPE_SENSE_MASK)) { |
@@ -1795,10 +1837,10 @@ static int dbg_gpio_show(struct seq_file *s, void *unused) | |||
1795 | trigger = "high"; | 1837 | trigger = "high"; |
1796 | break; | 1838 | break; |
1797 | case IRQ_TYPE_NONE: | 1839 | case IRQ_TYPE_NONE: |
1798 | trigger = "(unspecified)"; | 1840 | trigger = "(?)"; |
1799 | break; | 1841 | break; |
1800 | } | 1842 | } |
1801 | seq_printf(s, ", irq-%d %s%s", | 1843 | seq_printf(s, ", irq-%d %-8s%s", |
1802 | irq, trigger, | 1844 | irq, trigger, |
1803 | (bank->suspend_wakeup & mask) | 1845 | (bank->suspend_wakeup & mask) |
1804 | ? " wakeup" : ""); | 1846 | ? " wakeup" : ""); |