ARM/LPC32xx: Use irq not hwirq for __irq_set_handler_locked()
[linux-2.6-block.git] / arch / arm / mach-lpc32xx / irq.c
CommitLineData
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>
f5c42271
RS
25#include <linux/of.h>
26#include <linux/of_address.h>
27#include <linux/of_irq.h>
28#include <linux/irqdomain.h>
29#include <linux/module.h>
c4a0208f
KW
30
31#include <mach/irqs.h>
32#include <mach/hardware.h>
33#include <mach/platform.h>
34#include "common.h"
35
36/*
37 * Default value representing the Activation polarity of all internal
38 * interrupt sources
39 */
40#define MIC_APR_DEFAULT 0x3FF0EFE0
41#define SIC1_APR_DEFAULT 0xFBD27186
42#define SIC2_APR_DEFAULT 0x801810C0
43
44/*
45 * Default value representing the Activation Type of all internal
46 * interrupt sources. All are level sensitive.
47 */
48#define MIC_ATR_DEFAULT 0x00000000
49#define SIC1_ATR_DEFAULT 0x00026000
50#define SIC2_ATR_DEFAULT 0x00000000
51
f5c42271
RS
52static struct irq_domain *lpc32xx_mic_domain;
53static struct device_node *lpc32xx_mic_np;
54
c4a0208f
KW
55struct lpc32xx_event_group_regs {
56 void __iomem *enab_reg;
57 void __iomem *edge_reg;
58 void __iomem *maskstat_reg;
59 void __iomem *rawstat_reg;
60};
61
62static const struct lpc32xx_event_group_regs lpc32xx_event_int_regs = {
63 .enab_reg = LPC32XX_CLKPWR_INT_ER,
64 .edge_reg = LPC32XX_CLKPWR_INT_AP,
65 .maskstat_reg = LPC32XX_CLKPWR_INT_SR,
66 .rawstat_reg = LPC32XX_CLKPWR_INT_RS,
67};
68
69static const struct lpc32xx_event_group_regs lpc32xx_event_pin_regs = {
70 .enab_reg = LPC32XX_CLKPWR_PIN_ER,
71 .edge_reg = LPC32XX_CLKPWR_PIN_AP,
72 .maskstat_reg = LPC32XX_CLKPWR_PIN_SR,
73 .rawstat_reg = LPC32XX_CLKPWR_PIN_RS,
74};
75
76struct lpc32xx_event_info {
77 const struct lpc32xx_event_group_regs *event_group;
78 u32 mask;
79};
80
81/*
82 * Maps an IRQ number to and event mask and register
83 */
84static const struct lpc32xx_event_info lpc32xx_events[NR_IRQS] = {
85 [IRQ_LPC32XX_GPI_08] = {
86 .event_group = &lpc32xx_event_pin_regs,
87 .mask = LPC32XX_CLKPWR_EXTSRC_GPI_08_BIT,
88 },
89 [IRQ_LPC32XX_GPI_09] = {
90 .event_group = &lpc32xx_event_pin_regs,
91 .mask = LPC32XX_CLKPWR_EXTSRC_GPI_09_BIT,
92 },
93 [IRQ_LPC32XX_GPI_19] = {
94 .event_group = &lpc32xx_event_pin_regs,
95 .mask = LPC32XX_CLKPWR_EXTSRC_GPI_19_BIT,
96 },
97 [IRQ_LPC32XX_GPI_07] = {
98 .event_group = &lpc32xx_event_pin_regs,
99 .mask = LPC32XX_CLKPWR_EXTSRC_GPI_07_BIT,
100 },
101 [IRQ_LPC32XX_GPI_00] = {
102 .event_group = &lpc32xx_event_pin_regs,
103 .mask = LPC32XX_CLKPWR_EXTSRC_GPI_00_BIT,
104 },
105 [IRQ_LPC32XX_GPI_01] = {
106 .event_group = &lpc32xx_event_pin_regs,
107 .mask = LPC32XX_CLKPWR_EXTSRC_GPI_01_BIT,
108 },
109 [IRQ_LPC32XX_GPI_02] = {
110 .event_group = &lpc32xx_event_pin_regs,
111 .mask = LPC32XX_CLKPWR_EXTSRC_GPI_02_BIT,
112 },
113 [IRQ_LPC32XX_GPI_03] = {
114 .event_group = &lpc32xx_event_pin_regs,
115 .mask = LPC32XX_CLKPWR_EXTSRC_GPI_03_BIT,
116 },
117 [IRQ_LPC32XX_GPI_04] = {
118 .event_group = &lpc32xx_event_pin_regs,
119 .mask = LPC32XX_CLKPWR_EXTSRC_GPI_04_BIT,
120 },
121 [IRQ_LPC32XX_GPI_05] = {
122 .event_group = &lpc32xx_event_pin_regs,
123 .mask = LPC32XX_CLKPWR_EXTSRC_GPI_05_BIT,
124 },
125 [IRQ_LPC32XX_GPI_06] = {
126 .event_group = &lpc32xx_event_pin_regs,
127 .mask = LPC32XX_CLKPWR_EXTSRC_GPI_06_BIT,
128 },
f6737055
RS
129 [IRQ_LPC32XX_GPI_28] = {
130 .event_group = &lpc32xx_event_pin_regs,
131 .mask = LPC32XX_CLKPWR_EXTSRC_GPI_28_BIT,
132 },
c4a0208f
KW
133 [IRQ_LPC32XX_GPIO_00] = {
134 .event_group = &lpc32xx_event_int_regs,
135 .mask = LPC32XX_CLKPWR_INTSRC_GPIO_00_BIT,
136 },
137 [IRQ_LPC32XX_GPIO_01] = {
138 .event_group = &lpc32xx_event_int_regs,
139 .mask = LPC32XX_CLKPWR_INTSRC_GPIO_01_BIT,
140 },
141 [IRQ_LPC32XX_GPIO_02] = {
142 .event_group = &lpc32xx_event_int_regs,
143 .mask = LPC32XX_CLKPWR_INTSRC_GPIO_02_BIT,
144 },
145 [IRQ_LPC32XX_GPIO_03] = {
146 .event_group = &lpc32xx_event_int_regs,
147 .mask = LPC32XX_CLKPWR_INTSRC_GPIO_03_BIT,
148 },
149 [IRQ_LPC32XX_GPIO_04] = {
150 .event_group = &lpc32xx_event_int_regs,
151 .mask = LPC32XX_CLKPWR_INTSRC_GPIO_04_BIT,
152 },
153 [IRQ_LPC32XX_GPIO_05] = {
154 .event_group = &lpc32xx_event_int_regs,
155 .mask = LPC32XX_CLKPWR_INTSRC_GPIO_05_BIT,
156 },
157 [IRQ_LPC32XX_KEY] = {
158 .event_group = &lpc32xx_event_int_regs,
159 .mask = LPC32XX_CLKPWR_INTSRC_KEY_BIT,
160 },
c20b909b
RS
161 [IRQ_LPC32XX_ETHERNET] = {
162 .event_group = &lpc32xx_event_int_regs,
163 .mask = LPC32XX_CLKPWR_INTSRC_MAC_BIT,
164 },
c4a0208f
KW
165 [IRQ_LPC32XX_USB_OTG_ATX] = {
166 .event_group = &lpc32xx_event_int_regs,
167 .mask = LPC32XX_CLKPWR_INTSRC_USBATXINT_BIT,
168 },
169 [IRQ_LPC32XX_USB_HOST] = {
170 .event_group = &lpc32xx_event_int_regs,
171 .mask = LPC32XX_CLKPWR_INTSRC_USB_BIT,
172 },
173 [IRQ_LPC32XX_RTC] = {
174 .event_group = &lpc32xx_event_int_regs,
175 .mask = LPC32XX_CLKPWR_INTSRC_RTC_BIT,
176 },
177 [IRQ_LPC32XX_MSTIMER] = {
178 .event_group = &lpc32xx_event_int_regs,
179 .mask = LPC32XX_CLKPWR_INTSRC_MSTIMER_BIT,
180 },
181 [IRQ_LPC32XX_TS_AUX] = {
182 .event_group = &lpc32xx_event_int_regs,
183 .mask = LPC32XX_CLKPWR_INTSRC_TS_AUX_BIT,
184 },
185 [IRQ_LPC32XX_TS_P] = {
186 .event_group = &lpc32xx_event_int_regs,
187 .mask = LPC32XX_CLKPWR_INTSRC_TS_P_BIT,
188 },
189 [IRQ_LPC32XX_TS_IRQ] = {
190 .event_group = &lpc32xx_event_int_regs,
191 .mask = LPC32XX_CLKPWR_INTSRC_ADC_BIT,
192 },
193};
194
195static void get_controller(unsigned int irq, unsigned int *base,
196 unsigned int *irqbit)
197{
198 if (irq < 32) {
199 *base = LPC32XX_MIC_BASE;
200 *irqbit = 1 << irq;
201 } else if (irq < 64) {
202 *base = LPC32XX_SIC1_BASE;
203 *irqbit = 1 << (irq - 32);
204 } else {
205 *base = LPC32XX_SIC2_BASE;
206 *irqbit = 1 << (irq - 64);
207 }
208}
209
56385381 210static void lpc32xx_mask_irq(struct irq_data *d)
c4a0208f
KW
211{
212 unsigned int reg, ctrl, mask;
213
f5c42271 214 get_controller(d->hwirq, &ctrl, &mask);
c4a0208f
KW
215
216 reg = __raw_readl(LPC32XX_INTC_MASK(ctrl)) & ~mask;
217 __raw_writel(reg, LPC32XX_INTC_MASK(ctrl));
218}
219
56385381 220static void lpc32xx_unmask_irq(struct irq_data *d)
c4a0208f
KW
221{
222 unsigned int reg, ctrl, mask;
223
f5c42271 224 get_controller(d->hwirq, &ctrl, &mask);
c4a0208f
KW
225
226 reg = __raw_readl(LPC32XX_INTC_MASK(ctrl)) | mask;
227 __raw_writel(reg, LPC32XX_INTC_MASK(ctrl));
228}
229
56385381 230static void lpc32xx_ack_irq(struct irq_data *d)
c4a0208f
KW
231{
232 unsigned int ctrl, mask;
233
f5c42271 234 get_controller(d->hwirq, &ctrl, &mask);
c4a0208f
KW
235
236 __raw_writel(mask, LPC32XX_INTC_RAW_STAT(ctrl));
237
238 /* Also need to clear pending wake event */
f5c42271
RS
239 if (lpc32xx_events[d->hwirq].mask != 0)
240 __raw_writel(lpc32xx_events[d->hwirq].mask,
241 lpc32xx_events[d->hwirq].event_group->rawstat_reg);
c4a0208f
KW
242}
243
244static void __lpc32xx_set_irq_type(unsigned int irq, int use_high_level,
245 int use_edge)
246{
247 unsigned int reg, ctrl, mask;
248
249 get_controller(irq, &ctrl, &mask);
250
251 /* Activation level, high or low */
252 reg = __raw_readl(LPC32XX_INTC_POLAR(ctrl));
253 if (use_high_level)
254 reg |= mask;
255 else
256 reg &= ~mask;
257 __raw_writel(reg, LPC32XX_INTC_POLAR(ctrl));
258
259 /* Activation type, edge or level */
260 reg = __raw_readl(LPC32XX_INTC_ACT_TYPE(ctrl));
261 if (use_edge)
262 reg |= mask;
263 else
264 reg &= ~mask;
265 __raw_writel(reg, LPC32XX_INTC_ACT_TYPE(ctrl));
266
267 /* Use same polarity for the wake events */
268 if (lpc32xx_events[irq].mask != 0) {
269 reg = __raw_readl(lpc32xx_events[irq].event_group->edge_reg);
270
271 if (use_high_level)
272 reg |= lpc32xx_events[irq].mask;
273 else
274 reg &= ~lpc32xx_events[irq].mask;
275
276 __raw_writel(reg, lpc32xx_events[irq].event_group->edge_reg);
277 }
278}
279
56385381 280static int lpc32xx_set_irq_type(struct irq_data *d, unsigned int type)
c4a0208f
KW
281{
282 switch (type) {
283 case IRQ_TYPE_EDGE_RISING:
284 /* Rising edge sensitive */
f5c42271 285 __lpc32xx_set_irq_type(d->hwirq, 1, 1);
93b6eb77 286 __irq_set_handler_locked(d->irq, handle_edge_irq);
c4a0208f
KW
287 break;
288
289 case IRQ_TYPE_EDGE_FALLING:
290 /* Falling edge sensitive */
f5c42271 291 __lpc32xx_set_irq_type(d->hwirq, 0, 1);
93b6eb77 292 __irq_set_handler_locked(d->irq, handle_edge_irq);
c4a0208f
KW
293 break;
294
295 case IRQ_TYPE_LEVEL_LOW:
296 /* Low level sensitive */
f5c42271 297 __lpc32xx_set_irq_type(d->hwirq, 0, 0);
93b6eb77 298 __irq_set_handler_locked(d->irq, handle_level_irq);
c4a0208f
KW
299 break;
300
301 case IRQ_TYPE_LEVEL_HIGH:
302 /* High level sensitive */
f5c42271 303 __lpc32xx_set_irq_type(d->hwirq, 1, 0);
93b6eb77 304 __irq_set_handler_locked(d->irq, handle_level_irq);
c4a0208f
KW
305 break;
306
307 /* Other modes are not supported */
308 default:
309 return -EINVAL;
310 }
311
c4a0208f
KW
312 return 0;
313}
314
56385381 315static int lpc32xx_irq_wake(struct irq_data *d, unsigned int state)
c4a0208f
KW
316{
317 unsigned long eventreg;
318
f5c42271
RS
319 if (lpc32xx_events[d->hwirq].mask != 0) {
320 eventreg = __raw_readl(lpc32xx_events[d->hwirq].
c4a0208f
KW
321 event_group->enab_reg);
322
323 if (state)
f5c42271 324 eventreg |= lpc32xx_events[d->hwirq].mask;
94ed7830 325 else {
f5c42271 326 eventreg &= ~lpc32xx_events[d->hwirq].mask;
c4a0208f 327
94ed7830
RS
328 /*
329 * When disabling the wakeup, clear the latched
330 * event
331 */
f5c42271
RS
332 __raw_writel(lpc32xx_events[d->hwirq].mask,
333 lpc32xx_events[d->hwirq].
94ed7830
RS
334 event_group->rawstat_reg);
335 }
336
c4a0208f 337 __raw_writel(eventreg,
f5c42271 338 lpc32xx_events[d->hwirq].event_group->enab_reg);
c4a0208f
KW
339
340 return 0;
341 }
342
343 /* Clear event */
f5c42271
RS
344 __raw_writel(lpc32xx_events[d->hwirq].mask,
345 lpc32xx_events[d->hwirq].event_group->rawstat_reg);
c4a0208f
KW
346
347 return -ENODEV;
348}
349
350static void __init lpc32xx_set_default_mappings(unsigned int apr,
351 unsigned int atr, unsigned int offset)
352{
353 unsigned int i;
354
355 /* Set activation levels for each interrupt */
356 i = 0;
357 while (i < 32) {
358 __lpc32xx_set_irq_type(offset + i, ((apr >> i) & 0x1),
359 ((atr >> i) & 0x1));
360 i++;
361 }
362}
363
364static struct irq_chip lpc32xx_irq_chip = {
f5c42271 365 .name = "MIC",
56385381
LB
366 .irq_ack = lpc32xx_ack_irq,
367 .irq_mask = lpc32xx_mask_irq,
368 .irq_unmask = lpc32xx_unmask_irq,
369 .irq_set_type = lpc32xx_set_irq_type,
370 .irq_set_wake = lpc32xx_irq_wake
c4a0208f
KW
371};
372
373static void lpc32xx_sic1_handler(unsigned int irq, struct irq_desc *desc)
374{
375 unsigned long ints = __raw_readl(LPC32XX_INTC_STAT(LPC32XX_SIC1_BASE));
376
377 while (ints != 0) {
378 int irqno = fls(ints) - 1;
379
380 ints &= ~(1 << irqno);
381
382 generic_handle_irq(LPC32XX_SIC1_IRQ(irqno));
383 }
384}
385
386static void lpc32xx_sic2_handler(unsigned int irq, struct irq_desc *desc)
387{
388 unsigned long ints = __raw_readl(LPC32XX_INTC_STAT(LPC32XX_SIC2_BASE));
389
390 while (ints != 0) {
391 int irqno = fls(ints) - 1;
392
393 ints &= ~(1 << irqno);
394
395 generic_handle_irq(LPC32XX_SIC2_IRQ(irqno));
396 }
397}
398
f5c42271
RS
399static int __init __lpc32xx_mic_of_init(struct device_node *node,
400 struct device_node *parent)
401{
402 lpc32xx_mic_np = node;
403
404 return 0;
405}
406
407static const struct of_device_id mic_of_match[] __initconst = {
408 { .compatible = "nxp,lpc3220-mic", .data = __lpc32xx_mic_of_init },
409 { }
410};
411
c4a0208f
KW
412void __init lpc32xx_init_irq(void)
413{
414 unsigned int i;
415
416 /* Setup MIC */
417 __raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_MIC_BASE));
418 __raw_writel(MIC_APR_DEFAULT, LPC32XX_INTC_POLAR(LPC32XX_MIC_BASE));
419 __raw_writel(MIC_ATR_DEFAULT, LPC32XX_INTC_ACT_TYPE(LPC32XX_MIC_BASE));
420
421 /* Setup SIC1 */
422 __raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC1_BASE));
35dd0a75
RS
423 __raw_writel(SIC1_APR_DEFAULT, LPC32XX_INTC_POLAR(LPC32XX_SIC1_BASE));
424 __raw_writel(SIC1_ATR_DEFAULT,
425 LPC32XX_INTC_ACT_TYPE(LPC32XX_SIC1_BASE));
c4a0208f
KW
426
427 /* Setup SIC2 */
428 __raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC2_BASE));
35dd0a75
RS
429 __raw_writel(SIC2_APR_DEFAULT, LPC32XX_INTC_POLAR(LPC32XX_SIC2_BASE));
430 __raw_writel(SIC2_ATR_DEFAULT,
431 LPC32XX_INTC_ACT_TYPE(LPC32XX_SIC2_BASE));
c4a0208f
KW
432
433 /* Configure supported IRQ's */
434 for (i = 0; i < NR_IRQS; i++) {
f38c02f3
TG
435 irq_set_chip_and_handler(i, &lpc32xx_irq_chip,
436 handle_level_irq);
c4a0208f
KW
437 set_irq_flags(i, IRQF_VALID);
438 }
439
440 /* Set default mappings */
441 lpc32xx_set_default_mappings(MIC_APR_DEFAULT, MIC_ATR_DEFAULT, 0);
442 lpc32xx_set_default_mappings(SIC1_APR_DEFAULT, SIC1_ATR_DEFAULT, 32);
443 lpc32xx_set_default_mappings(SIC2_APR_DEFAULT, SIC2_ATR_DEFAULT, 64);
444
c4a0208f
KW
445 /* Initially disable all wake events */
446 __raw_writel(0, LPC32XX_CLKPWR_P01_ER);
447 __raw_writel(0, LPC32XX_CLKPWR_INT_ER);
448 __raw_writel(0, LPC32XX_CLKPWR_PIN_ER);
449
450 /*
451 * Default wake activation polarities, all pin sources are low edge
452 * triggered
453 */
454 __raw_writel(LPC32XX_CLKPWR_INTSRC_TS_P_BIT |
455 LPC32XX_CLKPWR_INTSRC_MSTIMER_BIT |
456 LPC32XX_CLKPWR_INTSRC_RTC_BIT,
457 LPC32XX_CLKPWR_INT_AP);
458 __raw_writel(0, LPC32XX_CLKPWR_PIN_AP);
459
460 /* Clear latched wake event states */
461 __raw_writel(__raw_readl(LPC32XX_CLKPWR_PIN_RS),
462 LPC32XX_CLKPWR_PIN_RS);
463 __raw_writel(__raw_readl(LPC32XX_CLKPWR_INT_RS),
464 LPC32XX_CLKPWR_INT_RS);
f5c42271
RS
465
466 of_irq_init(mic_of_match);
467
f5c42271 468 lpc32xx_mic_domain = irq_domain_add_legacy(lpc32xx_mic_np, NR_IRQS,
2998b1d3 469 0, 0, &irq_domain_simple_ops,
f5c42271
RS
470 NULL);
471 if (!lpc32xx_mic_domain)
472 panic("Unable to add MIC irq domain\n");
e40ec953
RS
473
474 /* MIC SUBIRQx interrupts will route handling to the chain handlers */
475 irq_set_chained_handler(IRQ_LPC32XX_SUB1IRQ, lpc32xx_sic1_handler);
476 irq_set_chained_handler(IRQ_LPC32XX_SUB2IRQ, lpc32xx_sic2_handler);
c4a0208f 477}