lkml.org 
[lkml]   [2021]   [Jul]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.13 590/800] clk: si5341: Wait for DEVICE_READY on startup
    Date
    From: Robert Hancock <robert.hancock@calian.com>

    [ Upstream commit 6e7d2de1e000d36990923ed80d2e78dfcb545cee ]

    The Si5341 datasheet warns that before accessing any other registers,
    including the PAGE register, we need to wait for the DEVICE_READY register
    to indicate the device is ready, or the process of the device loading its
    state from NVM can be corrupted. Wait for DEVICE_READY on startup before
    continuing initialization. This is done using a raw I2C register read
    prior to setting up regmap to avoid any potential unwanted automatic PAGE
    register accesses from regmap at this stage.

    Fixes: 3044a860fd ("clk: Add Si5341/Si5340 driver")
    Signed-off-by: Robert Hancock <robert.hancock@calian.com>
    Link: https://lore.kernel.org/r/20210325192643.2190069-3-robert.hancock@calian.com
    Signed-off-by: Stephen Boyd <sboyd@kernel.org>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/clk/clk-si5341.c | 32 ++++++++++++++++++++++++++++++++
    1 file changed, 32 insertions(+)

    diff --git a/drivers/clk/clk-si5341.c b/drivers/clk/clk-si5341.c
    index e0446e66fa64..b8a960e927bc 100644
    --- a/drivers/clk/clk-si5341.c
    +++ b/drivers/clk/clk-si5341.c
    @@ -94,6 +94,7 @@ struct clk_si5341_output_config {
    #define SI5341_STATUS 0x000C
    #define SI5341_SOFT_RST 0x001C
    #define SI5341_IN_SEL 0x0021
    +#define SI5341_DEVICE_READY 0x00FE
    #define SI5341_XAXB_CFG 0x090E
    #define SI5341_IN_EN 0x0949
    #define SI5341_INX_TO_PFD_EN 0x094A
    @@ -1189,6 +1190,32 @@ static const struct regmap_range_cfg si5341_regmap_ranges[] = {
    },
    };

    +static int si5341_wait_device_ready(struct i2c_client *client)
    +{
    + int count;
    +
    + /* Datasheet warns: Any attempt to read or write any register other
    + * than DEVICE_READY before DEVICE_READY reads as 0x0F may corrupt the
    + * NVM programming and may corrupt the register contents, as they are
    + * read from NVM. Note that this includes accesses to the PAGE register.
    + * Also: DEVICE_READY is available on every register page, so no page
    + * change is needed to read it.
    + * Do this outside regmap to avoid automatic PAGE register access.
    + * May take up to 300ms to complete.
    + */
    + for (count = 0; count < 15; ++count) {
    + s32 result = i2c_smbus_read_byte_data(client,
    + SI5341_DEVICE_READY);
    + if (result < 0)
    + return result;
    + if (result == 0x0F)
    + return 0;
    + msleep(20);
    + }
    + dev_err(&client->dev, "timeout waiting for DEVICE_READY\n");
    + return -EIO;
    +}
    +
    static const struct regmap_config si5341_regmap_config = {
    .reg_bits = 8,
    .val_bits = 8,
    @@ -1385,6 +1412,11 @@ static int si5341_probe(struct i2c_client *client,

    data->i2c_client = client;

    + /* Must be done before otherwise touching hardware */
    + err = si5341_wait_device_ready(client);
    + if (err)
    + return err;
    +
    for (i = 0; i < SI5341_NUM_INPUTS; ++i) {
    input = devm_clk_get(&client->dev, si5341_input_clock_names[i]);
    if (IS_ERR(input)) {
    --
    2.30.2


    \
     
     \ /
      Last update: 2021-07-12 11:10    [W:2.868 / U:0.448 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site