clk: si5351: Wait for bit clear after PLL reset
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> Link: https://lore.kernel.org/r/20201130091033.1687-1-s.hauer@pengutronix.de Signed-off-by: Stephen Boyd <sboyd@kernel.org>
This commit is contained in:
parent
3650b228f8
commit
5142cbcea3
|
@ -902,6 +902,10 @@ static int _si5351_clkout_set_disable_state(
|
||||||
static void _si5351_clkout_reset_pll(struct si5351_driver_data *drvdata, int num)
|
static void _si5351_clkout_reset_pll(struct si5351_driver_data *drvdata, int num)
|
||||||
{
|
{
|
||||||
u8 val = si5351_reg_read(drvdata, SI5351_CLK0_CTRL + 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) {
|
switch (val & SI5351_CLK_INPUT_MASK) {
|
||||||
case SI5351_CLK_INPUT_XTAL:
|
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 */
|
return; /* pll not used, no need to reset */
|
||||||
}
|
}
|
||||||
|
|
||||||
si5351_reg_write(drvdata, SI5351_PLL_RESET,
|
si5351_reg_write(drvdata, SI5351_PLL_RESET, mask);
|
||||||
val & SI5351_CLK_PLL_SELECT ? SI5351_PLL_RESET_B :
|
|
||||||
SI5351_PLL_RESET_A);
|
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",
|
dev_dbg(&drvdata->client->dev, "%s - %s: pll = %d\n",
|
||||||
__func__, clk_hw_get_name(&drvdata->clkout[num].hw),
|
__func__, clk_hw_get_name(&drvdata->clkout[num].hw),
|
||||||
|
|
Loading…
Reference in New Issue