diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2005-11-15 00:05:33 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2005-11-15 21:29:46 -0500 |
commit | b5166cc252190be80465f3b4f050e4a0310f71af (patch) | |
tree | 565d11c2ea25d1553489d6c8a9b4d2c00e110288 /arch/powerpc/platforms | |
parent | f9e4ec57c66586d0c165ed9373efaf9e329d5766 (diff) |
[PATCH] powerpc: pci_64 fixes & cleanups
I discovered that in some cases (PowerMac for example) we wouldn't
properly map the PCI IO space on recent kernels. In addition, the code
for initializing PCI host bridges was scattered all over the place with
some duplication between platforms.
This patch fixes the problem and does a small cleanup by creating a
pcibios_alloc_controller() in pci_64.c that is similar to the one in
pci_32.c (just takes an additional device node argument) that takes care
of all the grunt allocation and initialisation work. It should work for
both boot time and dynamically allocated PHBs.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r-- | arch/powerpc/platforms/iseries/pci.c | 3 | ||||
-rw-r--r-- | arch/powerpc/platforms/maple/pci.c | 16 | ||||
-rw-r--r-- | arch/powerpc/platforms/powermac/pci.c | 62 |
3 files changed, 34 insertions, 47 deletions
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index 4b75131773a6..dafc518fbb83 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c | |||
@@ -244,10 +244,9 @@ unsigned long __init find_and_init_phbs(void) | |||
244 | if (ret == 0) { | 244 | if (ret == 0) { |
245 | printk("bus %d appears to exist\n", bus); | 245 | printk("bus %d appears to exist\n", bus); |
246 | 246 | ||
247 | phb = (struct pci_controller *)kmalloc(sizeof(struct pci_controller), GFP_KERNEL); | 247 | phb = pcibios_alloc_controller(NULL); |
248 | if (phb == NULL) | 248 | if (phb == NULL) |
249 | return -ENOMEM; | 249 | return -ENOMEM; |
250 | pci_setup_pci_controller(phb); | ||
251 | 250 | ||
252 | phb->pci_mem_offset = phb->local_number = bus; | 251 | phb->pci_mem_offset = phb->local_number = bus; |
253 | phb->first_busno = bus; | 252 | phb->first_busno = bus; |
diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c index 895aeb3f75d0..f40451da037c 100644 --- a/arch/powerpc/platforms/maple/pci.c +++ b/arch/powerpc/platforms/maple/pci.c | |||
@@ -326,26 +326,12 @@ static int __init add_bridge(struct device_node *dev) | |||
326 | dev->full_name); | 326 | dev->full_name); |
327 | } | 327 | } |
328 | 328 | ||
329 | hose = alloc_bootmem(sizeof(struct pci_controller)); | 329 | hose = pcibios_alloc_controller(dev); |
330 | if (hose == NULL) | 330 | if (hose == NULL) |
331 | return -ENOMEM; | 331 | return -ENOMEM; |
332 | pci_setup_pci_controller(hose); | ||
333 | |||
334 | hose->arch_data = dev; | ||
335 | hose->first_busno = bus_range ? bus_range[0] : 0; | 332 | hose->first_busno = bus_range ? bus_range[0] : 0; |
336 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | 333 | hose->last_busno = bus_range ? bus_range[1] : 0xff; |
337 | 334 | ||
338 | of_prop = alloc_bootmem(sizeof(struct property) + | ||
339 | sizeof(hose->global_number)); | ||
340 | if (of_prop) { | ||
341 | memset(of_prop, 0, sizeof(struct property)); | ||
342 | of_prop->name = "linux,pci-domain"; | ||
343 | of_prop->length = sizeof(hose->global_number); | ||
344 | of_prop->value = (unsigned char *)&of_prop[1]; | ||
345 | memcpy(of_prop->value, &hose->global_number, sizeof(hose->global_number)); | ||
346 | prom_add_property(dev, of_prop); | ||
347 | } | ||
348 | |||
349 | disp_name = NULL; | 335 | disp_name = NULL; |
350 | if (device_is_compatible(dev, "u3-agp")) { | 336 | if (device_is_compatible(dev, "u3-agp")) { |
351 | setup_u3_agp(hose); | 337 | setup_u3_agp(hose); |
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index dfd41b9781a9..443be526cde7 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c | |||
@@ -640,15 +640,16 @@ static void __init setup_u3_ht(struct pci_controller* hose) | |||
640 | * the reg address cell, we shall fix that by killing struct | 640 | * the reg address cell, we shall fix that by killing struct |
641 | * reg_property and using some accessor functions instead | 641 | * reg_property and using some accessor functions instead |
642 | */ | 642 | */ |
643 | hose->cfg_data = (volatile unsigned char *)ioremap(0xf2000000, 0x02000000); | 643 | hose->cfg_data = (volatile unsigned char *)ioremap(0xf2000000, |
644 | 0x02000000); | ||
644 | 645 | ||
645 | /* | 646 | /* |
646 | * /ht node doesn't expose a "ranges" property, so we "remove" regions that | 647 | * /ht node doesn't expose a "ranges" property, so we "remove" |
647 | * have been allocated to AGP. So far, this version of the code doesn't assign | 648 | * regions that have been allocated to AGP. So far, this version of |
648 | * any of the 0xfxxxxxxx "fine" memory regions to /ht. | 649 | * the code doesn't assign any of the 0xfxxxxxxx "fine" memory regions |
649 | * We need to fix that sooner or later by either parsing all child "ranges" | 650 | * to /ht. We need to fix that sooner or later by either parsing all |
650 | * properties or figuring out the U3 address space decoding logic and | 651 | * child "ranges" properties or figuring out the U3 address space |
651 | * then read its configuration register (if any). | 652 | * decoding logic and then read its configuration register (if any). |
652 | */ | 653 | */ |
653 | hose->io_base_phys = 0xf4000000; | 654 | hose->io_base_phys = 0xf4000000; |
654 | hose->pci_io_size = 0x00400000; | 655 | hose->pci_io_size = 0x00400000; |
@@ -671,10 +672,10 @@ static void __init setup_u3_ht(struct pci_controller* hose) | |||
671 | return; | 672 | return; |
672 | } | 673 | } |
673 | 674 | ||
674 | /* We "remove" the AGP resources from the resources allocated to HT, that | 675 | /* We "remove" the AGP resources from the resources allocated to HT, |
675 | * is we create "holes". However, that code does assumptions that so far | 676 | * that is we create "holes". However, that code does assumptions |
676 | * happen to be true (cross fingers...), typically that resources in the | 677 | * that so far happen to be true (cross fingers...), typically that |
677 | * AGP node are properly ordered | 678 | * resources in the AGP node are properly ordered |
678 | */ | 679 | */ |
679 | cur = 0; | 680 | cur = 0; |
680 | for (i=0; i<3; i++) { | 681 | for (i=0; i<3; i++) { |
@@ -684,23 +685,30 @@ static void __init setup_u3_ht(struct pci_controller* hose) | |||
684 | /* We don't care about "fine" resources */ | 685 | /* We don't care about "fine" resources */ |
685 | if (res->start >= 0xf0000000) | 686 | if (res->start >= 0xf0000000) |
686 | continue; | 687 | continue; |
687 | /* Check if it's just a matter of "shrinking" us in one direction */ | 688 | /* Check if it's just a matter of "shrinking" us in one |
689 | * direction | ||
690 | */ | ||
688 | if (hose->mem_resources[cur].start == res->start) { | 691 | if (hose->mem_resources[cur].start == res->start) { |
689 | DBG("U3/HT: shrink start of %d, %08lx -> %08lx\n", | 692 | DBG("U3/HT: shrink start of %d, %08lx -> %08lx\n", |
690 | cur, hose->mem_resources[cur].start, res->end + 1); | 693 | cur, hose->mem_resources[cur].start, |
694 | res->end + 1); | ||
691 | hose->mem_resources[cur].start = res->end + 1; | 695 | hose->mem_resources[cur].start = res->end + 1; |
692 | continue; | 696 | continue; |
693 | } | 697 | } |
694 | if (hose->mem_resources[cur].end == res->end) { | 698 | if (hose->mem_resources[cur].end == res->end) { |
695 | DBG("U3/HT: shrink end of %d, %08lx -> %08lx\n", | 699 | DBG("U3/HT: shrink end of %d, %08lx -> %08lx\n", |
696 | cur, hose->mem_resources[cur].end, res->start - 1); | 700 | cur, hose->mem_resources[cur].end, |
701 | res->start - 1); | ||
697 | hose->mem_resources[cur].end = res->start - 1; | 702 | hose->mem_resources[cur].end = res->start - 1; |
698 | continue; | 703 | continue; |
699 | } | 704 | } |
700 | /* No, it's not the case, we need a hole */ | 705 | /* No, it's not the case, we need a hole */ |
701 | if (cur == 2) { | 706 | if (cur == 2) { |
702 | /* not enough resources for a hole, we drop part of the range */ | 707 | /* not enough resources for a hole, we drop part |
703 | printk(KERN_WARNING "Running out of resources for /ht host !\n"); | 708 | * of the range |
709 | */ | ||
710 | printk(KERN_WARNING "Running out of resources" | ||
711 | " for /ht host !\n"); | ||
704 | hose->mem_resources[cur].end = res->start - 1; | 712 | hose->mem_resources[cur].end = res->start - 1; |
705 | continue; | 713 | continue; |
706 | } | 714 | } |
@@ -714,17 +722,6 @@ static void __init setup_u3_ht(struct pci_controller* hose) | |||
714 | hose->mem_resources[cur-1].end = res->start - 1; | 722 | hose->mem_resources[cur-1].end = res->start - 1; |
715 | } | 723 | } |
716 | } | 724 | } |
717 | |||
718 | /* XXX this needs to be converged between ppc32 and ppc64... */ | ||
719 | static struct pci_controller * __init pcibios_alloc_controller(void) | ||
720 | { | ||
721 | struct pci_controller *hose; | ||
722 | |||
723 | hose = alloc_bootmem(sizeof(struct pci_controller)); | ||
724 | if (hose) | ||
725 | pci_setup_pci_controller(hose); | ||
726 | return hose; | ||
727 | } | ||
728 | #endif | 725 | #endif |
729 | 726 | ||
730 | /* | 727 | /* |
@@ -756,11 +753,16 @@ static int __init add_bridge(struct device_node *dev) | |||
756 | #endif | 753 | #endif |
757 | bus_range = (int *) get_property(dev, "bus-range", &len); | 754 | bus_range = (int *) get_property(dev, "bus-range", &len); |
758 | if (bus_range == NULL || len < 2 * sizeof(int)) { | 755 | if (bus_range == NULL || len < 2 * sizeof(int)) { |
759 | printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n", | 756 | printk(KERN_WARNING "Can't get bus-range for %s, assume" |
760 | dev->full_name); | 757 | " bus 0\n", dev->full_name); |
761 | } | 758 | } |
762 | 759 | ||
760 | /* XXX Different prototypes, to be merged */ | ||
761 | #ifdef CONFIG_PPC64 | ||
762 | hose = pcibios_alloc_controller(dev); | ||
763 | #else | ||
763 | hose = pcibios_alloc_controller(); | 764 | hose = pcibios_alloc_controller(); |
765 | #endif | ||
764 | if (!hose) | 766 | if (!hose) |
765 | return -ENOMEM; | 767 | return -ENOMEM; |
766 | hose->arch_data = dev; | 768 | hose->arch_data = dev; |
@@ -768,7 +770,7 @@ static int __init add_bridge(struct device_node *dev) | |||
768 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | 770 | hose->last_busno = bus_range ? bus_range[1] : 0xff; |
769 | 771 | ||
770 | disp_name = NULL; | 772 | disp_name = NULL; |
771 | #ifdef CONFIG_POWER4 | 773 | #ifdef CONFIG_PPC64 |
772 | if (device_is_compatible(dev, "u3-agp")) { | 774 | if (device_is_compatible(dev, "u3-agp")) { |
773 | setup_u3_agp(hose); | 775 | setup_u3_agp(hose); |
774 | disp_name = "U3-AGP"; | 776 | disp_name = "U3-AGP"; |