Message ID | 20201021143026.406-1-s.hauer@pengutronix.de (mailing list archive) |
---|---|
State | Superseded, archived |
Headers | show |
Series | clk: si5351: Wait for bit clear after PLL reset | expand |
Hi All, Any feedback to this one? It fixes a real issue here. Sascha On Wed, Oct 21, 2020 at 04:30:26PM +0200, Sascha Hauer wrote: > Documentation states that SI5351_PLL_RESET_B and SI5351_PLL_RESET_A bits > are self clearing bits, so wait until they are cleared before > continuing. > This fixes a case when the clock doesn't come up properly after a PLL > reset. It worked properly when the frequency was below 900MHz, but with > 900MHz it only works when we are waiting for the bit to clear. > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> > --- > drivers/clk/clk-si5351.c | 13 ++++++++++--- > 1 file changed, 10 insertions(+), 3 deletions(-) > > diff --git a/drivers/clk/clk-si5351.c b/drivers/clk/clk-si5351.c > index 1e1702e609cb..57e4597cdf4c 100644 > --- a/drivers/clk/clk-si5351.c > +++ b/drivers/clk/clk-si5351.c > @@ -902,6 +902,10 @@ static int _si5351_clkout_set_disable_state( > static void _si5351_clkout_reset_pll(struct si5351_driver_data *drvdata, int num) > { > u8 val = si5351_reg_read(drvdata, SI5351_CLK0_CTRL + num); > + u8 mask = val & SI5351_CLK_PLL_SELECT ? SI5351_PLL_RESET_B : > + SI5351_PLL_RESET_A; > + unsigned int v; > + int err; > > switch (val & SI5351_CLK_INPUT_MASK) { > case SI5351_CLK_INPUT_XTAL: > @@ -909,9 +913,12 @@ static void _si5351_clkout_reset_pll(struct si5351_driver_data *drvdata, int num > return; /* pll not used, no need to reset */ > } > > - si5351_reg_write(drvdata, SI5351_PLL_RESET, > - val & SI5351_CLK_PLL_SELECT ? SI5351_PLL_RESET_B : > - SI5351_PLL_RESET_A); > + si5351_reg_write(drvdata, SI5351_PLL_RESET, mask); > + > + err = regmap_read_poll_timeout(drvdata->regmap, SI5351_PLL_RESET, v, > + !(v & mask), 0, 20000); > + if (err < 0) > + dev_err(&drvdata->client->dev, "Reset bit didn't clear\n"); > > dev_dbg(&drvdata->client->dev, "%s - %s: pll = %d\n", > __func__, clk_hw_get_name(&drvdata->clkout[num].hw), > -- > 2.20.1 > >
diff --git a/drivers/clk/clk-si5351.c b/drivers/clk/clk-si5351.c index 1e1702e609cb..57e4597cdf4c 100644 --- a/drivers/clk/clk-si5351.c +++ b/drivers/clk/clk-si5351.c @@ -902,6 +902,10 @@ static int _si5351_clkout_set_disable_state( static void _si5351_clkout_reset_pll(struct si5351_driver_data *drvdata, int num) { u8 val = si5351_reg_read(drvdata, SI5351_CLK0_CTRL + num); + u8 mask = val & SI5351_CLK_PLL_SELECT ? SI5351_PLL_RESET_B : + SI5351_PLL_RESET_A; + unsigned int v; + int err; switch (val & SI5351_CLK_INPUT_MASK) { case SI5351_CLK_INPUT_XTAL: @@ -909,9 +913,12 @@ static void _si5351_clkout_reset_pll(struct si5351_driver_data *drvdata, int num return; /* pll not used, no need to reset */ } - si5351_reg_write(drvdata, SI5351_PLL_RESET, - val & SI5351_CLK_PLL_SELECT ? SI5351_PLL_RESET_B : - SI5351_PLL_RESET_A); + si5351_reg_write(drvdata, SI5351_PLL_RESET, mask); + + err = regmap_read_poll_timeout(drvdata->regmap, SI5351_PLL_RESET, v, + !(v & mask), 0, 20000); + if (err < 0) + dev_err(&drvdata->client->dev, "Reset bit didn't clear\n"); dev_dbg(&drvdata->client->dev, "%s - %s: pll = %d\n", __func__, clk_hw_get_name(&drvdata->clkout[num].hw),
Documentation states that SI5351_PLL_RESET_B and SI5351_PLL_RESET_A bits are self clearing bits, so wait until they are cleared before continuing. This fixes a case when the clock doesn't come up properly after a PLL reset. It worked properly when the frequency was below 900MHz, but with 900MHz it only works when we are waiting for the bit to clear. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/clk/clk-si5351.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)