blob: d080cb1123dd184bef219710a730df47e123c27e [file] [log] [blame]
Kevin Wellsc4a02082010-02-26 15:53:41 -08001/*
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
47struct 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
54static 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
61static 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
68struct 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 */
76static 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 },
Roland Stiggef6737052012-02-27 17:28:02 +0100121 [IRQ_LPC32XX_GPI_28] = {
122 .event_group = &lpc32xx_event_pin_regs,
123 .mask = LPC32XX_CLKPWR_EXTSRC_GPI_28_BIT,
124 },
Kevin Wellsc4a02082010-02-26 15:53:41 -0800125 [IRQ_LPC32XX_GPIO_00] = {
126 .event_group = &lpc32xx_event_int_regs,
127 .mask = LPC32XX_CLKPWR_INTSRC_GPIO_00_BIT,
128 },
129 [IRQ_LPC32XX_GPIO_01] = {
130 .event_group = &lpc32xx_event_int_regs,
131 .mask = LPC32XX_CLKPWR_INTSRC_GPIO_01_BIT,
132 },
133 [IRQ_LPC32XX_GPIO_02] = {
134 .event_group = &lpc32xx_event_int_regs,
135 .mask = LPC32XX_CLKPWR_INTSRC_GPIO_02_BIT,
136 },
137 [IRQ_LPC32XX_GPIO_03] = {
138 .event_group = &lpc32xx_event_int_regs,
139 .mask = LPC32XX_CLKPWR_INTSRC_GPIO_03_BIT,
140 },
141 [IRQ_LPC32XX_GPIO_04] = {
142 .event_group = &lpc32xx_event_int_regs,
143 .mask = LPC32XX_CLKPWR_INTSRC_GPIO_04_BIT,
144 },
145 [IRQ_LPC32XX_GPIO_05] = {
146 .event_group = &lpc32xx_event_int_regs,
147 .mask = LPC32XX_CLKPWR_INTSRC_GPIO_05_BIT,
148 },
149 [IRQ_LPC32XX_KEY] = {
150 .event_group = &lpc32xx_event_int_regs,
151 .mask = LPC32XX_CLKPWR_INTSRC_KEY_BIT,
152 },
Roland Stiggec20b9092012-03-12 22:27:28 +0100153 [IRQ_LPC32XX_ETHERNET] = {
154 .event_group = &lpc32xx_event_int_regs,
155 .mask = LPC32XX_CLKPWR_INTSRC_MAC_BIT,
156 },
Kevin Wellsc4a02082010-02-26 15:53:41 -0800157 [IRQ_LPC32XX_USB_OTG_ATX] = {
158 .event_group = &lpc32xx_event_int_regs,
159 .mask = LPC32XX_CLKPWR_INTSRC_USBATXINT_BIT,
160 },
161 [IRQ_LPC32XX_USB_HOST] = {
162 .event_group = &lpc32xx_event_int_regs,
163 .mask = LPC32XX_CLKPWR_INTSRC_USB_BIT,
164 },
165 [IRQ_LPC32XX_RTC] = {
166 .event_group = &lpc32xx_event_int_regs,
167 .mask = LPC32XX_CLKPWR_INTSRC_RTC_BIT,
168 },
169 [IRQ_LPC32XX_MSTIMER] = {
170 .event_group = &lpc32xx_event_int_regs,
171 .mask = LPC32XX_CLKPWR_INTSRC_MSTIMER_BIT,
172 },
173 [IRQ_LPC32XX_TS_AUX] = {
174 .event_group = &lpc32xx_event_int_regs,
175 .mask = LPC32XX_CLKPWR_INTSRC_TS_AUX_BIT,
176 },
177 [IRQ_LPC32XX_TS_P] = {
178 .event_group = &lpc32xx_event_int_regs,
179 .mask = LPC32XX_CLKPWR_INTSRC_TS_P_BIT,
180 },
181 [IRQ_LPC32XX_TS_IRQ] = {
182 .event_group = &lpc32xx_event_int_regs,
183 .mask = LPC32XX_CLKPWR_INTSRC_ADC_BIT,
184 },
185};
186
187static void get_controller(unsigned int irq, unsigned int *base,
188 unsigned int *irqbit)
189{
190 if (irq < 32) {
191 *base = LPC32XX_MIC_BASE;
192 *irqbit = 1 << irq;
193 } else if (irq < 64) {
194 *base = LPC32XX_SIC1_BASE;
195 *irqbit = 1 << (irq - 32);
196 } else {
197 *base = LPC32XX_SIC2_BASE;
198 *irqbit = 1 << (irq - 64);
199 }
200}
201
Lennert Buytenhek563853812010-11-29 10:35:20 +0100202static void lpc32xx_mask_irq(struct irq_data *d)
Kevin Wellsc4a02082010-02-26 15:53:41 -0800203{
204 unsigned int reg, ctrl, mask;
205
Lennert Buytenhek563853812010-11-29 10:35:20 +0100206 get_controller(d->irq, &ctrl, &mask);
Kevin Wellsc4a02082010-02-26 15:53:41 -0800207
208 reg = __raw_readl(LPC32XX_INTC_MASK(ctrl)) & ~mask;
209 __raw_writel(reg, LPC32XX_INTC_MASK(ctrl));
210}
211
Lennert Buytenhek563853812010-11-29 10:35:20 +0100212static void lpc32xx_unmask_irq(struct irq_data *d)
Kevin Wellsc4a02082010-02-26 15:53:41 -0800213{
214 unsigned int reg, ctrl, mask;
215
Lennert Buytenhek563853812010-11-29 10:35:20 +0100216 get_controller(d->irq, &ctrl, &mask);
Kevin Wellsc4a02082010-02-26 15:53:41 -0800217
218 reg = __raw_readl(LPC32XX_INTC_MASK(ctrl)) | mask;
219 __raw_writel(reg, LPC32XX_INTC_MASK(ctrl));
220}
221
Lennert Buytenhek563853812010-11-29 10:35:20 +0100222static void lpc32xx_ack_irq(struct irq_data *d)
Kevin Wellsc4a02082010-02-26 15:53:41 -0800223{
224 unsigned int ctrl, mask;
225
Lennert Buytenhek563853812010-11-29 10:35:20 +0100226 get_controller(d->irq, &ctrl, &mask);
Kevin Wellsc4a02082010-02-26 15:53:41 -0800227
228 __raw_writel(mask, LPC32XX_INTC_RAW_STAT(ctrl));
229
230 /* Also need to clear pending wake event */
Lennert Buytenhek563853812010-11-29 10:35:20 +0100231 if (lpc32xx_events[d->irq].mask != 0)
232 __raw_writel(lpc32xx_events[d->irq].mask,
233 lpc32xx_events[d->irq].event_group->rawstat_reg);
Kevin Wellsc4a02082010-02-26 15:53:41 -0800234}
235
236static void __lpc32xx_set_irq_type(unsigned int irq, int use_high_level,
237 int use_edge)
238{
239 unsigned int reg, ctrl, mask;
240
241 get_controller(irq, &ctrl, &mask);
242
243 /* Activation level, high or low */
244 reg = __raw_readl(LPC32XX_INTC_POLAR(ctrl));
245 if (use_high_level)
246 reg |= mask;
247 else
248 reg &= ~mask;
249 __raw_writel(reg, LPC32XX_INTC_POLAR(ctrl));
250
251 /* Activation type, edge or level */
252 reg = __raw_readl(LPC32XX_INTC_ACT_TYPE(ctrl));
253 if (use_edge)
254 reg |= mask;
255 else
256 reg &= ~mask;
257 __raw_writel(reg, LPC32XX_INTC_ACT_TYPE(ctrl));
258
259 /* Use same polarity for the wake events */
260 if (lpc32xx_events[irq].mask != 0) {
261 reg = __raw_readl(lpc32xx_events[irq].event_group->edge_reg);
262
263 if (use_high_level)
264 reg |= lpc32xx_events[irq].mask;
265 else
266 reg &= ~lpc32xx_events[irq].mask;
267
268 __raw_writel(reg, lpc32xx_events[irq].event_group->edge_reg);
269 }
270}
271
Lennert Buytenhek563853812010-11-29 10:35:20 +0100272static int lpc32xx_set_irq_type(struct irq_data *d, unsigned int type)
Kevin Wellsc4a02082010-02-26 15:53:41 -0800273{
274 switch (type) {
275 case IRQ_TYPE_EDGE_RISING:
276 /* Rising edge sensitive */
Lennert Buytenhek563853812010-11-29 10:35:20 +0100277 __lpc32xx_set_irq_type(d->irq, 1, 1);
Kevin Wellsc4a02082010-02-26 15:53:41 -0800278 break;
279
280 case IRQ_TYPE_EDGE_FALLING:
281 /* Falling edge sensitive */
Lennert Buytenhek563853812010-11-29 10:35:20 +0100282 __lpc32xx_set_irq_type(d->irq, 0, 1);
Kevin Wellsc4a02082010-02-26 15:53:41 -0800283 break;
284
285 case IRQ_TYPE_LEVEL_LOW:
286 /* Low level sensitive */
Lennert Buytenhek563853812010-11-29 10:35:20 +0100287 __lpc32xx_set_irq_type(d->irq, 0, 0);
Kevin Wellsc4a02082010-02-26 15:53:41 -0800288 break;
289
290 case IRQ_TYPE_LEVEL_HIGH:
291 /* High level sensitive */
Lennert Buytenhek563853812010-11-29 10:35:20 +0100292 __lpc32xx_set_irq_type(d->irq, 1, 0);
Kevin Wellsc4a02082010-02-26 15:53:41 -0800293 break;
294
295 /* Other modes are not supported */
296 default:
297 return -EINVAL;
298 }
299
300 /* Ok to use the level handler for all types */
Thomas Gleixner6845664a2011-03-24 13:25:22 +0100301 irq_set_handler(d->irq, handle_level_irq);
Kevin Wellsc4a02082010-02-26 15:53:41 -0800302
303 return 0;
304}
305
Lennert Buytenhek563853812010-11-29 10:35:20 +0100306static int lpc32xx_irq_wake(struct irq_data *d, unsigned int state)
Kevin Wellsc4a02082010-02-26 15:53:41 -0800307{
308 unsigned long eventreg;
309
Lennert Buytenhek563853812010-11-29 10:35:20 +0100310 if (lpc32xx_events[d->irq].mask != 0) {
311 eventreg = __raw_readl(lpc32xx_events[d->irq].
Kevin Wellsc4a02082010-02-26 15:53:41 -0800312 event_group->enab_reg);
313
314 if (state)
Lennert Buytenhek563853812010-11-29 10:35:20 +0100315 eventreg |= lpc32xx_events[d->irq].mask;
Roland Stigge94ed7832012-02-27 17:28:02 +0100316 else {
Lennert Buytenhek563853812010-11-29 10:35:20 +0100317 eventreg &= ~lpc32xx_events[d->irq].mask;
Kevin Wellsc4a02082010-02-26 15:53:41 -0800318
Roland Stigge94ed7832012-02-27 17:28:02 +0100319 /*
320 * When disabling the wakeup, clear the latched
321 * event
322 */
323 __raw_writel(lpc32xx_events[d->irq].mask,
324 lpc32xx_events[d->irq].
325 event_group->rawstat_reg);
326 }
327
Kevin Wellsc4a02082010-02-26 15:53:41 -0800328 __raw_writel(eventreg,
Lennert Buytenhek563853812010-11-29 10:35:20 +0100329 lpc32xx_events[d->irq].event_group->enab_reg);
Kevin Wellsc4a02082010-02-26 15:53:41 -0800330
331 return 0;
332 }
333
334 /* Clear event */
Lennert Buytenhek563853812010-11-29 10:35:20 +0100335 __raw_writel(lpc32xx_events[d->irq].mask,
336 lpc32xx_events[d->irq].event_group->rawstat_reg);
Kevin Wellsc4a02082010-02-26 15:53:41 -0800337
338 return -ENODEV;
339}
340
341static void __init lpc32xx_set_default_mappings(unsigned int apr,
342 unsigned int atr, unsigned int offset)
343{
344 unsigned int i;
345
346 /* Set activation levels for each interrupt */
347 i = 0;
348 while (i < 32) {
349 __lpc32xx_set_irq_type(offset + i, ((apr >> i) & 0x1),
350 ((atr >> i) & 0x1));
351 i++;
352 }
353}
354
355static struct irq_chip lpc32xx_irq_chip = {
Lennert Buytenhek563853812010-11-29 10:35:20 +0100356 .irq_ack = lpc32xx_ack_irq,
357 .irq_mask = lpc32xx_mask_irq,
358 .irq_unmask = lpc32xx_unmask_irq,
359 .irq_set_type = lpc32xx_set_irq_type,
360 .irq_set_wake = lpc32xx_irq_wake
Kevin Wellsc4a02082010-02-26 15:53:41 -0800361};
362
363static void lpc32xx_sic1_handler(unsigned int irq, struct irq_desc *desc)
364{
365 unsigned long ints = __raw_readl(LPC32XX_INTC_STAT(LPC32XX_SIC1_BASE));
366
367 while (ints != 0) {
368 int irqno = fls(ints) - 1;
369
370 ints &= ~(1 << irqno);
371
372 generic_handle_irq(LPC32XX_SIC1_IRQ(irqno));
373 }
374}
375
376static void lpc32xx_sic2_handler(unsigned int irq, struct irq_desc *desc)
377{
378 unsigned long ints = __raw_readl(LPC32XX_INTC_STAT(LPC32XX_SIC2_BASE));
379
380 while (ints != 0) {
381 int irqno = fls(ints) - 1;
382
383 ints &= ~(1 << irqno);
384
385 generic_handle_irq(LPC32XX_SIC2_IRQ(irqno));
386 }
387}
388
389void __init lpc32xx_init_irq(void)
390{
391 unsigned int i;
392
393 /* Setup MIC */
394 __raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_MIC_BASE));
395 __raw_writel(MIC_APR_DEFAULT, LPC32XX_INTC_POLAR(LPC32XX_MIC_BASE));
396 __raw_writel(MIC_ATR_DEFAULT, LPC32XX_INTC_ACT_TYPE(LPC32XX_MIC_BASE));
397
398 /* Setup SIC1 */
399 __raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC1_BASE));
Roland Stigge35dd0a72012-02-27 17:28:02 +0100400 __raw_writel(SIC1_APR_DEFAULT, LPC32XX_INTC_POLAR(LPC32XX_SIC1_BASE));
401 __raw_writel(SIC1_ATR_DEFAULT,
402 LPC32XX_INTC_ACT_TYPE(LPC32XX_SIC1_BASE));
Kevin Wellsc4a02082010-02-26 15:53:41 -0800403
404 /* Setup SIC2 */
405 __raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC2_BASE));
Roland Stigge35dd0a72012-02-27 17:28:02 +0100406 __raw_writel(SIC2_APR_DEFAULT, LPC32XX_INTC_POLAR(LPC32XX_SIC2_BASE));
407 __raw_writel(SIC2_ATR_DEFAULT,
408 LPC32XX_INTC_ACT_TYPE(LPC32XX_SIC2_BASE));
Kevin Wellsc4a02082010-02-26 15:53:41 -0800409
410 /* Configure supported IRQ's */
411 for (i = 0; i < NR_IRQS; i++) {
Thomas Gleixnerf38c02f2011-03-24 13:35:09 +0100412 irq_set_chip_and_handler(i, &lpc32xx_irq_chip,
413 handle_level_irq);
Kevin Wellsc4a02082010-02-26 15:53:41 -0800414 set_irq_flags(i, IRQF_VALID);
415 }
416
417 /* Set default mappings */
418 lpc32xx_set_default_mappings(MIC_APR_DEFAULT, MIC_ATR_DEFAULT, 0);
419 lpc32xx_set_default_mappings(SIC1_APR_DEFAULT, SIC1_ATR_DEFAULT, 32);
420 lpc32xx_set_default_mappings(SIC2_APR_DEFAULT, SIC2_ATR_DEFAULT, 64);
421
422 /* mask all interrupts except SUBIRQ */
423 __raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_MIC_BASE));
424 __raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC1_BASE));
425 __raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC2_BASE));
426
427 /* MIC SUBIRQx interrupts will route handling to the chain handlers */
Thomas Gleixner6845664a2011-03-24 13:25:22 +0100428 irq_set_chained_handler(IRQ_LPC32XX_SUB1IRQ, lpc32xx_sic1_handler);
429 irq_set_chained_handler(IRQ_LPC32XX_SUB2IRQ, lpc32xx_sic2_handler);
Kevin Wellsc4a02082010-02-26 15:53:41 -0800430
431 /* Initially disable all wake events */
432 __raw_writel(0, LPC32XX_CLKPWR_P01_ER);
433 __raw_writel(0, LPC32XX_CLKPWR_INT_ER);
434 __raw_writel(0, LPC32XX_CLKPWR_PIN_ER);
435
436 /*
437 * Default wake activation polarities, all pin sources are low edge
438 * triggered
439 */
440 __raw_writel(LPC32XX_CLKPWR_INTSRC_TS_P_BIT |
441 LPC32XX_CLKPWR_INTSRC_MSTIMER_BIT |
442 LPC32XX_CLKPWR_INTSRC_RTC_BIT,
443 LPC32XX_CLKPWR_INT_AP);
444 __raw_writel(0, LPC32XX_CLKPWR_PIN_AP);
445
446 /* Clear latched wake event states */
447 __raw_writel(__raw_readl(LPC32XX_CLKPWR_PIN_RS),
448 LPC32XX_CLKPWR_PIN_RS);
449 __raw_writel(__raw_readl(LPC32XX_CLKPWR_INT_RS),
450 LPC32XX_CLKPWR_INT_RS);
451}