diff options
Diffstat (limited to 'arch/arm/mach-pxa/irq.c')
-rw-r--r-- | arch/arm/mach-pxa/irq.c | 336 |
1 files changed, 35 insertions, 301 deletions
diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c index 36c6a68beca2..a9a0c3fab159 100644 --- a/arch/arm/mach-pxa/irq.c +++ b/arch/arm/mach-pxa/irq.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/mach-pxa/irq.c | 2 | * linux/arch/arm/mach-pxa/irq.c |
3 | * | 3 | * |
4 | * Generic PXA IRQ handling, GPIO IRQ demultiplexing, etc. | 4 | * Generic PXA IRQ handling |
5 | * | 5 | * |
6 | * Author: Nicolas Pitre | 6 | * Author: Nicolas Pitre |
7 | * Created: Jun 15, 2001 | 7 | * Created: Jun 15, 2001 |
@@ -21,308 +21,58 @@ | |||
21 | #include <asm/irq.h> | 21 | #include <asm/irq.h> |
22 | #include <asm/mach/irq.h> | 22 | #include <asm/mach/irq.h> |
23 | #include <asm/arch/pxa-regs.h> | 23 | #include <asm/arch/pxa-regs.h> |
24 | #include <asm/arch/pxa2xx-gpio.h> | ||
24 | 25 | ||
25 | #include "generic.h" | 26 | #include "generic.h" |
26 | 27 | ||
28 | #define IRQ_BIT(n) (((n) - PXA_IRQ(0)) & 0x1f) | ||
29 | #define _ICMR(n) (*((((n) - PXA_IRQ(0)) & ~0x1f) ? &ICMR2 : &ICMR)) | ||
30 | #define _ICLR(n) (*((((n) - PXA_IRQ(0)) & ~0x1f) ? &ICLR2 : &ICLR)) | ||
27 | 31 | ||
28 | /* | 32 | /* |
29 | * This is for peripheral IRQs internal to the PXA chip. | 33 | * This is for peripheral IRQs internal to the PXA chip. |
30 | */ | 34 | */ |
31 | 35 | ||
32 | static void pxa_mask_low_irq(unsigned int irq) | 36 | static int pxa_internal_irq_nr; |
37 | |||
38 | static void pxa_mask_irq(unsigned int irq) | ||
33 | { | 39 | { |
34 | ICMR &= ~(1 << irq); | 40 | _ICMR(irq) &= ~(1 << IRQ_BIT(irq)); |
35 | } | 41 | } |
36 | 42 | ||
37 | static void pxa_unmask_low_irq(unsigned int irq) | 43 | static void pxa_unmask_irq(unsigned int irq) |
38 | { | 44 | { |
39 | ICMR |= (1 << irq); | 45 | _ICMR(irq) |= 1 << IRQ_BIT(irq); |
40 | } | 46 | } |
41 | 47 | ||
42 | static struct irq_chip pxa_internal_chip_low = { | 48 | static struct irq_chip pxa_internal_irq_chip = { |
43 | .name = "SC", | 49 | .name = "SC", |
44 | .ack = pxa_mask_low_irq, | 50 | .ack = pxa_mask_irq, |
45 | .mask = pxa_mask_low_irq, | 51 | .mask = pxa_mask_irq, |
46 | .unmask = pxa_unmask_low_irq, | 52 | .unmask = pxa_unmask_irq, |
47 | }; | 53 | }; |
48 | 54 | ||
49 | void __init pxa_init_irq_low(void) | 55 | void __init pxa_init_irq(int irq_nr, set_wake_t fn) |
50 | { | 56 | { |
51 | int irq; | 57 | int irq; |
52 | 58 | ||
53 | /* disable all IRQs */ | 59 | pxa_internal_irq_nr = irq_nr; |
54 | ICMR = 0; | ||
55 | 60 | ||
56 | /* all IRQs are IRQ, not FIQ */ | 61 | for (irq = 0; irq < irq_nr; irq += 32) { |
57 | ICLR = 0; | 62 | _ICMR(irq) = 0; /* disable all IRQs */ |
63 | _ICLR(irq) = 0; /* all IRQs are IRQ, not FIQ */ | ||
64 | } | ||
58 | 65 | ||
59 | /* only unmasked interrupts kick us out of idle */ | 66 | /* only unmasked interrupts kick us out of idle */ |
60 | ICCR = 1; | 67 | ICCR = 1; |
61 | 68 | ||
62 | for (irq = PXA_IRQ(0); irq <= PXA_IRQ(31); irq++) { | 69 | for (irq = PXA_IRQ(0); irq < PXA_IRQ(irq_nr); irq++) { |
63 | set_irq_chip(irq, &pxa_internal_chip_low); | 70 | set_irq_chip(irq, &pxa_internal_irq_chip); |
64 | set_irq_handler(irq, handle_level_irq); | ||
65 | set_irq_flags(irq, IRQF_VALID); | ||
66 | } | ||
67 | } | ||
68 | |||
69 | #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) | ||
70 | |||
71 | /* | ||
72 | * This is for the second set of internal IRQs as found on the PXA27x. | ||
73 | */ | ||
74 | |||
75 | static void pxa_mask_high_irq(unsigned int irq) | ||
76 | { | ||
77 | ICMR2 &= ~(1 << (irq - 32)); | ||
78 | } | ||
79 | |||
80 | static void pxa_unmask_high_irq(unsigned int irq) | ||
81 | { | ||
82 | ICMR2 |= (1 << (irq - 32)); | ||
83 | } | ||
84 | |||
85 | static struct irq_chip pxa_internal_chip_high = { | ||
86 | .name = "SC-hi", | ||
87 | .ack = pxa_mask_high_irq, | ||
88 | .mask = pxa_mask_high_irq, | ||
89 | .unmask = pxa_unmask_high_irq, | ||
90 | }; | ||
91 | |||
92 | void __init pxa_init_irq_high(void) | ||
93 | { | ||
94 | int irq; | ||
95 | |||
96 | ICMR2 = 0; | ||
97 | ICLR2 = 0; | ||
98 | |||
99 | for (irq = PXA_IRQ(32); irq < PXA_IRQ(64); irq++) { | ||
100 | set_irq_chip(irq, &pxa_internal_chip_high); | ||
101 | set_irq_handler(irq, handle_level_irq); | 71 | set_irq_handler(irq, handle_level_irq); |
102 | set_irq_flags(irq, IRQF_VALID); | 72 | set_irq_flags(irq, IRQF_VALID); |
103 | } | 73 | } |
104 | } | ||
105 | #endif | ||
106 | |||
107 | /* | ||
108 | * PXA GPIO edge detection for IRQs: | ||
109 | * IRQs are generated on Falling-Edge, Rising-Edge, or both. | ||
110 | * Use this instead of directly setting GRER/GFER. | ||
111 | */ | ||
112 | |||
113 | static long GPIO_IRQ_rising_edge[4]; | ||
114 | static long GPIO_IRQ_falling_edge[4]; | ||
115 | static long GPIO_IRQ_mask[4]; | ||
116 | |||
117 | static int pxa_gpio_irq_type(unsigned int irq, unsigned int type) | ||
118 | { | ||
119 | int gpio, idx; | ||
120 | |||
121 | gpio = IRQ_TO_GPIO(irq); | ||
122 | idx = gpio >> 5; | ||
123 | |||
124 | if (type == IRQT_PROBE) { | ||
125 | /* Don't mess with enabled GPIOs using preconfigured edges or | ||
126 | GPIOs set to alternate function or to output during probe */ | ||
127 | if ((GPIO_IRQ_rising_edge[idx] | GPIO_IRQ_falling_edge[idx] | GPDR(gpio)) & | ||
128 | GPIO_bit(gpio)) | ||
129 | return 0; | ||
130 | if (GAFR(gpio) & (0x3 << (((gpio) & 0xf)*2))) | ||
131 | return 0; | ||
132 | type = __IRQT_RISEDGE | __IRQT_FALEDGE; | ||
133 | } | ||
134 | |||
135 | /* printk(KERN_DEBUG "IRQ%d (GPIO%d): ", irq, gpio); */ | ||
136 | |||
137 | pxa_gpio_mode(gpio | GPIO_IN); | ||
138 | |||
139 | if (type & __IRQT_RISEDGE) { | ||
140 | /* printk("rising "); */ | ||
141 | __set_bit (gpio, GPIO_IRQ_rising_edge); | ||
142 | } else { | ||
143 | __clear_bit (gpio, GPIO_IRQ_rising_edge); | ||
144 | } | ||
145 | |||
146 | if (type & __IRQT_FALEDGE) { | ||
147 | /* printk("falling "); */ | ||
148 | __set_bit (gpio, GPIO_IRQ_falling_edge); | ||
149 | } else { | ||
150 | __clear_bit (gpio, GPIO_IRQ_falling_edge); | ||
151 | } | ||
152 | |||
153 | /* printk("edges\n"); */ | ||
154 | |||
155 | GRER(gpio) = GPIO_IRQ_rising_edge[idx] & GPIO_IRQ_mask[idx]; | ||
156 | GFER(gpio) = GPIO_IRQ_falling_edge[idx] & GPIO_IRQ_mask[idx]; | ||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | /* | ||
161 | * GPIO IRQs must be acknowledged. This is for GPIO 0 and 1. | ||
162 | */ | ||
163 | |||
164 | static void pxa_ack_low_gpio(unsigned int irq) | ||
165 | { | ||
166 | GEDR0 = (1 << (irq - IRQ_GPIO0)); | ||
167 | } | ||
168 | |||
169 | static struct irq_chip pxa_low_gpio_chip = { | ||
170 | .name = "GPIO-l", | ||
171 | .ack = pxa_ack_low_gpio, | ||
172 | .mask = pxa_mask_low_irq, | ||
173 | .unmask = pxa_unmask_low_irq, | ||
174 | .set_type = pxa_gpio_irq_type, | ||
175 | }; | ||
176 | |||
177 | /* | ||
178 | * Demux handler for GPIO>=2 edge detect interrupts | ||
179 | */ | ||
180 | |||
181 | static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc) | ||
182 | { | ||
183 | unsigned int mask; | ||
184 | int loop; | ||
185 | |||
186 | do { | ||
187 | loop = 0; | ||
188 | |||
189 | mask = GEDR0 & GPIO_IRQ_mask[0] & ~3; | ||
190 | if (mask) { | ||
191 | GEDR0 = mask; | ||
192 | irq = IRQ_GPIO(2); | ||
193 | desc = irq_desc + irq; | ||
194 | mask >>= 2; | ||
195 | do { | ||
196 | if (mask & 1) | ||
197 | desc_handle_irq(irq, desc); | ||
198 | irq++; | ||
199 | desc++; | ||
200 | mask >>= 1; | ||
201 | } while (mask); | ||
202 | loop = 1; | ||
203 | } | ||
204 | |||
205 | mask = GEDR1 & GPIO_IRQ_mask[1]; | ||
206 | if (mask) { | ||
207 | GEDR1 = mask; | ||
208 | irq = IRQ_GPIO(32); | ||
209 | desc = irq_desc + irq; | ||
210 | do { | ||
211 | if (mask & 1) | ||
212 | desc_handle_irq(irq, desc); | ||
213 | irq++; | ||
214 | desc++; | ||
215 | mask >>= 1; | ||
216 | } while (mask); | ||
217 | loop = 1; | ||
218 | } | ||
219 | |||
220 | mask = GEDR2 & GPIO_IRQ_mask[2]; | ||
221 | if (mask) { | ||
222 | GEDR2 = mask; | ||
223 | irq = IRQ_GPIO(64); | ||
224 | desc = irq_desc + irq; | ||
225 | do { | ||
226 | if (mask & 1) | ||
227 | desc_handle_irq(irq, desc); | ||
228 | irq++; | ||
229 | desc++; | ||
230 | mask >>= 1; | ||
231 | } while (mask); | ||
232 | loop = 1; | ||
233 | } | ||
234 | |||
235 | mask = GEDR3 & GPIO_IRQ_mask[3]; | ||
236 | if (mask) { | ||
237 | GEDR3 = mask; | ||
238 | irq = IRQ_GPIO(96); | ||
239 | desc = irq_desc + irq; | ||
240 | do { | ||
241 | if (mask & 1) | ||
242 | desc_handle_irq(irq, desc); | ||
243 | irq++; | ||
244 | desc++; | ||
245 | mask >>= 1; | ||
246 | } while (mask); | ||
247 | loop = 1; | ||
248 | } | ||
249 | } while (loop); | ||
250 | } | ||
251 | |||
252 | static void pxa_ack_muxed_gpio(unsigned int irq) | ||
253 | { | ||
254 | int gpio = irq - IRQ_GPIO(2) + 2; | ||
255 | GEDR(gpio) = GPIO_bit(gpio); | ||
256 | } | ||
257 | |||
258 | static void pxa_mask_muxed_gpio(unsigned int irq) | ||
259 | { | ||
260 | int gpio = irq - IRQ_GPIO(2) + 2; | ||
261 | __clear_bit(gpio, GPIO_IRQ_mask); | ||
262 | GRER(gpio) &= ~GPIO_bit(gpio); | ||
263 | GFER(gpio) &= ~GPIO_bit(gpio); | ||
264 | } | ||
265 | |||
266 | static void pxa_unmask_muxed_gpio(unsigned int irq) | ||
267 | { | ||
268 | int gpio = irq - IRQ_GPIO(2) + 2; | ||
269 | int idx = gpio >> 5; | ||
270 | __set_bit(gpio, GPIO_IRQ_mask); | ||
271 | GRER(gpio) = GPIO_IRQ_rising_edge[idx] & GPIO_IRQ_mask[idx]; | ||
272 | GFER(gpio) = GPIO_IRQ_falling_edge[idx] & GPIO_IRQ_mask[idx]; | ||
273 | } | ||
274 | |||
275 | static struct irq_chip pxa_muxed_gpio_chip = { | ||
276 | .name = "GPIO", | ||
277 | .ack = pxa_ack_muxed_gpio, | ||
278 | .mask = pxa_mask_muxed_gpio, | ||
279 | .unmask = pxa_unmask_muxed_gpio, | ||
280 | .set_type = pxa_gpio_irq_type, | ||
281 | }; | ||
282 | |||
283 | void __init pxa_init_irq_gpio(int gpio_nr) | ||
284 | { | ||
285 | int irq, i; | ||
286 | |||
287 | pxa_last_gpio = gpio_nr - 1; | ||
288 | |||
289 | /* clear all GPIO edge detects */ | ||
290 | for (i = 0; i < gpio_nr; i += 32) { | ||
291 | GFER(i) = 0; | ||
292 | GRER(i) = 0; | ||
293 | GEDR(i) = GEDR(i); | ||
294 | } | ||
295 | |||
296 | /* GPIO 0 and 1 must have their mask bit always set */ | ||
297 | GPIO_IRQ_mask[0] = 3; | ||
298 | |||
299 | for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) { | ||
300 | set_irq_chip(irq, &pxa_low_gpio_chip); | ||
301 | set_irq_handler(irq, handle_edge_irq); | ||
302 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | ||
303 | } | ||
304 | 74 | ||
305 | for (irq = IRQ_GPIO(2); irq < IRQ_GPIO(gpio_nr); irq++) { | 75 | pxa_internal_irq_chip.set_wake = fn; |
306 | set_irq_chip(irq, &pxa_muxed_gpio_chip); | ||
307 | set_irq_handler(irq, handle_edge_irq); | ||
308 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | ||
309 | } | ||
310 | |||
311 | /* Install handler for GPIO>=2 edge detect interrupts */ | ||
312 | set_irq_chip(IRQ_GPIO_2_x, &pxa_internal_chip_low); | ||
313 | set_irq_chained_handler(IRQ_GPIO_2_x, pxa_gpio_demux_handler); | ||
314 | |||
315 | pxa_init_gpio(gpio_nr); | ||
316 | } | ||
317 | |||
318 | void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int)) | ||
319 | { | ||
320 | pxa_internal_chip_low.set_wake = set_wake; | ||
321 | #ifdef CONFIG_PXA27x | ||
322 | pxa_internal_chip_high.set_wake = set_wake; | ||
323 | #endif | ||
324 | pxa_low_gpio_chip.set_wake = set_wake; | ||
325 | pxa_muxed_gpio_chip.set_wake = set_wake; | ||
326 | } | 76 | } |
327 | 77 | ||
328 | #ifdef CONFIG_PM | 78 | #ifdef CONFIG_PM |
@@ -330,19 +80,11 @@ static unsigned long saved_icmr[2]; | |||
330 | 80 | ||
331 | static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state) | 81 | static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state) |
332 | { | 82 | { |
333 | switch (dev->id) { | 83 | int i, irq = PXA_IRQ(0); |
334 | case 0: | 84 | |
335 | saved_icmr[0] = ICMR; | 85 | for (i = 0; irq < PXA_IRQ(pxa_internal_irq_nr); i++, irq += 32) { |
336 | ICMR = 0; | 86 | saved_icmr[i] = _ICMR(irq); |
337 | break; | 87 | _ICMR(irq) = 0; |
338 | #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) | ||
339 | case 1: | ||
340 | saved_icmr[1] = ICMR2; | ||
341 | ICMR2 = 0; | ||
342 | break; | ||
343 | #endif | ||
344 | default: | ||
345 | return -EINVAL; | ||
346 | } | 88 | } |
347 | 89 | ||
348 | return 0; | 90 | return 0; |
@@ -350,22 +92,14 @@ static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state) | |||
350 | 92 | ||
351 | static int pxa_irq_resume(struct sys_device *dev) | 93 | static int pxa_irq_resume(struct sys_device *dev) |
352 | { | 94 | { |
353 | switch (dev->id) { | 95 | int i, irq = PXA_IRQ(0); |
354 | case 0: | 96 | |
355 | ICMR = saved_icmr[0]; | 97 | for (i = 0; irq < PXA_IRQ(pxa_internal_irq_nr); i++, irq += 32) { |
356 | ICLR = 0; | 98 | _ICMR(irq) = saved_icmr[i]; |
357 | ICCR = 1; | 99 | _ICLR(irq) = 0; |
358 | break; | ||
359 | #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) | ||
360 | case 1: | ||
361 | ICMR2 = saved_icmr[1]; | ||
362 | ICLR2 = 0; | ||
363 | break; | ||
364 | #endif | ||
365 | default: | ||
366 | return -EINVAL; | ||
367 | } | 100 | } |
368 | 101 | ||
102 | ICCR = 1; | ||
369 | return 0; | 103 | return 0; |
370 | } | 104 | } |
371 | #else | 105 | #else |