aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/pci-common.c
diff options
context:
space:
mode:
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}