OpenWrt – Rev 1

Subversion Repositories:
Rev:
From eddd13215d0f2b549ebc5f0e8796d5b1231f90a0 Mon Sep 17 00:00:00 2001
From: Sham Muthayyan <smuthayy@codeaurora.org>
Date: Tue, 19 Jul 2016 19:58:22 +0530
Subject: PCI: qcom: Fixed IPQ806x PCIE init changes

Change-Id: Ic319b1aec27a47809284759f8fcb6a8815b7cf7e
Signed-off-by: Sham Muthayyan <smuthayy@codeaurora.org>
---
 drivers/pci/host/pcie-qcom.c | 62 +++++++++++++++++++++++++++++++++++++-------
 1 file changed, 53 insertions(+), 9 deletions(-)

--- a/drivers/pci/dwc/pcie-qcom.c
+++ b/drivers/pci/dwc/pcie-qcom.c
@@ -52,7 +52,13 @@
 #define PCIE_CAP_CPL_TIMEOUT_DISABLE           0x10
 
 #define PCIE20_PARF_PHY_CTRL                   0x40
+#define PHY_CTRL_PHY_TX0_TERM_OFFSET_MASK      (0x1f << 16)
+#define PHY_CTRL_PHY_TX0_TERM_OFFSET(x)                (x << 16)
+
 #define PCIE20_PARF_PHY_REFCLK                 0x4C
+#define REF_SSP_EN                             BIT(16)
+#define REF_USE_PAD                            BIT(12)
+
 #define PCIE20_PARF_DBI_BASE_ADDR              0x168
 #define PCIE20_PARF_SLV_ADDR_SPACE_SIZE                0x16C
 #define PCIE20_PARF_MHI_CLOCK_RESET_CTRL       0x174
@@ -83,6 +89,18 @@
 #define DBI_RO_WR_EN                           1
 
 #define PERST_DELAY_US                         1000
+/* PARF registers */
+#define PCIE20_PARF_PCS_DEEMPH                 0x34
+#define PCS_DEEMPH_TX_DEEMPH_GEN1(x)           (x << 16)
+#define PCS_DEEMPH_TX_DEEMPH_GEN2_3_5DB(x)     (x << 8)
+#define PCS_DEEMPH_TX_DEEMPH_GEN2_6DB(x)       (x << 0)
+
+#define PCIE20_PARF_PCS_SWING                  0x38
+#define PCS_SWING_TX_SWING_FULL(x)             (x << 8)
+#define PCS_SWING_TX_SWING_LOW(x)              (x << 0)
+
+#define PCIE20_PARF_CONFIG_BITS                        0x50
+#define PHY_RX0_EQ(x)                          (x << 24)
 
 #define PCIE20_v3_PARF_SLV_ADDR_SPACE_SIZE     0x358
 #define SLV_ADDR_SPACE_SZ                      0x10000000
@@ -102,6 +120,7 @@ struct qcom_pcie_resources_2_1_0 {
        struct regulator *vdda;
        struct regulator *vdda_phy;
        struct regulator *vdda_refclk;
+       uint8_t phy_tx0_term_offset;
 };
 
 struct qcom_pcie_resources_1_0_0 {
@@ -179,6 +198,16 @@ struct qcom_pcie {
 
 #define to_qcom_pcie(x)                dev_get_drvdata((x)->dev)
 
+static inline void
+writel_masked(void __iomem *addr, u32 clear_mask, u32 set_mask)
+{
+       u32 val = readl(addr);
+
+       val &= ~clear_mask;
+       val |= set_mask;
+       writel(val, addr);
+}
+
 static void qcom_ep_reset_assert(struct qcom_pcie *pcie)
 {
        gpiod_set_value_cansleep(pcie->reset, 1);
@@ -280,6 +309,10 @@ static int qcom_pcie_get_resources_2_1_0
        if (IS_ERR(res->ext_reset))
                return PTR_ERR(res->ext_reset);
 
+       if (of_property_read_u8(dev->of_node, "phy-tx0-term-offset",
+                               &res->phy_tx0_term_offset))
+               res->phy_tx0_term_offset = 0;
+
        res->phy_reset = devm_reset_control_get_exclusive(dev, "phy");
        return PTR_ERR_OR_ZERO(res->phy_reset);
 }
@@ -309,7 +342,6 @@ static int qcom_pcie_init_2_1_0(struct q
        struct qcom_pcie_resources_2_1_0 *res = &pcie->res.v2_1_0;
        struct dw_pcie *pci = pcie->pci;
        struct device *dev = pci->dev;
-       u32 val;
        int ret;
 
        ret = reset_control_assert(res->ahb_reset);
@@ -378,15 +410,26 @@ static int qcom_pcie_init_2_1_0(struct q
                goto err_deassert_ahb;
        }
 
-       /* enable PCIe clocks and resets */
-       val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL);
-       val &= ~BIT(0);
-       writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL);
-
-       /* enable external reference clock */
-       val = readl(pcie->parf + PCIE20_PARF_PHY_REFCLK);
-       val |= BIT(16);
-       writel(val, pcie->parf + PCIE20_PARF_PHY_REFCLK);
+       writel_masked(pcie->parf + PCIE20_PARF_PHY_CTRL, BIT(0), 0);
+
+       /* Set Tx termination offset */
+       writel_masked(pcie->parf + PCIE20_PARF_PHY_CTRL,
+                     PHY_CTRL_PHY_TX0_TERM_OFFSET_MASK,
+                     PHY_CTRL_PHY_TX0_TERM_OFFSET(res->phy_tx0_term_offset));
+
+       /* PARF programming */
+       writel(PCS_DEEMPH_TX_DEEMPH_GEN1(0x18) |
+              PCS_DEEMPH_TX_DEEMPH_GEN2_3_5DB(0x18) |
+              PCS_DEEMPH_TX_DEEMPH_GEN2_6DB(0x22),
+              pcie->parf + PCIE20_PARF_PCS_DEEMPH);
+       writel(PCS_SWING_TX_SWING_FULL(0x78) |
+              PCS_SWING_TX_SWING_LOW(0x78),
+              pcie->parf + PCIE20_PARF_PCS_SWING);
+       writel(PHY_RX0_EQ(0x4), pcie->parf + PCIE20_PARF_CONFIG_BITS);
+
+       /* Enable reference clock */
+       writel_masked(pcie->parf + PCIE20_PARF_PHY_REFCLK,
+                     REF_USE_PAD, REF_SSP_EN);
 
        ret = reset_control_deassert(res->phy_reset);
        if (ret) {