diff options
| author | 2025-09-04 14:52:23 +0800 | |
|---|---|---|
| committer | 2025-09-04 22:24:04 +0530 | |
| commit | 37bf0f4e39de9b53bc6f8d3702b021e2c6b5bae3 (patch) | |
| tree | 671eeb164f843a9b90e0a273f993b84159257b92 /drivers/pci/controller/dwc/pcie-qcom-common.c | |
| parent | PCI: qcom: Restrict port parsing only to PCIe bridge child nodes (diff) | |
| download | wireguard-linux-37bf0f4e39de9b53bc6f8d3702b021e2c6b5bae3.tar.xz wireguard-linux-37bf0f4e39de9b53bc6f8d3702b021e2c6b5bae3.zip | |
PCI: qcom: Add equalization settings for 8.0 GT/s and 32.0 GT/s
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
Diffstat (limited to 'drivers/pci/controller/dwc/pcie-qcom-common.c')
| -rw-r--r-- | drivers/pci/controller/dwc/pcie-qcom-common.c | 58 |
1 files changed, 34 insertions, 24 deletions
diff --git a/drivers/pci/controller/dwc/pcie-qcom-common.c b/drivers/pci/controller/dwc/pcie-qcom-common.c index 3aad19b56da8..0c6f4514f922 100644 --- a/drivers/pci/controller/dwc/pcie-qcom-common.c +++ b/drivers/pci/controller/dwc/pcie-qcom-common.c @@ -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) { |
