Commit 6c6c3c6b authored by Akinobu Mita's avatar Akinobu Mita Committed by Greg Kroah-Hartman

iio: adc: ti-ads1015: add adequate wait time to get correct conversion

commit 4744d4e2 upstream.

This driver assumes that the device is operating in the continuous
conversion mode which performs the conversion continuously.  So this driver
inserts a wait time before reading the conversion register if the
configuration is changed from a previous request.

Currently, the wait time is only the period required for a single
conversion that is calculated as the reciprocal of the sampling frequency.
However we also need to wait for the the previous conversion to complete.
Otherwise we probably get the conversion result for the previous
configuration when the sampling frequency is lower.

Cc: Daniel Baluta <daniel.baluta@gmail.com>
Signed-off-by: default avatarAkinobu Mita <akinobu.mita@gmail.com>
Signed-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 00202ded
......@@ -242,27 +242,34 @@ static
int ads1015_get_adc_result(struct ads1015_data *data, int chan, int *val)
{
int ret, pga, dr, conv_time;
bool change;
unsigned int old, mask, cfg;
if (chan < 0 || chan >= ADS1015_CHANNELS)
return -EINVAL;
ret = regmap_read(data->regmap, ADS1015_CFG_REG, &old);
if (ret)
return ret;
pga = data->channel_data[chan].pga;
dr = data->channel_data[chan].data_rate;
mask = ADS1015_CFG_MUX_MASK | ADS1015_CFG_PGA_MASK |
ADS1015_CFG_DR_MASK;
cfg = chan << ADS1015_CFG_MUX_SHIFT | pga << ADS1015_CFG_PGA_SHIFT |
dr << ADS1015_CFG_DR_SHIFT;
ret = regmap_update_bits_check(data->regmap, ADS1015_CFG_REG,
ADS1015_CFG_MUX_MASK |
ADS1015_CFG_PGA_MASK |
ADS1015_CFG_DR_MASK,
chan << ADS1015_CFG_MUX_SHIFT |
pga << ADS1015_CFG_PGA_SHIFT |
dr << ADS1015_CFG_DR_SHIFT,
&change);
if (ret < 0)
cfg = (old & ~mask) | (cfg & mask);
ret = regmap_write(data->regmap, ADS1015_CFG_REG, cfg);
if (ret)
return ret;
if (change || data->conv_invalid) {
conv_time = DIV_ROUND_UP(USEC_PER_SEC, data->data_rate[dr]);
if (old != cfg || data->conv_invalid) {
int dr_old = (old & ADS1015_CFG_DR_MASK) >>
ADS1015_CFG_DR_SHIFT;
conv_time = DIV_ROUND_UP(USEC_PER_SEC, data->data_rate[dr_old]);
conv_time += DIV_ROUND_UP(USEC_PER_SEC, data->data_rate[dr]);
usleep_range(conv_time, conv_time + 1);
data->conv_invalid = false;
}
......
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