aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2005-10-26 03:19:06 -0400
committerPaul Mackerras <paulus@samba.org>2005-10-26 03:19:06 -0400
commit6d0124fc06be40deafca043c73a8203c78bbfe45 (patch)
treea2db556568bb9ecc698d1e8ea3f88fd0c022aa01 /arch/powerpc
parent830825d6c37a28061c0b6ca538a6411001cf3b2a (diff)
powerpc: Fix interrupt-tree parsing
The interrupt-tree parsing code wasn't offsetting interrupt numbers by 16 on 32-bit platforms with an i8259 interrupt controller, and it was confused about the encoding of interrupt sense and level (which is different for i8259 and openpic interrupt controllers, just to make things interesting). Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/kernel/prom.c40
1 files changed, 26 insertions, 14 deletions
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 16ac15e73b44..ab9b291dda54 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -296,13 +296,28 @@ static int __devinit map_interrupt(unsigned int **irq, struct device_node **ictr
296 return nintrc; 296 return nintrc;
297} 297}
298 298
299static unsigned char map_isa_senses[4] = {
300 IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE,
301 IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE,
302 IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE,
303 IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE
304};
305
306static unsigned char map_mpic_senses[4] = {
307 IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE,
308 IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE,
309 /* 2 seems to be used for the 8259 cascade... */
310 IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE,
311 IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE,
312};
313
299static int __devinit finish_node_interrupts(struct device_node *np, 314static int __devinit finish_node_interrupts(struct device_node *np,
300 unsigned long *mem_start, 315 unsigned long *mem_start,
301 int measure_only) 316 int measure_only)
302{ 317{
303 unsigned int *ints; 318 unsigned int *ints;
304 int intlen, intrcells, intrcount; 319 int intlen, intrcells, intrcount;
305 int i, j, n; 320 int i, j, n, sense;
306 unsigned int *irq, virq; 321 unsigned int *irq, virq;
307 struct device_node *ic; 322 struct device_node *ic;
308 323
@@ -332,7 +347,8 @@ static int __devinit finish_node_interrupts(struct device_node *np,
332 347
333 for (i = 0; i < np->n_intrs; ++i) { 348 for (i = 0; i < np->n_intrs; ++i) {
334 np->intrs[i].line = *ints++; 349 np->intrs[i].line = *ints++;
335 np->intrs[i].sense = 1; 350 np->intrs[i].sense = IRQ_SENSE_LEVEL
351 | IRQ_POLARITY_NEGATIVE;
336 } 352 }
337 return 0; 353 return 0;
338 } 354 }
@@ -359,19 +375,20 @@ static int __devinit finish_node_interrupts(struct device_node *np,
359 /* don't map IRQ numbers under a cascaded 8259 controller */ 375 /* don't map IRQ numbers under a cascaded 8259 controller */
360 if (ic && device_is_compatible(ic, "chrp,iic")) { 376 if (ic && device_is_compatible(ic, "chrp,iic")) {
361 np->intrs[intrcount].line = irq[0]; 377 np->intrs[intrcount].line = irq[0];
378 sense = (n > 1)? (irq[1] & 3): 3;
379 np->intrs[intrcount].sense = map_isa_senses[sense];
362 } else { 380 } else {
363#ifdef CONFIG_PPC64
364 virq = virt_irq_create_mapping(irq[0]); 381 virq = virt_irq_create_mapping(irq[0]);
382#ifdef CONFIG_PPC64
365 if (virq == NO_IRQ) { 383 if (virq == NO_IRQ) {
366 printk(KERN_CRIT "Could not allocate interrupt" 384 printk(KERN_CRIT "Could not allocate interrupt"
367 " number for %s\n", np->full_name); 385 " number for %s\n", np->full_name);
368 continue; 386 continue;
369 } 387 }
370 virq = irq_offset_up(virq);
371#else
372 virq = irq[0];
373#endif 388#endif
374 np->intrs[intrcount].line = virq; 389 np->intrs[intrcount].line = irq_offset_up(virq);
390 sense = (n > 1)? (irq[1] & 3): 1;
391 np->intrs[intrcount].sense = map_mpic_senses[sense];
375 } 392 }
376 393
377#ifdef CONFIG_PPC64 394#ifdef CONFIG_PPC64
@@ -386,9 +403,6 @@ static int __devinit finish_node_interrupts(struct device_node *np,
386 break; 403 break;
387 } 404 }
388#endif 405#endif
389 np->intrs[intrcount].sense = 1;
390 if (n > 1)
391 np->intrs[intrcount].sense = irq[1];
392 if (n > 2) { 406 if (n > 2) {
393 printk("hmmm, got %d intr cells for %s:", n, 407 printk("hmmm, got %d intr cells for %s:", n,
394 np->full_name); 408 np->full_name);
@@ -1401,15 +1415,13 @@ void __init prom_get_irq_senses(unsigned char *senses, int off, int max)
1401 int i, j; 1415 int i, j;
1402 1416
1403 /* default to level-triggered */ 1417 /* default to level-triggered */
1404 memset(senses, 1, max - off); 1418 memset(senses, IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE, max - off);
1405 1419
1406 for (np = allnodes; np != 0; np = np->allnext) { 1420 for (np = allnodes; np != 0; np = np->allnext) {
1407 for (j = 0; j < np->n_intrs; j++) { 1421 for (j = 0; j < np->n_intrs; j++) {
1408 i = np->intrs[j].line; 1422 i = np->intrs[j].line;
1409 if (i >= off && i < max) 1423 if (i >= off && i < max)
1410 senses[i-off] = np->intrs[j].sense ? 1424 senses[i-off] = np->intrs[j].sense;
1411 IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE :
1412 IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE;
1413 } 1425 }
1414 } 1426 }
1415} 1427}