Skip to content

Commit 73e3e3f

Browse files
mitajic23
authored andcommitted
iio: adc: ti-ads1015: avoid getting stale result after runtime resume
This driver assumes that the device is operating in the continuous conversion mode which performs the conversion continuously. So this driver doesn't insert a wait time before reading the conversion register if the configuration is not changed from a previous request. This assumption is broken if the device is runtime suspended and entered a power-down state. The forthcoming request causes reading a stale result from the conversion register as the device is runtime resumed just before. Fix it by adding a flag to detect that condition and insert a necessary wait time. Cc: Daniel Baluta <[email protected]> Signed-off-by: Akinobu Mita <[email protected]> Cc: <[email protected]> Signed-off-by: Jonathan Cameron <[email protected]>
1 parent e8245c6 commit 73e3e3f

File tree

1 file changed

+16
-2
lines changed

1 file changed

+16
-2
lines changed

drivers/iio/adc/ti-ads1015.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,12 @@ struct ads1015_data {
177177
struct ads1015_channel_data channel_data[ADS1015_CHANNELS];
178178

179179
unsigned int *data_rate;
180+
/*
181+
* Set to true when the ADC is switched to the continuous-conversion
182+
* mode and exits from a power-down state. This flag is used to avoid
183+
* getting the stale result from the conversion register.
184+
*/
185+
bool conv_invalid;
180186
};
181187

182188
static bool ads1015_is_writeable_reg(struct device *dev, unsigned int reg)
@@ -255,9 +261,10 @@ int ads1015_get_adc_result(struct ads1015_data *data, int chan, int *val)
255261
if (ret < 0)
256262
return ret;
257263

258-
if (change) {
264+
if (change || data->conv_invalid) {
259265
conv_time = DIV_ROUND_UP(USEC_PER_SEC, data->data_rate[dr]);
260266
usleep_range(conv_time, conv_time + 1);
267+
data->conv_invalid = false;
261268
}
262269

263270
return regmap_read(data->regmap, ADS1015_CONV_REG, val);
@@ -630,6 +637,8 @@ static int ads1015_probe(struct i2c_client *client,
630637
if (ret)
631638
return ret;
632639

640+
data->conv_invalid = true;
641+
633642
ret = pm_runtime_set_active(&client->dev);
634643
if (ret)
635644
goto err_buffer_cleanup;
@@ -685,10 +694,15 @@ static int ads1015_runtime_resume(struct device *dev)
685694
{
686695
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
687696
struct ads1015_data *data = iio_priv(indio_dev);
697+
int ret;
688698

689-
return regmap_update_bits(data->regmap, ADS1015_CFG_REG,
699+
ret = regmap_update_bits(data->regmap, ADS1015_CFG_REG,
690700
ADS1015_CFG_MOD_MASK,
691701
ADS1015_CONTINUOUS << ADS1015_CFG_MOD_SHIFT);
702+
if (!ret)
703+
data->conv_invalid = true;
704+
705+
return ret;
692706
}
693707
#endif
694708

0 commit comments

Comments
 (0)