]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
PCI: qcom: Add RX lane margining settings for 16.0 GT/s
authorShashank Babu Chinta Venkata <quic_schintav@quicinc.com>
Wed, 11 Sep 2024 15:26:29 +0000 (20:56 +0530)
committerKrzysztof Wilczyński <kwilczynski@kernel.org>
Fri, 13 Sep 2024 14:44:59 +0000 (14:44 +0000)
Add RX lane margining settings for 16.0 GT/s (GEN 4) data rate.

These settings improve link stability while operating at high date
rates and helps to improve signal quality.

Link: https://lore.kernel.org/linux-pci/20240911-pci-qcom-gen4-stability-v7-4-743f5c1fd027@linaro.org
Tested-by: Johan Hovold <johan+linaro@kernel.org>
Signed-off-by: Shashank Babu Chinta Venkata <quic_schintav@quicinc.com>
[mani: dropped the code refactoring and minor changes]
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
[kwilczynski: commit log]
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
Reviewed-by: Johan Hovold <johan+linaro@kernel.org>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
drivers/pci/controller/dwc/pcie-designware.h
drivers/pci/controller/dwc/pcie-qcom-common.c
drivers/pci/controller/dwc/pcie-qcom-common.h
drivers/pci/controller/dwc/pcie-qcom-ep.c
drivers/pci/controller/dwc/pcie-qcom.c

index 67cc2677ab2e71a4a83908691311a60c4cbd10ad..347ab74ac35aa4f061bc9d1f27c97e5fb9749107 100644 (file)
 
 #define PCIE_PL_CHK_REG_ERR_ADDR                       0xB28
 
+/*
+ * 16.0 GT/s (Gen 4) lane margining register definitions
+ */
+#define GEN4_LANE_MARGINING_1_OFF              0xB80
+#define MARGINING_MAX_VOLTAGE_OFFSET           GENMASK(29, 24)
+#define MARGINING_NUM_VOLTAGE_STEPS            GENMASK(22, 16)
+#define MARGINING_MAX_TIMING_OFFSET            GENMASK(13, 8)
+#define MARGINING_NUM_TIMING_STEPS             GENMASK(5, 0)
+
+#define GEN4_LANE_MARGINING_2_OFF              0xB84
+#define MARGINING_IND_ERROR_SAMPLER            BIT(28)
+#define MARGINING_SAMPLE_REPORTING_METHOD      BIT(27)
+#define MARGINING_IND_LEFT_RIGHT_TIMING                BIT(26)
+#define MARGINING_IND_UP_DOWN_VOLTAGE          BIT(25)
+#define MARGINING_VOLTAGE_SUPPORTED            BIT(24)
+#define MARGINING_MAXLANES                     GENMASK(20, 16)
+#define MARGINING_SAMPLE_RATE_TIMING           GENMASK(13, 8)
+#define MARGINING_SAMPLE_RATE_VOLTAGE          GENMASK(5, 0)
 /*
  * iATU Unroll-specific register definitions
  * From 4.80 core version the address translation will be made by unroll
index 596a35449de1216f99858d89fafd26a01da013c6..3aad19b56da8f6ea6525f1aad0102a4d8df0369b 100644 (file)
@@ -45,3 +45,34 @@ void qcom_pcie_common_set_16gt_equalization(struct dw_pcie *pci)
        dw_pcie_writel_dbi(pci, GEN3_EQ_CONTROL_OFF, reg);
 }
 EXPORT_SYMBOL_GPL(qcom_pcie_common_set_16gt_equalization);
+
+void qcom_pcie_common_set_16gt_lane_margining(struct dw_pcie *pci)
+{
+       u32 reg;
+
+       reg = dw_pcie_readl_dbi(pci, GEN4_LANE_MARGINING_1_OFF);
+       reg &= ~(MARGINING_MAX_VOLTAGE_OFFSET |
+               MARGINING_NUM_VOLTAGE_STEPS |
+               MARGINING_MAX_TIMING_OFFSET |
+               MARGINING_NUM_TIMING_STEPS);
+       reg |= FIELD_PREP(MARGINING_MAX_VOLTAGE_OFFSET, 0x24) |
+               FIELD_PREP(MARGINING_NUM_VOLTAGE_STEPS, 0x78) |
+               FIELD_PREP(MARGINING_MAX_TIMING_OFFSET, 0x32) |
+               FIELD_PREP(MARGINING_NUM_TIMING_STEPS, 0x10);
+       dw_pcie_writel_dbi(pci, GEN4_LANE_MARGINING_1_OFF, reg);
+
+       reg = dw_pcie_readl_dbi(pci, GEN4_LANE_MARGINING_2_OFF);
+       reg |= MARGINING_IND_ERROR_SAMPLER |
+               MARGINING_SAMPLE_REPORTING_METHOD |
+               MARGINING_IND_LEFT_RIGHT_TIMING |
+               MARGINING_VOLTAGE_SUPPORTED;
+       reg &= ~(MARGINING_IND_UP_DOWN_VOLTAGE |
+               MARGINING_MAXLANES |
+               MARGINING_SAMPLE_RATE_TIMING |
+               MARGINING_SAMPLE_RATE_VOLTAGE);
+       reg |= FIELD_PREP(MARGINING_MAXLANES, pci->num_lanes) |
+               FIELD_PREP(MARGINING_SAMPLE_RATE_TIMING, 0x3f) |
+               FIELD_PREP(MARGINING_SAMPLE_RATE_VOLTAGE, 0x3f);
+       dw_pcie_writel_dbi(pci, GEN4_LANE_MARGINING_2_OFF, reg);
+}
+EXPORT_SYMBOL_GPL(qcom_pcie_common_set_16gt_lane_margining);
index 536387e02e292e8d3461c9cf1c94cb2d441d8717..7d88d29e476611a302c8bff9afaff19ab9a917a9 100644 (file)
@@ -9,5 +9,6 @@
 struct dw_pcie;
 
 void qcom_pcie_common_set_16gt_equalization(struct dw_pcie *pci);
+void qcom_pcie_common_set_16gt_lane_margining(struct dw_pcie *pci);
 
 #endif
index 310d52393392fa209d0cce2453505819c4d1e02b..aa8443c995e7b2f826bc403950a4048fdbce7eda 100644 (file)
@@ -487,8 +487,10 @@ static int qcom_pcie_perst_deassert(struct dw_pcie *pci)
                goto err_disable_resources;
        }
 
-       if (pcie_link_speed[pci->max_link_speed] == PCIE_SPEED_16_0GT)
+       if (pcie_link_speed[pci->max_link_speed] == PCIE_SPEED_16_0GT) {
                qcom_pcie_common_set_16gt_equalization(pci);
+               qcom_pcie_common_set_16gt_lane_margining(pci);
+       }
 
        /*
         * The physical address of the MMIO region which is exposed as the BAR
index 1e84366ac0bb2a5b25048d496ac1a2af2e783324..22028d10b9944c11896514c4be2bcc098446b76c 100644 (file)
@@ -296,8 +296,10 @@ static int qcom_pcie_start_link(struct dw_pcie *pci)
 {
        struct qcom_pcie *pcie = to_qcom_pcie(pci);
 
-       if (pcie_link_speed[pci->max_link_speed] == PCIE_SPEED_16_0GT)
+       if (pcie_link_speed[pci->max_link_speed] == PCIE_SPEED_16_0GT) {
                qcom_pcie_common_set_16gt_equalization(pci);
+               qcom_pcie_common_set_16gt_lane_margining(pci);
+       }
 
        /* Enable Link Training state machine */
        if (pcie->cfg->ops->ltssm_enable)