aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/include/asm/prom.h24
-rw-r--r--arch/powerpc/kernel/prom_parse.c85
-rw-r--r--arch/powerpc/platforms/powermac/pic.c72
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
123extern 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 */
117extern unsigned int of_irq_workarounds;
118extern struct device_node *of_irq_dflt_pic;
119extern 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)
124static 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
685static unsigned int of_irq_workarounds;
686static struct device_node *of_irq_dflt_pic;
687
688static struct device_node *of_irq_find_parent(struct device_node *child) 685static 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 */
716void 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
751int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize, 710int 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}
923EXPORT_SYMBOL_GPL(of_irq_map_raw); 882EXPORT_SYMBOL_GPL(of_irq_map_raw);
924 883
925#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
926static 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) */
962static 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
969int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq) 884int 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 */
50unsigned int of_irq_workarounds;
51struct device_node *of_irq_dflt_pic;
52
49/* Default addresses */ 53/* Default addresses */
50static volatile struct pmac_irq_hw __iomem *pmac_irq_hw[4]; 54static 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
436int 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
433static void pmac_u3_cascade(unsigned int irq, struct irq_desc *desc) 473static 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
560void __init pmac_pic_init(void) 600void __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.