Skip to content

Commit 71dcc4d

Browse files
robhancocksedbebarino
authored andcommitted
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: 3044a86 ("clk: Add Si5341/Si5340 driver") Signed-off-by: Robert Hancock <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Stephen Boyd <[email protected]>
1 parent 78f6f40 commit 71dcc4d

File tree

1 file changed

+26
-0
lines changed

1 file changed

+26
-0
lines changed

drivers/clk/clk-si5341.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,22 @@ struct clk_si5341_output_config {
9292
#define SI5341_PN_BASE 0x0002
9393
#define SI5341_DEVICE_REV 0x0005
9494
#define SI5341_STATUS 0x000C
95+
#define SI5341_LOS 0x000D
96+
#define SI5341_STATUS_STICKY 0x0011
97+
#define SI5341_LOS_STICKY 0x0012
9598
#define SI5341_SOFT_RST 0x001C
9699
#define SI5341_IN_SEL 0x0021
97100
#define SI5341_DEVICE_READY 0x00FE
98101
#define SI5341_XAXB_CFG 0x090E
99102
#define SI5341_IN_EN 0x0949
100103
#define SI5341_INX_TO_PFD_EN 0x094A
101104

105+
/* Status bits */
106+
#define SI5341_STATUS_SYSINCAL BIT(0)
107+
#define SI5341_STATUS_LOSXAXB BIT(1)
108+
#define SI5341_STATUS_LOSREF BIT(2)
109+
#define SI5341_STATUS_LOL BIT(3)
110+
102111
/* Input selection */
103112
#define SI5341_IN_SEL_MASK 0x06
104113
#define SI5341_IN_SEL_SHIFT 1
@@ -1416,6 +1425,7 @@ static int si5341_probe(struct i2c_client *client,
14161425
unsigned int i;
14171426
struct clk_si5341_output_config config[SI5341_MAX_NUM_OUTPUTS];
14181427
bool initialization_required;
1428+
u32 status;
14191429

14201430
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
14211431
if (!data)
@@ -1583,6 +1593,22 @@ static int si5341_probe(struct i2c_client *client,
15831593
return err;
15841594
}
15851595

1596+
/* wait for device to report input clock present and PLL lock */
1597+
err = regmap_read_poll_timeout(data->regmap, SI5341_STATUS, status,
1598+
!(status & (SI5341_STATUS_LOSREF | SI5341_STATUS_LOL)),
1599+
10000, 250000);
1600+
if (err) {
1601+
dev_err(&client->dev, "Error waiting for input clock or PLL lock\n");
1602+
return err;
1603+
}
1604+
1605+
/* clear sticky alarm bits from initialization */
1606+
err = regmap_write(data->regmap, SI5341_STATUS_STICKY, 0);
1607+
if (err) {
1608+
dev_err(&client->dev, "unable to clear sticky status\n");
1609+
return err;
1610+
}
1611+
15861612
/* Free the names, clk framework makes copies */
15871613
for (i = 0; i < data->num_synth; ++i)
15881614
devm_kfree(&client->dev, (void *)synth_clock_names[i]);

0 commit comments

Comments
 (0)