The RX and TX termination values measured by the combo PHY are OR'd into AFE_RTERM_REG (PCIE_RX_REG1) and TX_RTERM_REG (PCIE_TX_REG1) without clearing those fields first, so any bit already set there, by reset or by an earlier stage, ends up in the result. EN_RTERM, which enables the refclock receiver termination, is never set.
Linux's k1_pcie_phy_init_pcie() clears each field before writing the calibrated value and sets EN_RTERM, on every lane. Do the same. Signed-off-by: Dave Klotz <[email protected]> --- drivers/phy/spacemit/phy-k1-pcie.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/phy/spacemit/phy-k1-pcie.c b/drivers/phy/spacemit/phy-k1-pcie.c index 308f7dec79..ab8349f7d1 100644 --- a/drivers/phy/spacemit/phy-k1-pcie.c +++ b/drivers/phy/spacemit/phy-k1-pcie.c @@ -231,10 +231,15 @@ static int k1_pcie_phy_init(struct phy *phy) lane = (k1_phy->pcie_lanes == 1) ? 1 : 2; - /* Apply rterm calibration value: LSB to RX_REG1 */ + /* + * Apply rterm calibration value: LSB to RX_REG1, and enable + * refclock receiver termination + */ for (i = 0; i < lane; i++) { val = readl(regs + PCIE_RX_REG1 + PHY_LANE_OFFSET * i); + val &= ~AFE_RTERM_REG; val |= FIELD_PREP(AFE_RTERM_REG, k1_phy_rterm_rx()); + val |= EN_RTERM; writel(val, regs + PCIE_RX_REG1 + PHY_LANE_OFFSET * i); } @@ -248,6 +253,7 @@ static int k1_pcie_phy_init(struct phy *phy) /* Apply rterm MSB to TX_REG1 */ for (i = 0; i < lane; i++) { val = readl(regs + PCIE_TX_REG1 + PHY_LANE_OFFSET * i); + val &= ~TX_RTERM_REG; val |= FIELD_PREP(TX_RTERM_REG, k1_phy_rterm_tx()); writel(val, regs + PCIE_TX_REG1 + PHY_LANE_OFFSET * i); } -- 2.55.0
