diff options
author | Erik Benada <erikbenada@yahoo.ca> | 2009-05-28 20:08:55 -0400 |
---|---|---|
committer | Nicolas Pitre <nico@cam.org> | 2009-06-08 13:04:57 -0400 |
commit | a88656553d18c324554855fccc730c9644048111 (patch) | |
tree | 6a77d6b11e3f0cf017f6dee21a9934c6c6378704 /arch/arm | |
parent | f14081e109e7074be3052f5410641161b6479abb (diff) |
[ARM] orion: convert gpio to use gpiolib
Signed-off-by: Erik Benada <erikbenada@yahoo.ca>
[ nico: fix locking, additional cleanups ]
Signed-off-by: Nicolas Pitre <nico@marvell.com>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/Kconfig | 3 | ||||
-rw-r--r-- | arch/arm/mach-kirkwood/mpp.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-mv78xx0/irq.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-orion5x/mpp.c | 3 | ||||
-rw-r--r-- | arch/arm/plat-orion/gpio.c | 194 | ||||
-rw-r--r-- | arch/arm/plat-orion/include/plat/gpio.h | 17 |
6 files changed, 95 insertions, 128 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 9d02cdb15b23..c6225ead7bff 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -398,6 +398,7 @@ config ARCH_KIRKWOOD | |||
398 | select CPU_FEROCEON | 398 | select CPU_FEROCEON |
399 | select PCI | 399 | select PCI |
400 | select GENERIC_GPIO | 400 | select GENERIC_GPIO |
401 | select ARCH_REQUIRE_GPIOLIB | ||
401 | select GENERIC_TIME | 402 | select GENERIC_TIME |
402 | select GENERIC_CLOCKEVENTS | 403 | select GENERIC_CLOCKEVENTS |
403 | select PLAT_ORION | 404 | select PLAT_ORION |
@@ -441,6 +442,7 @@ config ARCH_MV78XX0 | |||
441 | select CPU_FEROCEON | 442 | select CPU_FEROCEON |
442 | select PCI | 443 | select PCI |
443 | select GENERIC_GPIO | 444 | select GENERIC_GPIO |
445 | select ARCH_REQUIRE_GPIOLIB | ||
444 | select GENERIC_TIME | 446 | select GENERIC_TIME |
445 | select GENERIC_CLOCKEVENTS | 447 | select GENERIC_CLOCKEVENTS |
446 | select PLAT_ORION | 448 | select PLAT_ORION |
@@ -465,6 +467,7 @@ config ARCH_ORION5X | |||
465 | select CPU_FEROCEON | 467 | select CPU_FEROCEON |
466 | select PCI | 468 | select PCI |
467 | select GENERIC_GPIO | 469 | select GENERIC_GPIO |
470 | select ARCH_REQUIRE_GPIOLIB | ||
468 | select GENERIC_TIME | 471 | select GENERIC_TIME |
469 | select GENERIC_CLOCKEVENTS | 472 | select GENERIC_CLOCKEVENTS |
470 | select PLAT_ORION | 473 | select PLAT_ORION |
diff --git a/arch/arm/mach-kirkwood/mpp.c b/arch/arm/mach-kirkwood/mpp.c index 63c44934391a..a5900f64e38c 100644 --- a/arch/arm/mach-kirkwood/mpp.c +++ b/arch/arm/mach-kirkwood/mpp.c | |||
@@ -48,6 +48,9 @@ void __init kirkwood_mpp_conf(unsigned int *mpp_list) | |||
48 | if (!variant_mask) | 48 | if (!variant_mask) |
49 | return; | 49 | return; |
50 | 50 | ||
51 | /* Initialize gpiolib. */ | ||
52 | orion_gpio_init(); | ||
53 | |||
51 | printk(KERN_DEBUG "initial MPP regs:"); | 54 | printk(KERN_DEBUG "initial MPP regs:"); |
52 | for (i = 0; i < MPP_NR_REGS; i++) { | 55 | for (i = 0; i < MPP_NR_REGS; i++) { |
53 | mpp_ctrl[i] = readl(MPP_CTRL(i)); | 56 | mpp_ctrl[i] = readl(MPP_CTRL(i)); |
diff --git a/arch/arm/mach-mv78xx0/irq.c b/arch/arm/mach-mv78xx0/irq.c index f289b0ea7dcf..22b4ff893b3c 100644 --- a/arch/arm/mach-mv78xx0/irq.c +++ b/arch/arm/mach-mv78xx0/irq.c | |||
@@ -28,6 +28,9 @@ void __init mv78xx0_init_irq(void) | |||
28 | { | 28 | { |
29 | int i; | 29 | int i; |
30 | 30 | ||
31 | /* Initialize gpiolib. */ | ||
32 | orion_gpio_init(); | ||
33 | |||
31 | orion_irq_init(0, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF)); | 34 | orion_irq_init(0, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF)); |
32 | orion_irq_init(32, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF)); | 35 | orion_irq_init(32, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF)); |
33 | orion_irq_init(64, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_ERR_OFF)); | 36 | orion_irq_init(64, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_ERR_OFF)); |
diff --git a/arch/arm/mach-orion5x/mpp.c b/arch/arm/mach-orion5x/mpp.c index e23a3f91d6c6..bc4c3b9aaf83 100644 --- a/arch/arm/mach-orion5x/mpp.c +++ b/arch/arm/mach-orion5x/mpp.c | |||
@@ -124,6 +124,9 @@ void __init orion5x_mpp_conf(struct orion5x_mpp_mode *mode) | |||
124 | u32 mpp_8_15_ctrl = readl(MPP_8_15_CTRL); | 124 | u32 mpp_8_15_ctrl = readl(MPP_8_15_CTRL); |
125 | u32 mpp_16_19_ctrl = readl(MPP_16_19_CTRL); | 125 | u32 mpp_16_19_ctrl = readl(MPP_16_19_CTRL); |
126 | 126 | ||
127 | /* Initialize gpiolib. */ | ||
128 | orion_gpio_init(); | ||
129 | |||
127 | while (mode->mpp >= 0) { | 130 | while (mode->mpp >= 0) { |
128 | u32 *reg; | 131 | u32 *reg; |
129 | int num_type; | 132 | int num_type; |
diff --git a/arch/arm/plat-orion/gpio.c b/arch/arm/plat-orion/gpio.c index 32eb9e33bebb..e814803d4741 100644 --- a/arch/arm/plat-orion/gpio.c +++ b/arch/arm/plat-orion/gpio.c | |||
@@ -15,10 +15,9 @@ | |||
15 | #include <linux/spinlock.h> | 15 | #include <linux/spinlock.h> |
16 | #include <linux/bitops.h> | 16 | #include <linux/bitops.h> |
17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | #include <asm/gpio.h> | 18 | #include <linux/gpio.h> |
19 | 19 | ||
20 | static DEFINE_SPINLOCK(gpio_lock); | 20 | static DEFINE_SPINLOCK(gpio_lock); |
21 | static const char *gpio_label[GPIO_MAX]; /* non null for allocated GPIOs */ | ||
22 | static unsigned long gpio_valid_input[BITS_TO_LONGS(GPIO_MAX)]; | 21 | static unsigned long gpio_valid_input[BITS_TO_LONGS(GPIO_MAX)]; |
23 | static unsigned long gpio_valid_output[BITS_TO_LONGS(GPIO_MAX)]; | 22 | static unsigned long gpio_valid_output[BITS_TO_LONGS(GPIO_MAX)]; |
24 | 23 | ||
@@ -46,82 +45,54 @@ static void __set_level(unsigned pin, int high) | |||
46 | writel(u, GPIO_OUT(pin)); | 45 | writel(u, GPIO_OUT(pin)); |
47 | } | 46 | } |
48 | 47 | ||
49 | 48 | static inline void __set_blinking(unsigned pin, int blink) | |
50 | /* | ||
51 | * GENERIC_GPIO primitives. | ||
52 | */ | ||
53 | int gpio_direction_input(unsigned pin) | ||
54 | { | 49 | { |
55 | unsigned long flags; | 50 | u32 u; |
56 | |||
57 | if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid_input)) { | ||
58 | pr_debug("%s: invalid GPIO %d\n", __func__, pin); | ||
59 | return -EINVAL; | ||
60 | } | ||
61 | |||
62 | spin_lock_irqsave(&gpio_lock, flags); | ||
63 | |||
64 | /* | ||
65 | * Some callers might not have used gpio_request(), | ||
66 | * so flag this pin as requested now. | ||
67 | */ | ||
68 | if (gpio_label[pin] == NULL) | ||
69 | gpio_label[pin] = "?"; | ||
70 | 51 | ||
71 | /* | 52 | u = readl(GPIO_BLINK_EN(pin)); |
72 | * Configure GPIO direction. | 53 | if (blink) |
73 | */ | 54 | u |= 1 << (pin & 31); |
74 | __set_direction(pin, 1); | 55 | else |
56 | u &= ~(1 << (pin & 31)); | ||
57 | writel(u, GPIO_BLINK_EN(pin)); | ||
58 | } | ||
75 | 59 | ||
76 | spin_unlock_irqrestore(&gpio_lock, flags); | 60 | static inline int orion_gpio_is_valid(unsigned pin, int mode) |
61 | { | ||
62 | if (pin < GPIO_MAX) { | ||
63 | if ((mode & GPIO_INPUT_OK) && !test_bit(pin, gpio_valid_input)) | ||
64 | goto err_out; | ||
65 | if ((mode & GPIO_OUTPUT_OK) && !test_bit(pin, gpio_valid_output)) | ||
66 | goto err_out; | ||
67 | return true; | ||
68 | } | ||
77 | 69 | ||
78 | return 0; | 70 | err_out: |
71 | pr_debug("%s: invalid GPIO %d\n", __func__, pin); | ||
72 | return false; | ||
79 | } | 73 | } |
80 | EXPORT_SYMBOL(gpio_direction_input); | ||
81 | 74 | ||
82 | int gpio_direction_output(unsigned pin, int value) | 75 | /* |
76 | * GENERIC_GPIO primitives. | ||
77 | */ | ||
78 | static int orion_gpio_direction_input(struct gpio_chip *chip, unsigned pin) | ||
83 | { | 79 | { |
84 | unsigned long flags; | 80 | unsigned long flags; |
85 | u32 u; | ||
86 | 81 | ||
87 | if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid_output)) { | 82 | if (!orion_gpio_is_valid(pin, GPIO_INPUT_OK)) |
88 | pr_debug("%s: invalid GPIO %d\n", __func__, pin); | ||
89 | return -EINVAL; | 83 | return -EINVAL; |
90 | } | ||
91 | 84 | ||
92 | spin_lock_irqsave(&gpio_lock, flags); | 85 | spin_lock_irqsave(&gpio_lock, flags); |
93 | 86 | ||
94 | /* | 87 | /* Configure GPIO direction. */ |
95 | * Some callers might not have used gpio_request(), | 88 | __set_direction(pin, 1); |
96 | * so flag this pin as requested now. | ||
97 | */ | ||
98 | if (gpio_label[pin] == NULL) | ||
99 | gpio_label[pin] = "?"; | ||
100 | |||
101 | /* | ||
102 | * Disable blinking. | ||
103 | */ | ||
104 | u = readl(GPIO_BLINK_EN(pin)); | ||
105 | u &= ~(1 << (pin & 31)); | ||
106 | writel(u, GPIO_BLINK_EN(pin)); | ||
107 | |||
108 | /* | ||
109 | * Configure GPIO output value. | ||
110 | */ | ||
111 | __set_level(pin, value); | ||
112 | |||
113 | /* | ||
114 | * Configure GPIO direction. | ||
115 | */ | ||
116 | __set_direction(pin, 0); | ||
117 | 89 | ||
118 | spin_unlock_irqrestore(&gpio_lock, flags); | 90 | spin_unlock_irqrestore(&gpio_lock, flags); |
119 | 91 | ||
120 | return 0; | 92 | return 0; |
121 | } | 93 | } |
122 | EXPORT_SYMBOL(gpio_direction_output); | ||
123 | 94 | ||
124 | int gpio_get_value(unsigned pin) | 95 | static int orion_gpio_get_value(struct gpio_chip *chip, unsigned pin) |
125 | { | 96 | { |
126 | int val; | 97 | int val; |
127 | 98 | ||
@@ -132,83 +103,75 @@ int gpio_get_value(unsigned pin) | |||
132 | 103 | ||
133 | return (val >> (pin & 31)) & 1; | 104 | return (val >> (pin & 31)) & 1; |
134 | } | 105 | } |
135 | EXPORT_SYMBOL(gpio_get_value); | ||
136 | 106 | ||
137 | void gpio_set_value(unsigned pin, int value) | 107 | static int orion_gpio_direction_output(struct gpio_chip *chip, unsigned pin, |
108 | int value) | ||
138 | { | 109 | { |
139 | unsigned long flags; | 110 | unsigned long flags; |
140 | u32 u; | 111 | |
112 | if (!orion_gpio_is_valid(pin, GPIO_OUTPUT_OK)) | ||
113 | return -EINVAL; | ||
141 | 114 | ||
142 | spin_lock_irqsave(&gpio_lock, flags); | 115 | spin_lock_irqsave(&gpio_lock, flags); |
143 | 116 | ||
144 | /* | 117 | /* Disable blinking. */ |
145 | * Disable blinking. | 118 | __set_blinking(pin, 0); |
146 | */ | ||
147 | u = readl(GPIO_BLINK_EN(pin)); | ||
148 | u &= ~(1 << (pin & 31)); | ||
149 | writel(u, GPIO_BLINK_EN(pin)); | ||
150 | 119 | ||
151 | /* | 120 | /* Configure GPIO output value. */ |
152 | * Configure GPIO output value. | ||
153 | */ | ||
154 | __set_level(pin, value); | 121 | __set_level(pin, value); |
155 | 122 | ||
123 | /* Configure GPIO direction. */ | ||
124 | __set_direction(pin, 0); | ||
125 | |||
156 | spin_unlock_irqrestore(&gpio_lock, flags); | 126 | spin_unlock_irqrestore(&gpio_lock, flags); |
127 | |||
128 | return 0; | ||
157 | } | 129 | } |
158 | EXPORT_SYMBOL(gpio_set_value); | ||
159 | 130 | ||
160 | int gpio_request(unsigned pin, const char *label) | 131 | static void orion_gpio_set_value(struct gpio_chip *chip, unsigned pin, |
132 | int value) | ||
161 | { | 133 | { |
162 | unsigned long flags; | 134 | unsigned long flags; |
163 | int ret; | ||
164 | |||
165 | if (pin >= GPIO_MAX || | ||
166 | !(test_bit(pin, gpio_valid_input) || | ||
167 | test_bit(pin, gpio_valid_output))) { | ||
168 | pr_debug("%s: invalid GPIO %d\n", __func__, pin); | ||
169 | return -EINVAL; | ||
170 | } | ||
171 | 135 | ||
172 | spin_lock_irqsave(&gpio_lock, flags); | 136 | spin_lock_irqsave(&gpio_lock, flags); |
173 | if (gpio_label[pin] == NULL) { | ||
174 | gpio_label[pin] = label ? label : "?"; | ||
175 | ret = 0; | ||
176 | } else { | ||
177 | pr_debug("%s: GPIO %d already used as %s\n", | ||
178 | __func__, pin, gpio_label[pin]); | ||
179 | ret = -EBUSY; | ||
180 | } | ||
181 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
182 | 137 | ||
183 | return ret; | 138 | /* Configure GPIO output value. */ |
139 | __set_level(pin, value); | ||
140 | |||
141 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
184 | } | 142 | } |
185 | EXPORT_SYMBOL(gpio_request); | ||
186 | 143 | ||
187 | void gpio_free(unsigned pin) | 144 | static int orion_gpio_request(struct gpio_chip *chip, unsigned pin) |
188 | { | 145 | { |
189 | if (pin >= GPIO_MAX || | 146 | if (orion_gpio_is_valid(pin, GPIO_INPUT_OK) || |
190 | !(test_bit(pin, gpio_valid_input) || | 147 | orion_gpio_is_valid(pin, GPIO_OUTPUT_OK)) |
191 | test_bit(pin, gpio_valid_output))) { | 148 | return 0; |
192 | pr_debug("%s: invalid GPIO %d\n", __func__, pin); | 149 | return -EINVAL; |
193 | return; | ||
194 | } | ||
195 | |||
196 | if (gpio_label[pin] == NULL) | ||
197 | pr_warning("%s: GPIO %d already freed\n", __func__, pin); | ||
198 | else | ||
199 | gpio_label[pin] = NULL; | ||
200 | } | 150 | } |
201 | EXPORT_SYMBOL(gpio_free); | ||
202 | 151 | ||
152 | static struct gpio_chip orion_gpiochip = { | ||
153 | .label = "orion_gpio", | ||
154 | .direction_input = orion_gpio_direction_input, | ||
155 | .get = orion_gpio_get_value, | ||
156 | .direction_output = orion_gpio_direction_output, | ||
157 | .set = orion_gpio_set_value, | ||
158 | .request = orion_gpio_request, | ||
159 | .base = 0, | ||
160 | .ngpio = GPIO_MAX, | ||
161 | .can_sleep = 0, | ||
162 | }; | ||
163 | |||
164 | void __init orion_gpio_init(void) | ||
165 | { | ||
166 | gpiochip_add(&orion_gpiochip); | ||
167 | } | ||
203 | 168 | ||
204 | /* | 169 | /* |
205 | * Orion-specific GPIO API extensions. | 170 | * Orion-specific GPIO API extensions. |
206 | */ | 171 | */ |
207 | void __init orion_gpio_set_unused(unsigned pin) | 172 | void __init orion_gpio_set_unused(unsigned pin) |
208 | { | 173 | { |
209 | /* | 174 | /* Configure as output, drive low. */ |
210 | * Configure as output, drive low. | ||
211 | */ | ||
212 | __set_level(pin, 0); | 175 | __set_level(pin, 0); |
213 | __set_direction(pin, 0); | 176 | __set_direction(pin, 0); |
214 | } | 177 | } |
@@ -230,21 +193,14 @@ void __init orion_gpio_set_valid(unsigned pin, int mode) | |||
230 | void orion_gpio_set_blink(unsigned pin, int blink) | 193 | void orion_gpio_set_blink(unsigned pin, int blink) |
231 | { | 194 | { |
232 | unsigned long flags; | 195 | unsigned long flags; |
233 | u32 u; | ||
234 | 196 | ||
235 | spin_lock_irqsave(&gpio_lock, flags); | 197 | spin_lock_irqsave(&gpio_lock, flags); |
236 | 198 | ||
237 | /* | 199 | /* Set output value to zero. */ |
238 | * Set output value to zero. | ||
239 | */ | ||
240 | __set_level(pin, 0); | 200 | __set_level(pin, 0); |
241 | 201 | ||
242 | u = readl(GPIO_BLINK_EN(pin)); | 202 | /* Set blinking. */ |
243 | if (blink) | 203 | __set_blinking(pin, blink); |
244 | u |= 1 << (pin & 31); | ||
245 | else | ||
246 | u &= ~(1 << (pin & 31)); | ||
247 | writel(u, GPIO_BLINK_EN(pin)); | ||
248 | 204 | ||
249 | spin_unlock_irqrestore(&gpio_lock, flags); | 205 | spin_unlock_irqrestore(&gpio_lock, flags); |
250 | } | 206 | } |
@@ -368,7 +324,7 @@ static int gpio_irq_set_type(u32 irq, u32 type) | |||
368 | } | 324 | } |
369 | 325 | ||
370 | struct irq_chip orion_gpio_irq_chip = { | 326 | struct irq_chip orion_gpio_irq_chip = { |
371 | .name = "orion_gpio", | 327 | .name = "orion_gpio_irq", |
372 | .ack = gpio_irq_ack, | 328 | .ack = gpio_irq_ack, |
373 | .mask = gpio_irq_mask, | 329 | .mask = gpio_irq_mask, |
374 | .unmask = gpio_irq_unmask, | 330 | .unmask = gpio_irq_unmask, |
diff --git a/arch/arm/plat-orion/include/plat/gpio.h b/arch/arm/plat-orion/include/plat/gpio.h index 33f6c6aec185..9646a94ed3d0 100644 --- a/arch/arm/plat-orion/include/plat/gpio.h +++ b/arch/arm/plat-orion/include/plat/gpio.h | |||
@@ -14,12 +14,9 @@ | |||
14 | /* | 14 | /* |
15 | * GENERIC_GPIO primitives. | 15 | * GENERIC_GPIO primitives. |
16 | */ | 16 | */ |
17 | int gpio_request(unsigned pin, const char *label); | 17 | #define gpio_get_value __gpio_get_value |
18 | void gpio_free(unsigned pin); | 18 | #define gpio_set_value __gpio_set_value |
19 | int gpio_direction_input(unsigned pin); | 19 | #define gpio_cansleep __gpio_cansleep |
20 | int gpio_direction_output(unsigned pin, int value); | ||
21 | int gpio_get_value(unsigned pin); | ||
22 | void gpio_set_value(unsigned pin, int value); | ||
23 | 20 | ||
24 | /* | 21 | /* |
25 | * Orion-specific GPIO API extensions. | 22 | * Orion-specific GPIO API extensions. |
@@ -27,11 +24,13 @@ void gpio_set_value(unsigned pin, int value); | |||
27 | void orion_gpio_set_unused(unsigned pin); | 24 | void orion_gpio_set_unused(unsigned pin); |
28 | void orion_gpio_set_blink(unsigned pin, int blink); | 25 | void orion_gpio_set_blink(unsigned pin, int blink); |
29 | 26 | ||
30 | #define GPIO_BIDI_OK (1 << 0) | 27 | #define GPIO_INPUT_OK (1 << 0) |
31 | #define GPIO_INPUT_OK (1 << 1) | 28 | #define GPIO_OUTPUT_OK (1 << 1) |
32 | #define GPIO_OUTPUT_OK (1 << 2) | ||
33 | void orion_gpio_set_valid(unsigned pin, int mode); | 29 | void orion_gpio_set_valid(unsigned pin, int mode); |
34 | 30 | ||
31 | /* Initialize gpiolib. */ | ||
32 | void __init orion_gpio_init(void); | ||
33 | |||
35 | /* | 34 | /* |
36 | * GPIO interrupt handling. | 35 | * GPIO interrupt handling. |
37 | */ | 36 | */ |