[PATCH v5 4/4] iio: adc: ad9467: check for backend capabilities

Tomas Melin posted 4 patches 1 week, 3 days ago
There is a newer version of this series
[PATCH v5 4/4] iio: adc: ad9467: check for backend capabilities
Posted by Tomas Melin 1 week, 3 days ago
Add capability checks for operation with backends that do not necessarily
support full set of features, but are otherwise compatible with the device.
This ensures a fully functional device, but with limited capabilities.

Signed-off-by: Tomas Melin <tomas.melin@vaisala.com>
---
 drivers/iio/adc/ad9467.c | 69 ++++++++++++++++++++++++++++++------------------
 1 file changed, 43 insertions(+), 26 deletions(-)

diff --git a/drivers/iio/adc/ad9467.c b/drivers/iio/adc/ad9467.c
index 59c3fa3bcc9b..d768f7bf2a1c 100644
--- a/drivers/iio/adc/ad9467.c
+++ b/drivers/iio/adc/ad9467.c
@@ -913,7 +913,9 @@ static int __ad9467_update_clock(struct ad9467_state *st, long r_clk)
 		return ret;
 
 	guard(mutex)(&st->lock);
-	return ad9467_calibrate(st);
+	if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION))
+		return ad9467_calibrate(st);
+	return 0;
 }
 
 static int ad9467_write_raw(struct iio_dev *indio_dev,
@@ -1119,12 +1121,15 @@ static ssize_t ad9467_chan_test_mode_read(struct file *file,
 		len = scnprintf(buf, sizeof(buf), "Running \"%s\" Test:\n\t",
 				ad9467_test_modes[chan->mode]);
 
-		ret = iio_backend_debugfs_print_chan_status(st->back, chan->idx,
-							    buf + len,
-							    sizeof(buf) - len);
-		if (ret < 0)
-			return ret;
-		len += ret;
+		if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION)) {
+			ret = iio_backend_debugfs_print_chan_status(st->back,
+								    chan->idx,
+								    buf + len,
+								    sizeof(buf) - len);
+			if (ret < 0)
+				return ret;
+			len += ret;
+		}
 	} else if (chan->mode == AN877_ADC_TESTMODE_OFF) {
 		len = scnprintf(buf, sizeof(buf), "No test Running...\n");
 	} else {
@@ -1188,16 +1193,19 @@ static ssize_t ad9467_chan_test_mode_write(struct file *file,
 			return ret;
 
 		/*  some patterns have a backend matching monitoring block */
-		if (mode == AN877_ADC_TESTMODE_PN9_SEQ) {
-			ret = ad9467_backend_testmode_on(st, chan->idx,
+		if (iio_backend_has_caps(st->back,
+					 IIO_BACKEND_CAP_CALIBRATION)) {
+			if (mode == AN877_ADC_TESTMODE_PN9_SEQ) {
+				ret = ad9467_backend_testmode_on(st, chan->idx,
 							 IIO_BACKEND_ADI_PRBS_9A);
-			if (ret)
-				return ret;
-		} else if (mode == AN877_ADC_TESTMODE_PN23_SEQ) {
-			ret = ad9467_backend_testmode_on(st, chan->idx,
+				if (ret)
+					return ret;
+			} else if (mode == AN877_ADC_TESTMODE_PN23_SEQ) {
+				ret = ad9467_backend_testmode_on(st, chan->idx,
 							 IIO_BACKEND_ADI_PRBS_23A);
-			if (ret)
-				return ret;
+				if (ret)
+					return ret;
+			}
 		}
 	}
 
@@ -1263,8 +1271,10 @@ static void ad9467_debugfs_init(struct iio_dev *indio_dev)
 	if (!st->chan_test)
 		return;
 
-	debugfs_create_file("calibration_table_dump", 0400, d, st,
-			    &ad9467_calib_table_fops);
+	if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION)) {
+		debugfs_create_file("calibration_table_dump", 0400, d, st,
+				    &ad9467_calib_table_fops);
+	}
 
 	for (chan = 0; chan < st->info->num_channels; chan++) {
 		snprintf(attr_name, sizeof(attr_name), "in_voltage%u_test_mode",
@@ -1339,17 +1349,24 @@ static int ad9467_probe(struct spi_device *spi)
 	if (ret)
 		return ret;
 
-	ret = devm_iio_backend_request_buffer(&spi->dev, st->back, indio_dev);
-	if (ret)
-		return ret;
+	if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_BUFFERING)) {
+		ret = devm_iio_backend_request_buffer(&spi->dev, st->back,
+						      indio_dev);
+		if (ret)
+			return ret;
+	}
 
-	ret = devm_iio_backend_enable(&spi->dev, st->back);
-	if (ret)
-		return ret;
+	if (!iio_backend_has_caps(st->back, IIO_BACKEND_CAP_ALWAYS_ON)) {
+		ret = devm_iio_backend_enable(&spi->dev, st->back);
+		if (ret)
+			return ret;
+	}
 
-	ret = ad9467_calibrate(st);
-	if (ret)
-		return ret;
+	if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION)) {
+		ret = ad9467_calibrate(st);
+		if (ret)
+			return ret;
+	}
 
 	ret = devm_iio_device_register(&spi->dev, indio_dev);
 	if (ret)

