diff options
Diffstat (limited to 'arch/ppc64/kernel/pci.c')
| -rw-r--r-- | arch/ppc64/kernel/pci.c | 480 |
1 files changed, 393 insertions, 87 deletions
diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c index d0d55c7908ef..861138ad092c 100644 --- a/arch/ppc64/kernel/pci.c +++ b/arch/ppc64/kernel/pci.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/bootmem.h> | 21 | #include <linux/bootmem.h> |
| 22 | #include <linux/mm.h> | 22 | #include <linux/mm.h> |
| 23 | #include <linux/list.h> | 23 | #include <linux/list.h> |
| 24 | #include <linux/syscalls.h> | ||
| 24 | 25 | ||
| 25 | #include <asm/processor.h> | 26 | #include <asm/processor.h> |
| 26 | #include <asm/io.h> | 27 | #include <asm/io.h> |
| @@ -50,6 +51,10 @@ unsigned long io_page_mask; | |||
| 50 | 51 | ||
| 51 | EXPORT_SYMBOL(io_page_mask); | 52 | EXPORT_SYMBOL(io_page_mask); |
| 52 | 53 | ||
| 54 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
| 55 | static void fixup_resource(struct resource *res, struct pci_dev *dev); | ||
| 56 | static void do_bus_setup(struct pci_bus *bus); | ||
| 57 | #endif | ||
| 53 | 58 | ||
| 54 | unsigned int pcibios_assign_all_busses(void) | 59 | unsigned int pcibios_assign_all_busses(void) |
| 55 | { | 60 | { |
| @@ -84,7 +89,6 @@ static void fixup_broken_pcnet32(struct pci_dev* dev) | |||
| 84 | if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) { | 89 | if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) { |
| 85 | dev->vendor = PCI_VENDOR_ID_AMD; | 90 | dev->vendor = PCI_VENDOR_ID_AMD; |
| 86 | pci_write_config_word(dev, PCI_VENDOR_ID, PCI_VENDOR_ID_AMD); | 91 | pci_write_config_word(dev, PCI_VENDOR_ID, PCI_VENDOR_ID_AMD); |
| 87 | pci_name_device(dev); | ||
| 88 | } | 92 | } |
| 89 | } | 93 | } |
| 90 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32); | 94 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32); |
| @@ -225,10 +229,287 @@ static void __init pcibios_claim_of_setup(void) | |||
| 225 | } | 229 | } |
| 226 | #endif | 230 | #endif |
| 227 | 231 | ||
| 232 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
| 233 | static u32 get_int_prop(struct device_node *np, const char *name, u32 def) | ||
| 234 | { | ||
| 235 | u32 *prop; | ||
| 236 | int len; | ||
| 237 | |||
| 238 | prop = (u32 *) get_property(np, name, &len); | ||
| 239 | if (prop && len >= 4) | ||
| 240 | return *prop; | ||
| 241 | return def; | ||
| 242 | } | ||
| 243 | |||
| 244 | static unsigned int pci_parse_of_flags(u32 addr0) | ||
| 245 | { | ||
| 246 | unsigned int flags = 0; | ||
| 247 | |||
| 248 | if (addr0 & 0x02000000) { | ||
| 249 | flags |= IORESOURCE_MEM; | ||
| 250 | if (addr0 & 0x40000000) | ||
| 251 | flags |= IORESOURCE_PREFETCH; | ||
| 252 | } else if (addr0 & 0x01000000) | ||
| 253 | flags |= IORESOURCE_IO; | ||
| 254 | return flags; | ||
| 255 | } | ||
| 256 | |||
| 257 | #define GET_64BIT(prop, i) ((((u64) (prop)[(i)]) << 32) | (prop)[(i)+1]) | ||
| 258 | |||
| 259 | static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev) | ||
| 260 | { | ||
| 261 | u64 base, size; | ||
| 262 | unsigned int flags; | ||
| 263 | struct resource *res; | ||
| 264 | u32 *addrs, i; | ||
| 265 | int proplen; | ||
| 266 | |||
| 267 | addrs = (u32 *) get_property(node, "assigned-addresses", &proplen); | ||
| 268 | if (!addrs) | ||
| 269 | return; | ||
| 270 | for (; proplen >= 20; proplen -= 20, addrs += 5) { | ||
| 271 | flags = pci_parse_of_flags(addrs[0]); | ||
| 272 | if (!flags) | ||
| 273 | continue; | ||
| 274 | base = GET_64BIT(addrs, 1); | ||
| 275 | size = GET_64BIT(addrs, 3); | ||
| 276 | if (!size) | ||
| 277 | continue; | ||
| 278 | i = addrs[0] & 0xff; | ||
| 279 | if (PCI_BASE_ADDRESS_0 <= i && i <= PCI_BASE_ADDRESS_5) { | ||
| 280 | res = &dev->resource[(i - PCI_BASE_ADDRESS_0) >> 2]; | ||
| 281 | } else if (i == dev->rom_base_reg) { | ||
| 282 | res = &dev->resource[PCI_ROM_RESOURCE]; | ||
| 283 | flags |= IORESOURCE_READONLY | IORESOURCE_CACHEABLE; | ||
| 284 | } else { | ||
| 285 | printk(KERN_ERR "PCI: bad cfg reg num 0x%x\n", i); | ||
| 286 | continue; | ||
| 287 | } | ||
| 288 | res->start = base; | ||
| 289 | res->end = base + size - 1; | ||
| 290 | res->flags = flags; | ||
| 291 | res->name = pci_name(dev); | ||
| 292 | fixup_resource(res, dev); | ||
| 293 | } | ||
| 294 | } | ||
| 295 | |||
| 296 | static struct pci_dev *of_create_pci_dev(struct device_node *node, | ||
| 297 | struct pci_bus *bus, int devfn) | ||
| 298 | { | ||
| 299 | struct pci_dev *dev; | ||
| 300 | const char *type; | ||
| 301 | |||
| 302 | dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL); | ||
| 303 | if (!dev) | ||
| 304 | return NULL; | ||
| 305 | type = get_property(node, "device_type", NULL); | ||
| 306 | if (type == NULL) | ||
| 307 | type = ""; | ||
| 308 | |||
| 309 | memset(dev, 0, sizeof(struct pci_dev)); | ||
| 310 | dev->bus = bus; | ||
| 311 | dev->sysdata = node; | ||
| 312 | dev->dev.parent = bus->bridge; | ||
| 313 | dev->dev.bus = &pci_bus_type; | ||
| 314 | dev->devfn = devfn; | ||
| 315 | dev->multifunction = 0; /* maybe a lie? */ | ||
| 316 | |||
| 317 | dev->vendor = get_int_prop(node, "vendor-id", 0xffff); | ||
| 318 | dev->device = get_int_prop(node, "device-id", 0xffff); | ||
| 319 | dev->subsystem_vendor = get_int_prop(node, "subsystem-vendor-id", 0); | ||
| 320 | dev->subsystem_device = get_int_prop(node, "subsystem-id", 0); | ||
| 321 | |||
| 322 | dev->cfg_size = 256; /*pci_cfg_space_size(dev);*/ | ||
| 323 | |||
| 324 | sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus), | ||
| 325 | dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn)); | ||
| 326 | dev->class = get_int_prop(node, "class-code", 0); | ||
| 327 | |||
| 328 | dev->current_state = 4; /* unknown power state */ | ||
| 329 | |||
| 330 | if (!strcmp(type, "pci")) { | ||
| 331 | /* a PCI-PCI bridge */ | ||
| 332 | dev->hdr_type = PCI_HEADER_TYPE_BRIDGE; | ||
| 333 | dev->rom_base_reg = PCI_ROM_ADDRESS1; | ||
| 334 | } else if (!strcmp(type, "cardbus")) { | ||
| 335 | dev->hdr_type = PCI_HEADER_TYPE_CARDBUS; | ||
| 336 | } else { | ||
| 337 | dev->hdr_type = PCI_HEADER_TYPE_NORMAL; | ||
| 338 | dev->rom_base_reg = PCI_ROM_ADDRESS; | ||
| 339 | dev->irq = NO_IRQ; | ||
| 340 | if (node->n_intrs > 0) { | ||
| 341 | dev->irq = node->intrs[0].line; | ||
| 342 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, | ||
| 343 | dev->irq); | ||
| 344 | } | ||
| 345 | } | ||
| 346 | |||
| 347 | pci_parse_of_addrs(node, dev); | ||
| 348 | |||
| 349 | pci_device_add(dev, bus); | ||
| 350 | |||
| 351 | /* XXX pci_scan_msi_device(dev); */ | ||
| 352 | |||
| 353 | return dev; | ||
| 354 | } | ||
| 355 | |||
| 356 | static void of_scan_pci_bridge(struct device_node *node, struct pci_dev *dev); | ||
| 357 | |||
| 358 | static void __devinit of_scan_bus(struct device_node *node, | ||
| 359 | struct pci_bus *bus) | ||
| 360 | { | ||
| 361 | struct device_node *child = NULL; | ||
| 362 | u32 *reg; | ||
| 363 | int reglen, devfn; | ||
| 364 | struct pci_dev *dev; | ||
| 365 | |||
| 366 | while ((child = of_get_next_child(node, child)) != NULL) { | ||
| 367 | reg = (u32 *) get_property(child, "reg", ®len); | ||
| 368 | if (reg == NULL || reglen < 20) | ||
| 369 | continue; | ||
| 370 | devfn = (reg[0] >> 8) & 0xff; | ||
| 371 | /* create a new pci_dev for this device */ | ||
| 372 | dev = of_create_pci_dev(child, bus, devfn); | ||
| 373 | if (!dev) | ||
| 374 | continue; | ||
| 375 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || | ||
| 376 | dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) | ||
| 377 | of_scan_pci_bridge(child, dev); | ||
| 378 | } | ||
| 379 | |||
| 380 | do_bus_setup(bus); | ||
| 381 | } | ||
| 382 | |||
| 383 | static void __devinit of_scan_pci_bridge(struct device_node *node, | ||
| 384 | struct pci_dev *dev) | ||
| 385 | { | ||
| 386 | struct pci_bus *bus; | ||
| 387 | u32 *busrange, *ranges; | ||
| 388 | int len, i, mode; | ||
| 389 | struct resource *res; | ||
| 390 | unsigned int flags; | ||
| 391 | u64 size; | ||
| 392 | |||
| 393 | /* parse bus-range property */ | ||
| 394 | busrange = (u32 *) get_property(node, "bus-range", &len); | ||
| 395 | if (busrange == NULL || len != 8) { | ||
| 396 | printk(KERN_ERR "Can't get bus-range for PCI-PCI bridge %s\n", | ||
| 397 | node->full_name); | ||
| 398 | return; | ||
| 399 | } | ||
| 400 | ranges = (u32 *) get_property(node, "ranges", &len); | ||
| 401 | if (ranges == NULL) { | ||
| 402 | printk(KERN_ERR "Can't get ranges for PCI-PCI bridge %s\n", | ||
| 403 | node->full_name); | ||
| 404 | return; | ||
| 405 | } | ||
| 406 | |||
| 407 | bus = pci_add_new_bus(dev->bus, dev, busrange[0]); | ||
| 408 | if (!bus) { | ||
| 409 | printk(KERN_ERR "Failed to create pci bus for %s\n", | ||
| 410 | node->full_name); | ||
| 411 | return; | ||
| 412 | } | ||
| 413 | |||
| 414 | bus->primary = dev->bus->number; | ||
| 415 | bus->subordinate = busrange[1]; | ||
| 416 | bus->bridge_ctl = 0; | ||
| 417 | bus->sysdata = node; | ||
| 418 | |||
| 419 | /* parse ranges property */ | ||
| 420 | /* PCI #address-cells == 3 and #size-cells == 2 always */ | ||
| 421 | res = &dev->resource[PCI_BRIDGE_RESOURCES]; | ||
| 422 | for (i = 0; i < PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES; ++i) { | ||
| 423 | res->flags = 0; | ||
| 424 | bus->resource[i] = res; | ||
| 425 | ++res; | ||
| 426 | } | ||
| 427 | i = 1; | ||
| 428 | for (; len >= 32; len -= 32, ranges += 8) { | ||
| 429 | flags = pci_parse_of_flags(ranges[0]); | ||
| 430 | size = GET_64BIT(ranges, 6); | ||
| 431 | if (flags == 0 || size == 0) | ||
| 432 | continue; | ||
| 433 | if (flags & IORESOURCE_IO) { | ||
| 434 | res = bus->resource[0]; | ||
| 435 | if (res->flags) { | ||
| 436 | printk(KERN_ERR "PCI: ignoring extra I/O range" | ||
| 437 | " for bridge %s\n", node->full_name); | ||
| 438 | continue; | ||
| 439 | } | ||
| 440 | } else { | ||
| 441 | if (i >= PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES) { | ||
| 442 | printk(KERN_ERR "PCI: too many memory ranges" | ||
| 443 | " for bridge %s\n", node->full_name); | ||
| 444 | continue; | ||
| 445 | } | ||
| 446 | res = bus->resource[i]; | ||
| 447 | ++i; | ||
| 448 | } | ||
| 449 | res->start = GET_64BIT(ranges, 1); | ||
| 450 | res->end = res->start + size - 1; | ||
| 451 | res->flags = flags; | ||
| 452 | fixup_resource(res, dev); | ||
| 453 | } | ||
| 454 | sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus), | ||
| 455 | bus->number); | ||
| 456 | |||
| 457 | mode = PCI_PROBE_NORMAL; | ||
| 458 | if (ppc_md.pci_probe_mode) | ||
| 459 | mode = ppc_md.pci_probe_mode(bus); | ||
| 460 | if (mode == PCI_PROBE_DEVTREE) | ||
| 461 | of_scan_bus(node, bus); | ||
| 462 | else if (mode == PCI_PROBE_NORMAL) | ||
| 463 | pci_scan_child_bus(bus); | ||
| 464 | } | ||
| 465 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | ||
| 466 | |||
| 467 | static void __devinit scan_phb(struct pci_controller *hose) | ||
| 468 | { | ||
| 469 | struct pci_bus *bus; | ||
| 470 | struct device_node *node = hose->arch_data; | ||
| 471 | int i, mode; | ||
| 472 | struct resource *res; | ||
| 473 | |||
| 474 | bus = pci_create_bus(NULL, hose->first_busno, hose->ops, node); | ||
| 475 | if (bus == NULL) { | ||
| 476 | printk(KERN_ERR "Failed to create bus for PCI domain %04x\n", | ||
| 477 | hose->global_number); | ||
| 478 | return; | ||
| 479 | } | ||
| 480 | bus->secondary = hose->first_busno; | ||
| 481 | hose->bus = bus; | ||
| 482 | |||
| 483 | bus->resource[0] = res = &hose->io_resource; | ||
| 484 | if (res->flags && request_resource(&ioport_resource, res)) | ||
| 485 | printk(KERN_ERR "Failed to request PCI IO region " | ||
| 486 | "on PCI domain %04x\n", hose->global_number); | ||
| 487 | |||
| 488 | for (i = 0; i < 3; ++i) { | ||
| 489 | res = &hose->mem_resources[i]; | ||
| 490 | bus->resource[i+1] = res; | ||
| 491 | if (res->flags && request_resource(&iomem_resource, res)) | ||
| 492 | printk(KERN_ERR "Failed to request PCI memory region " | ||
| 493 | "on PCI domain %04x\n", hose->global_number); | ||
| 494 | } | ||
| 495 | |||
| 496 | mode = PCI_PROBE_NORMAL; | ||
| 497 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
| 498 | if (ppc_md.pci_probe_mode) | ||
| 499 | mode = ppc_md.pci_probe_mode(bus); | ||
| 500 | if (mode == PCI_PROBE_DEVTREE) { | ||
| 501 | bus->subordinate = hose->last_busno; | ||
| 502 | of_scan_bus(node, bus); | ||
| 503 | } | ||
| 504 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | ||
| 505 | if (mode == PCI_PROBE_NORMAL) | ||
| 506 | hose->last_busno = bus->subordinate = pci_scan_child_bus(bus); | ||
| 507 | pci_bus_add_devices(bus); | ||
| 508 | } | ||
| 509 | |||
| 228 | static int __init pcibios_init(void) | 510 | static int __init pcibios_init(void) |
| 229 | { | 511 | { |
| 230 | struct pci_controller *hose, *tmp; | 512 | struct pci_controller *hose, *tmp; |
| 231 | struct pci_bus *bus; | ||
| 232 | 513 | ||
| 233 | /* For now, override phys_mem_access_prot. If we need it, | 514 | /* For now, override phys_mem_access_prot. If we need it, |
| 234 | * later, we may move that initialization to each ppc_md | 515 | * later, we may move that initialization to each ppc_md |
| @@ -242,13 +523,8 @@ static int __init pcibios_init(void) | |||
| 242 | printk("PCI: Probing PCI hardware\n"); | 523 | printk("PCI: Probing PCI hardware\n"); |
| 243 | 524 | ||
| 244 | /* Scan all of the recorded PCI controllers. */ | 525 | /* Scan all of the recorded PCI controllers. */ |
| 245 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { | 526 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) |
| 246 | hose->last_busno = 0xff; | 527 | scan_phb(hose); |
| 247 | bus = pci_scan_bus(hose->first_busno, hose->ops, | ||
| 248 | hose->arch_data); | ||
| 249 | hose->bus = bus; | ||
| 250 | hose->last_busno = bus->subordinate; | ||
| 251 | } | ||
| 252 | 528 | ||
| 253 | #ifndef CONFIG_PPC_ISERIES | 529 | #ifndef CONFIG_PPC_ISERIES |
| 254 | if (pci_probe_only) | 530 | if (pci_probe_only) |
| @@ -820,118 +1096,89 @@ void phbs_remap_io(void) | |||
| 820 | /* | 1096 | /* |
| 821 | * ppc64 can have multifunction devices that do not respond to function 0. | 1097 | * ppc64 can have multifunction devices that do not respond to function 0. |
| 822 | * In this case we must scan all functions. | 1098 | * In this case we must scan all functions. |
| 1099 | * XXX this can go now, we use the OF device tree in all the | ||
| 1100 | * cases that caused problems. -- paulus | ||
| 823 | */ | 1101 | */ |
| 824 | int pcibios_scan_all_fns(struct pci_bus *bus, int devfn) | 1102 | int pcibios_scan_all_fns(struct pci_bus *bus, int devfn) |
| 825 | { | 1103 | { |
| 826 | struct device_node *busdn, *dn; | 1104 | return 0; |
| 1105 | } | ||
| 1106 | |||
| 1107 | static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev) | ||
| 1108 | { | ||
| 1109 | struct pci_controller *hose = pci_bus_to_host(dev->bus); | ||
| 1110 | unsigned long start, end, mask, offset; | ||
| 827 | 1111 | ||
| 828 | if (bus->self) | 1112 | if (res->flags & IORESOURCE_IO) { |
| 829 | busdn = pci_device_to_OF_node(bus->self); | 1113 | offset = (unsigned long)hose->io_base_virt - pci_io_base; |
| 830 | else | ||
| 831 | busdn = bus->sysdata; /* must be a phb */ | ||
| 832 | 1114 | ||
| 833 | if (busdn == NULL) | 1115 | start = res->start += offset; |
| 834 | return 0; | 1116 | end = res->end += offset; |
| 835 | 1117 | ||
| 836 | /* | 1118 | /* Need to allow IO access to pages that are in the |
| 837 | * Check to see if there is any of the 8 functions are in the | 1119 | ISA range */ |
| 838 | * device tree. If they are then we need to scan all the | 1120 | if (start < MAX_ISA_PORT) { |
| 839 | * functions of this slot. | 1121 | if (end > MAX_ISA_PORT) |
| 840 | */ | 1122 | end = MAX_ISA_PORT; |
| 841 | for (dn = busdn->child; dn; dn = dn->sibling) | ||
| 842 | if ((dn->devfn >> 3) == (devfn >> 3)) | ||
| 843 | return 1; | ||
| 844 | 1123 | ||
| 845 | return 0; | 1124 | start >>= PAGE_SHIFT; |
| 846 | } | 1125 | end >>= PAGE_SHIFT; |
| 847 | 1126 | ||
| 1127 | /* get the range of pages for the map */ | ||
| 1128 | mask = ((1 << (end+1)) - 1) ^ ((1 << start) - 1); | ||
| 1129 | io_page_mask |= mask; | ||
| 1130 | } | ||
| 1131 | } else if (res->flags & IORESOURCE_MEM) { | ||
| 1132 | res->start += hose->pci_mem_offset; | ||
| 1133 | res->end += hose->pci_mem_offset; | ||
| 1134 | } | ||
| 1135 | } | ||
| 848 | 1136 | ||
| 849 | void __devinit pcibios_fixup_device_resources(struct pci_dev *dev, | 1137 | void __devinit pcibios_fixup_device_resources(struct pci_dev *dev, |
| 850 | struct pci_bus *bus) | 1138 | struct pci_bus *bus) |
| 851 | { | 1139 | { |
| 852 | /* Update device resources. */ | 1140 | /* Update device resources. */ |
| 853 | struct pci_controller *hose = pci_bus_to_host(bus); | ||
| 854 | int i; | 1141 | int i; |
| 855 | 1142 | ||
| 856 | for (i = 0; i < PCI_NUM_RESOURCES; i++) { | 1143 | for (i = 0; i < PCI_NUM_RESOURCES; i++) |
| 857 | if (dev->resource[i].flags & IORESOURCE_IO) { | 1144 | if (dev->resource[i].flags) |
| 858 | unsigned long offset = (unsigned long)hose->io_base_virt | 1145 | fixup_resource(&dev->resource[i], dev); |
| 859 | - pci_io_base; | ||
| 860 | unsigned long start, end, mask; | ||
| 861 | |||
| 862 | start = dev->resource[i].start += offset; | ||
| 863 | end = dev->resource[i].end += offset; | ||
| 864 | |||
| 865 | /* Need to allow IO access to pages that are in the | ||
| 866 | ISA range */ | ||
| 867 | if (start < MAX_ISA_PORT) { | ||
| 868 | if (end > MAX_ISA_PORT) | ||
| 869 | end = MAX_ISA_PORT; | ||
| 870 | |||
| 871 | start >>= PAGE_SHIFT; | ||
| 872 | end >>= PAGE_SHIFT; | ||
| 873 | |||
| 874 | /* get the range of pages for the map */ | ||
| 875 | mask = ((1 << (end+1))-1) ^ ((1 << start)-1); | ||
| 876 | io_page_mask |= mask; | ||
| 877 | } | ||
| 878 | } | ||
| 879 | else if (dev->resource[i].flags & IORESOURCE_MEM) { | ||
| 880 | dev->resource[i].start += hose->pci_mem_offset; | ||
| 881 | dev->resource[i].end += hose->pci_mem_offset; | ||
| 882 | } | ||
| 883 | } | ||
| 884 | } | 1146 | } |
| 885 | EXPORT_SYMBOL(pcibios_fixup_device_resources); | 1147 | EXPORT_SYMBOL(pcibios_fixup_device_resources); |
| 886 | 1148 | ||
| 887 | void __devinit pcibios_fixup_bus(struct pci_bus *bus) | 1149 | static void __devinit do_bus_setup(struct pci_bus *bus) |
| 888 | { | 1150 | { |
| 889 | struct pci_controller *hose = pci_bus_to_host(bus); | 1151 | struct pci_dev *dev; |
| 890 | struct pci_dev *dev = bus->self; | ||
| 891 | struct resource *res; | ||
| 892 | int i; | ||
| 893 | 1152 | ||
| 894 | if (!dev) { | 1153 | ppc_md.iommu_bus_setup(bus); |
| 895 | /* Root bus. */ | ||
| 896 | 1154 | ||
| 897 | hose->bus = bus; | 1155 | list_for_each_entry(dev, &bus->devices, bus_list) |
| 898 | bus->resource[0] = res = &hose->io_resource; | 1156 | ppc_md.iommu_dev_setup(dev); |
| 899 | 1157 | ||
| 900 | if (res->flags && request_resource(&ioport_resource, res)) | 1158 | if (ppc_md.irq_bus_setup) |
| 901 | printk(KERN_ERR "Failed to request IO on " | 1159 | ppc_md.irq_bus_setup(bus); |
| 902 | "PCI domain %d\n", pci_domain_nr(bus)); | 1160 | } |
| 903 | 1161 | ||
| 904 | for (i = 0; i < 3; ++i) { | 1162 | void __devinit pcibios_fixup_bus(struct pci_bus *bus) |
| 905 | res = &hose->mem_resources[i]; | 1163 | { |
| 906 | bus->resource[i+1] = res; | 1164 | struct pci_dev *dev = bus->self; |
| 907 | if (res->flags && request_resource(&iomem_resource, res)) | 1165 | |
| 908 | printk(KERN_ERR "Failed to request MEM on " | 1166 | if (dev && pci_probe_only && |
| 909 | "PCI domain %d\n", | 1167 | (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { |
| 910 | pci_domain_nr(bus)); | ||
| 911 | } | ||
| 912 | } else if (pci_probe_only && | ||
| 913 | (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { | ||
| 914 | /* This is a subordinate bridge */ | 1168 | /* This is a subordinate bridge */ |
| 915 | 1169 | ||
| 916 | pci_read_bridge_bases(bus); | 1170 | pci_read_bridge_bases(bus); |
| 917 | pcibios_fixup_device_resources(dev, bus); | 1171 | pcibios_fixup_device_resources(dev, bus); |
| 918 | } | 1172 | } |
| 919 | 1173 | ||
| 920 | ppc_md.iommu_bus_setup(bus); | 1174 | do_bus_setup(bus); |
| 921 | |||
| 922 | list_for_each_entry(dev, &bus->devices, bus_list) | ||
| 923 | ppc_md.iommu_dev_setup(dev); | ||
| 924 | |||
| 925 | if (ppc_md.irq_bus_setup) | ||
| 926 | ppc_md.irq_bus_setup(bus); | ||
| 927 | 1175 | ||
| 928 | if (!pci_probe_only) | 1176 | if (!pci_probe_only) |
| 929 | return; | 1177 | return; |
| 930 | 1178 | ||
| 931 | list_for_each_entry(dev, &bus->devices, bus_list) { | 1179 | list_for_each_entry(dev, &bus->devices, bus_list) |
| 932 | if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI) | 1180 | if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI) |
| 933 | pcibios_fixup_device_resources(dev, bus); | 1181 | pcibios_fixup_device_resources(dev, bus); |
| 934 | } | ||
| 935 | } | 1182 | } |
| 936 | EXPORT_SYMBOL(pcibios_fixup_bus); | 1183 | EXPORT_SYMBOL(pcibios_fixup_bus); |
| 937 | 1184 | ||
| @@ -983,3 +1230,62 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar, | |||
| 983 | } | 1230 | } |
| 984 | 1231 | ||
| 985 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | 1232 | #endif /* CONFIG_PPC_MULTIPLATFORM */ |
| 1233 | |||
| 1234 | |||
| 1235 | #define IOBASE_BRIDGE_NUMBER 0 | ||
| 1236 | #define IOBASE_MEMORY 1 | ||
| 1237 | #define IOBASE_IO 2 | ||
| 1238 | #define IOBASE_ISA_IO 3 | ||
| 1239 | #define IOBASE_ISA_MEM 4 | ||
| 1240 | |||
| 1241 | long sys_pciconfig_iobase(long which, unsigned long in_bus, | ||
| 1242 | unsigned long in_devfn) | ||
| 1243 | { | ||
| 1244 | struct pci_controller* hose; | ||
| 1245 | struct list_head *ln; | ||
| 1246 | struct pci_bus *bus = NULL; | ||
| 1247 | struct device_node *hose_node; | ||
| 1248 | |||
| 1249 | /* Argh ! Please forgive me for that hack, but that's the | ||
| 1250 | * simplest way to get existing XFree to not lockup on some | ||
| 1251 | * G5 machines... So when something asks for bus 0 io base | ||
| 1252 | * (bus 0 is HT root), we return the AGP one instead. | ||
| 1253 | */ | ||
| 1254 | #ifdef CONFIG_PPC_PMAC | ||
| 1255 | if (systemcfg->platform == PLATFORM_POWERMAC && | ||
| 1256 | machine_is_compatible("MacRISC4")) | ||
| 1257 | if (in_bus == 0) | ||
| 1258 | in_bus = 0xf0; | ||
| 1259 | #endif /* CONFIG_PPC_PMAC */ | ||
| 1260 | |||
| 1261 | /* That syscall isn't quite compatible with PCI domains, but it's | ||
| 1262 | * used on pre-domains setup. We return the first match | ||
| 1263 | */ | ||
| 1264 | |||
| 1265 | for (ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) { | ||
| 1266 | bus = pci_bus_b(ln); | ||
| 1267 | if (in_bus >= bus->number && in_bus < (bus->number + bus->subordinate)) | ||
| 1268 | break; | ||
| 1269 | bus = NULL; | ||
| 1270 | } | ||
| 1271 | if (bus == NULL || bus->sysdata == NULL) | ||
| 1272 | return -ENODEV; | ||
| 1273 | |||
| 1274 | hose_node = (struct device_node *)bus->sysdata; | ||
| 1275 | hose = PCI_DN(hose_node)->phb; | ||
| 1276 | |||
| 1277 | switch (which) { | ||
| 1278 | case IOBASE_BRIDGE_NUMBER: | ||
| 1279 | return (long)hose->first_busno; | ||
| 1280 | case IOBASE_MEMORY: | ||
| 1281 | return (long)hose->pci_mem_offset; | ||
| 1282 | case IOBASE_IO: | ||
| 1283 | return (long)hose->io_base_phys; | ||
| 1284 | case IOBASE_ISA_IO: | ||
| 1285 | return (long)isa_io_base; | ||
| 1286 | case IOBASE_ISA_MEM: | ||
| 1287 | return -EINVAL; | ||
| 1288 | } | ||
| 1289 | |||
| 1290 | return -EOPNOTSUPP; | ||
| 1291 | } | ||
