diff options
author | Nuno Sá <nuno.sa@analog.com> | 2022-10-04 16:49:02 +0300 |
---|---|---|
committer | Jonathan Cameron <Jonathan.Cameron@huawei.com> | 2022-11-23 22:43:58 +0300 |
commit | f2bdea865e776b571557035eac2e8afde8ea7844 (patch) | |
tree | 3c0c43ad67200aa71d6667df18ec7410bbafa239 /drivers/iio/adc | |
parent | 8433aa3591afff6f4dc641a2e274e6171f66a4b7 (diff) | |
download | linux-f2bdea865e776b571557035eac2e8afde8ea7844.tar.xz |
iio: adc: vf610_adc: add helper function to read samples
This is a precursor change to make it simpler to remove the 'mlock'
usage. Having the code in it's own helper function, also makes it easier
to read the error paths.
Signed-off-by: Nuno Sá <nuno.sa@analog.com>
Reviewed-by: Haibo Chen <haibo.chen@nxp.com>
Link: https://lore.kernel.org/r/20221004134909.1692021-10-nuno.sa@analog.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Diffstat (limited to 'drivers/iio/adc')
-rw-r--r-- | drivers/iio/adc/vf610_adc.c | 94 |
1 files changed, 54 insertions, 40 deletions
diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c index c6b16cf6e367..a6f9182d7766 100644 --- a/drivers/iio/adc/vf610_adc.c +++ b/drivers/iio/adc/vf610_adc.c @@ -622,6 +622,58 @@ static const struct attribute_group vf610_attribute_group = { .attrs = vf610_attributes, }; +static int vf610_read_sample(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val) +{ + struct vf610_adc *info = iio_priv(indio_dev); + unsigned int hc_cfg; + int ret; + + mutex_lock(&indio_dev->mlock); + if (iio_buffer_enabled(indio_dev)) { + ret = -EBUSY; + goto out_unlock; + } + + reinit_completion(&info->completion); + hc_cfg = VF610_ADC_ADCHC(chan->channel); + hc_cfg |= VF610_ADC_AIEN; + writel(hc_cfg, info->regs + VF610_REG_ADC_HC0); + ret = wait_for_completion_interruptible_timeout(&info->completion, + VF610_ADC_TIMEOUT); + if (ret == 0) { + ret = -ETIMEDOUT; + goto out_unlock; + } + + if (ret < 0) + goto out_unlock; + + switch (chan->type) { + case IIO_VOLTAGE: + *val = info->value; + break; + case IIO_TEMP: + /* + * Calculate in degree Celsius times 1000 + * Using the typical sensor slope of 1.84 mV/°C + * and VREFH_ADC at 3.3V, V at 25°C of 699 mV + */ + *val = 25000 - ((int)info->value - VF610_VTEMP25_3V3) * + 1000000 / VF610_TEMP_SLOPE_COEFF; + + break; + default: + ret = -EINVAL; + break; + } + +out_unlock: + mutex_unlock(&indio_dev->mlock); + + return ret; +} + static int vf610_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, @@ -629,53 +681,15 @@ static int vf610_read_raw(struct iio_dev *indio_dev, long mask) { struct vf610_adc *info = iio_priv(indio_dev); - unsigned int hc_cfg; long ret; switch (mask) { case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_PROCESSED: - mutex_lock(&indio_dev->mlock); - if (iio_buffer_enabled(indio_dev)) { - mutex_unlock(&indio_dev->mlock); - return -EBUSY; - } - - reinit_completion(&info->completion); - hc_cfg = VF610_ADC_ADCHC(chan->channel); - hc_cfg |= VF610_ADC_AIEN; - writel(hc_cfg, info->regs + VF610_REG_ADC_HC0); - ret = wait_for_completion_interruptible_timeout - (&info->completion, VF610_ADC_TIMEOUT); - if (ret == 0) { - mutex_unlock(&indio_dev->mlock); - return -ETIMEDOUT; - } - if (ret < 0) { - mutex_unlock(&indio_dev->mlock); + ret = vf610_read_sample(indio_dev, chan, val); + if (ret < 0) return ret; - } - - switch (chan->type) { - case IIO_VOLTAGE: - *val = info->value; - break; - case IIO_TEMP: - /* - * Calculate in degree Celsius times 1000 - * Using the typical sensor slope of 1.84 mV/°C - * and VREFH_ADC at 3.3V, V at 25°C of 699 mV - */ - *val = 25000 - ((int)info->value - VF610_VTEMP25_3V3) * - 1000000 / VF610_TEMP_SLOPE_COEFF; - - break; - default: - mutex_unlock(&indio_dev->mlock); - return -EINVAL; - } - mutex_unlock(&indio_dev->mlock); return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: |