initial commit with v2.6.9
[linux-2.6.9-moxart.git] / arch / ppc / syslib / ppc4xx_pic.c
blob2dc63a58cec66f057bae6349ee07fdebb1d7c923
1 /*
3 * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
5 * Module name: ppc4xx_pic.c
7 * Description:
8 * Interrupt controller driver for PowerPC 4xx-based processors.
9 */
12 * The PowerPC 403 cores' Asynchronous Interrupt Controller (AIC) has
13 * 32 possible interrupts, a majority of which are not implemented on
14 * all cores. There are six configurable, external interrupt pins and
15 * there are eight internal interrupts for the on-chip serial port
16 * (SPU), DMA controller, and JTAG controller.
18 * The PowerPC 405/440 cores' Universal Interrupt Controller (UIC) has
19 * 32 possible interrupts as well. Depending on the core and SoC
20 * implementation, a portion of the interrrupts are used for on-chip
21 * peripherals and a portion of the interrupts are available to be
22 * configured for external devices generating interrupts.
24 * The PowerNP and 440GP (and most likely future implementations) have
25 * cascaded UICs.
29 #include <linux/init.h>
30 #include <linux/sched.h>
31 #include <linux/signal.h>
32 #include <linux/stddef.h>
34 #include <asm/processor.h>
35 #include <asm/system.h>
36 #include <asm/irq.h>
37 #include <asm/ppc4xx_pic.h>
39 /* Global Variables */
40 struct hw_interrupt_type *ppc4xx_pic;
42 * We define 4xxIRQ_InitSenses table thusly:
43 * bit 0x1: sense, 1 for edge and 0 for level.
44 * bit 0x2: polarity, 0 for negative, 1 for positive.
46 unsigned int ibm4xxPIC_NumInitSenses __initdata = 0;
47 unsigned char *ibm4xxPIC_InitSenses __initdata = NULL;
49 /* Six of one, half dozen of the other....#ifdefs, separate files,
50 * other tricks.....
52 * There are basically two types of interrupt controllers, the 403 AIC
53 * and the "others" with UIC. I just kept them both here separated
54 * with #ifdefs, but it seems to change depending upon how supporting
55 * files (like ppc4xx.h) change. -- Dan.
58 #ifdef CONFIG_403
60 /* Function Prototypes */
62 static void ppc403_aic_enable(unsigned int irq);
63 static void ppc403_aic_disable(unsigned int irq);
64 static void ppc403_aic_disable_and_ack(unsigned int irq);
66 static struct hw_interrupt_type ppc403_aic = {
67 "403GC AIC",
68 NULL,
69 NULL,
70 ppc403_aic_enable,
71 ppc403_aic_disable,
72 ppc403_aic_disable_and_ack,
76 int
77 ppc403_pic_get_irq(struct pt_regs *regs)
79 int irq;
80 unsigned long bits;
83 * Only report the status of those interrupts that are actually
84 * enabled.
87 bits = mfdcr(DCRN_EXISR) & mfdcr(DCRN_EXIER);
90 * Walk through the interrupts from highest priority to lowest, and
91 * report the first pending interrupt found.
92 * We want PPC, not C bit numbering, so just subtract the ffs()
93 * result from 32.
95 irq = 32 - ffs(bits);
97 if (irq == NR_AIC_IRQS)
98 irq = -1;
100 return (irq);
103 static void
104 ppc403_aic_enable(unsigned int irq)
106 int bit, word;
108 bit = irq & 0x1f;
109 word = irq >> 5;
111 ppc_cached_irq_mask[word] |= (1 << (31 - bit));
112 mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]);
115 static void
116 ppc403_aic_disable(unsigned int irq)
118 int bit, word;
120 bit = irq & 0x1f;
121 word = irq >> 5;
123 ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
124 mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]);
127 static void
128 ppc403_aic_disable_and_ack(unsigned int irq)
130 int bit, word;
132 bit = irq & 0x1f;
133 word = irq >> 5;
135 ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
136 mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]);
137 mtdcr(DCRN_EXISR, (1 << (31 - bit)));
140 #else
142 #ifndef UIC1
143 #define UIC1 UIC0
144 #endif
145 #ifndef UIC2
146 #define UIC2 UIC1
147 #endif
149 static void
150 ppc4xx_uic_enable(unsigned int irq)
152 int bit, word;
153 irq_desc_t *desc = irq_desc + irq;
155 bit = irq & 0x1f;
156 word = irq >> 5;
158 #ifdef UIC_DEBUG
159 printk("ppc4xx_uic_enable - irq %d word %d bit 0x%x\n", irq, word, bit);
160 #endif
161 ppc_cached_irq_mask[word] |= 1 << (31 - bit);
162 switch (word) {
163 case 0:
164 mtdcr(DCRN_UIC_ER(UIC0), ppc_cached_irq_mask[word]);
165 if ((mfdcr(DCRN_UIC_TR(UIC0)) & (1 << (31 - bit))) == 0)
166 desc->status |= IRQ_LEVEL;
167 else
168 desc->status = desc->status & ~IRQ_LEVEL;
169 break;
170 case 1:
171 mtdcr(DCRN_UIC_ER(UIC1), ppc_cached_irq_mask[word]);
172 if ((mfdcr(DCRN_UIC_TR(UIC1)) & (1 << (31 - bit))) == 0)
173 desc->status |= IRQ_LEVEL;
174 else
175 desc->status = desc->status & ~IRQ_LEVEL;
176 break;
177 case 2:
178 mtdcr(DCRN_UIC_ER(UIC2), ppc_cached_irq_mask[word]);
179 if ((mfdcr(DCRN_UIC_TR(UIC2)) & (1 << (31 - bit))) == 0)
180 desc->status |= IRQ_LEVEL;
181 else
182 desc->status = desc->status & ~IRQ_LEVEL;
183 break;
188 static void
189 ppc4xx_uic_disable(unsigned int irq)
191 int bit, word;
193 bit = irq & 0x1f;
194 word = irq >> 5;
195 #ifdef UIC_DEBUG
196 printk("ppc4xx_uic_disable - irq %d word %d bit 0x%x\n", irq, word,
197 bit);
198 #endif
199 ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
200 switch (word) {
201 case 0:
202 mtdcr(DCRN_UIC_ER(UIC0), ppc_cached_irq_mask[word]);
203 break;
204 case 1:
205 mtdcr(DCRN_UIC_ER(UIC1), ppc_cached_irq_mask[word]);
206 break;
207 case 2:
208 mtdcr(DCRN_UIC_ER(UIC2), ppc_cached_irq_mask[word]);
209 break;
213 static void
214 ppc4xx_uic_disable_and_ack(unsigned int irq)
216 int bit, word;
218 bit = irq & 0x1f;
219 word = irq >> 5;
221 #ifdef UIC_DEBUG
222 printk("ppc4xx_uic_disable_and_ack - irq %d word %d bit 0x%x\n", irq,
223 word, bit);
224 #endif
225 ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
226 switch (word) {
227 case 0:
228 mtdcr(DCRN_UIC_ER(UIC0), ppc_cached_irq_mask[word]);
229 mtdcr(DCRN_UIC_SR(UIC0), (1 << (31 - bit)));
230 #if (NR_UICS > 2)
231 mtdcr(DCRN_UIC_SR(UICB), UICB_UIC0NC);
232 #endif
233 break;
234 case 1:
235 mtdcr(DCRN_UIC_ER(UIC1), ppc_cached_irq_mask[word]);
236 mtdcr(DCRN_UIC_SR(UIC1), (1 << (31 - bit)));
237 #if (NR_UICS == 2)
238 mtdcr(DCRN_UIC_SR(UIC0), (1 << (31 - UIC0_UIC1NC)));
239 #endif
240 #if (NR_UICS > 2)
241 mtdcr(DCRN_UIC_SR(UICB), UICB_UIC1NC);
242 #endif
243 break;
244 case 2:
245 mtdcr(DCRN_UIC_ER(UIC2), ppc_cached_irq_mask[word]);
246 mtdcr(DCRN_UIC_SR(UIC2), (1 << (31 - bit)));
247 #if (NR_UICS > 2)
248 mtdcr(DCRN_UIC_SR(UICB), UICB_UIC2NC);
249 #endif
250 break;
255 static void
256 ppc4xx_uic_end(unsigned int irq)
258 int bit, word;
259 unsigned int tr_bits = 0;
261 bit = irq & 0x1f;
262 word = irq >> 5;
264 #ifdef UIC_DEBUG
265 printk("ppc4xx_uic_end - irq %d word %d bit 0x%x\n", irq, word, bit);
266 #endif
268 switch (word) {
269 case 0:
270 tr_bits = mfdcr(DCRN_UIC_TR(UIC0));
271 break;
272 case 1:
273 tr_bits = mfdcr(DCRN_UIC_TR(UIC1));
274 break;
275 case 2:
276 tr_bits = mfdcr(DCRN_UIC_TR(UIC2));
277 break;
280 if ((tr_bits & (1 << (31 - bit))) == 0) {
281 /* level trigger */
282 switch (word) {
283 case 0:
284 mtdcr(DCRN_UIC_SR(UIC0), 1 << (31 - bit));
285 #if (NR_UICS > 2)
286 mtdcr(DCRN_UIC_SR(UICB), UICB_UIC0NC);
287 #endif
288 break;
289 case 1:
290 mtdcr(DCRN_UIC_SR(UIC1), 1 << (31 - bit));
291 #if (NR_UICS == 2)
292 mtdcr(DCRN_UIC_SR(UIC0), (1 << (31 - UIC0_UIC1NC)));
293 #endif
294 #if (NR_UICS > 2)
295 mtdcr(DCRN_UIC_SR(UICB), UICB_UIC1NC);
296 #endif
297 break;
298 case 2:
299 mtdcr(DCRN_UIC_SR(UIC2), 1 << (31 - bit));
300 #if (NR_UICS > 2)
301 mtdcr(DCRN_UIC_SR(UICB), UICB_UIC2NC);
302 #endif
303 break;
307 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
308 ppc_cached_irq_mask[word] |= 1 << (31 - bit);
309 switch (word) {
310 case 0:
311 mtdcr(DCRN_UIC_ER(UIC0), ppc_cached_irq_mask[word]);
312 break;
313 case 1:
314 mtdcr(DCRN_UIC_ER(UIC1), ppc_cached_irq_mask[word]);
315 break;
316 case 2:
317 mtdcr(DCRN_UIC_ER(UIC2), ppc_cached_irq_mask[word]);
318 break;
323 static struct hw_interrupt_type ppc4xx_uic = {
324 #if (NR_UICS == 1)
325 "IBM UIC",
326 #else
327 "IBM UIC Cascade",
328 #endif
329 NULL,
330 NULL,
331 ppc4xx_uic_enable,
332 ppc4xx_uic_disable,
333 ppc4xx_uic_disable_and_ack,
334 ppc4xx_uic_end,
339 ppc4xx_pic_get_irq(struct pt_regs *regs)
341 int irq, cas_irq;
342 unsigned long bits;
343 cas_irq = 0;
345 * Only report the status of those interrupts that are actually
346 * enabled.
349 #if (NR_UICS > 2)
350 bits = mfdcr(DCRN_UIC_MSR(UICB));
351 #else
352 bits = mfdcr(DCRN_UIC_MSR(UIC0));
353 #endif
354 #if (NR_UICS > 2)
355 if (bits & UICB_UIC0NC) {
356 bits = mfdcr(DCRN_UIC_MSR(UIC0));
357 irq = 32 - ffs(bits);
358 } else if (bits & UICB_UIC1NC) {
359 bits = mfdcr(DCRN_UIC_MSR(UIC1));
360 irq = 64 - ffs(bits);
361 } else if (bits & UICB_UIC2NC) {
362 bits = mfdcr(DCRN_UIC_MSR(UIC2));
363 irq = 96 - ffs(bits);
364 } else {
365 irq = -1;
367 #elif (NR_UICS > 1)
368 if (bits & UIC_CASCADE_MASK) {
369 bits = mfdcr(DCRN_UIC_MSR(UIC1));
370 cas_irq = 32 - ffs(bits);
371 irq = 32 + cas_irq;
372 } else {
373 irq = 32 - ffs(bits);
374 if (irq == 32)
375 irq = -1;
377 #else
379 * Walk through the interrupts from highest priority to lowest, and
380 * report the first pending interrupt found.
381 * We want PPC, not C bit numbering, so just subtract the ffs()
382 * result from 32.
384 irq = 32 - ffs(bits);
385 #endif
386 if (irq == (NR_UIC_IRQS * NR_UICS))
387 irq = -1;
389 #ifdef UIC_DEBUG
390 printk("ppc4xx_pic_get_irq - irq %d bit 0x%x\n", irq, bits);
391 #endif
393 return (irq);
395 #endif
397 void __init
398 ppc4xx_extpic_init(void)
400 /* set polarity
401 * 1 = default/pos/rising , 0= neg/falling internal
402 * 1 = neg/falling , 0= pos/rising external
403 * Sense
404 * 0 = default level internal
405 * 0 = level, 1 = edge external
408 unsigned int sense, irq;
409 int bit, word;
410 unsigned long ppc_cached_sense_mask[NR_MASK_WORDS];
411 unsigned long ppc_cached_pol_mask[NR_MASK_WORDS];
412 ppc_cached_sense_mask[0] = 0;
413 ppc_cached_sense_mask[1] = 0;
414 ppc_cached_sense_mask[2] = 0;
415 ppc_cached_pol_mask[0] = 0;
416 ppc_cached_pol_mask[1] = 0;
417 ppc_cached_pol_mask[2] = 0;
419 for (irq = 0; irq < NR_IRQS; irq++) {
421 bit = irq & 0x1f;
422 word = irq >> 5;
424 sense =
425 (irq <
426 ibm4xxPIC_NumInitSenses) ? ibm4xxPIC_InitSenses[irq] : 3;
427 #ifdef PPC4xx_PIC_DEBUG
428 printk("PPC4xx_picext %d word:%x bit:%x sense:%x", irq, word,
429 bit, sense);
430 #endif
431 ppc_cached_sense_mask[word] |=
432 (~sense & IRQ_SENSE_MASK) << (31 - bit);
433 ppc_cached_pol_mask[word] |=
434 ((sense & IRQ_POLARITY_MASK) >> 1) << (31 - bit);
435 switch (word) {
436 case 0:
437 #ifdef PPC4xx_PIC_DEBUG
438 printk("Pol %x ", mfdcr(DCRN_UIC_PR(UIC0)));
439 printk("Level %x\n", mfdcr(DCRN_UIC_TR(UIC0)));
440 #endif
441 /* polarity setting */
442 mtdcr(DCRN_UIC_PR(UIC0), ppc_cached_pol_mask[word]);
444 /* Level setting */
445 mtdcr(DCRN_UIC_TR(UIC0), ppc_cached_sense_mask[word]);
447 break;
448 case 1:
449 #ifdef PPC4xx_PIC_DEBUG
450 printk("Pol %x ", mfdcr(DCRN_UIC_PR(UIC1)));
451 printk("Level %x\n", mfdcr(DCRN_UIC_TR(UIC1)));
452 #endif
453 /* polarity setting */
454 mtdcr(DCRN_UIC_PR(UIC1), ppc_cached_pol_mask[word]);
456 /* Level setting */
457 mtdcr(DCRN_UIC_TR(UIC1), ppc_cached_sense_mask[word]);
459 break;
460 case 2:
461 #ifdef PPC4xx_PIC_DEBUG
462 printk("Pol %x ", mfdcr(DCRN_UIC_PR(UIC2)));
463 printk("Level %x\n", mfdcr(DCRN_UIC_TR(UIC2)));
464 #endif
465 /* polarity setting */
466 mtdcr(DCRN_UIC_PR(UIC2), ppc_cached_pol_mask[word]);
468 /* Level setting */
469 mtdcr(DCRN_UIC_TR(UIC2), ppc_cached_sense_mask[word]);
471 break;
476 void __init
477 ppc4xx_pic_init(void)
480 * Disable all external interrupts until they are
481 * explicity requested.
483 ppc_cached_irq_mask[0] = 0;
484 ppc_cached_irq_mask[1] = 0;
485 ppc_cached_irq_mask[2] = 0;
487 #if defined CONFIG_403
488 mtdcr(DCRN_EXIER, ppc_cached_irq_mask[0]);
490 ppc4xx_pic = &ppc403_aic;
491 ppc_md.get_irq = ppc403_pic_get_irq;
492 #else
493 #if (NR_UICS > 2)
494 mtdcr(DCRN_UIC_ER(UICB), UICB_UIC0NC | UICB_UIC1NC | UICB_UIC2NC);
495 mtdcr(DCRN_UIC_CR(UICB), 0);
497 mtdcr(DCRN_UIC_ER(UIC2), ppc_cached_irq_mask[2]);
498 mtdcr(DCRN_UIC_CR(UIC2), 0);
500 #endif
501 #if (NR_UICS > 1)
502 #if (NR_UICS == 2)
503 /* enable cascading interrupt */
504 ppc_cached_irq_mask[0] |= 1 << (31 - UIC0_UIC1NC);
505 #endif
506 mtdcr(DCRN_UIC_ER(UIC1), ppc_cached_irq_mask[1]);
507 mtdcr(DCRN_UIC_CR(UIC1), 0);
508 #endif
509 mtdcr(DCRN_UIC_ER(UIC0), ppc_cached_irq_mask[0]);
510 mtdcr(DCRN_UIC_CR(UIC0), 0);
512 if (ibm4xxPIC_InitSenses != NULL)
513 ppc4xx_extpic_init();
515 /* Clear any pending interrupts */
516 #if (NR_UICS > 2)
517 mtdcr(DCRN_UIC_SR(UICB), 0xffffffff);
518 mtdcr(DCRN_UIC_SR(UIC2), 0xffffffff);
519 #endif
520 #if (NR_UICS > 1)
521 mtdcr(DCRN_UIC_SR(UIC1), 0xffffffff);
522 #endif
523 mtdcr(DCRN_UIC_SR(UIC0), 0xffffffff);
525 ppc4xx_pic = &ppc4xx_uic;
526 ppc_md.get_irq = ppc4xx_pic_get_irq;
527 #endif