diff options
author | Paul Mackerras <paulus@samba.org> | 2005-10-26 03:19:06 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2005-10-26 03:19:06 -0400 |
commit | 6d0124fc06be40deafca043c73a8203c78bbfe45 (patch) | |
tree | a2db556568bb9ecc698d1e8ea3f88fd0c022aa01 /arch/powerpc | |
parent | 830825d6c37a28061c0b6ca538a6411001cf3b2a (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.c | 40 |
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 | ||
299 | static 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 | |||
306 | static 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 | |||
299 | static int __devinit finish_node_interrupts(struct device_node *np, | 314 | static 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 | } |