aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/Kconfig1
-rw-r--r--arch/arm/plat-omap/gpio.c107
-rw-r--r--include/asm-arm/arch-omap/gpio.h57
3 files changed, 105 insertions, 60 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 4039a133006e..992028f46bd1 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -468,6 +468,7 @@ config ARCH_DAVINCI
468config ARCH_OMAP 468config ARCH_OMAP
469 bool "TI OMAP" 469 bool "TI OMAP"
470 select GENERIC_GPIO 470 select GENERIC_GPIO
471 select HAVE_GPIO_LIB
471 select GENERIC_TIME 472 select GENERIC_TIME
472 select GENERIC_CLOCKEVENTS 473 select GENERIC_CLOCKEVENTS
473 help 474 help
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index 8c78e4e57b5c..56889fdb0740 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;
@@ -150,6 +149,7 @@ struct gpio_bank {
150 u32 saved_risingdetect; 149 u32 saved_risingdetect;
151#endif 150#endif
152 spinlock_t lock; 151 spinlock_t lock;
152 struct gpio_chip chip;
153}; 153};
154 154
155#define METHOD_MPUIO 0 155#define METHOD_MPUIO 0
@@ -903,19 +903,17 @@ int omap_request_gpio(int gpio)
903{ 903{
904 struct gpio_bank *bank; 904 struct gpio_bank *bank;
905 unsigned long flags; 905 unsigned long flags;
906 int status;
906 907
907 if (check_gpio(gpio) < 0) 908 if (check_gpio(gpio) < 0)
908 return -EINVAL; 909 return -EINVAL;
909 910
911 status = gpio_request(gpio, NULL);
912 if (status < 0)
913 return status;
914
910 bank = get_gpio_bank(gpio); 915 bank = get_gpio_bank(gpio);
911 spin_lock_irqsave(&bank->lock, flags); 916 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 917
920 /* Set trigger to none. You need to enable the desired trigger with 918 /* Set trigger to none. You need to enable the desired trigger with
921 * request_irq() or set_irq_type(). 919 * request_irq() or set_irq_type().
@@ -945,10 +943,11 @@ void omap_free_gpio(int gpio)
945 return; 943 return;
946 bank = get_gpio_bank(gpio); 944 bank = get_gpio_bank(gpio);
947 spin_lock_irqsave(&bank->lock, flags); 945 spin_lock_irqsave(&bank->lock, flags);
948 if (unlikely(!(bank->reserved_map & (1 << get_gpio_index(gpio))))) { 946 if (unlikely(!gpiochip_is_requested(&bank->chip,
947 get_gpio_index(gpio)))) {
948 spin_unlock_irqrestore(&bank->lock, flags);
949 printk(KERN_ERR "omap-gpio: GPIO %d wasn't reserved!\n", gpio); 949 printk(KERN_ERR "omap-gpio: GPIO %d wasn't reserved!\n", gpio);
950 dump_stack(); 950 dump_stack();
951 spin_unlock_irqrestore(&bank->lock, flags);
952 return; 951 return;
953 } 952 }
954#ifdef CONFIG_ARCH_OMAP16XX 953#ifdef CONFIG_ARCH_OMAP16XX
@@ -965,9 +964,9 @@ void omap_free_gpio(int gpio)
965 __raw_writel(1 << get_gpio_index(gpio), reg); 964 __raw_writel(1 << get_gpio_index(gpio), reg);
966 } 965 }
967#endif 966#endif
968 bank->reserved_map &= ~(1 << get_gpio_index(gpio));
969 _reset_gpio(bank, gpio); 967 _reset_gpio(bank, gpio);
970 spin_unlock_irqrestore(&bank->lock, flags); 968 spin_unlock_irqrestore(&bank->lock, flags);
969 gpio_free(gpio);
971} 970}
972 971
973/* 972/*
@@ -1266,6 +1265,53 @@ static inline void mpuio_init(void) {}
1266 1265
1267/*---------------------------------------------------------------------*/ 1266/*---------------------------------------------------------------------*/
1268 1267
1268/* REVISIT these are stupid implementations! replace by ones that
1269 * don't switch on METHOD_* and which mostly avoid spinlocks
1270 */
1271
1272static int gpio_input(struct gpio_chip *chip, unsigned offset)
1273{
1274 struct gpio_bank *bank;
1275 unsigned long flags;
1276
1277 bank = container_of(chip, struct gpio_bank, chip);
1278 spin_lock_irqsave(&bank->lock, flags);
1279 _set_gpio_direction(bank, offset, 1);
1280 spin_unlock_irqrestore(&bank->lock, flags);
1281 return 0;
1282}
1283
1284static int gpio_get(struct gpio_chip *chip, unsigned offset)
1285{
1286 return omap_get_gpio_datain(chip->base + offset);
1287}
1288
1289static int gpio_output(struct gpio_chip *chip, unsigned offset, int value)
1290{
1291 struct gpio_bank *bank;
1292 unsigned long flags;
1293
1294 bank = container_of(chip, struct gpio_bank, chip);
1295 spin_lock_irqsave(&bank->lock, flags);
1296 _set_gpio_dataout(bank, offset, value);
1297 _set_gpio_direction(bank, offset, 0);
1298 spin_unlock_irqrestore(&bank->lock, flags);
1299 return 0;
1300}
1301
1302static void gpio_set(struct gpio_chip *chip, unsigned offset, int value)
1303{
1304 struct gpio_bank *bank;
1305 unsigned long flags;
1306
1307 bank = container_of(chip, struct gpio_bank, chip);
1308 spin_lock_irqsave(&bank->lock, flags);
1309 _set_gpio_dataout(bank, offset, value);
1310 spin_unlock_irqrestore(&bank->lock, flags);
1311}
1312
1313/*---------------------------------------------------------------------*/
1314
1269static int initialized; 1315static int initialized;
1270#if !defined(CONFIG_ARCH_OMAP3) 1316#if !defined(CONFIG_ARCH_OMAP3)
1271static struct clk * gpio_ick; 1317static struct clk * gpio_ick;
@@ -1293,6 +1339,7 @@ static struct lock_class_key gpio_lock_class;
1293static int __init _omap_gpio_init(void) 1339static int __init _omap_gpio_init(void)
1294{ 1340{
1295 int i; 1341 int i;
1342 int gpio = 0;
1296 struct gpio_bank *bank; 1343 struct gpio_bank *bank;
1297#if defined(CONFIG_ARCH_OMAP3) 1344#if defined(CONFIG_ARCH_OMAP3)
1298 char clk_name[11]; 1345 char clk_name[11];
@@ -1423,7 +1470,6 @@ static int __init _omap_gpio_init(void)
1423 int j, gpio_count = 16; 1470 int j, gpio_count = 16;
1424 1471
1425 bank = &gpio_bank[i]; 1472 bank = &gpio_bank[i];
1426 bank->reserved_map = 0;
1427 bank->base = IO_ADDRESS(bank->base); 1473 bank->base = IO_ADDRESS(bank->base);
1428 spin_lock_init(&bank->lock); 1474 spin_lock_init(&bank->lock);
1429 if (bank_is_mpuio(bank)) 1475 if (bank_is_mpuio(bank))
@@ -1461,6 +1507,26 @@ static int __init _omap_gpio_init(void)
1461 gpio_count = 32; 1507 gpio_count = 32;
1462 } 1508 }
1463#endif 1509#endif
1510
1511 /* REVISIT eventually switch from OMAP-specific gpio structs
1512 * over to the generic ones
1513 */
1514 bank->chip.direction_input = gpio_input;
1515 bank->chip.get = gpio_get;
1516 bank->chip.direction_output = gpio_output;
1517 bank->chip.set = gpio_set;
1518 if (bank_is_mpuio(bank)) {
1519 bank->chip.label = "mpuio";
1520 bank->chip.base = OMAP_MPUIO(0);
1521 } else {
1522 bank->chip.label = "gpio";
1523 bank->chip.base = gpio;
1524 gpio += gpio_count;
1525 }
1526 bank->chip.ngpio = gpio_count;
1527
1528 gpiochip_add(&bank->chip);
1529
1464 for (j = bank->virtual_irq_start; 1530 for (j = bank->virtual_irq_start;
1465 j < bank->virtual_irq_start + gpio_count; j++) { 1531 j < bank->virtual_irq_start + gpio_count; j++) {
1466 lockdep_set_class(&irq_desc[j].lock, &gpio_lock_class); 1532 lockdep_set_class(&irq_desc[j].lock, &gpio_lock_class);
@@ -1757,8 +1823,10 @@ static int dbg_gpio_show(struct seq_file *s, void *unused)
1757 1823
1758 for (j = 0; j < bankwidth; j++, gpio++, mask <<= 1) { 1824 for (j = 0; j < bankwidth; j++, gpio++, mask <<= 1) {
1759 unsigned irq, value, is_in, irqstat; 1825 unsigned irq, value, is_in, irqstat;
1826 const char *label;
1760 1827
1761 if (!(bank->reserved_map & mask)) 1828 label = gpiochip_is_requested(&bank->chip, j);
1829 if (!label)
1762 continue; 1830 continue;
1763 1831
1764 irq = bank->virtual_irq_start + j; 1832 irq = bank->virtual_irq_start + j;
@@ -1766,13 +1834,16 @@ static int dbg_gpio_show(struct seq_file *s, void *unused)
1766 is_in = gpio_is_input(bank, mask); 1834 is_in = gpio_is_input(bank, mask);
1767 1835
1768 if (bank_is_mpuio(bank)) 1836 if (bank_is_mpuio(bank))
1769 seq_printf(s, "MPUIO %2d: ", j); 1837 seq_printf(s, "MPUIO %2d ", j);
1770 else 1838 else
1771 seq_printf(s, "GPIO %3d: ", gpio); 1839 seq_printf(s, "GPIO %3d ", gpio);
1772 seq_printf(s, "%s %s", 1840 seq_printf(s, "(%10s): %s %s",
1841 label,
1773 is_in ? "in " : "out", 1842 is_in ? "in " : "out",
1774 value ? "hi" : "lo"); 1843 value ? "hi" : "lo");
1775 1844
1845/* FIXME for at least omap2, show pullup/pulldown state */
1846
1776 irqstat = irq_desc[irq].status; 1847 irqstat = irq_desc[irq].status;
1777 if (is_in && ((bank->suspend_wakeup & mask) 1848 if (is_in && ((bank->suspend_wakeup & mask)
1778 || irqstat & IRQ_TYPE_SENSE_MASK)) { 1849 || irqstat & IRQ_TYPE_SENSE_MASK)) {
@@ -1795,10 +1866,10 @@ static int dbg_gpio_show(struct seq_file *s, void *unused)
1795 trigger = "high"; 1866 trigger = "high";
1796 break; 1867 break;
1797 case IRQ_TYPE_NONE: 1868 case IRQ_TYPE_NONE:
1798 trigger = "(unspecified)"; 1869 trigger = "(?)";
1799 break; 1870 break;
1800 } 1871 }
1801 seq_printf(s, ", irq-%d %s%s", 1872 seq_printf(s, ", irq-%d %-8s%s",
1802 irq, trigger, 1873 irq, trigger,
1803 (bank->suspend_wakeup & mask) 1874 (bank->suspend_wakeup & mask)
1804 ? " wakeup" : ""); 1875 ? " wakeup" : "");
diff --git a/include/asm-arm/arch-omap/gpio.h b/include/asm-arm/arch-omap/gpio.h
index 164da09be095..86621a04cd8f 100644
--- a/include/asm-arm/arch-omap/gpio.h
+++ b/include/asm-arm/arch-omap/gpio.h
@@ -82,62 +82,35 @@ extern void omap_set_gpio_debounce_time(int gpio, int enable);
82 82
83/*-------------------------------------------------------------------------*/ 83/*-------------------------------------------------------------------------*/
84 84
85/* wrappers for "new style" GPIO calls. the old OMAP-specfic ones should 85/* Wrappers for "new style" GPIO calls, using the new infrastructure
86 * eventually be removed (along with this errno.h inclusion), and maybe 86 * which lets us plug in FPGA, I2C, and other implementations.
87 * gpios should put MPUIOs last too. 87 * *
88 * The original OMAP-specfic calls should eventually be removed.
88 */ 89 */
89 90
90#include <asm/errno.h> 91#include <linux/errno.h>
91 92#include <asm-generic/gpio.h>
92static inline int gpio_request(unsigned gpio, const char *label)
93{
94 return omap_request_gpio(gpio);
95}
96
97static inline void gpio_free(unsigned gpio)
98{
99 omap_free_gpio(gpio);
100}
101
102static inline int __gpio_set_direction(unsigned gpio, int is_input)
103{
104 if (cpu_class_is_omap2()) {
105 if (gpio > OMAP_MAX_GPIO_LINES)
106 return -EINVAL;
107 } else {
108 if (gpio > (OMAP_MAX_GPIO_LINES + 16 /* MPUIO */))
109 return -EINVAL;
110 }
111 omap_set_gpio_direction(gpio, is_input);
112 return 0;
113}
114
115static inline int gpio_direction_input(unsigned gpio)
116{
117 return __gpio_set_direction(gpio, 1);
118}
119
120static inline int gpio_direction_output(unsigned gpio, int value)
121{
122 omap_set_gpio_dataout(gpio, value);
123 return __gpio_set_direction(gpio, 0);
124}
125 93
126static inline int gpio_get_value(unsigned gpio) 94static inline int gpio_get_value(unsigned gpio)
127{ 95{
128 return omap_get_gpio_datain(gpio); 96 return __gpio_get_value(gpio);
129} 97}
130 98
131static inline void gpio_set_value(unsigned gpio, int value) 99static inline void gpio_set_value(unsigned gpio, int value)
132{ 100{
133 omap_set_gpio_dataout(gpio, value); 101 __gpio_set_value(gpio, value);
134} 102}
135 103
136#include <asm-generic/gpio.h> /* cansleep wrappers */ 104static inline int gpio_cansleep(unsigned gpio)
105{
106 return __gpio_cansleep(gpio);
107}
137 108
138static inline int gpio_to_irq(unsigned gpio) 109static inline int gpio_to_irq(unsigned gpio)
139{ 110{
140 return OMAP_GPIO_IRQ(gpio); 111 if (gpio < (OMAP_MAX_GPIO_LINES + 16))
112 return OMAP_GPIO_IRQ(gpio);
113 return -EINVAL;
141} 114}
142 115
143static inline int irq_to_gpio(unsigned irq) 116static inline int irq_to_gpio(unsigned irq)