diff options
| author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2006-07-10 07:44:43 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-07-10 16:24:20 -0400 |
| commit | 06fe98e6369330d522705d5e67a2eddac2fd5bba (patch) | |
| tree | f8f2e31087634f91a1d797a1c218be9c5325654a /arch/powerpc/sysdev | |
| parent | 6e99e4582861578fb00d84d085f8f283569f51dd (diff) | |
[PATCH] powerpc: fix MPIC OF tree parsing on Apple quad g5
The quad g5 currently doesn't boot due to two problems. This patch fixes the
first one: Apple new way of doing interrupt specifiers in OF for devices using
the HT APIC isn't properly parsed by the new MPIC driver code.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/powerpc/sysdev')
| -rw-r--r-- | arch/powerpc/sysdev/mpic.c | 38 |
1 files changed, 28 insertions, 10 deletions
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index c39c4a0b1cda..6e0281afa6c3 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c | |||
| @@ -204,7 +204,7 @@ static void mpic_startup_ht_interrupt(struct mpic *mpic, unsigned int source, | |||
| 204 | if (fixup->base == NULL) | 204 | if (fixup->base == NULL) |
| 205 | return; | 205 | return; |
| 206 | 206 | ||
| 207 | DBG("startup_ht_interrupt(%u, %u) index: %d\n", | 207 | DBG("startup_ht_interrupt(0x%x, 0x%x) index: %d\n", |
| 208 | source, irqflags, fixup->index); | 208 | source, irqflags, fixup->index); |
| 209 | spin_lock_irqsave(&mpic->fixup_lock, flags); | 209 | spin_lock_irqsave(&mpic->fixup_lock, flags); |
| 210 | /* Enable and configure */ | 210 | /* Enable and configure */ |
| @@ -227,7 +227,7 @@ static void mpic_shutdown_ht_interrupt(struct mpic *mpic, unsigned int source, | |||
| 227 | if (fixup->base == NULL) | 227 | if (fixup->base == NULL) |
| 228 | return; | 228 | return; |
| 229 | 229 | ||
| 230 | DBG("shutdown_ht_interrupt(%u, %u)\n", source, irqflags); | 230 | DBG("shutdown_ht_interrupt(0x%x, 0x%x)\n", source, irqflags); |
| 231 | 231 | ||
| 232 | /* Disable */ | 232 | /* Disable */ |
| 233 | spin_lock_irqsave(&mpic->fixup_lock, flags); | 233 | spin_lock_irqsave(&mpic->fixup_lock, flags); |
| @@ -588,8 +588,8 @@ static int mpic_set_irq_type(unsigned int virq, unsigned int flow_type) | |||
| 588 | struct irq_desc *desc = get_irq_desc(virq); | 588 | struct irq_desc *desc = get_irq_desc(virq); |
| 589 | unsigned int vecpri, vold, vnew; | 589 | unsigned int vecpri, vold, vnew; |
| 590 | 590 | ||
| 591 | pr_debug("mpic: set_irq_type(mpic:@%p,virq:%d,src:%d,type:0x%x)\n", | 591 | DBG("mpic: set_irq_type(mpic:@%p,virq:%d,src:0x%x,type:0x%x)\n", |
| 592 | mpic, virq, src, flow_type); | 592 | mpic, virq, src, flow_type); |
| 593 | 593 | ||
| 594 | if (src >= mpic->irq_count) | 594 | if (src >= mpic->irq_count) |
| 595 | return -EINVAL; | 595 | return -EINVAL; |
| @@ -661,15 +661,16 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq, | |||
| 661 | struct mpic *mpic = h->host_data; | 661 | struct mpic *mpic = h->host_data; |
| 662 | struct irq_chip *chip; | 662 | struct irq_chip *chip; |
| 663 | 663 | ||
| 664 | pr_debug("mpic: map virq %d, hwirq 0x%lx\n", virq, hw); | 664 | DBG("mpic: map virq %d, hwirq 0x%lx\n", virq, hw); |
| 665 | 665 | ||
| 666 | if (hw == MPIC_VEC_SPURRIOUS) | 666 | if (hw == MPIC_VEC_SPURRIOUS) |
| 667 | return -EINVAL; | 667 | return -EINVAL; |
| 668 | |||
| 668 | #ifdef CONFIG_SMP | 669 | #ifdef CONFIG_SMP |
| 669 | else if (hw >= MPIC_VEC_IPI_0) { | 670 | else if (hw >= MPIC_VEC_IPI_0) { |
| 670 | WARN_ON(!(mpic->flags & MPIC_PRIMARY)); | 671 | WARN_ON(!(mpic->flags & MPIC_PRIMARY)); |
| 671 | 672 | ||
| 672 | pr_debug("mpic: mapping as IPI\n"); | 673 | DBG("mpic: mapping as IPI\n"); |
| 673 | set_irq_chip_data(virq, mpic); | 674 | set_irq_chip_data(virq, mpic); |
| 674 | set_irq_chip_and_handler(virq, &mpic->hc_ipi, | 675 | set_irq_chip_and_handler(virq, &mpic->hc_ipi, |
| 675 | handle_percpu_irq); | 676 | handle_percpu_irq); |
| @@ -689,7 +690,7 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq, | |||
| 689 | chip = &mpic->hc_ht_irq; | 690 | chip = &mpic->hc_ht_irq; |
| 690 | #endif /* CONFIG_MPIC_BROKEN_U3 */ | 691 | #endif /* CONFIG_MPIC_BROKEN_U3 */ |
| 691 | 692 | ||
| 692 | pr_debug("mpic: mapping to irq chip @%p\n", chip); | 693 | DBG("mpic: mapping to irq chip @%p\n", chip); |
| 693 | 694 | ||
| 694 | set_irq_chip_data(virq, mpic); | 695 | set_irq_chip_data(virq, mpic); |
| 695 | set_irq_chip_and_handler(virq, chip, handle_fasteoi_irq); | 696 | set_irq_chip_and_handler(virq, chip, handle_fasteoi_irq); |
| @@ -713,11 +714,28 @@ static int mpic_host_xlate(struct irq_host *h, struct device_node *ct, | |||
| 713 | }; | 714 | }; |
| 714 | 715 | ||
| 715 | *out_hwirq = intspec[0]; | 716 | *out_hwirq = intspec[0]; |
| 716 | if (intsize > 1 && intspec[1] < 4) | 717 | if (intsize > 1) { |
| 717 | *out_flags = map_mpic_senses[intspec[1]]; | 718 | u32 mask = 0x3; |
| 718 | else | 719 | |
| 720 | /* Apple invented a new race of encoding on machines with | ||
| 721 | * an HT APIC. They encode, among others, the index within | ||
| 722 | * the HT APIC. We don't care about it here since thankfully, | ||
| 723 | * it appears that they have the APIC already properly | ||
| 724 | * configured, and thus our current fixup code that reads the | ||
| 725 | * APIC config works fine. However, we still need to mask out | ||
| 726 | * bits in the specifier to make sure we only get bit 0 which | ||
| 727 | * is the level/edge bit (the only sense bit exposed by Apple), | ||
| 728 | * as their bit 1 means something else. | ||
| 729 | */ | ||
| 730 | if (machine_is(powermac)) | ||
| 731 | mask = 0x1; | ||
| 732 | *out_flags = map_mpic_senses[intspec[1] & mask]; | ||
| 733 | } else | ||
| 719 | *out_flags = IRQ_TYPE_NONE; | 734 | *out_flags = IRQ_TYPE_NONE; |
| 720 | 735 | ||
| 736 | DBG("mpic: xlate (%d cells: 0x%08x 0x%08x) to line 0x%lx sense 0x%x\n", | ||
| 737 | intsize, intspec[0], intspec[1], *out_hwirq, *out_flags); | ||
| 738 | |||
| 721 | return 0; | 739 | return 0; |
| 722 | } | 740 | } |
| 723 | 741 | ||
