powerpc: Fix some late PowerMac G5 with PCIe ATI graphics
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Mon, 31 Aug 2009 21:34:36 +0000 (21:34 +0000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Wed, 2 Sep 2009 06:20:42 +0000 (16:20 +1000)
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>
arch/powerpc/platforms/powermac/pci.c
include/linux/pci_ids.h

index 04cdd32624d40b08ffac327f44e9d1124b58e41f..e81403b245b5d848f237ebe4aaeb17f00dc322df 100644 (file)
@@ -1286,3 +1286,64 @@ static void fixup_k2_sata(struct pci_dev* dev)
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, 0x0240, fixup_k2_sata);
 
+/*
+ * On U4 (aka CPC945) the PCIe root complex "P2P" bridge resource ranges aren't
+ * configured by the firmware. The bridge itself seems to ignore them but it
+ * causes problems with Linux which then re-assigns devices below the bridge,
+ * thus changing addresses of those devices from what was in the device-tree,
+ * which sucks when those are video cards using offb
+ *
+ * We could just mark it transparent but I prefer fixing up the resources to
+ * properly show what's going on here, as I have some doubts about having them
+ * badly configured potentially being an issue for DMA.
+ *
+ * We leave PIO alone, it seems to be fine
+ *
+ * Oh and there's another funny bug. The OF properties advertize the region
+ * 0xf1000000..0xf1ffffff as being forwarded as memory space. But that's
+ * actually not true, this region is the memory mapped config space. So we
+ * also need to filter it out or we'll map things in the wrong place.
+ */
+static void fixup_u4_pcie(struct pci_dev* dev)
+{
+       struct pci_controller *host = pci_bus_to_host(dev->bus);
+       struct resource *region = NULL;
+       u32 reg;
+       int i;
+
+       /* Only do that on PowerMac */
+       if (!machine_is(powermac))
+               return;
+
+       /* Find the largest MMIO region */
+       for (i = 0; i < 3; i++) {
+               struct resource *r = &host->mem_resources[i];
+               if (!(r->flags & IORESOURCE_MEM))
+                       continue;
+               /* Skip the 0xf0xxxxxx..f2xxxxxx regions, we know they
+                * are reserved by HW for other things
+                */
+               if (r->start >= 0xf0000000 && r->start < 0xf3000000)
+                       continue;
+               if (!region || (r->end - r->start) >
+                   (region->end - region->start))
+                       region = r;
+       }
+       /* Nothing found, bail */
+       if (region == 0)
+               return;
+
+       /* Print things out */
+       printk(KERN_INFO "PCI: Fixup U4 PCIe bridge range: %pR\n", region);
+
+       /* Fixup bridge config space. We know it's a Mac, resource aren't
+        * offset so let's just blast them as-is. We also know that they
+        * fit in 32 bits
+        */
+       reg = ((region->start >> 16) & 0xfff0) | (region->end & 0xfff00000);
+       pci_write_config_dword(dev, PCI_MEMORY_BASE, reg);
+       pci_write_config_dword(dev, PCI_PREF_BASE_UPPER32, 0);
+       pci_write_config_dword(dev, PCI_PREF_LIMIT_UPPER32, 0);
+       pci_write_config_dword(dev, PCI_PREF_MEMORY_BASE, 0);
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_U4_PCIE, fixup_u4_pcie);
index 73b46b6b904fc87b977ceeaae2b462c5ac0f5e60..c86bb6e3dfccc966b065ca6c6486224e9477976b 100644 (file)
 #define PCI_DEVICE_ID_APPLE_SH_SUNGEM   0x0051
 #define PCI_DEVICE_ID_APPLE_U3L_AGP    0x0058
 #define PCI_DEVICE_ID_APPLE_U3H_AGP    0x0059
+#define PCI_DEVICE_ID_APPLE_U4_PCIE    0x005b
 #define PCI_DEVICE_ID_APPLE_IPID2_AGP  0x0066
 #define PCI_DEVICE_ID_APPLE_IPID2_ATA  0x0069
 #define PCI_DEVICE_ID_APPLE_IPID2_FW   0x006a