summaryrefslogtreecommitdiff
path: root/drivers/iio
diff options
context:
space:
mode:
authorAkinobu Mita <akinobu.mita@gmail.com>2017-07-20 18:24:22 +0300
committerJonathan Cameron <Jonathan.Cameron@huawei.com>2017-08-20 17:41:14 +0300
commit4744d4e2afebf9644a439da9ca73d822fdd67bd9 (patch)
tree3c2c15a3f1231f544b3dfd21981a4de30dfd478a /drivers/iio
parenta6fe5e52d5ecfc98530034d6c9db73777cf41ede (diff)
downloadlinux-4744d4e2afebf9644a439da9ca73d822fdd67bd9.tar.xz
iio: adc: ti-ads1015: add adequate wait time to get correct conversion
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: Akinobu Mita <akinobu.mita@gmail.com> Cc: <Stable@vger.kernel.org> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Diffstat (limited to 'drivers/iio')
-rw-r--r--drivers/iio/adc/ti-ads1015.c31
1 files changed, 19 insertions, 12 deletions
diff --git a/drivers/iio/adc/ti-ads1015.c b/drivers/iio/adc/ti-ads1015.c
index d48515682dee..ed911776e283 100644
--- a/drivers/iio/adc/ti-ads1015.c
+++ b/drivers/iio/adc/ti-ads1015.c
@@ -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;
}