Commit | Line | Data |
---|---|---|
c4a0208f KW |
1 | /* |
2 | * arch/arm/mach-lpc32xx/irq.c | |
3 | * | |
4 | * Author: Kevin Wells <kevin.wells@nxp.com> | |
5 | * | |
6 | * Copyright (C) 2010 NXP Semiconductors | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify | |
9 | * it under the terms of the GNU General Public License as published by | |
10 | * the Free Software Foundation; either version 2 of the License, or | |
11 | * (at your option) any later version. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | */ | |
18 | ||
19 | #include <linux/kernel.h> | |
20 | #include <linux/types.h> | |
21 | #include <linux/interrupt.h> | |
22 | #include <linux/irq.h> | |
23 | #include <linux/err.h> | |
24 | #include <linux/io.h> | |
25 | ||
26 | #include <mach/irqs.h> | |
27 | #include <mach/hardware.h> | |
28 | #include <mach/platform.h> | |
29 | #include "common.h" | |
30 | ||
31 | /* | |
32 | * Default value representing the Activation polarity of all internal | |
33 | * interrupt sources | |
34 | */ | |
35 | #define MIC_APR_DEFAULT 0x3FF0EFE0 | |
36 | #define SIC1_APR_DEFAULT 0xFBD27186 | |
37 | #define SIC2_APR_DEFAULT 0x801810C0 | |
38 | ||
39 | /* | |
40 | * Default value representing the Activation Type of all internal | |
41 | * interrupt sources. All are level sensitive. | |
42 | */ | |
43 | #define MIC_ATR_DEFAULT 0x00000000 | |
44 | #define SIC1_ATR_DEFAULT 0x00026000 | |
45 | #define SIC2_ATR_DEFAULT 0x00000000 | |
46 | ||
47 | struct lpc32xx_event_group_regs { | |
48 | void __iomem *enab_reg; | |
49 | void __iomem *edge_reg; | |
50 | void __iomem *maskstat_reg; | |
51 | void __iomem *rawstat_reg; | |
52 | }; | |
53 | ||
54 | static const struct lpc32xx_event_group_regs lpc32xx_event_int_regs = { | |
55 | .enab_reg = LPC32XX_CLKPWR_INT_ER, | |
56 | .edge_reg = LPC32XX_CLKPWR_INT_AP, | |
57 | .maskstat_reg = LPC32XX_CLKPWR_INT_SR, | |
58 | .rawstat_reg = LPC32XX_CLKPWR_INT_RS, | |
59 | }; | |
60 | ||
61 | static const struct lpc32xx_event_group_regs lpc32xx_event_pin_regs = { | |
62 | .enab_reg = LPC32XX_CLKPWR_PIN_ER, | |
63 | .edge_reg = LPC32XX_CLKPWR_PIN_AP, | |
64 | .maskstat_reg = LPC32XX_CLKPWR_PIN_SR, | |
65 | .rawstat_reg = LPC32XX_CLKPWR_PIN_RS, | |
66 | }; | |
67 | ||
68 | struct lpc32xx_event_info { | |
69 | const struct lpc32xx_event_group_regs *event_group; | |
70 | u32 mask; | |
71 | }; | |
72 | ||
73 | /* | |
74 | * Maps an IRQ number to and event mask and register | |
75 | */ | |
76 | static const struct lpc32xx_event_info lpc32xx_events[NR_IRQS] = { | |
77 | [IRQ_LPC32XX_GPI_08] = { | |
78 | .event_group = &lpc32xx_event_pin_regs, | |
79 | .mask = LPC32XX_CLKPWR_EXTSRC_GPI_08_BIT, | |
80 | }, | |
81 | [IRQ_LPC32XX_GPI_09] = { | |
82 | .event_group = &lpc32xx_event_pin_regs, | |
83 | .mask = LPC32XX_CLKPWR_EXTSRC_GPI_09_BIT, | |
84 | }, | |
85 | [IRQ_LPC32XX_GPI_19] = { | |
86 | .event_group = &lpc32xx_event_pin_regs, | |
87 | .mask = LPC32XX_CLKPWR_EXTSRC_GPI_19_BIT, | |
88 | }, | |
89 | [IRQ_LPC32XX_GPI_07] = { | |
90 | .event_group = &lpc32xx_event_pin_regs, | |
91 | .mask = LPC32XX_CLKPWR_EXTSRC_GPI_07_BIT, | |
92 | }, | |
93 | [IRQ_LPC32XX_GPI_00] = { | |
94 | .event_group = &lpc32xx_event_pin_regs, | |
95 | .mask = LPC32XX_CLKPWR_EXTSRC_GPI_00_BIT, | |
96 | }, | |
97 | [IRQ_LPC32XX_GPI_01] = { | |
98 | .event_group = &lpc32xx_event_pin_regs, | |
99 | .mask = LPC32XX_CLKPWR_EXTSRC_GPI_01_BIT, | |
100 | }, | |
101 | [IRQ_LPC32XX_GPI_02] = { | |
102 | .event_group = &lpc32xx_event_pin_regs, | |
103 | .mask = LPC32XX_CLKPWR_EXTSRC_GPI_02_BIT, | |
104 | }, | |
105 | [IRQ_LPC32XX_GPI_03] = { | |
106 | .event_group = &lpc32xx_event_pin_regs, | |
107 | .mask = LPC32XX_CLKPWR_EXTSRC_GPI_03_BIT, | |
108 | }, | |
109 | [IRQ_LPC32XX_GPI_04] = { | |
110 | .event_group = &lpc32xx_event_pin_regs, | |
111 | .mask = LPC32XX_CLKPWR_EXTSRC_GPI_04_BIT, | |
112 | }, | |
113 | [IRQ_LPC32XX_GPI_05] = { | |
114 | .event_group = &lpc32xx_event_pin_regs, | |
115 | .mask = LPC32XX_CLKPWR_EXTSRC_GPI_05_BIT, | |
116 | }, | |
117 | [IRQ_LPC32XX_GPI_06] = { | |
118 | .event_group = &lpc32xx_event_pin_regs, | |
119 | .mask = LPC32XX_CLKPWR_EXTSRC_GPI_06_BIT, | |
120 | }, | |
121 | [IRQ_LPC32XX_GPIO_00] = { | |
122 | .event_group = &lpc32xx_event_int_regs, | |
123 | .mask = LPC32XX_CLKPWR_INTSRC_GPIO_00_BIT, | |
124 | }, | |
125 | [IRQ_LPC32XX_GPIO_01] = { | |
126 | .event_group = &lpc32xx_event_int_regs, | |
127 | .mask = LPC32XX_CLKPWR_INTSRC_GPIO_01_BIT, | |
128 | }, | |
129 | [IRQ_LPC32XX_GPIO_02] = { | |
130 | .event_group = &lpc32xx_event_int_regs, | |
131 | .mask = LPC32XX_CLKPWR_INTSRC_GPIO_02_BIT, | |
132 | }, | |
133 | [IRQ_LPC32XX_GPIO_03] = { | |
134 | .event_group = &lpc32xx_event_int_regs, | |
135 | .mask = LPC32XX_CLKPWR_INTSRC_GPIO_03_BIT, | |
136 | }, | |
137 | [IRQ_LPC32XX_GPIO_04] = { | |
138 | .event_group = &lpc32xx_event_int_regs, | |
139 | .mask = LPC32XX_CLKPWR_INTSRC_GPIO_04_BIT, | |
140 | }, | |
141 | [IRQ_LPC32XX_GPIO_05] = { | |
142 | .event_group = &lpc32xx_event_int_regs, | |
143 | .mask = LPC32XX_CLKPWR_INTSRC_GPIO_05_BIT, | |
144 | }, | |
145 | [IRQ_LPC32XX_KEY] = { | |
146 | .event_group = &lpc32xx_event_int_regs, | |
147 | .mask = LPC32XX_CLKPWR_INTSRC_KEY_BIT, | |
148 | }, | |
149 | [IRQ_LPC32XX_USB_OTG_ATX] = { | |
150 | .event_group = &lpc32xx_event_int_regs, | |
151 | .mask = LPC32XX_CLKPWR_INTSRC_USBATXINT_BIT, | |
152 | }, | |
153 | [IRQ_LPC32XX_USB_HOST] = { | |
154 | .event_group = &lpc32xx_event_int_regs, | |
155 | .mask = LPC32XX_CLKPWR_INTSRC_USB_BIT, | |
156 | }, | |
157 | [IRQ_LPC32XX_RTC] = { | |
158 | .event_group = &lpc32xx_event_int_regs, | |
159 | .mask = LPC32XX_CLKPWR_INTSRC_RTC_BIT, | |
160 | }, | |
161 | [IRQ_LPC32XX_MSTIMER] = { | |
162 | .event_group = &lpc32xx_event_int_regs, | |
163 | .mask = LPC32XX_CLKPWR_INTSRC_MSTIMER_BIT, | |
164 | }, | |
165 | [IRQ_LPC32XX_TS_AUX] = { | |
166 | .event_group = &lpc32xx_event_int_regs, | |
167 | .mask = LPC32XX_CLKPWR_INTSRC_TS_AUX_BIT, | |
168 | }, | |
169 | [IRQ_LPC32XX_TS_P] = { | |
170 | .event_group = &lpc32xx_event_int_regs, | |
171 | .mask = LPC32XX_CLKPWR_INTSRC_TS_P_BIT, | |
172 | }, | |
173 | [IRQ_LPC32XX_TS_IRQ] = { | |
174 | .event_group = &lpc32xx_event_int_regs, | |
175 | .mask = LPC32XX_CLKPWR_INTSRC_ADC_BIT, | |
176 | }, | |
177 | }; | |
178 | ||
179 | static void get_controller(unsigned int irq, unsigned int *base, | |
180 | unsigned int *irqbit) | |
181 | { | |
182 | if (irq < 32) { | |
183 | *base = LPC32XX_MIC_BASE; | |
184 | *irqbit = 1 << irq; | |
185 | } else if (irq < 64) { | |
186 | *base = LPC32XX_SIC1_BASE; | |
187 | *irqbit = 1 << (irq - 32); | |
188 | } else { | |
189 | *base = LPC32XX_SIC2_BASE; | |
190 | *irqbit = 1 << (irq - 64); | |
191 | } | |
192 | } | |
193 | ||
56385381 | 194 | static void lpc32xx_mask_irq(struct irq_data *d) |
c4a0208f KW |
195 | { |
196 | unsigned int reg, ctrl, mask; | |
197 | ||
56385381 | 198 | get_controller(d->irq, &ctrl, &mask); |
c4a0208f KW |
199 | |
200 | reg = __raw_readl(LPC32XX_INTC_MASK(ctrl)) & ~mask; | |
201 | __raw_writel(reg, LPC32XX_INTC_MASK(ctrl)); | |
202 | } | |
203 | ||
56385381 | 204 | static void lpc32xx_unmask_irq(struct irq_data *d) |
c4a0208f KW |
205 | { |
206 | unsigned int reg, ctrl, mask; | |
207 | ||
56385381 | 208 | get_controller(d->irq, &ctrl, &mask); |
c4a0208f KW |
209 | |
210 | reg = __raw_readl(LPC32XX_INTC_MASK(ctrl)) | mask; | |
211 | __raw_writel(reg, LPC32XX_INTC_MASK(ctrl)); | |
212 | } | |
213 | ||
56385381 | 214 | static void lpc32xx_ack_irq(struct irq_data *d) |
c4a0208f KW |
215 | { |
216 | unsigned int ctrl, mask; | |
217 | ||
56385381 | 218 | get_controller(d->irq, &ctrl, &mask); |
c4a0208f KW |
219 | |
220 | __raw_writel(mask, LPC32XX_INTC_RAW_STAT(ctrl)); | |
221 | ||
222 | /* Also need to clear pending wake event */ | |
56385381 LB |
223 | if (lpc32xx_events[d->irq].mask != 0) |
224 | __raw_writel(lpc32xx_events[d->irq].mask, | |
225 | lpc32xx_events[d->irq].event_group->rawstat_reg); | |
c4a0208f KW |
226 | } |
227 | ||
228 | static void __lpc32xx_set_irq_type(unsigned int irq, int use_high_level, | |
229 | int use_edge) | |
230 | { | |
231 | unsigned int reg, ctrl, mask; | |
232 | ||
233 | get_controller(irq, &ctrl, &mask); | |
234 | ||
235 | /* Activation level, high or low */ | |
236 | reg = __raw_readl(LPC32XX_INTC_POLAR(ctrl)); | |
237 | if (use_high_level) | |
238 | reg |= mask; | |
239 | else | |
240 | reg &= ~mask; | |
241 | __raw_writel(reg, LPC32XX_INTC_POLAR(ctrl)); | |
242 | ||
243 | /* Activation type, edge or level */ | |
244 | reg = __raw_readl(LPC32XX_INTC_ACT_TYPE(ctrl)); | |
245 | if (use_edge) | |
246 | reg |= mask; | |
247 | else | |
248 | reg &= ~mask; | |
249 | __raw_writel(reg, LPC32XX_INTC_ACT_TYPE(ctrl)); | |
250 | ||
251 | /* Use same polarity for the wake events */ | |
252 | if (lpc32xx_events[irq].mask != 0) { | |
253 | reg = __raw_readl(lpc32xx_events[irq].event_group->edge_reg); | |
254 | ||
255 | if (use_high_level) | |
256 | reg |= lpc32xx_events[irq].mask; | |
257 | else | |
258 | reg &= ~lpc32xx_events[irq].mask; | |
259 | ||
260 | __raw_writel(reg, lpc32xx_events[irq].event_group->edge_reg); | |
261 | } | |
262 | } | |
263 | ||
56385381 | 264 | static int lpc32xx_set_irq_type(struct irq_data *d, unsigned int type) |
c4a0208f KW |
265 | { |
266 | switch (type) { | |
267 | case IRQ_TYPE_EDGE_RISING: | |
268 | /* Rising edge sensitive */ | |
56385381 | 269 | __lpc32xx_set_irq_type(d->irq, 1, 1); |
c4a0208f KW |
270 | break; |
271 | ||
272 | case IRQ_TYPE_EDGE_FALLING: | |
273 | /* Falling edge sensitive */ | |
56385381 | 274 | __lpc32xx_set_irq_type(d->irq, 0, 1); |
c4a0208f KW |
275 | break; |
276 | ||
277 | case IRQ_TYPE_LEVEL_LOW: | |
278 | /* Low level sensitive */ | |
56385381 | 279 | __lpc32xx_set_irq_type(d->irq, 0, 0); |
c4a0208f KW |
280 | break; |
281 | ||
282 | case IRQ_TYPE_LEVEL_HIGH: | |
283 | /* High level sensitive */ | |
56385381 | 284 | __lpc32xx_set_irq_type(d->irq, 1, 0); |
c4a0208f KW |
285 | break; |
286 | ||
287 | /* Other modes are not supported */ | |
288 | default: | |
289 | return -EINVAL; | |
290 | } | |
291 | ||
292 | /* Ok to use the level handler for all types */ | |
6845664a | 293 | irq_set_handler(d->irq, handle_level_irq); |
c4a0208f KW |
294 | |
295 | return 0; | |
296 | } | |
297 | ||
56385381 | 298 | static int lpc32xx_irq_wake(struct irq_data *d, unsigned int state) |
c4a0208f KW |
299 | { |
300 | unsigned long eventreg; | |
301 | ||
56385381 LB |
302 | if (lpc32xx_events[d->irq].mask != 0) { |
303 | eventreg = __raw_readl(lpc32xx_events[d->irq]. | |
c4a0208f KW |
304 | event_group->enab_reg); |
305 | ||
306 | if (state) | |
56385381 | 307 | eventreg |= lpc32xx_events[d->irq].mask; |
c4a0208f | 308 | else |
56385381 | 309 | eventreg &= ~lpc32xx_events[d->irq].mask; |
c4a0208f KW |
310 | |
311 | __raw_writel(eventreg, | |
56385381 | 312 | lpc32xx_events[d->irq].event_group->enab_reg); |
c4a0208f KW |
313 | |
314 | return 0; | |
315 | } | |
316 | ||
317 | /* Clear event */ | |
56385381 LB |
318 | __raw_writel(lpc32xx_events[d->irq].mask, |
319 | lpc32xx_events[d->irq].event_group->rawstat_reg); | |
c4a0208f KW |
320 | |
321 | return -ENODEV; | |
322 | } | |
323 | ||
324 | static void __init lpc32xx_set_default_mappings(unsigned int apr, | |
325 | unsigned int atr, unsigned int offset) | |
326 | { | |
327 | unsigned int i; | |
328 | ||
329 | /* Set activation levels for each interrupt */ | |
330 | i = 0; | |
331 | while (i < 32) { | |
332 | __lpc32xx_set_irq_type(offset + i, ((apr >> i) & 0x1), | |
333 | ((atr >> i) & 0x1)); | |
334 | i++; | |
335 | } | |
336 | } | |
337 | ||
338 | static struct irq_chip lpc32xx_irq_chip = { | |
56385381 LB |
339 | .irq_ack = lpc32xx_ack_irq, |
340 | .irq_mask = lpc32xx_mask_irq, | |
341 | .irq_unmask = lpc32xx_unmask_irq, | |
342 | .irq_set_type = lpc32xx_set_irq_type, | |
343 | .irq_set_wake = lpc32xx_irq_wake | |
c4a0208f KW |
344 | }; |
345 | ||
346 | static void lpc32xx_sic1_handler(unsigned int irq, struct irq_desc *desc) | |
347 | { | |
348 | unsigned long ints = __raw_readl(LPC32XX_INTC_STAT(LPC32XX_SIC1_BASE)); | |
349 | ||
350 | while (ints != 0) { | |
351 | int irqno = fls(ints) - 1; | |
352 | ||
353 | ints &= ~(1 << irqno); | |
354 | ||
355 | generic_handle_irq(LPC32XX_SIC1_IRQ(irqno)); | |
356 | } | |
357 | } | |
358 | ||
359 | static void lpc32xx_sic2_handler(unsigned int irq, struct irq_desc *desc) | |
360 | { | |
361 | unsigned long ints = __raw_readl(LPC32XX_INTC_STAT(LPC32XX_SIC2_BASE)); | |
362 | ||
363 | while (ints != 0) { | |
364 | int irqno = fls(ints) - 1; | |
365 | ||
366 | ints &= ~(1 << irqno); | |
367 | ||
368 | generic_handle_irq(LPC32XX_SIC2_IRQ(irqno)); | |
369 | } | |
370 | } | |
371 | ||
372 | void __init lpc32xx_init_irq(void) | |
373 | { | |
374 | unsigned int i; | |
375 | ||
376 | /* Setup MIC */ | |
377 | __raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_MIC_BASE)); | |
378 | __raw_writel(MIC_APR_DEFAULT, LPC32XX_INTC_POLAR(LPC32XX_MIC_BASE)); | |
379 | __raw_writel(MIC_ATR_DEFAULT, LPC32XX_INTC_ACT_TYPE(LPC32XX_MIC_BASE)); | |
380 | ||
381 | /* Setup SIC1 */ | |
382 | __raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC1_BASE)); | |
383 | __raw_writel(MIC_APR_DEFAULT, LPC32XX_INTC_POLAR(LPC32XX_SIC1_BASE)); | |
384 | __raw_writel(MIC_ATR_DEFAULT, LPC32XX_INTC_ACT_TYPE(LPC32XX_SIC1_BASE)); | |
385 | ||
386 | /* Setup SIC2 */ | |
387 | __raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC2_BASE)); | |
388 | __raw_writel(MIC_APR_DEFAULT, LPC32XX_INTC_POLAR(LPC32XX_SIC2_BASE)); | |
389 | __raw_writel(MIC_ATR_DEFAULT, LPC32XX_INTC_ACT_TYPE(LPC32XX_SIC2_BASE)); | |
390 | ||
391 | /* Configure supported IRQ's */ | |
392 | for (i = 0; i < NR_IRQS; i++) { | |
f38c02f3 TG |
393 | irq_set_chip_and_handler(i, &lpc32xx_irq_chip, |
394 | handle_level_irq); | |
c4a0208f KW |
395 | set_irq_flags(i, IRQF_VALID); |
396 | } | |
397 | ||
398 | /* Set default mappings */ | |
399 | lpc32xx_set_default_mappings(MIC_APR_DEFAULT, MIC_ATR_DEFAULT, 0); | |
400 | lpc32xx_set_default_mappings(SIC1_APR_DEFAULT, SIC1_ATR_DEFAULT, 32); | |
401 | lpc32xx_set_default_mappings(SIC2_APR_DEFAULT, SIC2_ATR_DEFAULT, 64); | |
402 | ||
403 | /* mask all interrupts except SUBIRQ */ | |
404 | __raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_MIC_BASE)); | |
405 | __raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC1_BASE)); | |
406 | __raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC2_BASE)); | |
407 | ||
408 | /* MIC SUBIRQx interrupts will route handling to the chain handlers */ | |
6845664a TG |
409 | irq_set_chained_handler(IRQ_LPC32XX_SUB1IRQ, lpc32xx_sic1_handler); |
410 | irq_set_chained_handler(IRQ_LPC32XX_SUB2IRQ, lpc32xx_sic2_handler); | |
c4a0208f KW |
411 | |
412 | /* Initially disable all wake events */ | |
413 | __raw_writel(0, LPC32XX_CLKPWR_P01_ER); | |
414 | __raw_writel(0, LPC32XX_CLKPWR_INT_ER); | |
415 | __raw_writel(0, LPC32XX_CLKPWR_PIN_ER); | |
416 | ||
417 | /* | |
418 | * Default wake activation polarities, all pin sources are low edge | |
419 | * triggered | |
420 | */ | |
421 | __raw_writel(LPC32XX_CLKPWR_INTSRC_TS_P_BIT | | |
422 | LPC32XX_CLKPWR_INTSRC_MSTIMER_BIT | | |
423 | LPC32XX_CLKPWR_INTSRC_RTC_BIT, | |
424 | LPC32XX_CLKPWR_INT_AP); | |
425 | __raw_writel(0, LPC32XX_CLKPWR_PIN_AP); | |
426 | ||
427 | /* Clear latched wake event states */ | |
428 | __raw_writel(__raw_readl(LPC32XX_CLKPWR_PIN_RS), | |
429 | LPC32XX_CLKPWR_PIN_RS); | |
430 | __raw_writel(__raw_readl(LPC32XX_CLKPWR_INT_RS), | |
431 | LPC32XX_CLKPWR_INT_RS); | |
432 | } |