[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20201130091033.1687-1-s.hauer@pengutronix.de>
Date: Mon, 30 Nov 2020 10:10:33 +0100
From: Sascha Hauer <s.hauer@...gutronix.de>
To: linux-clk@...r.kernel.org
Cc: Michael Turquette <mturquette@...libre.com>,
Stephen Boyd <sboyd@...nel.org>, linux-kernel@...r.kernel.org,
Sebastian Hesselbarth <sebastian.hesselbarth@...il.com>,
Sascha Hauer <s.hauer@...gutronix.de>
Subject: [PATCH resend] 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@...gutronix.de>
---
I've already sent this in October without any reaction, this is just a
resend with +Cc Stephen Boyd and +Cc linux-kernel@...r.kernel.org
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
Powered by blists - more mailing lists