-- 
2.47.3
Re: [PATCH v5 4/4] iio: adc: ad9467: check for backend capabilities
Posted by Nuno Sá 1 week ago
On Fri, 2026-01-30 at 09:17 +0000, Tomas Melin wrote:
> Add capability checks for operation with backends that do not necessarily
> support full set of features, but are otherwise compatible with the device.
> This ensures a fully functional device, but with limited capabilities.
> 
> Signed-off-by: Tomas Melin <tomas.melin@vaisala.com>
> ---
>  drivers/iio/adc/ad9467.c | 69 ++++++++++++++++++++++++++++++------------------
>  1 file changed, 43 insertions(+), 26 deletions(-)
> 
> diff --git a/drivers/iio/adc/ad9467.c b/drivers/iio/adc/ad9467.c
> index 59c3fa3bcc9b..d768f7bf2a1c 100644
> --- a/drivers/iio/adc/ad9467.c
> +++ b/drivers/iio/adc/ad9467.c
> @@ -913,7 +913,9 @@ static int __ad9467_update_clock(struct ad9467_state *st, long r_clk)
>  		return ret;
>  
>  	guard(mutex)(&st->lock);
> -	return ad9467_calibrate(st);
> +	if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION))
> +		return ad9467_calibrate(st);
> +	return 0;
>  }
>  
>  static int ad9467_write_raw(struct iio_dev *indio_dev,
> @@ -1119,12 +1121,15 @@ static ssize_t ad9467_chan_test_mode_read(struct file *file,
>  		len = scnprintf(buf, sizeof(buf), "Running \"%s\" Test:\n\t",
>  				ad9467_test_modes[chan->mode]);
>  
> -		ret = iio_backend_debugfs_print_chan_status(st->back, chan->idx,
> -							    buf + len,
> -							    sizeof(buf) - len);
> -		if (ret < 0)
> -			return ret;
> -		len += ret;
> +		if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION)) {
> +			ret = iio_backend_debugfs_print_chan_status(st->back,
> +								    chan->idx,
> +								    buf + len,
> +								    sizeof(buf) - len);
> +			if (ret < 0)
> +				return ret;
> +			len += ret;

Given that we can't really check the status we could maybe do this in a better way. See
below...
> +		}
>  	} else if (chan->mode == AN877_ADC_TESTMODE_OFF) {
>  		len = scnprintf(buf, sizeof(buf), "No test Running...\n");
>  	} else {
> @@ -1188,16 +1193,19 @@ static ssize_t ad9467_chan_test_mode_write(struct file *file,
>  			return ret;
>  
>  		/*  some patterns have a backend matching monitoring block */
> -		if (mode == AN877_ADC_TESTMODE_PN9_SEQ) {
> -			ret = ad9467_backend_testmode_on(st, chan->idx,
> +		if (iio_backend_has_caps(st->back,
> +					 IIO_BACKEND_CAP_CALIBRATION)) {
> +			if (mode == AN877_ADC_TESTMODE_PN9_SEQ) {
> +				ret = ad9467_backend_testmode_on(st, chan->idx,
>  							 IIO_BACKEND_ADI_PRBS_9A);
> -			if (ret)
> -				return ret;
> -		} else if (mode == AN877_ADC_TESTMODE_PN23_SEQ) {
> -			ret = ad9467_backend_testmode_on(st, chan->idx,
> +				if (ret)
> +					return ret;
> +			} else if (mode == AN877_ADC_TESTMODE_PN23_SEQ) {
> +				ret = ad9467_backend_testmode_on(st, chan->idx,
>  							 IIO_BACKEND_ADI_PRBS_23A);
> -			if (ret)
> -				return ret;
> +				if (ret)
> +					return ret;
> +			}
>  		}
>  	}
>  
> @@ -1263,8 +1271,10 @@ static void ad9467_debugfs_init(struct iio_dev *indio_dev)
>  	if (!st->chan_test)
>  		return;
>  
> -	debugfs_create_file("calibration_table_dump", 0400, d, st,
> -			    &ad9467_calib_table_fops);
> +	if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION)) {
> +		debugfs_create_file("calibration_table_dump", 0400, d, st,
> +				    &ad9467_calib_table_fops);
> +	}
>  
>  	for (chan = 0; chan < st->info->num_channels; chan++) {
>  		snprintf(attr_name, sizeof(attr_name), "in_voltage%u_test_mode",

Change the permissions for in_voltage%u_test_mode so that is WO in case we can't
IIO_BACKEND_CAP_CALIBRATION. You can even reuse the above check to tweak the permissions
accordingly. Then no need to check for the capability in ad9467_chan_test_mode_read()

- Nuno Sá
Re: [PATCH v5 4/4] iio: adc: ad9467: check for backend capabilities
Posted by Tomas Melin 1 week ago
Hi,

On 02/02/2026 12:42, Nuno Sá wrote:
> On Fri, 2026-01-30 at 09:17 +0000, Tomas Melin wrote:
>> Add capability checks for operation with backends that do not necessarily
>> support full set of features, but are otherwise compatible with the device.
>> This ensures a fully functional device, but with limited capabilities.
...
>>  
>> @@ -1263,8 +1271,10 @@ static void ad9467_debugfs_init(struct iio_dev *indio_dev)
>>  	if (!st->chan_test)
>>  		return;
>>  
>> -	debugfs_create_file("calibration_table_dump", 0400, d, st,
>> -			    &ad9467_calib_table_fops);
>> +	if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION)) {
>> +		debugfs_create_file("calibration_table_dump", 0400, d, st,
>> +				    &ad9467_calib_table_fops);
>> +	}
>>  
>>  	for (chan = 0; chan < st->info->num_channels; chan++) {
>>  		snprintf(attr_name, sizeof(attr_name), "in_voltage%u_test_mode",
> 
> Change the permissions for in_voltage%u_test_mode so that is WO in case we can't
> IIO_BACKEND_CAP_CALIBRATION. You can even reuse the above check to tweak the permissions
> accordingly. Then no need to check for the capability in ad9467_chan_test_mode_read()

This RO would be then only for cases PN9, PN23. For the other attributes
RW would still be applicable. But basically I think the test modes in
the device are still available even if the backend status does not exist?

IMHO the current approach is slightly cleaner, as all the test modes the
device supports are available and no need to think about which ones have
RW/RO inside this function. Please let me know, in case you insist on
this kind of approach.

Thanks,
Tomas

Re: [PATCH v5 4/4] iio: adc: ad9467: check for backend capabilities
Posted by Nuno Sá 6 days, 5 hours ago
On Mon, 2026-02-02 at 14:03 +0200, Tomas Melin wrote:
> Hi,
> 
> On 02/02/2026 12:42, Nuno Sá wrote:
> > On Fri, 2026-01-30 at 09:17 +0000, Tomas Melin wrote:
> > > Add capability checks for operation with backends that do not necessarily
> > > support full set of features, but are otherwise compatible with the device.
> > > This ensures a fully functional device, but with limited capabilities.
> ...
> > >  
> > > @@ -1263,8 +1271,10 @@ static void ad9467_debugfs_init(struct iio_dev *indio_dev)
> > >  	if (!st->chan_test)
> > >  		return;
> > >  
> > > -	debugfs_create_file("calibration_table_dump", 0400, d, st,
> > > -			    &ad9467_calib_table_fops);
> > > +	if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION)) {
> > > +		debugfs_create_file("calibration_table_dump", 0400, d, st,
> > > +				    &ad9467_calib_table_fops);
> > > +	}
> > >  
> > >  	for (chan = 0; chan < st->info->num_channels; chan++) {
> > >  		snprintf(attr_name, sizeof(attr_name), "in_voltage%u_test_mode",
> > 
> > Change the permissions for in_voltage%u_test_mode so that is WO in case we can't
> > IIO_BACKEND_CAP_CALIBRATION. You can even reuse the above check to tweak the permissions
> > accordingly. Then no need to check for the capability in ad9467_chan_test_mode_read()
> 
> This RO would be then only for cases PN9, PN23. For the other attributes

> RW would still be applicable. But basically I think the test modes in
> the device are still available even if the backend status does not exist?

Yeah, they are. The backend is only validating the pattern to make sure it is what's
expected. TBH, I'm not sure what's the utility without the backend but I guess one might
want to connect the interface somewhere and check the patterns.

> IMHO the current approach is slightly cleaner, as all the test modes the
> device supports are available and no need to think about which ones have
> RW/RO inside this function. Please let me know, in case you insist on
> this kind of approach.
> 
> 
Ok, I reviewed the code and I see we still print some running status for all the patterns.
Feel free to leave as-is then

- Nuno Sá
Re: [PATCH v5 4/4] iio: adc: ad9467: check for backend capabilities
Posted by David Lechner 1 week, 1 day ago
On 1/30/26 3:17 AM, Tomas Melin wrote:
> Add capability checks for operation with backends that do not necessarily
> support full set of features, but are otherwise compatible with the device.
> This ensures a fully functional device, but with limited capabilities.
> 
> Signed-off-by: Tomas Melin <tomas.melin@vaisala.com>
> ---
>  drivers/iio/adc/ad9467.c | 69 ++++++++++++++++++++++++++++++------------------
>  1 file changed, 43 insertions(+), 26 deletions(-)
> 
> diff --git a/drivers/iio/adc/ad9467.c b/drivers/iio/adc/ad9467.c
> index 59c3fa3bcc9b..d768f7bf2a1c 100644
> --- a/drivers/iio/adc/ad9467.c
> +++ b/drivers/iio/adc/ad9467.c
> @@ -913,7 +913,9 @@ static int __ad9467_update_clock(struct ad9467_state *st, long r_clk)
>  		return ret;
>  
>  	guard(mutex)(&st->lock);

I saw in the changelog that leaving the guard here was intentional, but I
don't see why.

> -	return ad9467_calibrate(st);
> +	if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION))
> +		return ad9467_calibrate(st);
> +	return 0;
>  }
>  

...

>  static int ad9467_write_raw(struct iio_dev *indio_dev,
> @@ -1119,12 +1121,15 @@ static ssize_t ad9467_chan_test_mode_read(struct file *file,
>  		len = scnprintf(buf, sizeof(buf), "Running \"%s\" Test:\n\t",
>  				ad9467_test_modes[chan->mode]);
>  
> -		ret = iio_backend_debugfs_print_chan_status(st->back, chan->idx,
> -							    buf + len,
> -							    sizeof(buf) - len);
> -		if (ret < 0)
> -			return ret;
> -		len += ret;
> +		if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION)) {
> +			ret = iio_backend_debugfs_print_chan_status(st->back,
> +								    chan->idx,
> +								    buf + len,
> +								    sizeof(buf) - len);
> +			if (ret < 0)
> +				return ret;
> +			len += ret;
> +		}
>  	} else if (chan->mode == AN877_ADC_TESTMODE_OFF) {
>  		len = scnprintf(buf, sizeof(buf), "No test Running...\n");
>  	} else {
> @@ -1188,16 +1193,19 @@ static ssize_t ad9467_chan_test_mode_write(struct file *file,
>  			return ret;
>  
>  		/*  some patterns have a backend matching monitoring block */
> -		if (mode == AN877_ADC_TESTMODE_PN9_SEQ) {
> -			ret = ad9467_backend_testmode_on(st, chan->idx,
> +		if (iio_backend_has_caps(st->back,
> +					 IIO_BACKEND_CAP_CALIBRATION)) {
> +			if (mode == AN877_ADC_TESTMODE_PN9_SEQ) {
> +				ret = ad9467_backend_testmode_on(st, chan->idx,
>  							 IIO_BACKEND_ADI_PRBS_9A);
> -			if (ret)
> -				return ret;
> -		} else if (mode == AN877_ADC_TESTMODE_PN23_SEQ) {
> -			ret = ad9467_backend_testmode_on(st, chan->idx,
> +				if (ret)
> +					return ret;
> +			} else if (mode == AN877_ADC_TESTMODE_PN23_SEQ) {
> +				ret = ad9467_backend_testmode_on(st, chan->idx,
>  							 IIO_BACKEND_ADI_PRBS_23A);
> -			if (ret)
> -				return ret;
> +				if (ret)
> +					return ret;
> +			}
>  		}
>  	}
>  
> @@ -1263,8 +1271,10 @@ static void ad9467_debugfs_init(struct iio_dev *indio_dev)
>  	if (!st->chan_test)
>  		return;
>  
> -	debugfs_create_file("calibration_table_dump", 0400, d, st,
> -			    &ad9467_calib_table_fops);
> +	if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION)) {
> +		debugfs_create_file("calibration_table_dump", 0400, d, st,
> +				    &ad9467_calib_table_fops);
> +	}
>  
>  	for (chan = 0; chan < st->info->num_channels; chan++) {
>  		snprintf(attr_name, sizeof(attr_name), "in_voltage%u_test_mode",


Do we actually need to change these test mode/debugfs functions since
debugfs_create_file() is only callded if IIO_BACKEND_CAP_CALIBRATION
already?
Re: [PATCH v5 4/4] iio: adc: ad9467: check for backend capabilities
Posted by Tomas Melin 1 week ago
Hi,

On 31/01/2026 22:40, David Lechner wrote:
> On 1/30/26 3:17 AM, Tomas Melin wrote:
>> Add capability checks for operation with backends that do not necessarily
>> support full set of features, but are otherwise compatible with the device.
>> This ensures a fully functional device, but with limited capabilities.
>>
>> Signed-off-by: Tomas Melin <tomas.melin@vaisala.com>
>> ---
>>  drivers/iio/adc/ad9467.c | 69 ++++++++++++++++++++++++++++++------------------
>>  1 file changed, 43 insertions(+), 26 deletions(-)
>>
>> diff --git a/drivers/iio/adc/ad9467.c b/drivers/iio/adc/ad9467.c
>> index 59c3fa3bcc9b..d768f7bf2a1c 100644
>> --- a/drivers/iio/adc/ad9467.c
>> +++ b/drivers/iio/adc/ad9467.c
>> @@ -913,7 +913,9 @@ static int __ad9467_update_clock(struct ad9467_state *st, long r_clk)
>>  		return ret;
>>  
>>  	guard(mutex)(&st->lock);
> 
> I saw in the changelog that leaving the guard here was intentional, but I
> don't see why.

This was discussed here:
https://marc.info/?l=linux-iio&m=176900394618857&w=4

> 
>> -	return ad9467_calibrate(st);
>> +	if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION))
>> +		return ad9467_calibrate(st);
>> +	return 0;
>>  }
>>  
> 
> ...
> 
>>  static int ad9467_write_raw(struct iio_dev *indio_dev,
>> @@ -1119,12 +1121,15 @@ static ssize_t ad9467_chan_test_mode_read(struct file *file,
>>  		len = scnprintf(buf, sizeof(buf), "Running \"%s\" Test:\n\t",
>>  				ad9467_test_modes[chan->mode]);
>>  
>> -		ret = iio_backend_debugfs_print_chan_status(st->back, chan->idx,
>> -							    buf + len,
>> -							    sizeof(buf) - len);
>> -		if (ret < 0)
>> -			return ret;
>> -		len += ret;
>> +		if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION)) {
>> +			ret = iio_backend_debugfs_print_chan_status(st->back,
>> +								    chan->idx,
>> +								    buf + len,
>> +								    sizeof(buf) - len);
>> +			if (ret < 0)
>> +				return ret;
>> +			len += ret;
>> +		}
>>  	} else if (chan->mode == AN877_ADC_TESTMODE_OFF) {
>>  		len = scnprintf(buf, sizeof(buf), "No test Running...\n");
>>  	} else {
>> @@ -1188,16 +1193,19 @@ static ssize_t ad9467_chan_test_mode_write(struct file *file,
>>  			return ret;
>>  
>>  		/*  some patterns have a backend matching monitoring block */
>> -		if (mode == AN877_ADC_TESTMODE_PN9_SEQ) {
>> -			ret = ad9467_backend_testmode_on(st, chan->idx,
>> +		if (iio_backend_has_caps(st->back,
>> +					 IIO_BACKEND_CAP_CALIBRATION)) {
>> +			if (mode == AN877_ADC_TESTMODE_PN9_SEQ) {
>> +				ret = ad9467_backend_testmode_on(st, chan->idx,
>>  							 IIO_BACKEND_ADI_PRBS_9A);
>> -			if (ret)
>> -				return ret;
>> -		} else if (mode == AN877_ADC_TESTMODE_PN23_SEQ) {
>> -			ret = ad9467_backend_testmode_on(st, chan->idx,
>> +				if (ret)
>> +					return ret;
>> +			} else if (mode == AN877_ADC_TESTMODE_PN23_SEQ) {
>> +				ret = ad9467_backend_testmode_on(st, chan->idx,
>>  							 IIO_BACKEND_ADI_PRBS_23A);
>> -			if (ret)
>> -				return ret;
>> +				if (ret)
>> +					return ret;
>> +			}
>>  		}
>>  	}
>>  
>> @@ -1263,8 +1271,10 @@ static void ad9467_debugfs_init(struct iio_dev *indio_dev)
>>  	if (!st->chan_test)
>>  		return;
>>  
>> -	debugfs_create_file("calibration_table_dump", 0400, d, st,
>> -			    &ad9467_calib_table_fops);
>> +	if (iio_backend_has_caps(st->back, IIO_BACKEND_CAP_CALIBRATION)) {
>> +		debugfs_create_file("calibration_table_dump", 0400, d, st,
>> +				    &ad9467_calib_table_fops);
>> +	}
>>  
>>  	for (chan = 0; chan < st->info->num_channels; chan++) {
>>  		snprintf(attr_name, sizeof(attr_name), "in_voltage%u_test_mode",
> 
> 
> Do we actually need to change these test mode/debugfs functions since
> debugfs_create_file() is only callded if IIO_BACKEND_CAP_CALIBRATION
> already?

The set of available test modes as such are part of the device, not the
backend. Based on that I have concluded that they should remain intact.

Thanks,
Tomas


> 
>