diff options
Diffstat (limited to 'arch/sparc64/kernel/pci_psycho.c')
-rw-r--r-- | arch/sparc64/kernel/pci_psycho.c | 154 |
1 files changed, 18 insertions, 136 deletions
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index fda5db223d96..253d40ec2245 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c | |||
@@ -1,7 +1,6 @@ | |||
1 | /* $Id: pci_psycho.c,v 1.33 2002/02/01 00:58:33 davem Exp $ | 1 | /* pci_psycho.c: PSYCHO/U2P specific PCI controller support. |
2 | * pci_psycho.c: PSYCHO/U2P specific PCI controller support. | ||
3 | * | 2 | * |
4 | * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu) | 3 | * Copyright (C) 1997, 1998, 1999, 2007 David S. Miller (davem@davemloft.net) |
5 | * Copyright (C) 1998, 1999 Eddie C. Dost (ecd@skynet.be) | 4 | * Copyright (C) 1998, 1999 Eddie C. Dost (ecd@skynet.be) |
6 | * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com) | 5 | * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com) |
7 | */ | 6 | */ |
@@ -119,6 +118,10 @@ static int psycho_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, | |||
119 | u16 tmp16; | 118 | u16 tmp16; |
120 | u8 tmp8; | 119 | u8 tmp8; |
121 | 120 | ||
121 | if (bus_dev == pbm->pci_bus && devfn == 0x00) | ||
122 | return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where, | ||
123 | size, value); | ||
124 | |||
122 | switch (size) { | 125 | switch (size) { |
123 | case 1: | 126 | case 1: |
124 | *value = 0xff; | 127 | *value = 0xff; |
@@ -172,6 +175,9 @@ static int psycho_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, | |||
172 | unsigned char bus = bus_dev->number; | 175 | unsigned char bus = bus_dev->number; |
173 | u32 *addr; | 176 | u32 *addr; |
174 | 177 | ||
178 | if (bus_dev == pbm->pci_bus && devfn == 0x00) | ||
179 | return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where, | ||
180 | size, value); | ||
175 | addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where); | 181 | addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where); |
176 | if (!addr) | 182 | if (!addr) |
177 | return PCIBIOS_SUCCESSFUL; | 183 | return PCIBIOS_SUCCESSFUL; |
@@ -263,7 +269,7 @@ static void __psycho_check_one_stc(struct pci_controller_info *p, | |||
263 | struct pci_pbm_info *pbm, | 269 | struct pci_pbm_info *pbm, |
264 | int is_pbm_a) | 270 | int is_pbm_a) |
265 | { | 271 | { |
266 | struct pci_strbuf *strbuf = &pbm->stc; | 272 | struct strbuf *strbuf = &pbm->stc; |
267 | unsigned long regbase = p->pbm_A.controller_regs; | 273 | unsigned long regbase = p->pbm_A.controller_regs; |
268 | unsigned long err_base, tag_base, line_base; | 274 | unsigned long err_base, tag_base, line_base; |
269 | u64 control; | 275 | u64 control; |
@@ -412,7 +418,7 @@ static void psycho_check_iommu_error(struct pci_controller_info *p, | |||
412 | unsigned long afar, | 418 | unsigned long afar, |
413 | enum psycho_error_type type) | 419 | enum psycho_error_type type) |
414 | { | 420 | { |
415 | struct pci_iommu *iommu = p->pbm_A.iommu; | 421 | struct iommu *iommu = p->pbm_A.iommu; |
416 | unsigned long iommu_tag[16]; | 422 | unsigned long iommu_tag[16]; |
417 | unsigned long iommu_data[16]; | 423 | unsigned long iommu_data[16]; |
418 | unsigned long flags; | 424 | unsigned long flags; |
@@ -895,59 +901,6 @@ static void psycho_register_error_handlers(struct pci_controller_info *p) | |||
895 | } | 901 | } |
896 | 902 | ||
897 | /* PSYCHO boot time probing and initialization. */ | 903 | /* PSYCHO boot time probing and initialization. */ |
898 | static void psycho_resource_adjust(struct pci_dev *pdev, | ||
899 | struct resource *res, | ||
900 | struct resource *root) | ||
901 | { | ||
902 | res->start += root->start; | ||
903 | res->end += root->start; | ||
904 | } | ||
905 | |||
906 | static void psycho_base_address_update(struct pci_dev *pdev, int resource) | ||
907 | { | ||
908 | struct pcidev_cookie *pcp = pdev->sysdata; | ||
909 | struct pci_pbm_info *pbm = pcp->pbm; | ||
910 | struct resource *res, *root; | ||
911 | u32 reg; | ||
912 | int where, size, is_64bit; | ||
913 | |||
914 | res = &pdev->resource[resource]; | ||
915 | if (resource < 6) { | ||
916 | where = PCI_BASE_ADDRESS_0 + (resource * 4); | ||
917 | } else if (resource == PCI_ROM_RESOURCE) { | ||
918 | where = pdev->rom_base_reg; | ||
919 | } else { | ||
920 | /* Somebody might have asked allocation of a non-standard resource */ | ||
921 | return; | ||
922 | } | ||
923 | |||
924 | is_64bit = 0; | ||
925 | if (res->flags & IORESOURCE_IO) | ||
926 | root = &pbm->io_space; | ||
927 | else { | ||
928 | root = &pbm->mem_space; | ||
929 | if ((res->flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) | ||
930 | == PCI_BASE_ADDRESS_MEM_TYPE_64) | ||
931 | is_64bit = 1; | ||
932 | } | ||
933 | |||
934 | size = res->end - res->start; | ||
935 | pci_read_config_dword(pdev, where, ®); | ||
936 | reg = ((reg & size) | | ||
937 | (((u32)(res->start - root->start)) & ~size)); | ||
938 | if (resource == PCI_ROM_RESOURCE) { | ||
939 | reg |= PCI_ROM_ADDRESS_ENABLE; | ||
940 | res->flags |= IORESOURCE_ROM_ENABLE; | ||
941 | } | ||
942 | pci_write_config_dword(pdev, where, reg); | ||
943 | |||
944 | /* This knows that the upper 32-bits of the address | ||
945 | * must be zero. Our PCI common layer enforces this. | ||
946 | */ | ||
947 | if (is_64bit) | ||
948 | pci_write_config_dword(pdev, where + 4, 0); | ||
949 | } | ||
950 | |||
951 | static void pbm_config_busmastering(struct pci_pbm_info *pbm) | 904 | static void pbm_config_busmastering(struct pci_pbm_info *pbm) |
952 | { | 905 | { |
953 | u8 *addr; | 906 | u8 *addr; |
@@ -968,28 +921,7 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm) | |||
968 | static void pbm_scan_bus(struct pci_controller_info *p, | 921 | static void pbm_scan_bus(struct pci_controller_info *p, |
969 | struct pci_pbm_info *pbm) | 922 | struct pci_pbm_info *pbm) |
970 | { | 923 | { |
971 | struct pcidev_cookie *cookie = kzalloc(sizeof(*cookie), GFP_KERNEL); | 924 | pbm->pci_bus = pci_scan_one_pbm(pbm); |
972 | |||
973 | if (!cookie) { | ||
974 | prom_printf("PSYCHO: Critical allocation failure.\n"); | ||
975 | prom_halt(); | ||
976 | } | ||
977 | |||
978 | /* All we care about is the PBM. */ | ||
979 | cookie->pbm = pbm; | ||
980 | |||
981 | pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno, | ||
982 | p->pci_ops, | ||
983 | pbm); | ||
984 | pci_fixup_host_bridge_self(pbm->pci_bus); | ||
985 | pbm->pci_bus->self->sysdata = cookie; | ||
986 | |||
987 | pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node); | ||
988 | pci_record_assignments(pbm, pbm->pci_bus); | ||
989 | pci_assign_unassigned(pbm, pbm->pci_bus); | ||
990 | pci_fixup_irq(pbm, pbm->pci_bus); | ||
991 | pci_determine_66mhz_disposition(pbm, pbm->pci_bus); | ||
992 | pci_setup_busmastering(pbm, pbm->pci_bus); | ||
993 | } | 925 | } |
994 | 926 | ||
995 | static void psycho_scan_bus(struct pci_controller_info *p) | 927 | static void psycho_scan_bus(struct pci_controller_info *p) |
@@ -1009,7 +941,7 @@ static void psycho_scan_bus(struct pci_controller_info *p) | |||
1009 | 941 | ||
1010 | static void psycho_iommu_init(struct pci_controller_info *p) | 942 | static void psycho_iommu_init(struct pci_controller_info *p) |
1011 | { | 943 | { |
1012 | struct pci_iommu *iommu = p->pbm_A.iommu; | 944 | struct iommu *iommu = p->pbm_A.iommu; |
1013 | unsigned long i; | 945 | unsigned long i; |
1014 | u64 control; | 946 | u64 control; |
1015 | 947 | ||
@@ -1094,19 +1026,6 @@ static void psycho_controller_hwinit(struct pci_controller_info *p) | |||
1094 | psycho_write(p->pbm_A.controller_regs + PSYCHO_PCIB_DIAG, tmp); | 1026 | psycho_write(p->pbm_A.controller_regs + PSYCHO_PCIB_DIAG, tmp); |
1095 | } | 1027 | } |
1096 | 1028 | ||
1097 | static void pbm_register_toplevel_resources(struct pci_controller_info *p, | ||
1098 | struct pci_pbm_info *pbm) | ||
1099 | { | ||
1100 | char *name = pbm->name; | ||
1101 | |||
1102 | pbm->io_space.name = pbm->mem_space.name = name; | ||
1103 | |||
1104 | request_resource(&ioport_resource, &pbm->io_space); | ||
1105 | request_resource(&iomem_resource, &pbm->mem_space); | ||
1106 | pci_register_legacy_regions(&pbm->io_space, | ||
1107 | &pbm->mem_space); | ||
1108 | } | ||
1109 | |||
1110 | static void psycho_pbm_strbuf_init(struct pci_controller_info *p, | 1029 | static void psycho_pbm_strbuf_init(struct pci_controller_info *p, |
1111 | struct pci_pbm_info *pbm, | 1030 | struct pci_pbm_info *pbm, |
1112 | int is_pbm_a) | 1031 | int is_pbm_a) |
@@ -1172,19 +1091,11 @@ static void psycho_pbm_init(struct pci_controller_info *p, | |||
1172 | unsigned int *busrange; | 1091 | unsigned int *busrange; |
1173 | struct property *prop; | 1092 | struct property *prop; |
1174 | struct pci_pbm_info *pbm; | 1093 | struct pci_pbm_info *pbm; |
1175 | int len; | ||
1176 | 1094 | ||
1177 | if (is_pbm_a) { | 1095 | if (is_pbm_a) |
1178 | pbm = &p->pbm_A; | 1096 | pbm = &p->pbm_A; |
1179 | pbm->pci_first_slot = 1; | 1097 | else |
1180 | pbm->io_space.start = pbm->controller_regs + PSYCHO_IOSPACE_A; | ||
1181 | pbm->mem_space.start = pbm->controller_regs + PSYCHO_MEMSPACE_A; | ||
1182 | } else { | ||
1183 | pbm = &p->pbm_B; | 1098 | pbm = &p->pbm_B; |
1184 | pbm->pci_first_slot = 2; | ||
1185 | pbm->io_space.start = pbm->controller_regs + PSYCHO_IOSPACE_B; | ||
1186 | pbm->mem_space.start = pbm->controller_regs + PSYCHO_MEMSPACE_B; | ||
1187 | } | ||
1188 | 1099 | ||
1189 | pbm->chip_type = PBM_CHIP_TYPE_PSYCHO; | 1100 | pbm->chip_type = PBM_CHIP_TYPE_PSYCHO; |
1190 | pbm->chip_version = 0; | 1101 | pbm->chip_version = 0; |
@@ -1196,41 +1107,15 @@ static void psycho_pbm_init(struct pci_controller_info *p, | |||
1196 | if (prop) | 1107 | if (prop) |
1197 | pbm->chip_revision = *(int *) prop->value; | 1108 | pbm->chip_revision = *(int *) prop->value; |
1198 | 1109 | ||
1199 | pbm->io_space.end = pbm->io_space.start + PSYCHO_IOSPACE_SIZE; | ||
1200 | pbm->io_space.flags = IORESOURCE_IO; | ||
1201 | pbm->mem_space.end = pbm->mem_space.start + PSYCHO_MEMSPACE_SIZE; | ||
1202 | pbm->mem_space.flags = IORESOURCE_MEM; | ||
1203 | |||
1204 | pbm->parent = p; | 1110 | pbm->parent = p; |
1205 | pbm->prom_node = dp; | 1111 | pbm->prom_node = dp; |
1206 | pbm->name = dp->full_name; | 1112 | pbm->name = dp->full_name; |
1207 | 1113 | ||
1208 | pbm_register_toplevel_resources(p, pbm); | ||
1209 | |||
1210 | printk("%s: PSYCHO PCI Bus Module ver[%x:%x]\n", | 1114 | printk("%s: PSYCHO PCI Bus Module ver[%x:%x]\n", |
1211 | pbm->name, | 1115 | pbm->name, |
1212 | pbm->chip_version, pbm->chip_revision); | 1116 | pbm->chip_version, pbm->chip_revision); |
1213 | 1117 | ||
1214 | prop = of_find_property(dp, "ranges", &len); | 1118 | pci_determine_mem_io_space(pbm); |
1215 | if (prop) { | ||
1216 | pbm->pbm_ranges = prop->value; | ||
1217 | pbm->num_pbm_ranges = | ||
1218 | (len / sizeof(struct linux_prom_pci_ranges)); | ||
1219 | } else { | ||
1220 | pbm->num_pbm_ranges = 0; | ||
1221 | } | ||
1222 | |||
1223 | prop = of_find_property(dp, "interrupt-map", &len); | ||
1224 | if (prop) { | ||
1225 | pbm->pbm_intmap = prop->value; | ||
1226 | pbm->num_pbm_intmap = | ||
1227 | (len / sizeof(struct linux_prom_pci_intmap)); | ||
1228 | |||
1229 | prop = of_find_property(dp, "interrupt-map-mask", NULL); | ||
1230 | pbm->pbm_intmask = prop->value; | ||
1231 | } else { | ||
1232 | pbm->num_pbm_intmap = 0; | ||
1233 | } | ||
1234 | 1119 | ||
1235 | prop = of_find_property(dp, "bus-range", NULL); | 1120 | prop = of_find_property(dp, "bus-range", NULL); |
1236 | busrange = prop->value; | 1121 | busrange = prop->value; |
@@ -1246,7 +1131,7 @@ void psycho_init(struct device_node *dp, char *model_name) | |||
1246 | { | 1131 | { |
1247 | struct linux_prom64_registers *pr_regs; | 1132 | struct linux_prom64_registers *pr_regs; |
1248 | struct pci_controller_info *p; | 1133 | struct pci_controller_info *p; |
1249 | struct pci_iommu *iommu; | 1134 | struct iommu *iommu; |
1250 | struct property *prop; | 1135 | struct property *prop; |
1251 | u32 upa_portid; | 1136 | u32 upa_portid; |
1252 | int is_pbm_a; | 1137 | int is_pbm_a; |
@@ -1269,7 +1154,7 @@ void psycho_init(struct device_node *dp, char *model_name) | |||
1269 | prom_printf("PSYCHO: Fatal memory allocation error.\n"); | 1154 | prom_printf("PSYCHO: Fatal memory allocation error.\n"); |
1270 | prom_halt(); | 1155 | prom_halt(); |
1271 | } | 1156 | } |
1272 | iommu = kzalloc(sizeof(struct pci_iommu), GFP_ATOMIC); | 1157 | iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); |
1273 | if (!iommu) { | 1158 | if (!iommu) { |
1274 | prom_printf("PSYCHO: Fatal memory allocation error.\n"); | 1159 | prom_printf("PSYCHO: Fatal memory allocation error.\n"); |
1275 | prom_halt(); | 1160 | prom_halt(); |
@@ -1282,10 +1167,7 @@ void psycho_init(struct device_node *dp, char *model_name) | |||
1282 | p->pbm_A.portid = upa_portid; | 1167 | p->pbm_A.portid = upa_portid; |
1283 | p->pbm_B.portid = upa_portid; | 1168 | p->pbm_B.portid = upa_portid; |
1284 | p->index = pci_num_controllers++; | 1169 | p->index = pci_num_controllers++; |
1285 | p->pbms_same_domain = 0; | ||
1286 | p->scan_bus = psycho_scan_bus; | 1170 | p->scan_bus = psycho_scan_bus; |
1287 | p->base_address_update = psycho_base_address_update; | ||
1288 | p->resource_adjust = psycho_resource_adjust; | ||
1289 | p->pci_ops = &psycho_ops; | 1171 | p->pci_ops = &psycho_ops; |
1290 | 1172 | ||
1291 | prop = of_find_property(dp, "reg", NULL); | 1173 | prop = of_find_property(dp, "reg", NULL); |