Skip to content

Commit

Permalink
iio: pressure: dps310: Reset chip after timeout
Browse files Browse the repository at this point in the history
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: ba6ec48 ("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>
  • Loading branch information
Eddie James authored and jic23 committed Sep 21, 2022
1 parent c232971 commit 7b4ab4a
Showing 1 changed file with 64 additions and 10 deletions.
74 changes: 64 additions & 10 deletions drivers/iio/pressure/dps310.c
Original file line number Diff line number Diff line change
Expand Up @@ -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[] = {
Expand Down Expand Up @@ -393,11 +394,69 @@ static int dps310_get_temp_k(struct dps310_data *data)
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];
Expand All @@ -409,9 +468,7 @@ static int dps310_read_pres_raw(struct dps310_data *data)
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;

Expand Down Expand Up @@ -448,7 +505,6 @@ static int dps310_read_temp_raw(struct dps310_data *data)
{
int rc;
int rate;
int ready;
int timeout;

if (mutex_lock_interruptible(&data->lock))
Expand All @@ -458,10 +514,8 @@ static int dps310_read_temp_raw(struct dps310_data *data)
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);
Expand Down Expand Up @@ -756,7 +810,7 @@ static void dps310_reset(void *action_data)
{
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 = {
Expand Down

0 comments on commit 7b4ab4a

Please sign in to comment.