diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2008-10-27 15:48:29 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2008-11-05 06:11:53 -0500 |
commit | 53280323350621985b3f2f8ffe649215304bcc5f (patch) | |
tree | ec4c126dd620ecb1b36f67fc4201e24fcca6ab18 /arch/powerpc | |
parent | b0494bc8ee449f0534afa92a51e2e3bb27bab69b (diff) |
powerpc/pci: Use common PHB resource hookup
The 32-bit and 64-bit powerpc PCI code used to set up the resource
pointers of the root bus of a given PHB in completely different
places.
This unifies this in large part, by making 32-bit use a routine very
similar to what 64-bit does when initially scanning the PCI busses.
The actual setup of the PHB resources itself is then moved to a
common function in pci-common.c.
This should cause no functional change on 64-bit. On 32-bit, the
effect is that the PHB resources are going to be setup a bit earlier,
instead of being setup from pcibios_fixup_bus().
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/include/asm/pci-bridge.h | 1 | ||||
-rw-r--r-- | arch/powerpc/kernel/pci-common.c | 58 | ||||
-rw-r--r-- | arch/powerpc/kernel/pci_32.c | 78 | ||||
-rw-r--r-- | arch/powerpc/kernel/pci_64.c | 19 |
4 files changed, 96 insertions, 60 deletions
diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index 9047af7baa69..2dfa8a3d8c76 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h | |||
@@ -290,6 +290,7 @@ extern void pci_process_bridge_OF_ranges(struct pci_controller *hose, | |||
290 | /* Allocate & free a PCI host bridge structure */ | 290 | /* Allocate & free a PCI host bridge structure */ |
291 | extern struct pci_controller *pcibios_alloc_controller(struct device_node *dev); | 291 | extern struct pci_controller *pcibios_alloc_controller(struct device_node *dev); |
292 | extern void pcibios_free_controller(struct pci_controller *phb); | 292 | extern void pcibios_free_controller(struct pci_controller *phb); |
293 | extern void pcibios_setup_phb_resources(struct pci_controller *hose); | ||
293 | 294 | ||
294 | #ifdef CONFIG_PCI | 295 | #ifdef CONFIG_PCI |
295 | extern unsigned long pci_address_to_pio(phys_addr_t address); | 296 | extern unsigned long pci_address_to_pio(phys_addr_t address); |
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 09ac98e2a502..6d46bfabdbe4 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c | |||
@@ -1421,3 +1421,61 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) | |||
1421 | 1421 | ||
1422 | return pci_enable_resources(dev, mask); | 1422 | return pci_enable_resources(dev, mask); |
1423 | } | 1423 | } |
1424 | |||
1425 | void __devinit pcibios_setup_phb_resources(struct pci_controller *hose) | ||
1426 | { | ||
1427 | struct pci_bus *bus = hose->bus; | ||
1428 | struct resource *res; | ||
1429 | int i; | ||
1430 | |||
1431 | /* Hookup PHB IO resource */ | ||
1432 | bus->resource[0] = res = &hose->io_resource; | ||
1433 | |||
1434 | if (!res->flags) { | ||
1435 | printk(KERN_WARNING "PCI: I/O resource not set for host" | ||
1436 | " bridge %s (domain %d)\n", | ||
1437 | hose->dn->full_name, hose->global_number); | ||
1438 | #ifdef CONFIG_PPC32 | ||
1439 | /* Workaround for lack of IO resource only on 32-bit */ | ||
1440 | res->start = (unsigned long)hose->io_base_virt - isa_io_base; | ||
1441 | res->end = res->start + IO_SPACE_LIMIT; | ||
1442 | res->flags = IORESOURCE_IO; | ||
1443 | #endif /* CONFIG_PPC32 */ | ||
1444 | } | ||
1445 | |||
1446 | pr_debug("PCI: PHB IO resource = %016llx-%016llx [%lx]\n", | ||
1447 | (unsigned long long)res->start, | ||
1448 | (unsigned long long)res->end, | ||
1449 | (unsigned long)res->flags); | ||
1450 | |||
1451 | /* Hookup PHB Memory resources */ | ||
1452 | for (i = 0; i < 3; ++i) { | ||
1453 | res = &hose->mem_resources[i]; | ||
1454 | if (!res->flags) { | ||
1455 | if (i > 0) | ||
1456 | continue; | ||
1457 | printk(KERN_ERR "PCI: Memory resource 0 not set for " | ||
1458 | "host bridge %s (domain %d)\n", | ||
1459 | hose->dn->full_name, hose->global_number); | ||
1460 | #ifdef CONFIG_PPC32 | ||
1461 | /* Workaround for lack of MEM resource only on 32-bit */ | ||
1462 | res->start = hose->pci_mem_offset; | ||
1463 | res->end = (resource_size_t)-1LL; | ||
1464 | res->flags = IORESOURCE_MEM; | ||
1465 | #endif /* CONFIG_PPC32 */ | ||
1466 | } | ||
1467 | bus->resource[i+1] = res; | ||
1468 | |||
1469 | pr_debug("PCI: PHB MEM resource %d = %016llx-%016llx [%lx]\n", i, | ||
1470 | (unsigned long long)res->start, | ||
1471 | (unsigned long long)res->end, | ||
1472 | (unsigned long)res->flags); | ||
1473 | } | ||
1474 | |||
1475 | pr_debug("PCI: PHB MEM offset = %016llx\n", | ||
1476 | (unsigned long long)hose->pci_mem_offset); | ||
1477 | pr_debug("PCI: PHB IO offset = %08lx\n", | ||
1478 | (unsigned long)hose->io_base_virt - _IO_BASE); | ||
1479 | |||
1480 | } | ||
1481 | |||
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index fdcc898e58db..883040358273 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c | |||
@@ -373,10 +373,41 @@ void pcibios_make_OF_bus_map(void) | |||
373 | } | 373 | } |
374 | #endif /* CONFIG_PPC_OF */ | 374 | #endif /* CONFIG_PPC_OF */ |
375 | 375 | ||
376 | static void __devinit pcibios_scan_phb(struct pci_controller *hose) | ||
377 | { | ||
378 | struct pci_bus *bus; | ||
379 | struct device_node *node = hose->dn; | ||
380 | unsigned long io_offset; | ||
381 | struct resource *res = &hose->io_resource; | ||
382 | |||
383 | pr_debug("PCI: Scanning PHB %s\n", | ||
384 | node ? node->full_name : "<NO NAME>"); | ||
385 | |||
386 | /* Create an empty bus for the toplevel */ | ||
387 | bus = pci_create_bus(hose->parent, hose->first_busno, hose->ops, hose); | ||
388 | if (bus == NULL) { | ||
389 | printk(KERN_ERR "Failed to create bus for PCI domain %04x\n", | ||
390 | hose->global_number); | ||
391 | return; | ||
392 | } | ||
393 | bus->secondary = hose->first_busno; | ||
394 | hose->bus = bus; | ||
395 | |||
396 | /* Fixup IO space offset */ | ||
397 | io_offset = (unsigned long)hose->io_base_virt - isa_io_base; | ||
398 | res->start = (res->start + io_offset) & 0xffffffffu; | ||
399 | res->end = (res->end + io_offset) & 0xffffffffu; | ||
400 | |||
401 | /* Wire up PHB bus resources */ | ||
402 | pcibios_setup_phb_resources(hose); | ||
403 | |||
404 | /* Scan children */ | ||
405 | hose->last_busno = bus->subordinate = pci_scan_child_bus(bus); | ||
406 | } | ||
407 | |||
376 | static int __init pcibios_init(void) | 408 | static int __init pcibios_init(void) |
377 | { | 409 | { |
378 | struct pci_controller *hose, *tmp; | 410 | struct pci_controller *hose, *tmp; |
379 | struct pci_bus *bus; | ||
380 | int next_busno = 0; | 411 | int next_busno = 0; |
381 | 412 | ||
382 | printk(KERN_INFO "PCI: Probing PCI hardware\n"); | 413 | printk(KERN_INFO "PCI: Probing PCI hardware\n"); |
@@ -389,12 +420,8 @@ static int __init pcibios_init(void) | |||
389 | if (pci_assign_all_buses) | 420 | if (pci_assign_all_buses) |
390 | hose->first_busno = next_busno; | 421 | hose->first_busno = next_busno; |
391 | hose->last_busno = 0xff; | 422 | hose->last_busno = 0xff; |
392 | bus = pci_scan_bus_parented(hose->parent, hose->first_busno, | 423 | pcibios_scan_phb(hose); |
393 | hose->ops, hose); | 424 | pci_bus_add_devices(hose->bus); |
394 | if (bus) { | ||
395 | pci_bus_add_devices(bus); | ||
396 | hose->last_busno = bus->subordinate; | ||
397 | } | ||
398 | if (pci_assign_all_buses || next_busno <= hose->last_busno) | 425 | if (pci_assign_all_buses || next_busno <= hose->last_busno) |
399 | next_busno = hose->last_busno + pcibios_assign_bus_offset; | 426 | next_busno = hose->last_busno + pcibios_assign_bus_offset; |
400 | } | 427 | } |
@@ -421,45 +448,8 @@ subsys_initcall(pcibios_init); | |||
421 | 448 | ||
422 | void __devinit pcibios_do_bus_setup(struct pci_bus *bus) | 449 | void __devinit pcibios_do_bus_setup(struct pci_bus *bus) |
423 | { | 450 | { |
424 | struct pci_controller *hose = (struct pci_controller *) bus->sysdata; | ||
425 | unsigned long io_offset; | ||
426 | struct resource *res; | ||
427 | int i; | ||
428 | struct pci_dev *dev; | 451 | struct pci_dev *dev; |
429 | 452 | ||
430 | /* Hookup PHB resources */ | ||
431 | io_offset = (unsigned long)hose->io_base_virt - isa_io_base; | ||
432 | if (bus->parent == NULL) { | ||
433 | /* This is a host bridge - fill in its resources */ | ||
434 | hose->bus = bus; | ||
435 | |||
436 | bus->resource[0] = res = &hose->io_resource; | ||
437 | if (!res->flags) { | ||
438 | if (io_offset) | ||
439 | printk(KERN_ERR "I/O resource not set for host" | ||
440 | " bridge %d\n", hose->global_number); | ||
441 | res->start = 0; | ||
442 | res->end = IO_SPACE_LIMIT; | ||
443 | res->flags = IORESOURCE_IO; | ||
444 | } | ||
445 | res->start = (res->start + io_offset) & 0xffffffffu; | ||
446 | res->end = (res->end + io_offset) & 0xffffffffu; | ||
447 | |||
448 | for (i = 0; i < 3; ++i) { | ||
449 | res = &hose->mem_resources[i]; | ||
450 | if (!res->flags) { | ||
451 | if (i > 0) | ||
452 | continue; | ||
453 | printk(KERN_ERR "Memory resource not set for " | ||
454 | "host bridge %d\n", hose->global_number); | ||
455 | res->start = hose->pci_mem_offset; | ||
456 | res->end = ~0U; | ||
457 | res->flags = IORESOURCE_MEM; | ||
458 | } | ||
459 | bus->resource[i+1] = res; | ||
460 | } | ||
461 | } | ||
462 | |||
463 | if (ppc_md.pci_dma_bus_setup) | 453 | if (ppc_md.pci_dma_bus_setup) |
464 | ppc_md.pci_dma_bus_setup(bus); | 454 | ppc_md.pci_dma_bus_setup(bus); |
465 | 455 | ||
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index ffada88a4484..f5fc547284bc 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c | |||
@@ -322,7 +322,7 @@ void __devinit scan_phb(struct pci_controller *hose) | |||
322 | { | 322 | { |
323 | struct pci_bus *bus; | 323 | struct pci_bus *bus; |
324 | struct device_node *node = hose->dn; | 324 | struct device_node *node = hose->dn; |
325 | int i, mode; | 325 | int mode; |
326 | 326 | ||
327 | pr_debug("PCI: Scanning PHB %s\n", | 327 | pr_debug("PCI: Scanning PHB %s\n", |
328 | node ? node->full_name : "<NO NAME>"); | 328 | node ? node->full_name : "<NO NAME>"); |
@@ -341,20 +341,7 @@ void __devinit scan_phb(struct pci_controller *hose) | |||
341 | pcibios_map_io_space(bus); | 341 | pcibios_map_io_space(bus); |
342 | 342 | ||
343 | /* Wire up PHB bus resources */ | 343 | /* Wire up PHB bus resources */ |
344 | pr_debug("PCI: PHB IO resource = %016lx-%016lx [%lx]\n", | 344 | pcibios_setup_phb_resources(hose); |
345 | hose->io_resource.start, hose->io_resource.end, | ||
346 | hose->io_resource.flags); | ||
347 | bus->resource[0] = &hose->io_resource; | ||
348 | for (i = 0; i < 3; ++i) { | ||
349 | pr_debug("PCI: PHB MEM resource %d = %016lx-%016lx [%lx]\n", i, | ||
350 | hose->mem_resources[i].start, | ||
351 | hose->mem_resources[i].end, | ||
352 | hose->mem_resources[i].flags); | ||
353 | bus->resource[i+1] = &hose->mem_resources[i]; | ||
354 | } | ||
355 | pr_debug("PCI: PHB MEM offset = %016lx\n", hose->pci_mem_offset); | ||
356 | pr_debug("PCI: PHB IO offset = %08lx\n", | ||
357 | (unsigned long)hose->io_base_virt - _IO_BASE); | ||
358 | 345 | ||
359 | /* Get probe mode and perform scan */ | 346 | /* Get probe mode and perform scan */ |
360 | mode = PCI_PROBE_NORMAL; | 347 | mode = PCI_PROBE_NORMAL; |
@@ -376,7 +363,7 @@ static int __init pcibios_init(void) | |||
376 | 363 | ||
377 | printk(KERN_INFO "PCI: Probing PCI hardware\n"); | 364 | printk(KERN_INFO "PCI: Probing PCI hardware\n"); |
378 | 365 | ||
379 | /* For now, override phys_mem_access_prot. If we need it, | 366 | /* For now, override phys_mem_access_prot. If we need it,g |
380 | * later, we may move that initialization to each ppc_md | 367 | * later, we may move that initialization to each ppc_md |
381 | */ | 368 | */ |
382 | ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot; | 369 | ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot; |