Commit 71dcc4d1 authored by Robert Hancock's avatar Robert Hancock Committed by Stephen Boyd

clk: si5341: Check for input clock presence and PLL lock on startup

After initializing the device, wait for it to report that the input
clock is present and the PLL has locked before declaring success.

Fixes: 3044a860 ("clk: Add Si5341/Si5340 driver")
Signed-off-by: default avatarRobert Hancock <robert.hancock@calian.com>
Link: https://lore.kernel.org/r/20210325192643.2190069-5-robert.hancock@calian.comSigned-off-by: default avatarStephen Boyd <sboyd@kernel.org>
parent 78f6f406
......@@ -92,6 +92,9 @@ struct clk_si5341_output_config {
#define SI5341_PN_BASE 0x0002
#define SI5341_DEVICE_REV 0x0005
#define SI5341_STATUS 0x000C
#define SI5341_LOS 0x000D
#define SI5341_STATUS_STICKY 0x0011
#define SI5341_LOS_STICKY 0x0012
#define SI5341_SOFT_RST 0x001C
#define SI5341_IN_SEL 0x0021
#define SI5341_DEVICE_READY 0x00FE
......@@ -99,6 +102,12 @@ struct clk_si5341_output_config {
#define SI5341_IN_EN 0x0949
#define SI5341_INX_TO_PFD_EN 0x094A
/* Status bits */
#define SI5341_STATUS_SYSINCAL BIT(0)
#define SI5341_STATUS_LOSXAXB BIT(1)
#define SI5341_STATUS_LOSREF BIT(2)
#define SI5341_STATUS_LOL BIT(3)
/* Input selection */
#define SI5341_IN_SEL_MASK 0x06
#define SI5341_IN_SEL_SHIFT 1
......@@ -1416,6 +1425,7 @@ static int si5341_probe(struct i2c_client *client,
unsigned int i;
struct clk_si5341_output_config config[SI5341_MAX_NUM_OUTPUTS];
bool initialization_required;
u32 status;
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
if (!data)
......@@ -1583,6 +1593,22 @@ static int si5341_probe(struct i2c_client *client,
return err;
}
/* wait for device to report input clock present and PLL lock */
err = regmap_read_poll_timeout(data->regmap, SI5341_STATUS, status,
!(status & (SI5341_STATUS_LOSREF | SI5341_STATUS_LOL)),
10000, 250000);
if (err) {
dev_err(&client->dev, "Error waiting for input clock or PLL lock\n");
return err;
}
/* clear sticky alarm bits from initialization */
err = regmap_write(data->regmap, SI5341_STATUS_STICKY, 0);
if (err) {
dev_err(&client->dev, "unable to clear sticky status\n");
return err;
}
/* Free the names, clk framework makes copies */
for (i = 0; i < data->num_synth; ++i)
devm_kfree(&client->dev, (void *)synth_clock_names[i]);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment