]> www.infradead.org Git - users/hch/misc.git/commitdiff
PCI: qcom: Add equalization settings for 8.0 GT/s and 32.0 GT/s
authorZiyue Zhang <ziyue.zhang@oss.qualcomm.com>
Thu, 4 Sep 2025 06:52:23 +0000 (14:52 +0800)
committerManivannan Sadhasivam <mani@kernel.org>
Thu, 4 Sep 2025 16:54:04 +0000 (22:24 +0530)
Add lane equalization setting for 8.0 GT/s and 32.0 GT/s to enhance link
stability and avoid AER Correctable Errors reported on some platforms
(eg. SA8775P).

8.0 GT/s, 16.0 GT/s and 32.0 GT/s require the same equalization setting.
This setting is programmed into a group of shadow registers, which can be
switched to configure equalization for different speeds by writing 00b,
01b and 10b to `RATE_SHADOW_SEL`.

Hence, program equalization registers in a loop using link speed as index,
so that equalization setting can be programmed for 8.0 GT/s, 16.0 GT/s
and 32.0 GT/s.

Fixes: 489f14be0e0a ("arm64: dts: qcom: sa8775p: Add pcie0 and pcie1 nodes")
Co-developed-by: Qiang Yu <qiang.yu@oss.qualcomm.com>
Signed-off-by: Qiang Yu <qiang.yu@oss.qualcomm.com>
Signed-off-by: Ziyue Zhang <ziyue.zhang@oss.qualcomm.com>
[mani: wrapped the warning to fit 100 columns, used post-increment for loop]
Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>
Link: https://patch.msgid.link/20250904065225.1762793-2-ziyue.zhang@oss.qualcomm.com
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 00f52d472dcdd794013a865ad6c4c7cc251edb48..cc71a2d90cd48c48c2d87d020b6240403bb0a40c 100644 (file)
 #define GEN3_RELATED_OFF_GEN3_EQ_DISABLE       BIT(16)
 #define GEN3_RELATED_OFF_RATE_SHADOW_SEL_SHIFT 24
 #define GEN3_RELATED_OFF_RATE_SHADOW_SEL_MASK  GENMASK(25, 24)
-#define GEN3_RELATED_OFF_RATE_SHADOW_SEL_16_0GT        0x1
 
 #define GEN3_EQ_CONTROL_OFF                    0x8A8
 #define GEN3_EQ_CONTROL_OFF_FB_MODE            GENMASK(3, 0)
index 3aad19b56da8f6ea6525f1aad0102a4d8df0369b..0c6f4514f922f406af788e6313ae3076eda78fe1 100644 (file)
@@ -8,9 +8,11 @@
 #include "pcie-designware.h"
 #include "pcie-qcom-common.h"
 
