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

Reply via email to