aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Boyer <jwboyer@linux.vnet.ibm.com>2008-06-17 19:01:38 -0400
committerJosh Boyer <jwboyer@linux.vnet.ibm.com>2008-06-17 19:01:38 -0400
commit5ce4b59653b2c2053cd9a011918ac1e4747f24cc (patch)
tree9dd8ba43094c80c31459caa43d2014668617c2e2
parentd2146cb274e494dd14e50f5b4cdeb7a5e5af5421 (diff)
powerpc/4xx: Workaround for PPC440EPx/GRx PCI_28 Errata
The 440EPx/GRx chips don't support PCI MRM commands. Drivers determine this by looking for a zero value in the PCI cache line size register. However, some drivers write to this register upon initialization. This can cause MRMs to be used on these chips, which may cause deadlocks on PLB4. The workaround implemented here introduces a new indirect_type flag, called PPC_INDIRECT_TYPE_BROKEN_MRM. This is set in the pci_controller structure in the pci fixup function for 4xx PCI bridges by determining if the bridge is compatible with 440EPx/GRx. The flag is checked in the indirect_write_config function, and forces any writes to the PCI_CACHE_LINE_SIZE register to be zero, which will disable MRMs for these chips. A similar workaround has been tested by AMCC on various PCI cards, such as the Silicon Image ATA card and Intel E1000 GIGE card. Hangs were seen with the Silicon Image card, and MRMs were seen on the bus with a PCI analyzer. With the workaround in place, the card functioned properly and only Memory Reads were seen on the bus with the analyzer. Acked-by: Stefan Roese <sr@denx.de> Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com>
-rw-r--r--arch/powerpc/sysdev/indirect_pci.c6
-rw-r--r--arch/powerpc/sysdev/ppc4xx_pci.c5
-rw-r--r--include/asm-powerpc/pci-bridge.h3
3 files changed, 14 insertions, 0 deletions
diff --git a/arch/powerpc/sysdev/indirect_pci.c b/arch/powerpc/sysdev/indirect_pci.c
index cfbd2aae93e8..7fd49c97501a 100644
--- a/arch/powerpc/sysdev/indirect_pci.c
+++ b/arch/powerpc/sysdev/indirect_pci.c
@@ -123,6 +123,12 @@ indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
123 (bus->number == hose->first_busno)) 123 (bus->number == hose->first_busno))
124 val &= 0xffffff00; 124 val &= 0xffffff00;
125 125
126 /* Workaround for PCI_28 Errata in 440EPx/GRx */
127 if ((hose->indirect_type & PPC_INDIRECT_TYPE_BROKEN_MRM) &&
128 offset == PCI_CACHE_LINE_SIZE) {
129 val = 0;
130 }
131
126 /* 132 /*
127 * Note: the caller has already checked that offset is 133 * Note: the caller has already checked that offset is
128 * suitably aligned and that len is 1, 2 or 4. 134 * suitably aligned and that len is 1, 2 or 4.
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c
index 76886cf0e6dc..fb368dfde5d4 100644
--- a/arch/powerpc/sysdev/ppc4xx_pci.c
+++ b/arch/powerpc/sysdev/ppc4xx_pci.c
@@ -75,6 +75,11 @@ static void fixup_ppc4xx_pci_bridge(struct pci_dev *dev)
75 !of_device_is_compatible(hose->dn, "ibm,plb-pci")) 75 !of_device_is_compatible(hose->dn, "ibm,plb-pci"))
76 return; 76 return;
77 77
78 if (of_device_is_compatible(hose->dn, "ibm,plb440epx-pci") ||
79 of_device_is_compatible(hose->dn, "ibm,plb440grx-pci")) {
80 hose->indirect_type |= PPC_INDIRECT_TYPE_BROKEN_MRM;
81 }
82
78 /* Hide the PCI host BARs from the kernel as their content doesn't 83 /* Hide the PCI host BARs from the kernel as their content doesn't
79 * fit well in the resource management 84 * fit well in the resource management
80 */ 85 */
diff --git a/include/asm-powerpc/pci-bridge.h b/include/asm-powerpc/pci-bridge.h
index b95d033ae6e6..ae2ea803a0f2 100644
--- a/include/asm-powerpc/pci-bridge.h
+++ b/include/asm-powerpc/pci-bridge.h
@@ -92,12 +92,15 @@ struct pci_controller {
92 * anything but the PHB. Only allow talking to the PHB if this is 92 * anything but the PHB. Only allow talking to the PHB if this is
93 * set. 93 * set.
94 * BIG_ENDIAN - cfg_addr is a big endian register 94 * BIG_ENDIAN - cfg_addr is a big endian register
95 * BROKEN_MRM - the 440EPx/GRx chips have an errata that causes hangs on
96 * the PLB4. Effectively disable MRM commands by setting this.
95 */ 97 */
96#define PPC_INDIRECT_TYPE_SET_CFG_TYPE 0x00000001 98#define PPC_INDIRECT_TYPE_SET_CFG_TYPE 0x00000001
97#define PPC_INDIRECT_TYPE_EXT_REG 0x00000002 99#define PPC_INDIRECT_TYPE_EXT_REG 0x00000002
98#define PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS 0x00000004 100#define PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS 0x00000004
99#define PPC_INDIRECT_TYPE_NO_PCIE_LINK 0x00000008 101#define PPC_INDIRECT_TYPE_NO_PCIE_LINK 0x00000008
100#define PPC_INDIRECT_TYPE_BIG_ENDIAN 0x00000010 102#define PPC_INDIRECT_TYPE_BIG_ENDIAN 0x00000010
103#define PPC_INDIRECT_TYPE_BROKEN_MRM 0x00000020
101 u32 indirect_type; 104 u32 indirect_type;
102#endif /* !CONFIG_PPC64 */ 105#endif /* !CONFIG_PPC64 */
103 /* Currently, we limit ourselves to 1 IO range and 3 mem 106 /* Currently, we limit ourselves to 1 IO range and 3 mem