diff options
author | Eric Miao <eric.y.miao@gmail.com> | 2009-12-26 03:23:02 -0500 |
---|---|---|
committer | Eric Miao <eric.y.miao@gmail.com> | 2010-03-01 18:40:51 -0500 |
commit | 19851c58e680f71d087b79b53edbf814193e1d33 (patch) | |
tree | 50a1c533c9953ec5e9c95d970a1e9788cf5308aa /arch/arm/common | |
parent | 08fa159003aa510027951671b94aadc380ab2d2a (diff) |
[ARM] sa1111: allow cascaded IRQs to be used by platforms
Signed-off-by: Eric Miao <eric.y.miao@gmail.com>
Diffstat (limited to 'arch/arm/common')
-rw-r--r-- | arch/arm/common/sa1111.c | 112 |
1 files changed, 88 insertions, 24 deletions
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c index 8ba7044c554d..a52a27c1d9be 100644 --- a/arch/arm/common/sa1111.c +++ b/arch/arm/common/sa1111.c | |||
@@ -35,6 +35,58 @@ | |||
35 | 35 | ||
36 | #include <asm/hardware/sa1111.h> | 36 | #include <asm/hardware/sa1111.h> |
37 | 37 | ||
38 | /* SA1111 IRQs */ | ||
39 | #define IRQ_GPAIN0 (0) | ||
40 | #define IRQ_GPAIN1 (1) | ||
41 | #define IRQ_GPAIN2 (2) | ||
42 | #define IRQ_GPAIN3 (3) | ||
43 | #define IRQ_GPBIN0 (4) | ||
44 | #define IRQ_GPBIN1 (5) | ||
45 | #define IRQ_GPBIN2 (6) | ||
46 | #define IRQ_GPBIN3 (7) | ||
47 | #define IRQ_GPBIN4 (8) | ||
48 | #define IRQ_GPBIN5 (9) | ||
49 | #define IRQ_GPCIN0 (10) | ||
50 | #define IRQ_GPCIN1 (11) | ||
51 | #define IRQ_GPCIN2 (12) | ||
52 | #define IRQ_GPCIN3 (13) | ||
53 | #define IRQ_GPCIN4 (14) | ||
54 | #define IRQ_GPCIN5 (15) | ||
55 | #define IRQ_GPCIN6 (16) | ||
56 | #define IRQ_GPCIN7 (17) | ||
57 | #define IRQ_MSTXINT (18) | ||
58 | #define IRQ_MSRXINT (19) | ||
59 | #define IRQ_MSSTOPERRINT (20) | ||
60 | #define IRQ_TPTXINT (21) | ||
61 | #define IRQ_TPRXINT (22) | ||
62 | #define IRQ_TPSTOPERRINT (23) | ||
63 | #define SSPXMTINT (24) | ||
64 | #define SSPRCVINT (25) | ||
65 | #define SSPROR (26) | ||
66 | #define AUDXMTDMADONEA (32) | ||
67 | #define AUDRCVDMADONEA (33) | ||
68 | #define AUDXMTDMADONEB (34) | ||
69 | #define AUDRCVDMADONEB (35) | ||
70 | #define AUDTFSR (36) | ||
71 | #define AUDRFSR (37) | ||
72 | #define AUDTUR (38) | ||
73 | #define AUDROR (39) | ||
74 | #define AUDDTS (40) | ||
75 | #define AUDRDD (41) | ||
76 | #define AUDSTO (42) | ||
77 | #define IRQ_USBPWR (43) | ||
78 | #define IRQ_HCIM (44) | ||
79 | #define IRQ_HCIBUFFACC (45) | ||
80 | #define IRQ_HCIRMTWKP (46) | ||
81 | #define IRQ_NHCIMFCIR (47) | ||
82 | #define IRQ_USB_PORT_RESUME (48) | ||
83 | #define IRQ_S0_READY_NINT (49) | ||
84 | #define IRQ_S1_READY_NINT (50) | ||
85 | #define IRQ_S0_CD_VALID (51) | ||
86 | #define IRQ_S1_CD_VALID (52) | ||
87 | #define IRQ_S0_BVD1_STSCHG (53) | ||
88 | #define IRQ_S1_BVD1_STSCHG (54) | ||
89 | |||
38 | extern void __init sa1110_mb_enable(void); | 90 | extern void __init sa1110_mb_enable(void); |
39 | 91 | ||
40 | /* | 92 | /* |
@@ -49,6 +101,7 @@ struct sa1111 { | |||
49 | struct clk *clk; | 101 | struct clk *clk; |
50 | unsigned long phys; | 102 | unsigned long phys; |
51 | int irq; | 103 | int irq; |
104 | int irq_base; /* base for cascaded on-chip IRQs */ | ||
52 | spinlock_t lock; | 105 | spinlock_t lock; |
53 | void __iomem *base; | 106 | void __iomem *base; |
54 | #ifdef CONFIG_PM | 107 | #ifdef CONFIG_PM |
@@ -152,36 +205,37 @@ static void | |||
152 | sa1111_irq_handler(unsigned int irq, struct irq_desc *desc) | 205 | sa1111_irq_handler(unsigned int irq, struct irq_desc *desc) |
153 | { | 206 | { |
154 | unsigned int stat0, stat1, i; | 207 | unsigned int stat0, stat1, i; |
155 | void __iomem *base = get_irq_data(irq); | 208 | struct sa1111 *sachip = get_irq_data(irq); |
209 | void __iomem *mapbase = sachip->base + SA1111_INTC; | ||
156 | 210 | ||
157 | stat0 = sa1111_readl(base + SA1111_INTSTATCLR0); | 211 | stat0 = sa1111_readl(mapbase + SA1111_INTSTATCLR0); |
158 | stat1 = sa1111_readl(base + SA1111_INTSTATCLR1); | 212 | stat1 = sa1111_readl(mapbase + SA1111_INTSTATCLR1); |
159 | 213 | ||
160 | sa1111_writel(stat0, base + SA1111_INTSTATCLR0); | 214 | sa1111_writel(stat0, mapbase + SA1111_INTSTATCLR0); |
161 | 215 | ||
162 | desc->chip->ack(irq); | 216 | desc->chip->ack(irq); |
163 | 217 | ||
164 | sa1111_writel(stat1, base + SA1111_INTSTATCLR1); | 218 | sa1111_writel(stat1, mapbase + SA1111_INTSTATCLR1); |
165 | 219 | ||
166 | if (stat0 == 0 && stat1 == 0) { | 220 | if (stat0 == 0 && stat1 == 0) { |
167 | do_bad_IRQ(irq, desc); | 221 | do_bad_IRQ(irq, desc); |
168 | return; | 222 | return; |
169 | } | 223 | } |
170 | 224 | ||
171 | for (i = IRQ_SA1111_START; stat0; i++, stat0 >>= 1) | 225 | for (i = 0; stat0; i++, stat0 >>= 1) |
172 | if (stat0 & 1) | 226 | if (stat0 & 1) |
173 | handle_edge_irq(i, irq_desc + i); | 227 | generic_handle_irq(i + sachip->irq_base); |
174 | 228 | ||
175 | for (i = IRQ_SA1111_START + 32; stat1; i++, stat1 >>= 1) | 229 | for (i = 32; stat1; i++, stat1 >>= 1) |
176 | if (stat1 & 1) | 230 | if (stat1 & 1) |
177 | handle_edge_irq(i, irq_desc + i); | 231 | generic_handle_irq(i + sachip->irq_base); |
178 | 232 | ||
179 | /* For level-based interrupts */ | 233 | /* For level-based interrupts */ |
180 | desc->chip->unmask(irq); | 234 | desc->chip->unmask(irq); |
181 | } | 235 | } |
182 | 236 | ||
183 | #define SA1111_IRQMASK_LO(x) (1 << (x - IRQ_SA1111_START)) | 237 | #define SA1111_IRQMASK_LO(x) (1 << (x - sachip->irq_base)) |
184 | #define SA1111_IRQMASK_HI(x) (1 << (x - IRQ_SA1111_START - 32)) | 238 | #define SA1111_IRQMASK_HI(x) (1 << (x - sachip->irq_base - 32)) |
185 | 239 | ||
186 | static void sa1111_ack_irq(unsigned int irq) | 240 | static void sa1111_ack_irq(unsigned int irq) |
187 | { | 241 | { |
@@ -189,7 +243,8 @@ static void sa1111_ack_irq(unsigned int irq) | |||
189 | 243 | ||
190 | static void sa1111_mask_lowirq(unsigned int irq) | 244 | static void sa1111_mask_lowirq(unsigned int irq) |
191 | { | 245 | { |
192 | void __iomem *mapbase = get_irq_chip_data(irq); | 246 | struct sa1111 *sachip = get_irq_chip_data(irq); |
247 | void __iomem *mapbase = sachip->base + SA1111_INTC; | ||
193 | unsigned long ie0; | 248 | unsigned long ie0; |
194 | 249 | ||
195 | ie0 = sa1111_readl(mapbase + SA1111_INTEN0); | 250 | ie0 = sa1111_readl(mapbase + SA1111_INTEN0); |
@@ -199,7 +254,8 @@ static void sa1111_mask_lowirq(unsigned int irq) | |||
199 | 254 | ||
200 | static void sa1111_unmask_lowirq(unsigned int irq) | 255 | static void sa1111_unmask_lowirq(unsigned int irq) |
201 | { | 256 | { |
202 | void __iomem *mapbase = get_irq_chip_data(irq); | 257 | struct sa1111 *sachip = get_irq_chip_data(irq); |
258 | void __iomem *mapbase = sachip->base + SA1111_INTC; | ||
203 | unsigned long ie0; | 259 | unsigned long ie0; |
204 | 260 | ||
205 | ie0 = sa1111_readl(mapbase + SA1111_INTEN0); | 261 | ie0 = sa1111_readl(mapbase + SA1111_INTEN0); |
@@ -216,8 +272,9 @@ static void sa1111_unmask_lowirq(unsigned int irq) | |||
216 | */ | 272 | */ |
217 | static int sa1111_retrigger_lowirq(unsigned int irq) | 273 | static int sa1111_retrigger_lowirq(unsigned int irq) |
218 | { | 274 | { |
275 | struct sa1111 *sachip = get_irq_chip_data(irq); | ||
276 | void __iomem *mapbase = sachip->base + SA1111_INTC; | ||
219 | unsigned int mask = SA1111_IRQMASK_LO(irq); | 277 | unsigned int mask = SA1111_IRQMASK_LO(irq); |
220 | void __iomem *mapbase = get_irq_chip_data(irq); | ||
221 | unsigned long ip0; | 278 | unsigned long ip0; |
222 | int i; | 279 | int i; |
223 | 280 | ||
@@ -237,8 +294,9 @@ static int sa1111_retrigger_lowirq(unsigned int irq) | |||
237 | 294 | ||
238 | static int sa1111_type_lowirq(unsigned int irq, unsigned int flags) | 295 | static int sa1111_type_lowirq(unsigned int irq, unsigned int flags) |
239 | { | 296 | { |
297 | struct sa1111 *sachip = get_irq_chip_data(irq); | ||
298 | void __iomem *mapbase = sachip->base + SA1111_INTC; | ||
240 | unsigned int mask = SA1111_IRQMASK_LO(irq); | 299 | unsigned int mask = SA1111_IRQMASK_LO(irq); |
241 | void __iomem *mapbase = get_irq_chip_data(irq); | ||
242 | unsigned long ip0; | 300 | unsigned long ip0; |
243 | 301 | ||
244 | if (flags == IRQ_TYPE_PROBE) | 302 | if (flags == IRQ_TYPE_PROBE) |
@@ -260,8 +318,9 @@ static int sa1111_type_lowirq(unsigned int irq, unsigned int flags) | |||
260 | 318 | ||
261 | static int sa1111_wake_lowirq(unsigned int irq, unsigned int on) | 319 | static int sa1111_wake_lowirq(unsigned int irq, unsigned int on) |
262 | { | 320 | { |
321 | struct sa1111 *sachip = get_irq_chip_data(irq); | ||
322 | void __iomem *mapbase = sachip->base + SA1111_INTC; | ||
263 | unsigned int mask = SA1111_IRQMASK_LO(irq); | 323 | unsigned int mask = SA1111_IRQMASK_LO(irq); |
264 | void __iomem *mapbase = get_irq_chip_data(irq); | ||
265 | unsigned long we0; | 324 | unsigned long we0; |
266 | 325 | ||
267 | we0 = sa1111_readl(mapbase + SA1111_WAKEEN0); | 326 | we0 = sa1111_readl(mapbase + SA1111_WAKEEN0); |
@@ -286,7 +345,8 @@ static struct irq_chip sa1111_low_chip = { | |||
286 | 345 | ||
287 | static void sa1111_mask_highirq(unsigned int irq) | 346 | static void sa1111_mask_highirq(unsigned int irq) |
288 | { | 347 | { |
289 | void __iomem *mapbase = get_irq_chip_data(irq); | 348 | struct sa1111 *sachip = get_irq_chip_data(irq); |
349 | void __iomem *mapbase = sachip->base + SA1111_INTC; | ||
290 | unsigned long ie1; | 350 | unsigned long ie1; |
291 | 351 | ||
292 | ie1 = sa1111_readl(mapbase + SA1111_INTEN1); | 352 | ie1 = sa1111_readl(mapbase + SA1111_INTEN1); |
@@ -296,7 +356,8 @@ static void sa1111_mask_highirq(unsigned int irq) | |||
296 | 356 | ||
297 | static void sa1111_unmask_highirq(unsigned int irq) | 357 | static void sa1111_unmask_highirq(unsigned int irq) |
298 | { | 358 | { |
299 | void __iomem *mapbase = get_irq_chip_data(irq); | 359 | struct sa1111 *sachip = get_irq_chip_data(irq); |
360 | void __iomem *mapbase = sachip->base + SA1111_INTC; | ||
300 | unsigned long ie1; | 361 | unsigned long ie1; |
301 | 362 | ||
302 | ie1 = sa1111_readl(mapbase + SA1111_INTEN1); | 363 | ie1 = sa1111_readl(mapbase + SA1111_INTEN1); |
@@ -313,8 +374,9 @@ static void sa1111_unmask_highirq(unsigned int irq) | |||
313 | */ | 374 | */ |
314 | static int sa1111_retrigger_highirq(unsigned int irq) | 375 | static int sa1111_retrigger_highirq(unsigned int irq) |
315 | { | 376 | { |
377 | struct sa1111 *sachip = get_irq_chip_data(irq); | ||
378 | void __iomem *mapbase = sachip->base + SA1111_INTC; | ||
316 | unsigned int mask = SA1111_IRQMASK_HI(irq); | 379 | unsigned int mask = SA1111_IRQMASK_HI(irq); |
317 | void __iomem *mapbase = get_irq_chip_data(irq); | ||
318 | unsigned long ip1; | 380 | unsigned long ip1; |
319 | int i; | 381 | int i; |
320 | 382 | ||
@@ -334,8 +396,9 @@ static int sa1111_retrigger_highirq(unsigned int irq) | |||
334 | 396 | ||
335 | static int sa1111_type_highirq(unsigned int irq, unsigned int flags) | 397 | static int sa1111_type_highirq(unsigned int irq, unsigned int flags) |
336 | { | 398 | { |
399 | struct sa1111 *sachip = get_irq_chip_data(irq); | ||
400 | void __iomem *mapbase = sachip->base + SA1111_INTC; | ||
337 | unsigned int mask = SA1111_IRQMASK_HI(irq); | 401 | unsigned int mask = SA1111_IRQMASK_HI(irq); |
338 | void __iomem *mapbase = get_irq_chip_data(irq); | ||
339 | unsigned long ip1; | 402 | unsigned long ip1; |
340 | 403 | ||
341 | if (flags == IRQ_TYPE_PROBE) | 404 | if (flags == IRQ_TYPE_PROBE) |
@@ -357,8 +420,9 @@ static int sa1111_type_highirq(unsigned int irq, unsigned int flags) | |||
357 | 420 | ||
358 | static int sa1111_wake_highirq(unsigned int irq, unsigned int on) | 421 | static int sa1111_wake_highirq(unsigned int irq, unsigned int on) |
359 | { | 422 | { |
423 | struct sa1111 *sachip = get_irq_chip_data(irq); | ||
424 | void __iomem *mapbase = sachip->base + SA1111_INTC; | ||
360 | unsigned int mask = SA1111_IRQMASK_HI(irq); | 425 | unsigned int mask = SA1111_IRQMASK_HI(irq); |
361 | void __iomem *mapbase = get_irq_chip_data(irq); | ||
362 | unsigned long we1; | 426 | unsigned long we1; |
363 | 427 | ||
364 | we1 = sa1111_readl(mapbase + SA1111_WAKEEN1); | 428 | we1 = sa1111_readl(mapbase + SA1111_WAKEEN1); |
@@ -412,14 +476,14 @@ static void sa1111_setup_irq(struct sa1111 *sachip) | |||
412 | 476 | ||
413 | for (irq = IRQ_GPAIN0; irq <= SSPROR; irq++) { | 477 | for (irq = IRQ_GPAIN0; irq <= SSPROR; irq++) { |
414 | set_irq_chip(irq, &sa1111_low_chip); | 478 | set_irq_chip(irq, &sa1111_low_chip); |
415 | set_irq_chip_data(irq, irqbase); | 479 | set_irq_chip_data(irq, sachip); |
416 | set_irq_handler(irq, handle_edge_irq); | 480 | set_irq_handler(irq, handle_edge_irq); |
417 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | 481 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); |
418 | } | 482 | } |
419 | 483 | ||
420 | for (irq = AUDXMTDMADONEA; irq <= IRQ_S1_BVD1_STSCHG; irq++) { | 484 | for (irq = AUDXMTDMADONEA; irq <= IRQ_S1_BVD1_STSCHG; irq++) { |
421 | set_irq_chip(irq, &sa1111_high_chip); | 485 | set_irq_chip(irq, &sa1111_high_chip); |
422 | set_irq_chip_data(irq, irqbase); | 486 | set_irq_chip_data(irq, sachip); |
423 | set_irq_handler(irq, handle_edge_irq); | 487 | set_irq_handler(irq, handle_edge_irq); |
424 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | 488 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); |
425 | } | 489 | } |
@@ -428,7 +492,7 @@ static void sa1111_setup_irq(struct sa1111 *sachip) | |||
428 | * Register SA1111 interrupt | 492 | * Register SA1111 interrupt |
429 | */ | 493 | */ |
430 | set_irq_type(sachip->irq, IRQ_TYPE_EDGE_RISING); | 494 | set_irq_type(sachip->irq, IRQ_TYPE_EDGE_RISING); |
431 | set_irq_data(sachip->irq, irqbase); | 495 | set_irq_data(sachip->irq, sachip); |
432 | set_irq_chained_handler(sachip->irq, sa1111_irq_handler); | 496 | set_irq_chained_handler(sachip->irq, sa1111_irq_handler); |
433 | } | 497 | } |
434 | 498 | ||