mirror of
https://github.com/torvalds/linux.git
synced 2024-11-13 07:31:45 +00:00
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: ba6ec48e76
("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>
This commit is contained in:
parent
c2329717bd
commit
7b4ab4abce
@ -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 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];
|
||||
@ -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;
|
||||
|
||||
@ -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))
|
||||
@ -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);
|
||||
@ -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 = {
|
||||
|
Loading…
Reference in New Issue
Block a user