CLKSEL in PCIE_RC_CAL_REG2 selects the input clock of the lane's RC calibration. It is set only on lane 0, so the second lane of ports B and C keeps its reset value, and it is OR'd in, so a value already in the field is merged with CLKSEL_24M rather than replaced.
Linux's k1_pcie_phy_init_pcie() sets CLKSEL to 24 MHz on every lane, before toggling RC_CAL_TOGGLE on that lane. Do the same, clearing the field before writing it. (Linux masks with "val &= CLKSEL", which also clears every other field of the register; this keeps the other fields, as this driver did before.) Signed-off-by: Dave Klotz <[email protected]> --- drivers/phy/spacemit/phy-k1-pcie.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/phy/spacemit/phy-k1-pcie.c b/drivers/phy/spacemit/phy-k1-pcie.c index ab8349f7d1..0e18f29024 100644 --- a/drivers/phy/spacemit/phy-k1-pcie.c +++ b/drivers/phy/spacemit/phy-k1-pcie.c @@ -265,10 +265,13 @@ static int k1_pcie_phy_init(struct phy *phy) writel(val, regs + PCIE_TX_REG1 + PHY_LANE_OFFSET * i); } - /* Set CLKSEL_24M on lane0 */ - val = readl(regs + PCIE_RC_CAL_REG2); - val |= FIELD_PREP(CLKSEL, CLKSEL_24M); - writel(val, regs + PCIE_RC_CAL_REG2); + /* Select the 24 MHz input clock for all lanes */ + for (i = 0; i < lane; i++) { + val = readl(regs + PCIE_RC_CAL_REG2 + PHY_LANE_OFFSET * i); + val &= ~CLKSEL; + val |= FIELD_PREP(CLKSEL, CLKSEL_24M); + writel(val, regs + PCIE_RC_CAL_REG2 + PHY_LANE_OFFSET * i); + } /* Toggle RC_CAL_TOGGLE for all lanes */ for (i = 0; i < lane; i++) { -- 2.55.0