-void qcom_pcie_common_set_16gt_equalization(struct dw_pcie *pci)
+void qcom_pcie_common_set_equalization(struct dw_pcie *pci)
 {
+       struct device *dev = pci->dev;
        u32 reg;
+       u16 speed;
 
        /*
         * GEN3_RELATED_OFF register is repurposed to apply equalization
@@ -19,32 +21,40 @@ void qcom_pcie_common_set_16gt_equalization(struct dw_pcie *pci)
         * determines the data rate for which these equalization settings are
         * applied.
         */
-       reg = dw_pcie_readl_dbi(pci, GEN3_RELATED_OFF);
-       reg &= ~GEN3_RELATED_OFF_GEN3_ZRXDC_NONCOMPL;
-       reg &= ~GEN3_RELATED_OFF_RATE_SHADOW_SEL_MASK;
-       reg |= FIELD_PREP(GEN3_RELATED_OFF_RATE_SHADOW_SEL_MASK,
-                         GEN3_RELATED_OFF_RATE_SHADOW_SEL_16_0GT);
-       dw_pcie_writel_dbi(pci, GEN3_RELATED_OFF, reg);
 
-       reg = dw_pcie_readl_dbi(pci, GEN3_EQ_FB_MODE_DIR_CHANGE_OFF);
-       reg &= ~(GEN3_EQ_FMDC_T_MIN_PHASE23 |
-               GEN3_EQ_FMDC_N_EVALS |
-               GEN3_EQ_FMDC_MAX_PRE_CUSROR_DELTA |
-               GEN3_EQ_FMDC_MAX_POST_CUSROR_DELTA);
-       reg |= FIELD_PREP(GEN3_EQ_FMDC_T_MIN_PHASE23, 0x1) |
-               FIELD_PREP(GEN3_EQ_FMDC_N_EVALS, 0xd) |
-               FIELD_PREP(GEN3_EQ_FMDC_MAX_PRE_CUSROR_DELTA, 0x5) |
-               FIELD_PREP(GEN3_EQ_FMDC_MAX_POST_CUSROR_DELTA, 0x5);
-       dw_pcie_writel_dbi(pci, GEN3_EQ_FB_MODE_DIR_CHANGE_OFF, reg);
+       for (speed = PCIE_SPEED_8_0GT; speed <= pcie_link_speed[pci->max_link_speed]; speed++) {
+               if (speed > PCIE_SPEED_32_0GT) {
+                       dev_warn(dev, "Skipped equalization settings for unsupported data rate\n");
+                       break;
+               }
 
-       reg = dw_pcie_readl_dbi(pci, GEN3_EQ_CONTROL_OFF);
-       reg &= ~(GEN3_EQ_CONTROL_OFF_FB_MODE |
-               GEN3_EQ_CONTROL_OFF_PHASE23_EXIT_MODE |
-               GEN3_EQ_CONTROL_OFF_FOM_INC_INITIAL_EVAL |
-               GEN3_EQ_CONTROL_OFF_PSET_REQ_VEC);
-       dw_pcie_writel_dbi(pci, GEN3_EQ_CONTROL_OFF, reg);
+               reg = dw_pcie_readl_dbi(pci, GEN3_RELATED_OFF);
+               reg &= ~GEN3_RELATED_OFF_GEN3_ZRXDC_NONCOMPL;
+               reg &= ~GEN3_RELATED_OFF_RATE_SHADOW_SEL_MASK;
+               reg |= FIELD_PREP(GEN3_RELATED_OFF_RATE_SHADOW_SEL_MASK,
+                         speed - PCIE_SPEED_8_0GT);
+               dw_pcie_writel_dbi(pci, GEN3_RELATED_OFF, reg);
+
+               reg = dw_pcie_readl_dbi(pci, GEN3_EQ_FB_MODE_DIR_CHANGE_OFF);
+               reg &= ~(GEN3_EQ_FMDC_T_MIN_PHASE23 |
+                       GEN3_EQ_FMDC_N_EVALS |
+                       GEN3_EQ_FMDC_MAX_PRE_CUSROR_DELTA |
+                       GEN3_EQ_FMDC_MAX_POST_CUSROR_DELTA);
+               reg |= FIELD_PREP(GEN3_EQ_FMDC_T_MIN_PHASE23, 0x1) |
+                       FIELD_PREP(GEN3_EQ_FMDC_N_EVALS, 0xd) |
+                       FIELD_PREP(GEN3_EQ_FMDC_MAX_PRE_CUSROR_DELTA, 0x5) |
+                       FIELD_PREP(GEN3_EQ_FMDC_MAX_POST_CUSROR_DELTA, 0x5);
+               dw_pcie_writel_dbi(pci, GEN3_EQ_FB_MODE_DIR_CHANGE_OFF, reg);
+
+               reg = dw_pcie_readl_dbi(pci, GEN3_EQ_CONTROL_OFF);
+               reg &= ~(GEN3_EQ_CONTROL_OFF_FB_MODE |
+                       GEN3_EQ_CONTROL_OFF_PHASE23_EXIT_MODE |
+                       GEN3_EQ_CONTROL_OFF_FOM_INC_INITIAL_EVAL |
+                       GEN3_EQ_CONTROL_OFF_PSET_REQ_VEC);
+               dw_pcie_writel_dbi(pci, GEN3_EQ_CONTROL_OFF, reg);
+       }
 }
-EXPORT_SYMBOL_GPL(qcom_pcie_common_set_16gt_equalization);
+EXPORT_SYMBOL_GPL(qcom_pcie_common_set_equalization);
 
 void qcom_pcie_common_set_16gt_lane_margining(struct dw_pcie *pci)
 {
index 7d88d29e476611a302c8bff9afaff19ab9a917a9..7f5ca2fd9a72fc0a22e438728a1f01160169e4ec 100644 (file)
@@ -8,7 +8,7 @@
 
 struct dw_pcie;
 
-void qcom_pcie_common_set_16gt_equalization(struct dw_pcie *pci);
+void qcom_pcie_common_set_equalization(struct dw_pcie *pci);
 void qcom_pcie_common_set_16gt_lane_margining(struct dw_pcie *pci);
 
 #endif
index bf7c6ac0f3e3962de8346ab6e75dfff1d9642aad..aaf060bf39d40b6927e190b0aba5a86dcd320d0d 100644 (file)
@@ -511,10 +511,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) {
-               qcom_pcie_common_set_16gt_equalization(pci);
+       qcom_pcie_common_set_equalization(pci);
+
+       if (pcie_link_speed[pci->max_link_speed] == PCIE_SPEED_16_0GT)
                qcom_pcie_common_set_16gt_lane_margining(pci);
-       }
 
        /*
         * The physical address of the MMIO region which is exposed as the BAR
index fbed7130d7475aafb0d8adf07427c3495921152f..a93740ae602f2a25b76e9ce61cb27d46445540f7 100644 (file)
@@ -322,10 +322,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) {
-               qcom_pcie_common_set_16gt_equalization(pci);
+       qcom_pcie_common_set_equalization(pci);
+
+       if (pcie_link_speed[pci->max_link_speed] == PCIE_SPEED_16_0GT)
                qcom_pcie_common_set_16gt_lane_margining(pci);
-       }
 
        /* Enable Link Training state machine */
        if (pcie->cfg->ops->ltssm_enable)