lkml.org 
[lkml]   [2022]   [Oct]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 6.0 028/862] iio: pressure: dps310: Reset chip after timeout
    Date
    From: Eddie James <eajames@linux.ibm.com>

    commit 7b4ab4abcea4c0c10b25187bf2569e5a07e9a20c upstream.

    The DPS310 chip has been observed to get "stuck" such that pressure
    and temperature measurements are never indicated as "ready" in the
    MEAS_CFG register. The only solution is to reset the device and try
    again. In order to avoid continual failures, use a boolean flag to
    only try the reset after timeout once if errors persist.

    Fixes: ba6ec48e76bc ("iio: Add driver for Infineon DPS310")
    Cc: <stable@vger.kernel.org>
    Signed-off-by: Eddie James <eajames@linux.ibm.com>
    Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
    Link: https://lore.kernel.org/r/20220915195719.136812-3-eajames@linux.ibm.com
    Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/iio/pressure/dps310.c | 74 ++++++++++++++++++++++++++++++++++++------
    1 file changed, 64 insertions(+), 10 deletions(-)

    --- a/drivers/iio/pressure/dps310.c
    +++ b/drivers/iio/pressure/dps310.c
    @@ -89,6 +89,7 @@ struct dps310_data {
    s32 c00, c10, c20, c30, c01, c11, c21;
    s32 pressure_raw;
    s32 temp_raw;
    + bool timeout_recovery_failed;
    };

    static const struct iio_chan_spec dps310_channels[] = {
    @@ -393,11 +394,69 @@ static int dps310_get_temp_k(struct dps3
    return scale_factors[ilog2(rc)];
    }

    +static int dps310_reset_wait(struct dps310_data *data)
    +{
    + int rc;
    +
    + rc = regmap_write(data->regmap, DPS310_RESET, DPS310_RESET_MAGIC);
    + if (rc)
    + return rc;
    +
    + /* Wait for device chip access: 2.5ms in specification */
    + usleep_range(2500, 12000);
    + return 0;
    +}
    +
    +static int dps310_reset_reinit(struct dps310_data *data)
    +{
    + int rc;
    +
    + rc = dps310_reset_wait(data);
    + if (rc)
    + return rc;
    +
    + return dps310_startup(data);
    +}
    +
    +static int dps310_ready_status(struct dps310_data *data, int ready_bit, int timeout)
    +{
    + int sleep = DPS310_POLL_SLEEP_US(timeout);
    + int ready;
    +
    + return regmap_read_poll_timeout(data->regmap, DPS310_MEAS_CFG, ready, ready & ready_bit,
    + sleep, timeout);
    +}
    +
    +static int dps310_ready(struct dps310_data *data, int ready_bit, int timeout)
    +{
    + int rc;
    +
    + rc = dps310_ready_status(data, ready_bit, timeout);
    + if (rc) {
    + if (rc == -ETIMEDOUT && !data->timeout_recovery_failed) {
    + /* Reset and reinitialize the chip. */
    + if (dps310_reset_reinit(data)) {
    + data->timeout_recovery_failed = true;
    + } else {
    + /* Try again to get sensor ready status. */
    + if (dps310_ready_status(data, ready_bit, timeout))
    + data->timeout_recovery_failed = true;
    + else
    + return 0;
    + }
    + }
    +
    + return rc;
    + }
    +
    + data->timeout_recovery_failed = false;
    + return 0;
    +}
    +
    static int dps310_read_pres_raw(struct dps310_data *data)
    {
    int rc;
    int rate;
    - int ready;
    int timeout;
    s32 raw;
    u8 val[3];
    @@ -409,9 +468,7 @@ static int dps310_read_pres_raw(struct d
    timeout = DPS310_POLL_TIMEOUT_US(rate);

    /* Poll for sensor readiness; base the timeout upon the sample rate. */
    - rc = regmap_read_poll_timeout(data->regmap, DPS310_MEAS_CFG, ready,
    - ready & DPS310_PRS_RDY,
    - DPS310_POLL_SLEEP_US(timeout), timeout);
    + rc = dps310_ready(data, DPS310_PRS_RDY, timeout);
    if (rc)
    goto done;

    @@ -448,7 +505,6 @@ static int dps310_read_temp_raw(struct d
    {
    int rc;
    int rate;
    - int ready;
    int timeout;

    if (mutex_lock_interruptible(&data->lock))
    @@ -458,10 +514,8 @@ static int dps310_read_temp_raw(struct d
    timeout = DPS310_POLL_TIMEOUT_US(rate);

    /* Poll for sensor readiness; base the timeout upon the sample rate. */
    - rc = regmap_read_poll_timeout(data->regmap, DPS310_MEAS_CFG, ready,
    - ready & DPS310_TMP_RDY,
    - DPS310_POLL_SLEEP_US(timeout), timeout);
    - if (rc < 0)
    + rc = dps310_ready(data, DPS310_TMP_RDY, timeout);
    + if (rc)
    goto done;

    rc = dps310_read_temp_ready(data);
    @@ -756,7 +810,7 @@ static void dps310_reset(void *action_da
    {
    struct dps310_data *data = action_data;

    - regmap_write(data->regmap, DPS310_RESET, DPS310_RESET_MAGIC);
    + dps310_reset_wait(data);
    }

    static const struct regmap_config dps310_regmap_config = {

    \
     
     \ /
      Last update: 2022-10-19 10:47    [W:2.132 / U:0.092 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site