diff options
author | Grant Likely <grant.likely@secretlab.ca> | 2010-06-18 13:10:01 -0400 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2010-07-05 18:14:25 -0400 |
commit | b83da291b4c73eaddc20e2edb614123a6d681b3b (patch) | |
tree | de3388516ccdc635b93839492279fed3ca7e20d0 /arch | |
parent | b6295c8b85fe83e5679b7b8bebe4df85deebebfc (diff) |
of/powerpc: Move Powermac irq quirk code into powermac pic driver code
The code that figures out what is wrong with the powermac irq device
tree data belongs with the rest of the powermac irq code. This patch
moves it out of prom_parse.c and into powermac/pic.c so that it is only
compiled in when actually needed.
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Stephen Rothwell <sfr@canb.auug.org.au>
Diffstat (limited to 'arch')
-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. |