diff options
-rw-r--r-- | arch/arm/mach-pxa/generic.h | 6 | ||||
-rw-r--r-- | arch/arm/mach-pxa/gpio.c | 113 | ||||
-rw-r--r-- | arch/arm/mach-pxa/include/mach/gpio.h | 38 | ||||
-rw-r--r-- | arch/arm/mach-pxa/irq.c | 68 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pxa25x.c | 5 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pxa27x.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-pxa/pxa3xx.c | 3 |
7 files changed, 138 insertions, 98 deletions
diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h index dc876a8e6668..bc12c9421cef 100644 --- a/arch/arm/mach-pxa/generic.h +++ b/arch/arm/mach-pxa/generic.h | |||
@@ -9,13 +9,11 @@ | |||
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | typedef int (*set_wake_t)(unsigned int, unsigned int); | ||
13 | |||
14 | struct sys_timer; | 12 | struct sys_timer; |
15 | 13 | ||
16 | extern struct sys_timer pxa_timer; | 14 | extern struct sys_timer pxa_timer; |
17 | extern void __init pxa_init_irq(int irq_nr, set_wake_t fn); | 15 | extern void __init pxa_init_irq(int irq_nr, |
18 | extern void __init pxa_init_gpio(int gpio_nr, set_wake_t fn); | 16 | int (*set_wake)(unsigned int, unsigned int)); |
19 | extern void __init pxa25x_init_irq(void); | 17 | extern void __init pxa25x_init_irq(void); |
20 | extern void __init pxa27x_init_irq(void); | 18 | extern void __init pxa27x_init_irq(void); |
21 | extern void __init pxa3xx_init_irq(void); | 19 | extern void __init pxa3xx_init_irq(void); |
diff --git a/arch/arm/mach-pxa/gpio.c b/arch/arm/mach-pxa/gpio.c index 5fec1e479cb3..198246019028 100644 --- a/arch/arm/mach-pxa/gpio.c +++ b/arch/arm/mach-pxa/gpio.c | |||
@@ -45,18 +45,6 @@ struct pxa_gpio_chip { | |||
45 | 45 | ||
46 | int pxa_last_gpio; | 46 | int pxa_last_gpio; |
47 | 47 | ||
48 | #ifdef CONFIG_CPU_PXA26x | ||
49 | /* GPIO86/87/88/89 on PXA26x have their direction bits in GPDR2 inverted, | ||
50 | * as well as their Alternate Function value being '1' for GPIO in GAFRx. | ||
51 | */ | ||
52 | static int __gpio_is_inverted(unsigned gpio) | ||
53 | { | ||
54 | return cpu_is_pxa25x() && gpio > 85; | ||
55 | } | ||
56 | #else | ||
57 | #define __gpio_is_inverted(gpio) (0) | ||
58 | #endif | ||
59 | |||
60 | /* | 48 | /* |
61 | * Configure pins for GPIO or other functions | 49 | * Configure pins for GPIO or other functions |
62 | */ | 50 | */ |
@@ -185,6 +173,20 @@ static struct pxa_gpio_chip pxa_gpio_chip[] = { | |||
185 | #endif | 173 | #endif |
186 | }; | 174 | }; |
187 | 175 | ||
176 | static void __init pxa_init_gpio_chip(int gpio_nr) | ||
177 | { | ||
178 | int i, gpio; | ||
179 | |||
180 | /* add a GPIO chip for each register bank. | ||
181 | * the last PXA25x register only contains 21 GPIOs | ||
182 | */ | ||
183 | for (gpio = 0, i = 0; gpio < gpio_nr; gpio += 32, i++) { | ||
184 | if (gpio + 32 > gpio_nr) | ||
185 | pxa_gpio_chip[i].chip.ngpio = gpio_nr - gpio; | ||
186 | gpiochip_add(&pxa_gpio_chip[i].chip); | ||
187 | } | ||
188 | } | ||
189 | |||
188 | /* | 190 | /* |
189 | * PXA GPIO edge detection for IRQs: | 191 | * PXA GPIO edge detection for IRQs: |
190 | * IRQs are generated on Falling-Edge, Rising-Edge, or both. | 192 | * IRQs are generated on Falling-Edge, Rising-Edge, or both. |
@@ -195,27 +197,6 @@ static unsigned long GPIO_IRQ_rising_edge[4]; | |||
195 | static unsigned long GPIO_IRQ_falling_edge[4]; | 197 | static unsigned long GPIO_IRQ_falling_edge[4]; |
196 | static unsigned long GPIO_IRQ_mask[4]; | 198 | static unsigned long GPIO_IRQ_mask[4]; |
197 | 199 | ||
198 | /* | ||
199 | * On PXA25x and PXA27x, GAFRx and GPDRx together decide the alternate | ||
200 | * function of a GPIO, and GPDRx cannot be altered once configured. It | ||
201 | * is attributed as "occupied" here (I know this terminology isn't | ||
202 | * accurate, you are welcome to propose a better one :-) | ||
203 | */ | ||
204 | static int __gpio_is_occupied(unsigned gpio) | ||
205 | { | ||
206 | if (cpu_is_pxa27x() || cpu_is_pxa25x()) { | ||
207 | int af = (GAFR(gpio) >> ((gpio & 0xf) * 2)) & 0x3; | ||
208 | int dir = GPDR(gpio) & GPIO_bit(gpio); | ||
209 | |||
210 | if (__gpio_is_inverted(gpio)) | ||
211 | return af != 1 || dir == 0; | ||
212 | else | ||
213 | return af != 0 || dir != 0; | ||
214 | } | ||
215 | |||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | static int pxa_gpio_irq_type(unsigned int irq, unsigned int type) | 200 | static int pxa_gpio_irq_type(unsigned int irq, unsigned int type) |
220 | { | 201 | { |
221 | int gpio, idx; | 202 | int gpio, idx; |
@@ -262,33 +243,6 @@ static int pxa_gpio_irq_type(unsigned int irq, unsigned int type) | |||
262 | } | 243 | } |
263 | 244 | ||
264 | /* | 245 | /* |
265 | * GPIO IRQs must be acknowledged. This is for GPIO 0 and 1. | ||
266 | */ | ||
267 | |||
268 | static void pxa_ack_low_gpio(unsigned int irq) | ||
269 | { | ||
270 | GEDR0 = (1 << (irq - IRQ_GPIO0)); | ||
271 | } | ||
272 | |||
273 | static void pxa_mask_low_gpio(unsigned int irq) | ||
274 | { | ||
275 | ICMR &= ~(1 << (irq - PXA_IRQ(0))); | ||
276 | } | ||
277 | |||
278 | static void pxa_unmask_low_gpio(unsigned int irq) | ||
279 | { | ||
280 | ICMR |= 1 << (irq - PXA_IRQ(0)); | ||
281 | } | ||
282 | |||
283 | static struct irq_chip pxa_low_gpio_chip = { | ||
284 | .name = "GPIO-l", | ||
285 | .ack = pxa_ack_low_gpio, | ||
286 | .mask = pxa_mask_low_gpio, | ||
287 | .unmask = pxa_unmask_low_gpio, | ||
288 | .set_type = pxa_gpio_irq_type, | ||
289 | }; | ||
290 | |||
291 | /* | ||
292 | * Demux handler for GPIO>=2 edge detect interrupts | 246 | * Demux handler for GPIO>=2 edge detect interrupts |
293 | */ | 247 | */ |
294 | 248 | ||
@@ -352,48 +306,31 @@ static struct irq_chip pxa_muxed_gpio_chip = { | |||
352 | .set_type = pxa_gpio_irq_type, | 306 | .set_type = pxa_gpio_irq_type, |
353 | }; | 307 | }; |
354 | 308 | ||
355 | void __init pxa_init_gpio(int gpio_nr, set_wake_t fn) | 309 | void __init pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn) |
356 | { | 310 | { |
357 | int irq, i, gpio; | 311 | int irq, i; |
358 | 312 | ||
359 | pxa_last_gpio = gpio_nr - 1; | 313 | pxa_last_gpio = end; |
360 | 314 | ||
361 | /* clear all GPIO edge detects */ | 315 | /* clear all GPIO edge detects */ |
362 | for (i = 0; i < gpio_nr; i += 32) { | 316 | for (i = start; i <= end; i += 32) { |
363 | GFER(i) = 0; | 317 | GFER(i) &= ~GPIO_IRQ_mask[i]; |
364 | GRER(i) = 0; | 318 | GRER(i) &= ~GPIO_IRQ_mask[i]; |
365 | GEDR(i) = GEDR(i); | 319 | GEDR(i) = GPIO_IRQ_mask[i]; |
366 | } | 320 | } |
367 | 321 | ||
368 | /* GPIO 0 and 1 must have their mask bit always set */ | 322 | for (irq = gpio_to_irq(start); irq <= gpio_to_irq(end); irq++) { |
369 | GPIO_IRQ_mask[0] = 3; | ||
370 | |||
371 | for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) { | ||
372 | set_irq_chip(irq, &pxa_low_gpio_chip); | ||
373 | set_irq_handler(irq, handle_edge_irq); | ||
374 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | ||
375 | } | ||
376 | |||
377 | for (irq = IRQ_GPIO(2); irq < IRQ_GPIO(gpio_nr); irq++) { | ||
378 | set_irq_chip(irq, &pxa_muxed_gpio_chip); | 323 | set_irq_chip(irq, &pxa_muxed_gpio_chip); |
379 | set_irq_handler(irq, handle_edge_irq); | 324 | set_irq_handler(irq, handle_edge_irq); |
380 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | 325 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); |
381 | } | 326 | } |
382 | 327 | ||
383 | /* Install handler for GPIO>=2 edge detect interrupts */ | 328 | /* Install handler for GPIO>=2 edge detect interrupts */ |
384 | set_irq_chained_handler(IRQ_GPIO_2_x, pxa_gpio_demux_handler); | 329 | set_irq_chained_handler(mux_irq, pxa_gpio_demux_handler); |
385 | |||
386 | pxa_low_gpio_chip.set_wake = fn; | ||
387 | pxa_muxed_gpio_chip.set_wake = fn; | 330 | pxa_muxed_gpio_chip.set_wake = fn; |
388 | 331 | ||
389 | /* add a GPIO chip for each register bank. | 332 | /* Initialize GPIO chips */ |
390 | * the last PXA25x register only contains 21 GPIOs | 333 | pxa_init_gpio_chip(end + 1); |
391 | */ | ||
392 | for (gpio = 0, i = 0; gpio < gpio_nr; gpio += 32, i++) { | ||
393 | if (gpio + 32 > gpio_nr) | ||
394 | pxa_gpio_chip[i].chip.ngpio = gpio_nr - gpio; | ||
395 | gpiochip_add(&pxa_gpio_chip[i].chip); | ||
396 | } | ||
397 | } | 334 | } |
398 | 335 | ||
399 | #ifdef CONFIG_PM | 336 | #ifdef CONFIG_PM |
diff --git a/arch/arm/mach-pxa/include/mach/gpio.h b/arch/arm/mach-pxa/include/mach/gpio.h index 2c538d8c362d..c7ac3d62d34d 100644 --- a/arch/arm/mach-pxa/include/mach/gpio.h +++ b/arch/arm/mach-pxa/include/mach/gpio.h | |||
@@ -56,10 +56,44 @@ static inline void gpio_set_value(unsigned gpio, int value) | |||
56 | } | 56 | } |
57 | } | 57 | } |
58 | 58 | ||
59 | #define gpio_cansleep __gpio_cansleep | 59 | #define gpio_cansleep __gpio_cansleep |
60 | |||
61 | #define gpio_to_irq(gpio) IRQ_GPIO(gpio) | 60 | #define gpio_to_irq(gpio) IRQ_GPIO(gpio) |
62 | #define irq_to_gpio(irq) IRQ_TO_GPIO(irq) | 61 | #define irq_to_gpio(irq) IRQ_TO_GPIO(irq) |
63 | 62 | ||
64 | 63 | ||
64 | #ifdef CONFIG_CPU_PXA26x | ||
65 | /* GPIO86/87/88/89 on PXA26x have their direction bits in GPDR2 inverted, | ||
66 | * as well as their Alternate Function value being '1' for GPIO in GAFRx. | ||
67 | */ | ||
68 | static inline int __gpio_is_inverted(unsigned gpio) | ||
69 | { | ||
70 | return cpu_is_pxa25x() && gpio > 85; | ||
71 | } | ||
72 | #else | ||
73 | static inline int __gpio_is_inverted(unsigned gpio) { return 0; } | ||
74 | #endif | ||
75 | |||
76 | /* | ||
77 | * On PXA25x and PXA27x, GAFRx and GPDRx together decide the alternate | ||
78 | * function of a GPIO, and GPDRx cannot be altered once configured. It | ||
79 | * is attributed as "occupied" here (I know this terminology isn't | ||
80 | * accurate, you are welcome to propose a better one :-) | ||
81 | */ | ||
82 | static inline int __gpio_is_occupied(unsigned gpio) | ||
83 | { | ||
84 | if (cpu_is_pxa27x() || cpu_is_pxa25x()) { | ||
85 | int af = (GAFR(gpio) >> ((gpio & 0xf) * 2)) & 0x3; | ||
86 | int dir = GPDR(gpio) & GPIO_bit(gpio); | ||
87 | |||
88 | if (__gpio_is_inverted(gpio)) | ||
89 | return af != 1 || dir == 0; | ||
90 | else | ||
91 | return af != 0 || dir != 0; | ||
92 | } else | ||
93 | return GPDR(gpio) & GPIO_bit(gpio); | ||
94 | } | ||
95 | |||
96 | typedef int (*set_wake_t)(unsigned int irq, unsigned int on); | ||
97 | |||
98 | extern void pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn); | ||
65 | #endif | 99 | #endif |
diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c index fa69c3a6a38e..d3d40a31f9da 100644 --- a/arch/arm/mach-pxa/irq.c +++ b/arch/arm/mach-pxa/irq.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <asm/irq.h> | 21 | #include <asm/irq.h> |
22 | #include <asm/mach/irq.h> | 22 | #include <asm/mach/irq.h> |
23 | #include <mach/pxa-regs.h> | 23 | #include <mach/pxa-regs.h> |
24 | #include <mach/gpio.h> | ||
24 | 25 | ||
25 | #include "generic.h" | 26 | #include "generic.h" |
26 | 27 | ||
@@ -51,6 +52,72 @@ static struct irq_chip pxa_internal_irq_chip = { | |||
51 | .unmask = pxa_unmask_irq, | 52 | .unmask = pxa_unmask_irq, |
52 | }; | 53 | }; |
53 | 54 | ||
55 | /* | ||
56 | * GPIO IRQs for GPIO 0 and 1 | ||
57 | */ | ||
58 | static int pxa_set_low_gpio_type(unsigned int irq, unsigned int type) | ||
59 | { | ||
60 | int gpio = irq - IRQ_GPIO0; | ||
61 | |||
62 | if (__gpio_is_occupied(gpio)) { | ||
63 | pr_err("%s failed: GPIO is configured\n", __func__); | ||
64 | return -EINVAL; | ||
65 | } | ||
66 | |||
67 | if (type & IRQ_TYPE_EDGE_RISING) | ||
68 | GRER0 |= GPIO_bit(gpio); | ||
69 | else | ||
70 | GRER0 &= ~GPIO_bit(gpio); | ||
71 | |||
72 | if (type & IRQ_TYPE_EDGE_FALLING) | ||
73 | GFER0 |= GPIO_bit(gpio); | ||
74 | else | ||
75 | GFER0 &= ~GPIO_bit(gpio); | ||
76 | |||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static void pxa_ack_low_gpio(unsigned int irq) | ||
81 | { | ||
82 | GEDR0 = (1 << (irq - IRQ_GPIO0)); | ||
83 | } | ||
84 | |||
85 | static void pxa_mask_low_gpio(unsigned int irq) | ||
86 | { | ||
87 | ICMR &= ~(1 << (irq - PXA_IRQ(0))); | ||
88 | } | ||
89 | |||
90 | static void pxa_unmask_low_gpio(unsigned int irq) | ||
91 | { | ||
92 | ICMR |= 1 << (irq - PXA_IRQ(0)); | ||
93 | } | ||
94 | |||
95 | static struct irq_chip pxa_low_gpio_chip = { | ||
96 | .name = "GPIO-l", | ||
97 | .ack = pxa_ack_low_gpio, | ||
98 | .mask = pxa_mask_low_gpio, | ||
99 | .unmask = pxa_unmask_low_gpio, | ||
100 | .set_type = pxa_set_low_gpio_type, | ||
101 | }; | ||
102 | |||
103 | static void __init pxa_init_low_gpio_irq(set_wake_t fn) | ||
104 | { | ||
105 | int irq; | ||
106 | |||
107 | /* clear edge detection on GPIO 0 and 1 */ | ||
108 | GFER0 &= ~0x3; | ||
109 | GRER0 &= ~0x3; | ||
110 | GEDR0 = 0x3; | ||
111 | |||
112 | for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) { | ||
113 | set_irq_chip(irq, &pxa_low_gpio_chip); | ||
114 | set_irq_handler(irq, handle_edge_irq); | ||
115 | set_irq_flags(irq, IRQF_VALID); | ||
116 | } | ||
117 | |||
118 | pxa_low_gpio_chip.set_wake = fn; | ||
119 | } | ||
120 | |||
54 | void __init pxa_init_irq(int irq_nr, set_wake_t fn) | 121 | void __init pxa_init_irq(int irq_nr, set_wake_t fn) |
55 | { | 122 | { |
56 | int irq; | 123 | int irq; |
@@ -72,6 +139,7 @@ void __init pxa_init_irq(int irq_nr, set_wake_t fn) | |||
72 | } | 139 | } |
73 | 140 | ||
74 | pxa_internal_irq_chip.set_wake = fn; | 141 | pxa_internal_irq_chip.set_wake = fn; |
142 | pxa_init_low_gpio_irq(fn); | ||
75 | } | 143 | } |
76 | 144 | ||
77 | #ifdef CONFIG_PM | 145 | #ifdef CONFIG_PM |
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index 2332e2dc3504..77c2693cfeef 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c | |||
@@ -25,6 +25,7 @@ | |||
25 | 25 | ||
26 | #include <mach/hardware.h> | 26 | #include <mach/hardware.h> |
27 | #include <mach/irqs.h> | 27 | #include <mach/irqs.h> |
28 | #include <mach/gpio.h> | ||
28 | #include <mach/pxa25x.h> | 29 | #include <mach/pxa25x.h> |
29 | #include <mach/reset.h> | 30 | #include <mach/reset.h> |
30 | #include <mach/pm.h> | 31 | #include <mach/pm.h> |
@@ -308,14 +309,14 @@ set_pwer: | |||
308 | void __init pxa25x_init_irq(void) | 309 | void __init pxa25x_init_irq(void) |
309 | { | 310 | { |
310 | pxa_init_irq(32, pxa25x_set_wake); | 311 | pxa_init_irq(32, pxa25x_set_wake); |
311 | pxa_init_gpio(85, pxa25x_set_wake); | 312 | pxa_init_gpio(IRQ_GPIO_2_x, 2, 84, pxa25x_set_wake); |
312 | } | 313 | } |
313 | 314 | ||
314 | #ifdef CONFIG_CPU_PXA26x | 315 | #ifdef CONFIG_CPU_PXA26x |
315 | void __init pxa26x_init_irq(void) | 316 | void __init pxa26x_init_irq(void) |
316 | { | 317 | { |
317 | pxa_init_irq(32, pxa25x_set_wake); | 318 | pxa_init_irq(32, pxa25x_set_wake); |
318 | pxa_init_gpio(90, pxa25x_set_wake); | 319 | pxa_init_gpio(IRQ_GPIO_2_x, 2, 89, pxa25x_set_wake); |
319 | } | 320 | } |
320 | #endif | 321 | #endif |
321 | 322 | ||
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index c8b469bbcf3b..a425ec71e657 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <mach/hardware.h> | 21 | #include <mach/hardware.h> |
22 | #include <asm/irq.h> | 22 | #include <asm/irq.h> |
23 | #include <mach/irqs.h> | 23 | #include <mach/irqs.h> |
24 | #include <mach/gpio.h> | ||
24 | #include <mach/pxa27x.h> | 25 | #include <mach/pxa27x.h> |
25 | #include <mach/reset.h> | 26 | #include <mach/reset.h> |
26 | #include <mach/ohci.h> | 27 | #include <mach/ohci.h> |
@@ -330,7 +331,7 @@ static int pxa27x_set_wake(unsigned int irq, unsigned int on) | |||
330 | void __init pxa27x_init_irq(void) | 331 | void __init pxa27x_init_irq(void) |
331 | { | 332 | { |
332 | pxa_init_irq(34, pxa27x_set_wake); | 333 | pxa_init_irq(34, pxa27x_set_wake); |
333 | pxa_init_gpio(121, pxa27x_set_wake); | 334 | pxa_init_gpio(IRQ_GPIO_2_x, 2, 120, pxa27x_set_wake); |
334 | } | 335 | } |
335 | 336 | ||
336 | /* | 337 | /* |
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c index e626b79cbee4..b02d4544dc95 100644 --- a/arch/arm/mach-pxa/pxa3xx.c +++ b/arch/arm/mach-pxa/pxa3xx.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/sysdev.h> | 23 | #include <linux/sysdev.h> |
24 | 24 | ||
25 | #include <mach/hardware.h> | 25 | #include <mach/hardware.h> |
26 | #include <mach/gpio.h> | ||
26 | #include <mach/pxa3xx-regs.h> | 27 | #include <mach/pxa3xx-regs.h> |
27 | #include <mach/reset.h> | 28 | #include <mach/reset.h> |
28 | #include <mach/ohci.h> | 29 | #include <mach/ohci.h> |
@@ -538,7 +539,7 @@ void __init pxa3xx_init_irq(void) | |||
538 | __asm__ __volatile__("mcr p15, 0, %0, c15, c1, 0\n": :"r"(value)); | 539 | __asm__ __volatile__("mcr p15, 0, %0, c15, c1, 0\n": :"r"(value)); |
539 | 540 | ||
540 | pxa_init_irq(56, pxa3xx_set_wake); | 541 | pxa_init_irq(56, pxa3xx_set_wake); |
541 | pxa_init_gpio(128, NULL); | 542 | pxa_init_gpio(IRQ_GPIO_2_x, 2, 127, NULL); |
542 | } | 543 | } |
543 | 544 | ||
544 | /* | 545 | /* |