[PATCH 2/4] fsl_pci: Add a workaround for PCI 5 errata

Zhao Chenhui chenhui.zhao at freescale.com
Wed Mar 14 21:15:49 EST 2012


From: chenhui zhao <chenhui.zhao at freescale.com>

Issue:
As a master, the PCI IP block can combine a memory write to the last PCI double
word (4 bytes) of a cacheline with a 4 byte memory write to the first PCI double
word of the subsequent cacheline. This affects 32-bit PCI target devices that
blindly assert STOP on memory-write transactions, without detecting that the
data beat being transferred is the last data beat of the transaction. It can
cause a hang. PCI-X operation is not affected by this erratum.

Workaround:
Setting the bit MDS in the PCI Bus Function Register will disable the combining
of crossing cacheline boundary requests into one burst transaction. Therefore,
it can prevent the errata scenario from occurring.

This errata exists in MPC8543, MPC8543E, MPC8545, MPC8545E, MPC8547, MPC8547E,
MPC8548 and MPC8548E. Refer to PCI 5 in MPC8548 errata document.

Signed-off-by: Gong Chen <g.chen at freescale.com>
Signed-off-by: Zhao Chenhui <chenhui.zhao at freescale.com>
Signed-off-by: Li Yang <leoli at freescale.com>
---
Changes for v2:
 * add 8543, 8545 and 8547

 arch/powerpc/include/asm/mpc85xx.h |    1 +
 arch/powerpc/sysdev/fsl_pci.c      |   23 +++++++++++++++++++++++
 2 files changed, 24 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/include/asm/mpc85xx.h b/arch/powerpc/include/asm/mpc85xx.h
index 451777c..fafca9f 100644
--- a/arch/powerpc/include/asm/mpc85xx.h
+++ b/arch/powerpc/include/asm/mpc85xx.h
@@ -37,6 +37,7 @@
 #define SVR_8544_E	0x803C01
 #define SVR_8545	0x803102
 #define SVR_8545_E	0x803902
+#define SVR_8547	0x803101
 #define SVR_8547_E	0x803901
 #define SVR_8548	0x803100
 #define SVR_8548_E	0x803900
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 6073288..f595117 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -31,6 +31,7 @@
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
 #include <asm/machdep.h>
+#include <asm/mpc85xx.h>
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
 
@@ -426,6 +427,7 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary)
 	struct resource rsrc;
 	const int *bus_range;
 	u8 progif;
+	u16 temp;
 
 	if (!of_device_is_available(dev)) {
 		pr_warning("%s: disabled\n", dev->full_name);
@@ -476,6 +478,27 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary)
 			PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS;
 		if (fsl_pcie_check_link(hose))
 			hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK;
+	} else {
+		/*
+		 * Set PBFR(PCI Bus Function Register)[10] = 1 to
+		 * disable the combining of crossing cacheline
+		 * boundary requests into one burst transaction.
+		 * PCI-X operation is not affected.
+		 * Fix erratum PCI 5 on MPC8548
+		 */
+#define PCI_BUS_FUNCTION 0x44
+#define PCI_BUS_FUNCTION_MDS 0x400	/* Master disable streaming */
+		if ((fsl_svr_is(SVR_8543) || fsl_svr_is(SVR_8543_E) ||
+		     fsl_svr_is(SVR_8545) || fsl_svr_is(SVR_8545_E) ||
+		     fsl_svr_is(SVR_8547) || fsl_svr_is(SVR_8547_E) ||
+		     fsl_svr_is(SVR_8548) || fsl_svr_is(SVR_8548_E)) &&
+		    !early_find_capability(hose, 0, 0, PCI_CAP_ID_PCIX)) {
+			early_read_config_word(hose, 0, 0,
+						PCI_BUS_FUNCTION, &temp);
+			temp |= PCI_BUS_FUNCTION_MDS;
+			early_write_config_word(hose, 0, 0,
+						PCI_BUS_FUNCTION, temp);
+		}
 	}
 
 	printk(KERN_INFO "Found FSL PCI host bridge at 0x%016llx. "
-- 
1.6.4.1




More information about the Linuxppc-dev mailing list