aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2009-08-31 17:34:36 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2009-09-02 02:20:42 -0400
commitcede3930f0ca6fef353fa01306c72a01420bd45e (patch)
tree5483f711e206722152cef543a552176e2d1abb7f /arch/powerpc/platforms
parent76acc2c1a7a9a8c2cae7e9cf8d0a8b374a48aa94 (diff)
powerpc: Fix some late PowerMac G5 with PCIe ATI graphics
A misconfiguration by the firmware of the U4 PCIe bridge on PowerMac G5 with the U4 bridge (latest generations, may also affect the iMac G5 "iSight") is causing us to re-assign the PCI BARs of the video card, which can get it out of sync with the firmware, thus breaking offb. This works around it by fixing up the bridge configuration properly at boot time. It also fixes a bug where the firmware provides us with an incorrect set of accessible regions in the device-tree. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r--arch/powerpc/platforms/powermac/pci.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c
index 04cdd32624d4..e81403b245b5 100644
--- a/arch/powerpc/platforms/powermac/pci.c
+++ b/arch/powerpc/platforms/powermac/pci.c
@@ -1286,3 +1286,64 @@ static void fixup_k2_sata(struct pci_dev* dev)
1286} 1286}
1287DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, 0x0240, fixup_k2_sata); 1287DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, 0x0240, fixup_k2_sata);
1288 1288
1289/*
1290 * On U4 (aka CPC945) the PCIe root complex "P2P" bridge resource ranges aren't
1291 * configured by the firmware. The bridge itself seems to ignore them but it
1292 * causes problems with Linux which then re-assigns devices below the bridge,
1293 * thus changing addresses of those devices from what was in the device-tree,
1294 * which sucks when those are video cards using offb
1295 *
1296 * We could just mark it transparent but I prefer fixing up the resources to
1297 * properly show what's going on here, as I have some doubts about having them
1298 * badly configured potentially being an issue for DMA.
1299 *
1300 * We leave PIO alone, it seems to be fine
1301 *
1302 * Oh and there's another funny bug. The OF properties advertize the region
1303 * 0xf1000000..0xf1ffffff as being forwarded as memory space. But that's
1304 * actually not true, this region is the memory mapped config space. So we
1305 * also need to filter it out or we'll map things in the wrong place.
1306 */
1307static void fixup_u4_pcie(struct pci_dev* dev)
1308{
1309 struct pci_controller *host = pci_bus_to_host(dev->bus);
1310 struct resource *region = NULL;
1311 u32 reg;
1312 int i;
1313
1314 /* Only do that on PowerMac */
1315 if (!machine_is(powermac))
1316 return;
1317
1318 /* Find the largest MMIO region */
1319 for (i = 0; i < 3; i++) {
1320 struct resource *r = &host->mem_resources[i];
1321 if (!(r->flags & IORESOURCE_MEM))
1322 continue;
1323 /* Skip the 0xf0xxxxxx..f2xxxxxx regions, we know they
1324 * are reserved by HW for other things
1325 */
1326 if (r->start >= 0xf0000000 && r->start < 0xf3000000)
1327 continue;
1328 if (!region || (r->end - r->start) >
1329 (region->end - region->start))
1330 region = r;
1331 }
1332 /* Nothing found, bail */
1333 if (region == 0)
1334 return;
1335
1336 /* Print things out */
1337 printk(KERN_INFO "PCI: Fixup U4 PCIe bridge range: %pR\n", region);
1338
1339 /* Fixup bridge config space. We know it's a Mac, resource aren't
1340 * offset so let's just blast them as-is. We also know that they
1341 * fit in 32 bits
1342 */
1343 reg = ((region->start >> 16) & 0xfff0) | (region->end & 0xfff00000);
1344 pci_write_config_dword(dev, PCI_MEMORY_BASE, reg);
1345 pci_write_config_dword(dev, PCI_PREF_BASE_UPPER32, 0);
1346 pci_write_config_dword(dev, PCI_PREF_LIMIT_UPPER32, 0);
1347 pci_write_config_dword(dev, PCI_PREF_MEMORY_BASE, 0);
1348}
1349DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_U4_PCIE, fixup_u4_pcie);