diff options
Diffstat (limited to 'arch/powerpc/kernel/pci-common.c')
-rw-r--r-- | arch/powerpc/kernel/pci-common.c | 292 |
1 files changed, 292 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index c61e9324f770..d804c8d0be00 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c | |||
@@ -53,6 +53,8 @@ static int global_phb_number; /* Global phb counter */ | |||
53 | /* ISA Memory physical address */ | 53 | /* ISA Memory physical address */ |
54 | resource_size_t isa_mem_base; | 54 | resource_size_t isa_mem_base; |
55 | 55 | ||
56 | /* Default PCI flags is 0 */ | ||
57 | unsigned int ppc_pci_flags; | ||
56 | 58 | ||
57 | struct pci_controller *pcibios_alloc_controller(struct device_node *dev) | 59 | struct pci_controller *pcibios_alloc_controller(struct device_node *dev) |
58 | { | 60 | { |
@@ -821,3 +823,293 @@ void __devinit pcibios_fixup_of_probed_bus(struct pci_bus *bus) | |||
821 | { | 823 | { |
822 | __pcibios_fixup_bus(bus); | 824 | __pcibios_fixup_bus(bus); |
823 | } | 825 | } |
826 | |||
827 | static int skip_isa_ioresource_align(struct pci_dev *dev) | ||
828 | { | ||
829 | if ((ppc_pci_flags & PPC_PCI_CAN_SKIP_ISA_ALIGN) && | ||
830 | !(dev->bus->bridge_ctl & PCI_BRIDGE_CTL_ISA)) | ||
831 | return 1; | ||
832 | return 0; | ||
833 | } | ||
834 | |||
835 | /* | ||
836 | * We need to avoid collisions with `mirrored' VGA ports | ||
837 | * and other strange ISA hardware, so we always want the | ||
838 | * addresses to be allocated in the 0x000-0x0ff region | ||
839 | * modulo 0x400. | ||
840 | * | ||
841 | * Why? Because some silly external IO cards only decode | ||
842 | * the low 10 bits of the IO address. The 0x00-0xff region | ||
843 | * is reserved for motherboard devices that decode all 16 | ||
844 | * bits, so it's ok to allocate at, say, 0x2800-0x28ff, | ||
845 | * but we want to try to avoid allocating at 0x2900-0x2bff | ||
846 | * which might have be mirrored at 0x0100-0x03ff.. | ||
847 | */ | ||
848 | void pcibios_align_resource(void *data, struct resource *res, | ||
849 | resource_size_t size, resource_size_t align) | ||
850 | { | ||
851 | struct pci_dev *dev = data; | ||
852 | |||
853 | if (res->flags & IORESOURCE_IO) { | ||
854 | resource_size_t start = res->start; | ||
855 | |||
856 | if (skip_isa_ioresource_align(dev)) | ||
857 | return; | ||
858 | if (start & 0x300) { | ||
859 | start = (start + 0x3ff) & ~0x3ff; | ||
860 | res->start = start; | ||
861 | } | ||
862 | } | ||
863 | } | ||
864 | EXPORT_SYMBOL(pcibios_align_resource); | ||
865 | |||
866 | /* | ||
867 | * Reparent resource children of pr that conflict with res | ||
868 | * under res, and make res replace those children. | ||
869 | */ | ||
870 | static int __init reparent_resources(struct resource *parent, | ||
871 | struct resource *res) | ||
872 | { | ||
873 | struct resource *p, **pp; | ||
874 | struct resource **firstpp = NULL; | ||
875 | |||
876 | for (pp = &parent->child; (p = *pp) != NULL; pp = &p->sibling) { | ||
877 | if (p->end < res->start) | ||
878 | continue; | ||
879 | if (res->end < p->start) | ||
880 | break; | ||
881 | if (p->start < res->start || p->end > res->end) | ||
882 | return -1; /* not completely contained */ | ||
883 | if (firstpp == NULL) | ||
884 | firstpp = pp; | ||
885 | } | ||
886 | if (firstpp == NULL) | ||
887 | return -1; /* didn't find any conflicting entries? */ | ||
888 | res->parent = parent; | ||
889 | res->child = *firstpp; | ||
890 | res->sibling = *pp; | ||
891 | *firstpp = res; | ||
892 | *pp = NULL; | ||
893 | for (p = res->child; p != NULL; p = p->sibling) { | ||
894 | p->parent = res; | ||
895 | DBG(KERN_INFO "PCI: reparented %s [%llx..%llx] under %s\n", | ||
896 | p->name, | ||
897 | (unsigned long long)p->start, | ||
898 | (unsigned long long)p->end, res->name); | ||
899 | } | ||
900 | return 0; | ||
901 | } | ||
902 | |||
903 | /* | ||
904 | * Handle resources of PCI devices. If the world were perfect, we could | ||
905 | * just allocate all the resource regions and do nothing more. It isn't. | ||
906 | * On the other hand, we cannot just re-allocate all devices, as it would | ||
907 | * require us to know lots of host bridge internals. So we attempt to | ||
908 | * keep as much of the original configuration as possible, but tweak it | ||
909 | * when it's found to be wrong. | ||
910 | * | ||
911 | * Known BIOS problems we have to work around: | ||
912 | * - I/O or memory regions not configured | ||
913 | * - regions configured, but not enabled in the command register | ||
914 | * - bogus I/O addresses above 64K used | ||
915 | * - expansion ROMs left enabled (this may sound harmless, but given | ||
916 | * the fact the PCI specs explicitly allow address decoders to be | ||
917 | * shared between expansion ROMs and other resource regions, it's | ||
918 | * at least dangerous) | ||
919 | * | ||
920 | * Our solution: | ||
921 | * (1) Allocate resources for all buses behind PCI-to-PCI bridges. | ||
922 | * This gives us fixed barriers on where we can allocate. | ||
923 | * (2) Allocate resources for all enabled devices. If there is | ||
924 | * a collision, just mark the resource as unallocated. Also | ||
925 | * disable expansion ROMs during this step. | ||
926 | * (3) Try to allocate resources for disabled devices. If the | ||
927 | * resources were assigned correctly, everything goes well, | ||
928 | * if they weren't, they won't disturb allocation of other | ||
929 | * resources. | ||
930 | * (4) Assign new addresses to resources which were either | ||
931 | * not configured at all or misconfigured. If explicitly | ||
932 | * requested by the user, configure expansion ROM address | ||
933 | * as well. | ||
934 | */ | ||
935 | |||
936 | static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) | ||
937 | { | ||
938 | struct pci_bus *bus; | ||
939 | int i; | ||
940 | struct resource *res, *pr; | ||
941 | |||
942 | /* Depth-First Search on bus tree */ | ||
943 | list_for_each_entry(bus, bus_list, node) { | ||
944 | for (i = 0; i < PCI_BUS_NUM_RESOURCES; ++i) { | ||
945 | if ((res = bus->resource[i]) == NULL || !res->flags | ||
946 | || res->start > res->end) | ||
947 | continue; | ||
948 | if (bus->parent == NULL) | ||
949 | pr = (res->flags & IORESOURCE_IO)? | ||
950 | &ioport_resource : &iomem_resource; | ||
951 | else { | ||
952 | /* Don't bother with non-root busses when | ||
953 | * re-assigning all resources. We clear the | ||
954 | * resource flags as if they were colliding | ||
955 | * and as such ensure proper re-allocation | ||
956 | * later. | ||
957 | */ | ||
958 | if (ppc_pci_flags & PPC_PCI_REASSIGN_ALL_RSRC) | ||
959 | goto clear_resource; | ||
960 | pr = pci_find_parent_resource(bus->self, res); | ||
961 | if (pr == res) { | ||
962 | /* this happens when the generic PCI | ||
963 | * code (wrongly) decides that this | ||
964 | * bridge is transparent -- paulus | ||
965 | */ | ||
966 | continue; | ||
967 | } | ||
968 | } | ||
969 | |||
970 | DBG("PCI: %s (bus %d) bridge rsrc %d: %016llx-%016llx " | ||
971 | "[0x%x], parent %p (%s)\n", | ||
972 | bus->self ? pci_name(bus->self) : "PHB", | ||
973 | bus->number, i, | ||
974 | (unsigned long long)res->start, | ||
975 | (unsigned long long)res->end, | ||
976 | (unsigned int)res->flags, | ||
977 | pr, (pr && pr->name) ? pr->name : "nil"); | ||
978 | |||
979 | if (pr && !(pr->flags & IORESOURCE_UNSET)) { | ||
980 | if (request_resource(pr, res) == 0) | ||
981 | continue; | ||
982 | /* | ||
983 | * Must be a conflict with an existing entry. | ||
984 | * Move that entry (or entries) under the | ||
985 | * bridge resource and try again. | ||
986 | */ | ||
987 | if (reparent_resources(pr, res) == 0) | ||
988 | continue; | ||
989 | } | ||
990 | printk(KERN_WARNING | ||
991 | "PCI: Cannot allocate resource region " | ||
992 | "%d of PCI bridge %d, will remap\n", | ||
993 | i, bus->number); | ||
994 | clear_resource: | ||
995 | res->flags = 0; | ||
996 | } | ||
997 | pcibios_allocate_bus_resources(&bus->children); | ||
998 | } | ||
999 | } | ||
1000 | |||
1001 | static inline void __devinit alloc_resource(struct pci_dev *dev, int idx) | ||
1002 | { | ||
1003 | struct resource *pr, *r = &dev->resource[idx]; | ||
1004 | |||
1005 | DBG("PCI: Allocating %s: Resource %d: %016llx..%016llx [%x]\n", | ||
1006 | pci_name(dev), idx, | ||
1007 | (unsigned long long)r->start, | ||
1008 | (unsigned long long)r->end, | ||
1009 | (unsigned int)r->flags); | ||
1010 | |||
1011 | pr = pci_find_parent_resource(dev, r); | ||
1012 | if (!pr || (pr->flags & IORESOURCE_UNSET) || | ||
1013 | request_resource(pr, r) < 0) { | ||
1014 | printk(KERN_WARNING "PCI: Cannot allocate resource region %d" | ||
1015 | " of device %s, will remap\n", idx, pci_name(dev)); | ||
1016 | if (pr) | ||
1017 | DBG("PCI: parent is %p: %016llx-%016llx [%x]\n", pr, | ||
1018 | (unsigned long long)pr->start, | ||
1019 | (unsigned long long)pr->end, | ||
1020 | (unsigned int)pr->flags); | ||
1021 | /* We'll assign a new address later */ | ||
1022 | r->flags |= IORESOURCE_UNSET; | ||
1023 | r->end -= r->start; | ||
1024 | r->start = 0; | ||
1025 | } | ||
1026 | } | ||
1027 | |||
1028 | static void __init pcibios_allocate_resources(int pass) | ||
1029 | { | ||
1030 | struct pci_dev *dev = NULL; | ||
1031 | int idx, disabled; | ||
1032 | u16 command; | ||
1033 | struct resource *r; | ||
1034 | |||
1035 | for_each_pci_dev(dev) { | ||
1036 | pci_read_config_word(dev, PCI_COMMAND, &command); | ||
1037 | for (idx = 0; idx < 6; idx++) { | ||
1038 | r = &dev->resource[idx]; | ||
1039 | if (r->parent) /* Already allocated */ | ||
1040 | continue; | ||
1041 | if (!r->flags || (r->flags & IORESOURCE_UNSET)) | ||
1042 | continue; /* Not assigned at all */ | ||
1043 | if (r->flags & IORESOURCE_IO) | ||
1044 | disabled = !(command & PCI_COMMAND_IO); | ||
1045 | else | ||
1046 | disabled = !(command & PCI_COMMAND_MEMORY); | ||
1047 | if (pass == disabled) | ||
1048 | alloc_resource(dev, idx); | ||
1049 | } | ||
1050 | if (pass) | ||
1051 | continue; | ||
1052 | r = &dev->resource[PCI_ROM_RESOURCE]; | ||
1053 | if (r->flags & IORESOURCE_ROM_ENABLE) { | ||
1054 | /* Turn the ROM off, leave the resource region, | ||
1055 | * but keep it unregistered. | ||
1056 | */ | ||
1057 | u32 reg; | ||
1058 | DBG("PCI: Switching off ROM of %s\n", pci_name(dev)); | ||
1059 | r->flags &= ~IORESOURCE_ROM_ENABLE; | ||
1060 | pci_read_config_dword(dev, dev->rom_base_reg, ®); | ||
1061 | pci_write_config_dword(dev, dev->rom_base_reg, | ||
1062 | reg & ~PCI_ROM_ADDRESS_ENABLE); | ||
1063 | } | ||
1064 | } | ||
1065 | } | ||
1066 | |||
1067 | void __init pcibios_resource_survey(void) | ||
1068 | { | ||
1069 | /* Allocate and assign resources. If we re-assign everything, then | ||
1070 | * we skip the allocate phase | ||
1071 | */ | ||
1072 | pcibios_allocate_bus_resources(&pci_root_buses); | ||
1073 | |||
1074 | if (!(ppc_pci_flags & PPC_PCI_REASSIGN_ALL_RSRC)) { | ||
1075 | pcibios_allocate_resources(0); | ||
1076 | pcibios_allocate_resources(1); | ||
1077 | } | ||
1078 | |||
1079 | if (!(ppc_pci_flags & PPC_PCI_PROBE_ONLY)) { | ||
1080 | DBG("PCI: Assigning unassigned resouces...\n"); | ||
1081 | pci_assign_unassigned_resources(); | ||
1082 | } | ||
1083 | |||
1084 | /* Call machine dependent fixup */ | ||
1085 | if (ppc_md.pcibios_fixup) | ||
1086 | ppc_md.pcibios_fixup(); | ||
1087 | } | ||
1088 | |||
1089 | #ifdef CONFIG_HOTPLUG | ||
1090 | /* This is used by the pSeries hotplug driver to allocate resource | ||
1091 | * of newly plugged busses. We can try to consolidate with the | ||
1092 | * rest of the code later, for now, keep it as-is | ||
1093 | */ | ||
1094 | void __devinit pcibios_claim_one_bus(struct pci_bus *bus) | ||
1095 | { | ||
1096 | struct pci_dev *dev; | ||
1097 | struct pci_bus *child_bus; | ||
1098 | |||
1099 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
1100 | int i; | ||
1101 | |||
1102 | for (i = 0; i < PCI_NUM_RESOURCES; i++) { | ||
1103 | struct resource *r = &dev->resource[i]; | ||
1104 | |||
1105 | if (r->parent || !r->start || !r->flags) | ||
1106 | continue; | ||
1107 | pci_claim_resource(dev, i); | ||
1108 | } | ||
1109 | } | ||
1110 | |||
1111 | list_for_each_entry(child_bus, &bus->children, node) | ||
1112 | pcibios_claim_one_bus(child_bus); | ||
1113 | } | ||
1114 | EXPORT_SYMBOL_GPL(pcibios_claim_one_bus); | ||
1115 | #endif /* CONFIG_HOTPLUG */ | ||