summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHou Zhiqiang <Zhiqiang.Hou@nxp.com>2018-11-06 10:14:57 +0800
committerRussell King (Oracle) <rmk+kernel@armlinux.org.uk>2025-09-29 10:19:22 +0100
commit013dbeca2bb2fd73aa01d40e39638c6511cfc18d (patch)
tree837f08a277d5afc21b5599561783869f028448a4
parent4efee0482030f17ac4245ef329a0caec30a727aa (diff)
PCI: mobiveil: ls_pcie_g4: add Workaround for A-011451
When LX2 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 LX2 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 patch implemented part 1, the part 2 can be set by kernel parameter 'pci=pcie_bus_perf' This ERRATA is only for LX2160A Rev1.0, and it will be fixed in Rev2.0. Signed-off-by: Hou Zhiqiang <Zhiqiang.Hou@nxp.com> [fixed up for mainline -- rmk] Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
-rw-r--r--drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c15
-rw-r--r--drivers/pci/controller/mobiveil/pcie-mobiveil.h4
2 files changed, 19 insertions, 0 deletions
diff --git a/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c b/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c
index b07cf6de1e6e..311ff520ea95 100644
--- a/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c
+++ b/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c
@@ -80,12 +80,27 @@ static bool ls_g4_pcie_is_bridge(struct ls_g4_pcie *pcie)
return header_type == PCI_HEADER_TYPE_BRIDGE;
}
+static void workaround_A011451(struct ls_g4_pcie *pcie)
+{
+ struct mobiveil_pcie *mv_pci = &pcie->pci;
+ u32 val;
+
+ /* Set ACK latency timeout */
+ val = mobiveil_csr_readl(mv_pci, GPEX_ACK_REPLAY_TO);
+ val &= ~(ACK_LAT_TO_VAL_MASK << ACK_LAT_TO_VAL_SHIFT);
+ val |= (4 << ACK_LAT_TO_VAL_SHIFT);
+ mobiveil_csr_writel(mv_pci, val, GPEX_ACK_REPLAY_TO);
+}
+
static int ls_g4_pcie_host_init(struct mobiveil_pcie *pci)
{
struct ls_g4_pcie *pcie = to_ls_g4_pcie(pci);
pcie->rev = mobiveil_csr_readb(pci, PCI_REVISION_ID);
+ if (pcie->rev == REV_1_0)
+ workaround_A011451(pcie);
+
return 0;
}
diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil.h b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
index 77e067be4a6d..2d309eacfe64 100644
--- a/drivers/pci/controller/mobiveil/pcie-mobiveil.h
+++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
@@ -86,6 +86,10 @@
#define PAB_AXI_AMAP_PEX_WIN_H(win) PAB_REG_ADDR(0x0bac, win)
#define PAB_INTP_AXI_PIO_CLASS 0x474
+#define GPEX_ACK_REPLAY_TO 0x438
+#define ACK_LAT_TO_VAL_MASK 0x1fff
+#define ACK_LAT_TO_VAL_SHIFT 0
+
#define PAB_PEX_AMAP_CTRL(win) PAB_REG_ADDR(0x4ba0, win)
#define AMAP_CTRL_EN_SHIFT 0
#define AMAP_CTRL_TYPE_SHIFT 1