diff options
-rw-r--r-- | arch/powerpc/include/asm/prom.h | 24 | ||||
-rw-r--r-- | arch/powerpc/kernel/prom_parse.c | 85 | ||||
-rw-r--r-- | arch/powerpc/platforms/powermac/pic.c | 72 |
3 files changed, 81 insertions, 100 deletions
diff --git a/arch/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h index 47d41b67c94d..4486765db6e7 100644 --- a/arch/powerpc/include/asm/prom.h +++ b/arch/powerpc/include/asm/prom.h | |||
@@ -109,18 +109,24 @@ extern const void *of_get_mac_address(struct device_node *np); | |||
109 | * OF interrupt mapping | 109 | * OF interrupt mapping |
110 | */ | 110 | */ |
111 | 111 | ||
112 | /** | ||
113 | * of_irq_map_init - Initialize the irq remapper | ||
114 | * @flags: flags defining workarounds to enable | ||
115 | * | ||
116 | * Some machines have bugs in the device-tree which require certain workarounds | ||
117 | * to be applied. Call this before any interrupt mapping attempts to enable | ||
118 | * those workarounds. | ||
119 | */ | ||
120 | #define OF_IMAP_OLDWORLD_MAC 0x00000001 | 112 | #define OF_IMAP_OLDWORLD_MAC 0x00000001 |
121 | #define OF_IMAP_NO_PHANDLE 0x00000002 | 113 | #define OF_IMAP_NO_PHANDLE 0x00000002 |
122 | 114 | ||
123 | extern void of_irq_map_init(unsigned int flags); | 115 | #if defined(CONFIG_PPC32) && defined(CONFIG_PPC_PMAC) |
116 | /* Workarounds only needed for 32bit powermac machines */ | ||
117 | extern unsigned int of_irq_workarounds; | ||
118 | extern struct device_node *of_irq_dflt_pic; | ||
119 | extern int of_irq_map_oldworld(struct device_node *device, int index, | ||
120 | struct of_irq *out_irq); | ||
121 | #else | ||
122 | #define of_irq_workarounds (0) | ||
123 | #define of_irq_dflt_pic (NULL) | ||
124 | static inline int of_irq_map_oldworld(struct device_node *device, int index, | ||
125 | struct of_irq *out_irq) | ||
126 | { | ||
127 | return -EINVAL; | ||
128 | } | ||
129 | #endif | ||
124 | 130 | ||
125 | /** | 131 | /** |
126 | * of_irq_map_raw - Low level interrupt tree parsing | 132 | * of_irq_map_raw - Low level interrupt tree parsing |
diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c index 8362620c9e6f..dfa6de6572bb 100644 --- a/arch/powerpc/kernel/prom_parse.c +++ b/arch/powerpc/kernel/prom_parse.c | |||
@@ -682,9 +682,6 @@ void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop, | |||
682 | * Interrupt remapper | 682 | * Interrupt remapper |
683 | */ | 683 | */ |
684 | 684 | ||
685 | static unsigned int of_irq_workarounds; | ||
686 | static struct device_node *of_irq_dflt_pic; | ||
687 | |||
688 | static struct device_node *of_irq_find_parent(struct device_node *child) | 685 | static struct device_node *of_irq_find_parent(struct device_node *child) |
689 | { | 686 | { |
690 | struct device_node *p; | 687 | struct device_node *p; |
@@ -710,44 +707,6 @@ static struct device_node *of_irq_find_parent(struct device_node *child) | |||
710 | return p; | 707 | return p; |
711 | } | 708 | } |
712 | 709 | ||
713 | /* This doesn't need to be called if you don't have any special workaround | ||
714 | * flags to pass | ||
715 | */ | ||
716 | void of_irq_map_init(unsigned int flags) | ||
717 | { | ||
718 | of_irq_workarounds = flags; | ||
719 | |||
720 | /* OldWorld, don't bother looking at other things */ | ||
721 | if (flags & OF_IMAP_OLDWORLD_MAC) | ||
722 | return; | ||
723 | |||
724 | /* If we don't have phandles, let's try to locate a default interrupt | ||
725 | * controller (happens when booting with BootX). We do a first match | ||
726 | * here, hopefully, that only ever happens on machines with one | ||
727 | * controller. | ||
728 | */ | ||
729 | if (flags & OF_IMAP_NO_PHANDLE) { | ||
730 | struct device_node *np; | ||
731 | |||
732 | for_each_node_with_property(np, "interrupt-controller") { | ||
733 | /* Skip /chosen/interrupt-controller */ | ||
734 | if (strcmp(np->name, "chosen") == 0) | ||
735 | continue; | ||
736 | /* It seems like at least one person on this planet wants | ||
737 | * to use BootX on a machine with an AppleKiwi controller | ||
738 | * which happens to pretend to be an interrupt | ||
739 | * controller too. | ||
740 | */ | ||
741 | if (strcmp(np->name, "AppleKiwi") == 0) | ||
742 | continue; | ||
743 | /* I think we found one ! */ | ||
744 | of_irq_dflt_pic = np; | ||
745 | break; | ||
746 | } | ||
747 | } | ||
748 | |||
749 | } | ||
750 | |||
751 | int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize, | 710 | int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize, |
752 | const u32 *addr, struct of_irq *out_irq) | 711 | const u32 *addr, struct of_irq *out_irq) |
753 | { | 712 | { |
@@ -922,50 +881,6 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize, | |||
922 | } | 881 | } |
923 | EXPORT_SYMBOL_GPL(of_irq_map_raw); | 882 | EXPORT_SYMBOL_GPL(of_irq_map_raw); |
924 | 883 | ||
925 | #if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32) | ||
926 | static int of_irq_map_oldworld(struct device_node *device, int index, | ||
927 | struct of_irq *out_irq) | ||
928 | { | ||
929 | const u32 *ints = NULL; | ||
930 | int intlen; | ||
931 | |||
932 | /* | ||
933 | * Old machines just have a list of interrupt numbers | ||
934 | * and no interrupt-controller nodes. We also have dodgy | ||
935 | * cases where the APPL,interrupts property is completely | ||
936 | * missing behind pci-pci bridges and we have to get it | ||
937 | * from the parent (the bridge itself, as apple just wired | ||
938 | * everything together on these) | ||
939 | */ | ||
940 | while (device) { | ||
941 | ints = of_get_property(device, "AAPL,interrupts", &intlen); | ||
942 | if (ints != NULL) | ||
943 | break; | ||
944 | device = device->parent; | ||
945 | if (device && strcmp(device->type, "pci") != 0) | ||
946 | break; | ||
947 | } | ||
948 | if (ints == NULL) | ||
949 | return -EINVAL; | ||
950 | intlen /= sizeof(u32); | ||
951 | |||
952 | if (index >= intlen) | ||
953 | return -EINVAL; | ||
954 | |||
955 | out_irq->controller = NULL; | ||
956 | out_irq->specifier[0] = ints[index]; | ||
957 | out_irq->size = 1; | ||
958 | |||
959 | return 0; | ||
960 | } | ||
961 | #else /* defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32) */ | ||
962 | static int of_irq_map_oldworld(struct device_node *device, int index, | ||
963 | struct of_irq *out_irq) | ||
964 | { | ||
965 | return -EINVAL; | ||
966 | } | ||
967 | #endif /* !(defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)) */ | ||
968 | |||
969 | int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq) | 884 | int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq) |
970 | { | 885 | { |
971 | struct device_node *p; | 886 | struct device_node *p; |
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c index 630a533d0e59..890d5f72b198 100644 --- a/arch/powerpc/platforms/powermac/pic.c +++ b/arch/powerpc/platforms/powermac/pic.c | |||
@@ -46,6 +46,10 @@ struct pmac_irq_hw { | |||
46 | unsigned int level; | 46 | unsigned int level; |
47 | }; | 47 | }; |
48 | 48 | ||
49 | /* Workaround flags for 32bit powermac machines */ | ||
50 | unsigned int of_irq_workarounds; | ||
51 | struct device_node *of_irq_dflt_pic; | ||
52 | |||
49 | /* Default addresses */ | 53 | /* Default addresses */ |
50 | static volatile struct pmac_irq_hw __iomem *pmac_irq_hw[4]; | 54 | static volatile struct pmac_irq_hw __iomem *pmac_irq_hw[4]; |
51 | 55 | ||
@@ -428,6 +432,42 @@ static void __init pmac_pic_probe_oldstyle(void) | |||
428 | setup_irq(irq_create_mapping(NULL, 20), &xmon_action); | 432 | setup_irq(irq_create_mapping(NULL, 20), &xmon_action); |
429 | #endif | 433 | #endif |
430 | } | 434 | } |
435 | |||
436 | int of_irq_map_oldworld(struct device_node *device, int index, | ||
437 | struct of_irq *out_irq) | ||
438 | { | ||
439 | const u32 *ints = NULL; | ||
440 | int intlen; | ||
441 | |||
442 | /* | ||
443 | * Old machines just have a list of interrupt numbers | ||
444 | * and no interrupt-controller nodes. We also have dodgy | ||
445 | * cases where the APPL,interrupts property is completely | ||
446 | * missing behind pci-pci bridges and we have to get it | ||
447 | * from the parent (the bridge itself, as apple just wired | ||
448 | * everything together on these) | ||
449 | */ | ||
450 | while (device) { | ||
451 | ints = of_get_property(device, "AAPL,interrupts", &intlen); | ||
452 | if (ints != NULL) | ||
453 | break; | ||
454 | device = device->parent; | ||
455 | if (device && strcmp(device->type, "pci") != 0) | ||
456 | break; | ||
457 | } | ||
458 | if (ints == NULL) | ||
459 | return -EINVAL; | ||
460 | intlen /= sizeof(u32); | ||
461 | |||
462 | if (index >= intlen) | ||
463 | return -EINVAL; | ||
464 | |||
465 | out_irq->controller = NULL; | ||
466 | out_irq->specifier[0] = ints[index]; | ||
467 | out_irq->size = 1; | ||
468 | |||
469 | return 0; | ||
470 | } | ||
431 | #endif /* CONFIG_PPC32 */ | 471 | #endif /* CONFIG_PPC32 */ |
432 | 472 | ||
433 | static void pmac_u3_cascade(unsigned int irq, struct irq_desc *desc) | 473 | static void pmac_u3_cascade(unsigned int irq, struct irq_desc *desc) |
@@ -559,19 +599,39 @@ static int __init pmac_pic_probe_mpic(void) | |||
559 | 599 | ||
560 | void __init pmac_pic_init(void) | 600 | void __init pmac_pic_init(void) |
561 | { | 601 | { |
562 | unsigned int flags = 0; | ||
563 | |||
564 | /* We configure the OF parsing based on our oldworld vs. newworld | 602 | /* We configure the OF parsing based on our oldworld vs. newworld |
565 | * platform type and wether we were booted by BootX. | 603 | * platform type and wether we were booted by BootX. |
566 | */ | 604 | */ |
567 | #ifdef CONFIG_PPC32 | 605 | #ifdef CONFIG_PPC32 |
568 | if (!pmac_newworld) | 606 | if (!pmac_newworld) |
569 | flags |= OF_IMAP_OLDWORLD_MAC; | 607 | of_irq_workarounds |= OF_IMAP_OLDWORLD_MAC; |
570 | if (of_get_property(of_chosen, "linux,bootx", NULL) != NULL) | 608 | if (of_get_property(of_chosen, "linux,bootx", NULL) != NULL) |
571 | flags |= OF_IMAP_NO_PHANDLE; | 609 | of_irq_workarounds |= OF_IMAP_NO_PHANDLE; |
572 | #endif /* CONFIG_PPC_32 */ | ||
573 | 610 | ||
574 | of_irq_map_init(flags); | 611 | /* If we don't have phandles on a newworld, then try to locate a |
612 | * default interrupt controller (happens when booting with BootX). | ||
613 | * We do a first match here, hopefully, that only ever happens on | ||
614 | * machines with one controller. | ||
615 | */ | ||
616 | if (pmac_newworld && (of_irq_workarounds & OF_IMAP_NO_PHANDLE)) { | ||
617 | struct device_node *np; | ||
618 | |||
619 | for_each_node_with_property(np, "interrupt-controller") { | ||
620 | /* Skip /chosen/interrupt-controller */ | ||
621 | if (strcmp(np->name, "chosen") == 0) | ||
622 | continue; | ||
623 | /* It seems like at least one person wants | ||
624 | * to use BootX on a machine with an AppleKiwi | ||
625 | * controller which happens to pretend to be an | ||
626 | * interrupt controller too. */ | ||
627 | if (strcmp(np->name, "AppleKiwi") == 0) | ||
628 | continue; | ||
629 | /* I think we found one ! */ | ||
630 | of_irq_dflt_pic = np; | ||
631 | break; | ||
632 | } | ||
633 | } | ||
634 | #endif /* CONFIG_PPC32 */ | ||
575 | 635 | ||
576 | /* We first try to detect Apple's new Core99 chipset, since mac-io | 636 | /* We first try to detect Apple's new Core99 chipset, since mac-io |
577 | * is quite different on those machines and contains an IBM MPIC2. | 637 | * is quite different on those machines and contains an IBM MPIC2. |