[PATCH v4 2/4] iio: adc: ad799x: cache regulator voltage during probe

Archit Anant posted 4 patches 1 month ago
There is a newer version of this series
[PATCH v4 2/4] iio: adc: ad799x: cache regulator voltage during probe
Posted by Archit Anant 1 month ago
Reading the regulator voltage via regulator_get_voltage() can be a slow
operation. Since the reference voltage for this ADC is not expected to
change at runtime, it is inefficient to query the regulator API every
time userspace reads the IIO_CHAN_INFO_SCALE attribute.

Determine the active reference voltage (either VREF or VCC) during
probe() and cache it in a single variable in the state structure.
This improves the performance of ad799x_read_raw(), removes the
dependency on the regulator pointers during fast-path reads, and
allows the removal of a redundant negative-value check.

Suggested-by: Jonathan Cameron <jic23@kernel.org>
Suggested-by: David Lechner <dlechner@baylibre.com>
Signed-off-by: Archit Anant <architanant5@gmail.com>
---
 drivers/iio/adc/ad799x.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/iio/adc/ad799x.c b/drivers/iio/adc/ad799x.c
index c1a7fa37706f..28f1901698a6 100644
--- a/drivers/iio/adc/ad799x.c
+++ b/drivers/iio/adc/ad799x.c
@@ -135,6 +135,9 @@ struct ad799x_state {
 	u16				config;
 
 	unsigned int			transfer_size;
+
+	int				vref_uV;
+
 	IIO_DECLARE_BUFFER_WITH_TS(__be16, rx_buf, AD799X_MAX_CHANNELS);
 };
 
@@ -302,14 +305,7 @@ static int ad799x_read_raw(struct iio_dev *indio_dev,
 			GENMASK(chan->scan_type.realbits - 1, 0);
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
-		if (st->vref)
-			ret = regulator_get_voltage(st->vref);
-		else
-			ret = regulator_get_voltage(st->reg);
-
-		if (ret < 0)
-			return ret;
-		*val = ret / 1000;
+		*val = st->vref_uV / 1000;
 		*val2 = chan->scan_type.realbits;
 		return IIO_VAL_FRACTIONAL_LOG2;
 	}
@@ -809,6 +805,10 @@ static int ad799x_probe(struct i2c_client *client)
 	ret = regulator_enable(st->reg);
 	if (ret)
 		return ret;
+	ret = regulator_get_voltage(st->reg);
+	if (ret < 0)
+		goto error_disable_reg;
+	st->vref_uV = ret;
 
 	/* check if an external reference is supplied */
 	if (chip_info->has_vref) {
@@ -827,6 +827,11 @@ static int ad799x_probe(struct i2c_client *client)
 			ret = regulator_enable(st->vref);
 			if (ret)
 				goto error_disable_reg;
+
+			ret = regulator_get_voltage(st->vref);
+			if (ret < 0)
+				goto error_disable_vref;
+			st->vref_uV = ret;
 		}
 	}
 
-- 
2.39.5
Re: [PATCH v4 2/4] iio: adc: ad799x: cache regulator voltage during probe
Posted by Jonathan Cameron 1 month ago
On Sun,  8 Mar 2026 23:58:09 +0530
Archit Anant <architanant5@gmail.com> wrote:

> Reading the regulator voltage via regulator_get_voltage() can be a slow
> operation. Since the reference voltage for this ADC is not expected to
> change at runtime, it is inefficient to query the regulator API every
> time userspace reads the IIO_CHAN_INFO_SCALE attribute.
> 
> Determine the active reference voltage (either VREF or VCC) during
> probe() and cache it in a single variable in the state structure.
> This improves the performance of ad799x_read_raw(), removes the
> dependency on the regulator pointers during fast-path reads, and
> allows the removal of a redundant negative-value check.
> 
> Suggested-by: Jonathan Cameron <jic23@kernel.org>
> Suggested-by: David Lechner <dlechner@baylibre.com>
> Signed-off-by: Archit Anant <architanant5@gmail.com>
This is a little more complex. See below.

> ---
>  drivers/iio/adc/ad799x.c | 21 +++++++++++++--------
>  1 file changed, 13 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/iio/adc/ad799x.c b/drivers/iio/adc/ad799x.c
> index c1a7fa37706f..28f1901698a6 100644
> --- a/drivers/iio/adc/ad799x.c
> +++ b/drivers/iio/adc/ad799x.c
> @@ -135,6 +135,9 @@ struct ad799x_state {
>  	u16				config;
>  
>  	unsigned int			transfer_size;
> +
> +	int				vref_uV;
> +
>  	IIO_DECLARE_BUFFER_WITH_TS(__be16, rx_buf, AD799X_MAX_CHANNELS);
>  };
>  
> @@ -302,14 +305,7 @@ static int ad799x_read_raw(struct iio_dev *indio_dev,
>  			GENMASK(chan->scan_type.realbits - 1, 0);
>  		return IIO_VAL_INT;
>  	case IIO_CHAN_INFO_SCALE:
> -		if (st->vref)
> -			ret = regulator_get_voltage(st->vref);
> -		else
> -			ret = regulator_get_voltage(st->reg);
> -
> -		if (ret < 0)
> -			return ret;
> -		*val = ret / 1000;
> +		*val = st->vref_uV / 1000;
>  		*val2 = chan->scan_type.realbits;
>  		return IIO_VAL_FRACTIONAL_LOG2;
>  	}
> @@ -809,6 +805,10 @@ static int ad799x_probe(struct i2c_client *client)
>  	ret = regulator_enable(st->reg);
>  	if (ret)
>  		return ret;
> +	ret = regulator_get_voltage(st->reg);
This is broken for some cases.  If the vcc reg is a stub provided
by the regulator framework, or a regulator that we simply have no way
to read back the voltage from, then this will return an error.
Previously that was only a problem if we actually need this voltage.
i.e. we didn't have a vref.

So we need to read this voltage only if there is no vref.

> +	if (ret < 0)
> +		goto error_disable_reg;
> +	st->vref_uV = ret;
>  
>  	/* check if an external reference is supplied */
>  	if (chip_info->has_vref) {
> @@ -827,6 +827,11 @@ static int ad799x_probe(struct i2c_client *client)
>  			ret = regulator_enable(st->vref);
>  			if (ret)
>  				goto error_disable_reg;
> +
> +			ret = regulator_get_voltage(st->vref);

For this you can use
	devm_regulator_get_enable_read_voltage()
Read the comments for how that works with optional regulators.

> +			if (ret < 0)
> +				goto error_disable_vref;
> +			st->vref_uV = ret;
>  		}
>  	}
>
Re: [PATCH v4 2/4] iio: adc: ad799x: cache regulator voltage during probe
Posted by Andy Shevchenko 1 month ago
On Sun, Mar 08, 2026 at 11:58:09PM +0530, Archit Anant wrote:
> Reading the regulator voltage via regulator_get_voltage() can be a slow
> operation. Since the reference voltage for this ADC is not expected to
> change at runtime, it is inefficient to query the regulator API every
> time userspace reads the IIO_CHAN_INFO_SCALE attribute.
> 
> Determine the active reference voltage (either VREF or VCC) during
> probe() and cache it in a single variable in the state structure.
> This improves the performance of ad799x_read_raw(), removes the
> dependency on the regulator pointers during fast-path reads, and
> allows the removal of a redundant negative-value check.

...

> +		*val = st->vref_uV / 1000;

Perhaps "(MICRO / MILLI)" instead of "1000" until we have a dedicate constant?

-- 
With Best Regards,
Andy Shevchenko