The current implementation of serdes_am654_mux_clk_set_parent() assumes that the register for programming the clock parents is exclusive to the SERDES instance. However, that isn't the case when both instances of the SERDES on the AM654 SoC are used (for PCIe x2 Lane as an example), which results in the second SERDES instance's clock parent programming overwriting that of the first one.
Fix this by using a dynamic mask rather than the existing static mask namely SERDES_CTL_CLK_SEL_MASK. Signed-off-by: Siddharth Vadapalli <[email protected]> --- drivers/phy/phy-ti-am654.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/phy/phy-ti-am654.c b/drivers/phy/phy-ti-am654.c index c3d9972397a..23a5d1483b2 100644 --- a/drivers/phy/phy-ti-am654.c +++ b/drivers/phy/phy-ti-am654.c @@ -142,8 +142,8 @@ static int mux_table[SERDES_NUM_CLOCKS][3] = { static int serdes_am654_mux_clk_set_parent(struct clk *clk, struct clk *parent) { struct serdes_am654_mux_clk_data *data = dev_get_priv(clk->dev); - u32 val; - int i; + u32 val, mask = 0; + int i, j; debug("%s(clk=%s, parent=%s)\n", __func__, clk->dev->name, parent->dev->name); @@ -169,10 +169,16 @@ static int serdes_am654_mux_clk_set_parent(struct clk *clk, struct clk *parent) if (i >= data->parents.count) return -EINVAL; + for (j = 0; j < SERDES_NUM_CLOCKS; j++) { + if (mux_table[clk->id][j] != -1) + mask |= mux_table[clk->id][j]; + } + + mask <<= SERDES_CTL_CLK_SEL_SHIFT; val = mux_table[clk->id][i]; val <<= SERDES_CTL_CLK_SEL_SHIFT; - regmap_update_bits(data->regmap, 0, SERDES_CTL_CLK_SEL_MASK, val); + regmap_update_bits(data->regmap, 0, mask, val); return 0; } -- 2.51.1
