mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-30 10:39:04 +00:00
36a96a4493
In current state there's huge regression on ipq806x target that causes the device to transmit broken/malformed frames that are not corrected/detected by error control mechanisms and other less severe issues. https://bugs.lede-project.org/index.php?do=details&task_id=1197 This finally had been narrowed down to patch 0071-pcie-qcom-fixes.patch Meanwhile QSDK contains a handful of commits that add support for ipq806x to upstream qcom pcie driver https://source.codeaurora.org/quic/qsdk/oss/kernel/linux-msm/log/drivers/pci/host/pcie-qcom.c?h=eggplant Unfortunately qca developers do not bother to push it upstream. Using those commits instead of lede 0071 patch fixes mentioned issue and probably many others as it seems that corrupted data has been originating within pcie misconfiguration. Fixes: FS#1197 and probably others Signed-off-by: Pavel Kubelun <be.dissent@gmail.com>
114 lines
4.0 KiB
Diff
114 lines
4.0 KiB
Diff
From d27c303e828d7e42f339a459d2abfe30c51698e9 Mon Sep 17 00:00:00 2001
|
|
From: Sham Muthayyan <smuthayy@codeaurora.org>
|
|
Date: Tue, 26 Jul 2016 12:28:31 +0530
|
|
Subject: PCI: qcom: Programming the PCIE iATU for IPQ806x
|
|
|
|
Resolved PCIE EP detection errors caused due to missing iATU programming.
|
|
|
|
Change-Id: Ie95c0f8cb940abc0192a8a3c4e825ddba54b72fe
|
|
Signed-off-by: Sham Muthayyan <smuthayy@codeaurora.org>
|
|
---
|
|
drivers/pci/host/pcie-qcom.c | 77 ++++++++++++++++++++++++++++++++++++++++++++
|
|
1 file changed, 77 insertions(+)
|
|
|
|
--- a/drivers/pci/host/pcie-qcom.c
|
|
+++ b/drivers/pci/host/pcie-qcom.c
|
|
@@ -52,6 +52,29 @@
|
|
#define PCIE20_ELBI_SYS_CTRL_LT_ENABLE BIT(0)
|
|
|
|
#define PCIE20_CAP 0x70
|
|
+#define PCIE20_CAP_LINKCTRLSTATUS (PCIE20_CAP + 0x10)
|
|
+
|
|
+#define PCIE20_AXI_MSTR_RESP_COMP_CTRL0 0x818
|
|
+#define PCIE20_AXI_MSTR_RESP_COMP_CTRL1 0x81c
|
|
+
|
|
+#define PCIE20_PLR_IATU_VIEWPORT 0x900
|
|
+#define PCIE20_PLR_IATU_REGION_OUTBOUND (0x0 << 31)
|
|
+#define PCIE20_PLR_IATU_REGION_INDEX(x) (x << 0)
|
|
+
|
|
+#define PCIE20_PLR_IATU_CTRL1 0x904
|
|
+#define PCIE20_PLR_IATU_TYPE_CFG0 (0x4 << 0)
|
|
+#define PCIE20_PLR_IATU_TYPE_MEM (0x0 << 0)
|
|
+
|
|
+#define PCIE20_PLR_IATU_CTRL2 0x908
|
|
+#define PCIE20_PLR_IATU_ENABLE BIT(31)
|
|
+
|
|
+#define PCIE20_PLR_IATU_LBAR 0x90C
|
|
+#define PCIE20_PLR_IATU_UBAR 0x910
|
|
+#define PCIE20_PLR_IATU_LAR 0x914
|
|
+#define PCIE20_PLR_IATU_LTAR 0x918
|
|
+#define PCIE20_PLR_IATU_UTAR 0x91c
|
|
+
|
|
+#define MSM_PCIE_DEV_CFG_ADDR 0x01000000
|
|
|
|
#define PERST_DELAY_US 1000
|
|
/* PARF registers */
|
|
@@ -163,6 +186,57 @@ static int qcom_pcie_establish_link(stru
|
|
return dw_pcie_wait_for_link(&pcie->pp);
|
|
}
|
|
|
|
+static void qcom_pcie_prog_viewport_cfg0(struct qcom_pcie *pcie, u32 busdev)
|
|
+{
|
|
+ struct pcie_port *pp = &pcie->pp;
|
|
+
|
|
+ /*
|
|
+ * program and enable address translation region 0 (device config
|
|
+ * address space); region type config;
|
|
+ * axi config address range to device config address range
|
|
+ */
|
|
+ writel(PCIE20_PLR_IATU_REGION_OUTBOUND |
|
|
+ PCIE20_PLR_IATU_REGION_INDEX(0),
|
|
+ pcie->pp.dbi_base + PCIE20_PLR_IATU_VIEWPORT);
|
|
+
|
|
+ writel(PCIE20_PLR_IATU_TYPE_CFG0, pcie->pp.dbi_base + PCIE20_PLR_IATU_CTRL1);
|
|
+ writel(PCIE20_PLR_IATU_ENABLE, pcie->pp.dbi_base + PCIE20_PLR_IATU_CTRL2);
|
|
+ writel(pp->cfg0_base, pcie->pp.dbi_base + PCIE20_PLR_IATU_LBAR);
|
|
+ writel((pp->cfg0_base >> 32), pcie->pp.dbi_base + PCIE20_PLR_IATU_UBAR);
|
|
+ writel((pp->cfg0_base + pp->cfg0_size - 1),
|
|
+ pcie->pp.dbi_base + PCIE20_PLR_IATU_LAR);
|
|
+ writel(busdev, pcie->pp.dbi_base + PCIE20_PLR_IATU_LTAR);
|
|
+ writel(0, pcie->pp.dbi_base + PCIE20_PLR_IATU_UTAR);
|
|
+}
|
|
+
|
|
+static void qcom_pcie_prog_viewport_mem2_outbound(struct qcom_pcie *pcie)
|
|
+{
|
|
+ struct pcie_port *pp = &pcie->pp;
|
|
+
|
|
+ /*
|
|
+ * program and enable address translation region 2 (device resource
|
|
+ * address space); region type memory;
|
|
+ * axi device bar address range to device bar address range
|
|
+ */
|
|
+ writel(PCIE20_PLR_IATU_REGION_OUTBOUND |
|
|
+ PCIE20_PLR_IATU_REGION_INDEX(2),
|
|
+ pcie->pp.dbi_base + PCIE20_PLR_IATU_VIEWPORT);
|
|
+
|
|
+ writel(PCIE20_PLR_IATU_TYPE_MEM, pcie->pp.dbi_base + PCIE20_PLR_IATU_CTRL1);
|
|
+ writel(PCIE20_PLR_IATU_ENABLE, pcie->pp.dbi_base + PCIE20_PLR_IATU_CTRL2);
|
|
+ writel(pp->mem_base, pcie->pp.dbi_base + PCIE20_PLR_IATU_LBAR);
|
|
+ writel((pp->mem_base >> 32), pcie->pp.dbi_base + PCIE20_PLR_IATU_UBAR);
|
|
+ writel(pp->mem_base + pp->mem_size - 1,
|
|
+ pcie->pp.dbi_base + PCIE20_PLR_IATU_LAR);
|
|
+ writel(pp->mem_bus_addr, pcie->pp.dbi_base + PCIE20_PLR_IATU_LTAR);
|
|
+ writel(upper_32_bits(pp->mem_bus_addr),
|
|
+ pcie->pp.dbi_base + PCIE20_PLR_IATU_UTAR);
|
|
+
|
|
+ /* 256B PCIE buffer setting */
|
|
+ writel(0x1, pcie->pp.dbi_base + PCIE20_AXI_MSTR_RESP_COMP_CTRL0);
|
|
+ writel(0x1, pcie->pp.dbi_base + PCIE20_AXI_MSTR_RESP_COMP_CTRL1);
|
|
+}
|
|
+
|
|
static int qcom_pcie_get_resources_v0(struct qcom_pcie *pcie)
|
|
{
|
|
struct qcom_pcie_resources_v0 *res = &pcie->res.v0;
|
|
@@ -404,6 +478,9 @@ static int qcom_pcie_init_v0(struct qcom
|
|
/* wait for clock acquisition */
|
|
usleep_range(1000, 1500);
|
|
|
|
+ qcom_pcie_prog_viewport_cfg0(pcie, MSM_PCIE_DEV_CFG_ADDR);
|
|
+ qcom_pcie_prog_viewport_mem2_outbound(pcie);
|
|
+
|
|
return 0;
|
|
|
|
err_deassert_ahb:
|