aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/powermac
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2007-12-19 22:55:01 -0500
committerPaul Mackerras <paulus@samba.org>2007-12-20 00:18:13 -0500
commit444532d44aa6bc4d6e3ca74d8ad99c36f3b4d9f0 (patch)
tree334e0e474cadee057ae98220f4d052b49643ef91 /arch/powerpc/platforms/powermac
parentbcf988a19458f08950551f66c110e41fac452b2b (diff)
[POWERPC] Enable self-view of the HT host bridge on PowerMac G5
This enables the PCI code to see the device that represents the HT host bridge on the PowerMac G5. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/platforms/powermac')
-rw-r--r--arch/powerpc/platforms/powermac/pci.c54
-rw-r--r--arch/powerpc/platforms/powermac/setup.c4
2 files changed, 38 insertions, 20 deletions
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c
index 73deace0ec01..6c93e7c0da15 100644
--- a/arch/powerpc/platforms/powermac/pci.c
+++ b/arch/powerpc/platforms/powermac/pci.c
@@ -314,10 +314,13 @@ static int u3_ht_skip_device(struct pci_controller *hose,
314 314
315 /* We only allow config cycles to devices that are in OF device-tree 315 /* We only allow config cycles to devices that are in OF device-tree
316 * as we are apparently having some weird things going on with some 316 * as we are apparently having some weird things going on with some
317 * revs of K2 on recent G5s 317 * revs of K2 on recent G5s, except for the host bridge itself, which
318 * is missing from the tree but we know we can probe.
318 */ 319 */
319 if (bus->self) 320 if (bus->self)
320 busdn = pci_device_to_OF_node(bus->self); 321 busdn = pci_device_to_OF_node(bus->self);
322 else if (devfn == 0)
323 return 0;
321 else 324 else
322 busdn = hose->dn; 325 busdn = hose->dn;
323 for (dn = busdn->child; dn; dn = dn->sibling) 326 for (dn = busdn->child; dn; dn = dn->sibling)
@@ -344,14 +347,15 @@ static int u3_ht_skip_device(struct pci_controller *hose,
344 + (((unsigned int)bus) << 16) \ 347 + (((unsigned int)bus) << 16) \
345 + 0x01000000UL) 348 + 0x01000000UL)
346 349
347static volatile void __iomem *u3_ht_cfg_access(struct pci_controller* hose, 350static void __iomem *u3_ht_cfg_access(struct pci_controller *hose, u8 bus,
348 u8 bus, u8 devfn, u8 offset) 351 u8 devfn, u8 offset, int *swap)
349{ 352{
353 *swap = 1;
350 if (bus == hose->first_busno) { 354 if (bus == hose->first_busno) {
351 /* For now, we don't self probe U3 HT bridge */ 355 if (devfn != 0)
352 if (PCI_SLOT(devfn) == 0) 356 return hose->cfg_data + U3_HT_CFA0(devfn, offset);
353 return NULL; 357 *swap = 0;
354 return hose->cfg_data + U3_HT_CFA0(devfn, offset); 358 return ((void __iomem *)hose->cfg_addr) + (offset << 2);
355 } else 359 } else
356 return hose->cfg_data + U3_HT_CFA1(bus, devfn, offset); 360 return hose->cfg_data + U3_HT_CFA1(bus, devfn, offset);
357} 361}
@@ -360,14 +364,15 @@ static int u3_ht_read_config(struct pci_bus *bus, unsigned int devfn,
360 int offset, int len, u32 *val) 364 int offset, int len, u32 *val)
361{ 365{
362 struct pci_controller *hose; 366 struct pci_controller *hose;
363 volatile void __iomem *addr; 367 void __iomem *addr;
368 int swap;
364 369
365 hose = pci_bus_to_host(bus); 370 hose = pci_bus_to_host(bus);
366 if (hose == NULL) 371 if (hose == NULL)
367 return PCIBIOS_DEVICE_NOT_FOUND; 372 return PCIBIOS_DEVICE_NOT_FOUND;
368 if (offset >= 0x100) 373 if (offset >= 0x100)
369 return PCIBIOS_BAD_REGISTER_NUMBER; 374 return PCIBIOS_BAD_REGISTER_NUMBER;
370 addr = u3_ht_cfg_access(hose, bus->number, devfn, offset); 375 addr = u3_ht_cfg_access(hose, bus->number, devfn, offset, &swap);
371 if (!addr) 376 if (!addr)
372 return PCIBIOS_DEVICE_NOT_FOUND; 377 return PCIBIOS_DEVICE_NOT_FOUND;
373 378
@@ -397,10 +402,10 @@ static int u3_ht_read_config(struct pci_bus *bus, unsigned int devfn,
397 *val = in_8(addr); 402 *val = in_8(addr);
398 break; 403 break;
399 case 2: 404 case 2:
400 *val = in_le16(addr); 405 *val = swap ? in_le16(addr) : in_be16(addr);
401 break; 406 break;
402 default: 407 default:
403 *val = in_le32(addr); 408 *val = swap ? in_le32(addr) : in_be32(addr);
404 break; 409 break;
405 } 410 }
406 return PCIBIOS_SUCCESSFUL; 411 return PCIBIOS_SUCCESSFUL;
@@ -410,14 +415,15 @@ static int u3_ht_write_config(struct pci_bus *bus, unsigned int devfn,
410 int offset, int len, u32 val) 415 int offset, int len, u32 val)
411{ 416{
412 struct pci_controller *hose; 417 struct pci_controller *hose;
413 volatile void __iomem *addr; 418 void __iomem *addr;
419 int swap;
414 420
415 hose = pci_bus_to_host(bus); 421 hose = pci_bus_to_host(bus);
416 if (hose == NULL) 422 if (hose == NULL)
417 return PCIBIOS_DEVICE_NOT_FOUND; 423 return PCIBIOS_DEVICE_NOT_FOUND;
418 if (offset >= 0x100) 424 if (offset >= 0x100)
419 return PCIBIOS_BAD_REGISTER_NUMBER; 425 return PCIBIOS_BAD_REGISTER_NUMBER;
420 addr = u3_ht_cfg_access(hose, bus->number, devfn, offset); 426 addr = u3_ht_cfg_access(hose, bus->number, devfn, offset, &swap);
421 if (!addr) 427 if (!addr)
422 return PCIBIOS_DEVICE_NOT_FOUND; 428 return PCIBIOS_DEVICE_NOT_FOUND;
423 429
@@ -439,10 +445,10 @@ static int u3_ht_write_config(struct pci_bus *bus, unsigned int devfn,
439 out_8(addr, val); 445 out_8(addr, val);
440 break; 446 break;
441 case 2: 447 case 2:
442 out_le16(addr, val); 448 swap ? out_le16(addr, val) : out_be16(addr, val);
443 break; 449 break;
444 default: 450 default:
445 out_le32((u32 __iomem *)addr, val); 451 swap ? out_le32(addr, val) : out_be32(addr, val);
446 break; 452 break;
447 } 453 }
448 return PCIBIOS_SUCCESSFUL; 454 return PCIBIOS_SUCCESSFUL;
@@ -780,16 +786,26 @@ static void __init setup_u3_ht(struct pci_controller* hose)
780{ 786{
781 struct device_node *np = hose->dn; 787 struct device_node *np = hose->dn;
782 struct pci_controller *other = NULL; 788 struct pci_controller *other = NULL;
789 struct resource cfg_res, self_res;
783 int i, cur; 790 int i, cur;
784 791
785 792
786 hose->ops = &u3_ht_pci_ops; 793 hose->ops = &u3_ht_pci_ops;
787 794
788 /* We hard code the address because of the different size of 795 /* Get base addresses from OF tree
789 * the reg address cell, we shall fix that by killing struct 796 */
790 * reg_property and using some accessor functions instead 797 if (of_address_to_resource(np, 0, &cfg_res) ||
798 of_address_to_resource(np, 1, &self_res)) {
799 printk(KERN_ERR "PCI: Failed to get U3/U4 HT resources !\n");
800 return;
801 }
802
803 /* Map external cfg space access into cfg_data and self registers
804 * into cfg_addr
791 */ 805 */
792 hose->cfg_data = ioremap(0xf2000000, 0x02000000); 806 hose->cfg_data = ioremap(cfg_res.start, 0x02000000);
807 hose->cfg_addr = ioremap(self_res.start,
808 self_res.end - self_res.start + 1);
793 809
794 /* 810 /*
795 * /ht node doesn't expose a "ranges" property, so we "remove" 811 * /ht node doesn't expose a "ranges" property, so we "remove"
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 3acb59d5cdf5..869ca45cf919 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -613,9 +613,11 @@ static int pmac_pci_probe_mode(struct pci_bus *bus)
613 613
614 /* We need to use normal PCI probing for the AGP bus, 614 /* We need to use normal PCI probing for the AGP bus,
615 * since the device for the AGP bridge isn't in the tree. 615 * since the device for the AGP bridge isn't in the tree.
616 * Same for the PCIe host on U4 and the HT host bridge.
616 */ 617 */
617 if (bus->self == NULL && (of_device_is_compatible(node, "u3-agp") || 618 if (bus->self == NULL && (of_device_is_compatible(node, "u3-agp") ||
618 of_device_is_compatible(node, "u4-pcie"))) 619 of_device_is_compatible(node, "u4-pcie") ||
620 of_device_is_compatible(node, "u3-ht")))
619 return PCI_PROBE_NORMAL; 621 return PCI_PROBE_NORMAL;
620 return PCI_PROBE_DEVTREE; 622 return PCI_PROBE_DEVTREE;
621} 623}