aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/pci-common.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2007-12-19 22:54:51 -0500
committerPaul Mackerras <paulus@samba.org>2007-12-20 00:18:09 -0500
commitbf5e2ba28f24f82a64524ef4772c9ebe12e2cd2a (patch)
treef35c139d124a9276b71260c13c8bddf0aa02b4d7 /arch/powerpc/kernel/pci-common.c
parentfe2d338cdcc628e0abdb4f70570a7fa864c617db (diff)
[POWERPC] Merge PCI resource fixups
The PCI code in 32 and 64 bits fixes up resources differently. 32 bits uses a header quirk plus handles bridges in pcibios_fixup_bus() while 64 bits does things in various places depending on whether you are using OF probing, using PCI hotplug, etc... This merges those by basically using the 32 bits approach for both, with various tweaks to make 64 bits work with the new approach. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/pci-common.c')
-rw-r--r--arch/powerpc/kernel/pci-common.c130
1 files changed, 130 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 0245c989d30a..c61e9324f770 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -691,3 +691,133 @@ void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
691 res->end = (region->end + offset) & mask; 691 res->end = (region->end + offset) & mask;
692} 692}
693EXPORT_SYMBOL(pcibios_bus_to_resource); 693EXPORT_SYMBOL(pcibios_bus_to_resource);
694
695/* Fixup a bus resource into a linux resource */
696static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev)
697{
698 struct pci_controller *hose = pci_bus_to_host(dev->bus);
699 resource_size_t offset = 0, mask = (resource_size_t)-1;
700
701 if (res->flags & IORESOURCE_IO) {
702 offset = (unsigned long)hose->io_base_virt - _IO_BASE;
703 mask = 0xffffffffu;
704 } else if (res->flags & IORESOURCE_MEM)
705 offset = hose->pci_mem_offset;
706
707 res->start = (res->start + offset) & mask;
708 res->end = (res->end + offset) & mask;
709
710 pr_debug("PCI:%s %016llx-%016llx\n",
711 pci_name(dev),
712 (unsigned long long)res->start,
713 (unsigned long long)res->end);
714}
715
716
717/* This header fixup will do the resource fixup for all devices as they are
718 * probed, but not for bridge ranges
719 */
720static void __devinit pcibios_fixup_resources(struct pci_dev *dev)
721{
722 struct pci_controller *hose = pci_bus_to_host(dev->bus);
723 int i;
724
725 if (!hose) {
726 printk(KERN_ERR "No host bridge for PCI dev %s !\n",
727 pci_name(dev));
728 return;
729 }
730 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
731 struct resource *res = dev->resource + i;
732 if (!res->flags)
733 continue;
734 if (res->end == 0xffffffff) {
735 pr_debug("PCI:%s Resource %d %016llx-%016llx [%x] is unassigned\n",
736 pci_name(dev), i,
737 (unsigned long long)res->start,
738 (unsigned long long)res->end,
739 (unsigned int)res->flags);
740 res->end -= res->start;
741 res->start = 0;
742 res->flags |= IORESOURCE_UNSET;
743 continue;
744 }
745
746 pr_debug("PCI:%s Resource %d %016llx-%016llx [%x] fixup...\n",
747 pci_name(dev), i,
748 (unsigned long long)res->start,\
749 (unsigned long long)res->end,
750 (unsigned int)res->flags);
751
752 fixup_resource(res, dev);
753 }
754
755 /* Call machine specific resource fixup */
756 if (ppc_md.pcibios_fixup_resources)
757 ppc_md.pcibios_fixup_resources(dev);
758}
759DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources);
760
761static void __devinit __pcibios_fixup_bus(struct pci_bus *bus)
762{
763 struct pci_dev *dev = bus->self;
764
765 pr_debug("PCI: Fixup bus %d (%s)\n", bus->number, dev ? pci_name(dev) : "PHB");
766
767 /* Fixup PCI<->PCI bridges. Host bridges are handled separately, for
768 * now differently between 32 and 64 bits.
769 */
770 if (dev != NULL) {
771 struct resource *res;
772 int i;
773
774 for (i = 0; i < PCI_BUS_NUM_RESOURCES; ++i) {
775 if ((res = bus->resource[i]) == NULL)
776 continue;
777 if (!res->flags || bus->self->transparent)
778 continue;
779
780 pr_debug("PCI:%s Bus rsrc %d %016llx-%016llx [%x] fixup...\n",
781 pci_name(dev), i,
782 (unsigned long long)res->start,\
783 (unsigned long long)res->end,
784 (unsigned int)res->flags);
785
786 fixup_resource(res, dev);
787 }
788 }
789
790 /* Additional setup that is different between 32 and 64 bits for now */
791 pcibios_do_bus_setup(bus);
792
793 /* Platform specific bus fixups */
794 if (ppc_md.pcibios_fixup_bus)
795 ppc_md.pcibios_fixup_bus(bus);
796
797 /* Read default IRQs and fixup if necessary */
798 list_for_each_entry(dev, &bus->devices, bus_list) {
799 pci_read_irq_line(dev);
800 if (ppc_md.pci_irq_fixup)
801 ppc_md.pci_irq_fixup(dev);
802 }
803}
804
805void __devinit pcibios_fixup_bus(struct pci_bus *bus)
806{
807 /* When called from the generic PCI probe, read PCI<->PCI bridge
808 * bases before proceeding
809 */
810 if (bus->self != NULL)
811 pci_read_bridge_bases(bus);
812 __pcibios_fixup_bus(bus);
813}
814EXPORT_SYMBOL(pcibios_fixup_bus);
815
816/* When building a bus from the OF tree rather than probing, we need a
817 * slightly different version of the fixup which doesn't read the
818 * bridge bases using config space accesses
819 */
820void __devinit pcibios_fixup_of_probed_bus(struct pci_bus *bus)
821{
822 __pcibios_fixup_bus(bus);
823}