Commit 7b4ab4ab authored by Eddie James's avatar Eddie James Committed by Jonathan Cameron

iio: pressure: dps310: Reset chip after timeout

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: ba6ec48e ("iio: Add driver for Infineon DPS310")
Cc: <stable@vger.kernel.org>
Signed-off-by: default avatarEddie James <eajames@linux.ibm.com>
Reviewed-by: default avatarAndy Shevchenko <andy.shevchenko@gmail.com>
Link: https://lore.kernel.org/r/20220915195719.136812-3-eajames@linux.ibm.comSigned-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
parent c2329717
...@@ -89,6 +89,7 @@ struct dps310_data { ...@@ -89,6 +89,7 @@ struct dps310_data {
s32 c00, c10, c20, c30, c01, c11, c21; s32 c00, c10, c20, c30, c01, c11, c21;
s32 pressure_raw; s32 pressure_raw;
s32 temp_raw; s32 temp_raw;
bool timeout_recovery_failed;
}; };
static const struct iio_chan_spec dps310_channels[] = { static const struct iio_chan_spec dps310_channels[] = {
...@@ -393,11 +394,69 @@ static int dps310_get_temp_k(struct dps310_data *data) ...@@ -393,11 +394,69 @@ static int dps310_get_temp_k(struct dps310_data *data)
return scale_factors[ilog2(rc)]; 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) static int dps310_read_pres_raw(struct dps310_data *data)
{ {
int rc; int rc;
int rate; int rate;
int ready;
int timeout; int timeout;
s32 raw; s32 raw;
u8 val[3]; u8 val[3];
...@@ -409,9 +468,7 @@ static int dps310_read_pres_raw(struct dps310_data *data) ...@@ -409,9 +468,7 @@ static int dps310_read_pres_raw(struct dps310_data *data)
timeout = DPS310_POLL_TIMEOUT_US(rate); timeout = DPS310_POLL_TIMEOUT_US(rate);
/* Poll for sensor readiness; base the timeout upon the sample rate. */ /* Poll for sensor readiness; base the timeout upon the sample rate. */
rc = regmap_read_poll_timeout(data->regmap, DPS310_MEAS_CFG, ready, rc = dps310_ready(data, DPS310_PRS_RDY, timeout);
ready & DPS310_PRS_RDY,
DPS310_POLL_SLEEP_US(timeout), timeout);
if (rc) if (rc)
goto done; goto done;
...@@ -448,7 +505,6 @@ static int dps310_read_temp_raw(struct dps310_data *data) ...@@ -448,7 +505,6 @@ static int dps310_read_temp_raw(struct dps310_data *data)
{ {
int rc; int rc;
int rate; int rate;
int ready;
int timeout; int timeout;
if (mutex_lock_interruptible(&data->lock)) if (mutex_lock_interruptible(&data->lock))
...@@ -458,10 +514,8 @@ static int dps310_read_temp_raw(struct dps310_data *data) ...@@ -458,10 +514,8 @@ static int dps310_read_temp_raw(struct dps310_data *data)
timeout = DPS310_POLL_TIMEOUT_US(rate); timeout = DPS310_POLL_TIMEOUT_US(rate);
/* Poll for sensor readiness; base the timeout upon the sample rate. */ /* Poll for sensor readiness; base the timeout upon the sample rate. */
rc = regmap_read_poll_timeout(data->regmap, DPS310_MEAS_CFG, ready, rc = dps310_ready(data, DPS310_TMP_RDY, timeout);
ready & DPS310_TMP_RDY, if (rc)
DPS310_POLL_SLEEP_US(timeout), timeout);
if (rc < 0)
goto done; goto done;
rc = dps310_read_temp_ready(data); rc = dps310_read_temp_ready(data);
...@@ -756,7 +810,7 @@ static void dps310_reset(void *action_data) ...@@ -756,7 +810,7 @@ static void dps310_reset(void *action_data)
{ {
struct dps310_data *data = 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 = { static const struct regmap_config dps310_regmap_config = {
......
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