[U-Boot] [PATCHv4 11/12] pci: ls_pcie_g4: Add Workaround for A-011451

Z.q. Hou zhiqiang.hou at nxp.com
Mon Mar 11 02:58:39 UTC 2019


From: Hou Zhiqiang <Zhiqiang.Hou at nxp.com>

When LAYERSCAPE Gen4 PCIe controller is sending multiple split
completions and ACK latency expires indicating that ACK should
be send at priority. But because of large number of split
completions and FC update DLLP, the controller does not give
priority to ACK transmission. This results into ACK latency
timer timeout error at the link partner and the pending TLPs
are replayed by the link partner again.

Workaround:
1. Reduce the ACK latency timeout value to a very small value.
2. Restrict the number of completions from the PCIe controller
   to 1, by changing the Max Read Request Size (MRRS) of link
   partner to the same value as Max Packet size (MPS).

This ERRATA is only for LX2160A Rev1.0 and will be fixed in Rev2.0.

Signed-off-by: Hou Zhiqiang <Zhiqiang.Hou at nxp.com>
---
V4:
 - V3 patch find root port wrongly, fix it in V4.
 - Change to use the MPS and MRRS accessors.

 drivers/pci/pci_auto.c             | 35 ++++++++++++++++++++++++++++++
 drivers/pci/pcie_layerscape_gen4.c |  8 +++++++
 drivers/pci/pcie_layerscape_gen4.h |  4 ++++
 include/pci_ids.h                  |  1 +
 4 files changed, 48 insertions(+)

diff --git a/drivers/pci/pci_auto.c b/drivers/pci/pci_auto.c
index d7237f6eee..611462d1d4 100644
--- a/drivers/pci/pci_auto.c
+++ b/drivers/pci/pci_auto.c
@@ -22,6 +22,8 @@ void dm_pciauto_setup_device(struct udevice *dev, int bars_num,
 			     struct pci_region *prefetch, struct pci_region *io,
 			     bool enum_only)
 {
+	struct udevice *ctrl = pci_get_controller(dev);
+	struct udevice *rp;
 	u32 bar_response;
 	pci_size_t bar_size;
 	u16 cmdstat = 0;
@@ -32,6 +34,8 @@ void dm_pciauto_setup_device(struct udevice *dev, int bars_num,
 	struct pci_region *bar_res = NULL;
 	int found_mem64 = 0;
 	u16 class;
+	u16 vendor, dev_id;
+	u8 rev;
 
 	dm_pci_read_config16(dev, PCI_COMMAND, &cmdstat);
 	cmdstat = (cmdstat & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) |
@@ -161,6 +165,37 @@ void dm_pciauto_setup_device(struct udevice *dev, int bars_num,
 	dm_pci_write_config8(dev, PCI_CACHE_LINE_SIZE,
 			     CONFIG_SYS_PCI_CACHE_LINE_SIZE);
 	dm_pci_write_config8(dev, PCI_LATENCY_TIMER, 0x80);
+
+	/*
+	 * When NXP LAYERSCAPE Gen4 PCIe controller is sending multiple split
+	 * completions and ACK latency expires indicating that ACK should be
+	 * send at priority. But because of large number of split completions
+	 * and FC update DLLP, the controller does not give priority to ACK
+	 * transmission. This results into ACK latency timer timeout error at
+	 * the link partner and the pending TLPs are replayed by the link
+	 * partner again.
+	 *
+	 * The workaround:
+	 * Restrict the number of completions from the PCIe controller to 1,
+	 * by changing the Max Read Request Size (MRRS) of link partner to the
+	 * same value as Max Packet size (MPS).
+	 *
+	 * So, set both the MPS and MRRS to the minimum 128B.
+	 */
+	device_find_first_child(ctrl, &rp);
+	if (!rp) {
+		debug("%s: Host: %s, RP is NULL\n", __func__, ctrl->name);
+		return;
+	}
+
+	dm_pci_read_config16(rp, PCI_VENDOR_ID, &vendor);
+	dm_pci_read_config16(rp, PCI_DEVICE_ID, &dev_id);
+	dm_pci_read_config8(rp, PCI_REVISION_ID, &rev);
+	if (vendor == PCI_VENDOR_ID_FREESCALE &&
+	    dev_id == PCI_DEVICE_ID_LX2160A && rev == 0x10) {
+		dm_pci_set_mps(dev, 128);
+		dm_pci_set_readrq(dev, 128);
+	}
 }
 
 void dm_pciauto_prescan_setup_bridge(struct udevice *dev, int sub_bus)
diff --git a/drivers/pci/pcie_layerscape_gen4.c b/drivers/pci/pcie_layerscape_gen4.c
index 799da2f7df..b530a9979c 100644
--- a/drivers/pci/pcie_layerscape_gen4.c
+++ b/drivers/pci/pcie_layerscape_gen4.c
@@ -526,6 +526,14 @@ static int ls_pcie_g4_probe(struct udevice *dev)
 
 	pcie->rev = readb(pcie->ccsr + PCI_REVISION_ID);
 
+	/* Set ACK latency timeout */
+	if (pcie->rev == REV_1_0) {
+		val = ccsr_readl(pcie, GPEX_ACK_REPLAY_TO);
+		val &= ~(ACK_LAT_TO_VAL_MASK << ACK_LAT_TO_VAL_SHIFT);
+		val |= (4 << ACK_LAT_TO_VAL_SHIFT);
+		ccsr_writel(pcie, GPEX_ACK_REPLAY_TO, val);
+	}
+
 	pcie->mode = readb(pcie->ccsr + PCI_HEADER_TYPE) & 0x7f;
 
 	if (pcie->mode == PCI_HEADER_TYPE_NORMAL) {
diff --git a/drivers/pci/pcie_layerscape_gen4.h b/drivers/pci/pcie_layerscape_gen4.h
index 137768cae7..ebde52e49a 100644
--- a/drivers/pci/pcie_layerscape_gen4.h
+++ b/drivers/pci/pcie_layerscape_gen4.h
@@ -58,6 +58,10 @@
 #define INI_VF_SHIFT				0
 #define GPEX_SRIOV_VF_OFFSET_STRIDE(pf)		(0x704 + (pf) * 4)
 
+#define GPEX_ACK_REPLAY_TO			0x438
+#define ACK_LAT_TO_VAL_SHIFT			0
+#define ACK_LAT_TO_VAL_MASK			0x1fff
+
 /* PAB CSR */
 #define PAB_CTRL				0x808
 #define PAB_CTRL_APIO_EN			BIT(0)
diff --git a/include/pci_ids.h b/include/pci_ids.h
index fdda679cc0..92a4339e3e 100644
--- a/include/pci_ids.h
+++ b/include/pci_ids.h
@@ -2481,6 +2481,7 @@
 #define PCI_DEVICE_ID_MPC8641		0x7010
 #define PCI_DEVICE_ID_MPC8641D		0x7011
 #define PCI_DEVICE_ID_MPC8610		0x7018
+#define PCI_DEVICE_ID_LX2160A		0x8D80
 
 #define PCI_VENDOR_ID_PASEMI		0x1959
 
-- 
2.17.1



More information about the U-Boot mailing list