Add support for ADAQ776x-1 ADC Family
Subsystems (4)
v3 cover Add support for ADAQ776x-1 ADC Family
This adds support for the ADAQ7767-1, ADAQ7768-1 and ADAQ7769-1 devices.
The ADAQ7768-1 and ADAQ7769-1 integrate a programmable gain amplifier (PGA) with 7 and 8 gain options, respectively. The ADAQ7767-1 and ADAQ7769-1 also feature a 3-pin selectable Anti-aliasing filter (AAF) gain.
---
Changes in v3:
* Renamed adi,gain-milli to adi,aaf-gain-bp. Now it represents basis points (one hundredth of a percent).
* ad7768_channel_masks removed along with available_masks element in ad7768_chip_info struct. It does not add anything for single channels, so not needed, at least for now.
* New patch adding 64-bit fractional number types to math.h.
* Moved aaf gain parsing to its own function, and now returning after warning to avoid setting a variable when it shouldn't (avoid confusion).
* ad7768_set_pga_gain(): removed the pgia enable check, relying on the regmap cache.
* Addressed other review comments, see individual patches.
Changes in v2:
* adi,aaf-gain property renamed to adi,gain-milli. Default value added.
* fixed some commit messages.
* Added 'select RATIONAL' to Kconfig.
* Added lock to protect PGA value access.
* rewrote AAF gain check and replaced error returns with warnings.
* Addressed other review comments, see individual patches.
* Link to v1: https://lore.kernel.org/linux-iio/[email protected]/T/#t
---
Jonathan Santos (4):
dt-bindings: iio: adc: ad7768-1: add new supported parts
iio: adc: ad7768-1: introduce chip info for future multidevice support
math.h: Add 64-bit fractional numbers types
iio: adc: ad7768-1: add support for ADAQ776x-1 ADC Family
.../bindings/iio/adc/adi,ad7768-1.yaml | 44 ++- drivers/iio/adc/Kconfig | 1 + drivers/iio/adc/ad7768-1.c | 359 ++++++++++++++++-- include/linux/math.h | 2 + 4 files changed, 377 insertions(+), 29 deletions(-)
base-commit: 91812d3843409c235f336f32f1c37ddc790f1e03
Signature · 1 line
2.34.1
PATCH v3 1/4 dt-bindings: iio: adc: ad7768-1: add new supported parts
Add compatibles for supported parts in the ad7768-1 family:
ADAQ7767-1, ADAQ7768-1 and ADAQ7769-1
Add property and checks for AFF gain, supported by ADAQ7767-1 and ADAQ7769-1 parts:
adi,aaf-gain-bp
---
v3 Changes:
* Renamed adi,gain-milli to adi,aaf-gain-bp. Now it represents basis points (one hundredth of a percent) as suggested by Krzysztof. Description was adjusted.
Note: permille (1/1000) was also suggested as unit for this property.
v2 Changes:
* adi,aaf-gain property renamed to adi,gain-milli. Description was simplified.
* default value add to adi,gain-milli.
--- .../bindings/iio/adc/adi,ad7768-1.yaml | 44 +++++++++++++++++-- 1 file changed, 40 insertions(+), 4 deletions(-)
Documentation/devicetree/bindings/iio/adc/adi,ad7768-1.yaml +40 -4
@@ -4,18 +4,26 @@ $id: http://devicetree.org/schemas/iio/adc/adi,ad7768-1.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Analog Devices AD7768-1 ADC device driver +title: Analog Devices AD7768-1 ADC family maintainers: - Michael Hennerich <[email protected]> description: | - Datasheet at: - https://www.analog.com/media/en/technical-documentation/data-sheets/ad7768-1.pdf + Analog Devices AD7768-1 24-Bit Single Channel Low Power sigma-delta ADC family + + https://www.analog.com/media/en/technical-documentation/data-sheets/ad7768-1.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/adaq7767-1.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/adaq7768-1.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/adaq7769-1.pdf properties: compatible: - const: adi,ad7768-1 + enum: + - adi,ad7768-1 + - adi,adaq7767-1 + - adi,adaq7768-1 + - adi,adaq7769-1 reg: maxItems: 1
@@ -58,6 +66,19 @@ properties: description: ADC reference voltage supply + adi,aaf-gain-bp: + description: | + Specifies the gain applied by the Analog Anti-Aliasing Filter (AAF) + to the ADC input in basis points (one hundredth of a percent). + The hardware gain is determined by which input pin(s) the signal goes + through into the AAF. The possible connections are: + * For the ADAQ7767-1: Input connected to IN1±, IN2± or IN3±. + * For the ADAQ7769-1: OUT_PGA pin connected to IN1_AAF+, IN2_AAF+, + or IN3_AAF+. + $ref: /schemas/types.yaml#/definitions/uint16 + enum: [1430, 3640, 10000] + default: 10000 + adi,sync-in-gpios: maxItems: 1 description:
@@ -147,6 +168,21 @@ patternProperties: allOf: - $ref: /schemas/spi/spi-peripheral-props.yaml# + # AAF Gain property only applies to ADAQ7767-1 and ADAQ7769-1 devices + - if: + properties: + compatible: + contains: + enum: + - adi,adaq7767-1 + - adi,adaq7769-1 + then: + required: + - adi,aaf-gain-bp + else: + properties: + adi,aaf-gain-bp: false + unevaluatedProperties: false examples:
Signature · 1 line
2.34.1
David Lechner
reviewerRe: [PATCH v3 1/4] dt-bindings: iio: adc: ad7768-1: add new supported parts
Quoted 36 lines · Jonathan Santos
Add compatibles for supported parts in the ad7768-1 family:
ADAQ7767-1, ADAQ7768-1 and ADAQ7769-1Add property and checks for AFF gain, supported by ADAQ7767-1 and ADAQ7769-1 parts:
adi,aaf-gain-bpSigned-off-by Jonathan Santos <[email protected]>---
v3 Changes:
* Renamed adi,gain-milli to adi,aaf-gain-bp. Now it represents basis points (one hundredth of a percent) as suggested by Krzysztof. Description was adjusted.
Note: permille (1/1000) was also suggested as unit for this property.v2 Changes:
* adi,aaf-gain property renamed to adi,gain-milli. Description was simplified.
* default value add to adi,gain-milli.--- .../bindings/iio/adc/adi,ad7768-1.yaml | 44 +++++++++++++++++-- 1 file changed, 40 insertions(+), 4 deletions(-)Documentation/devicetree/bindings/iio/adc/adi,ad7768-1.yaml +1
-1@@ -4,18 +4,26 @@ $id: http://devicetree.org/schemas/iio/adc/adi,ad7768-1.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Analog Devices AD7768-1 ADC device driver +title: Analog Devices AD7768-1 ADC family maintainers: - Michael Hennerich <[email protected]>
Documentation/devicetree/bindings/iio/adc/adi,ad7768-1.yaml line 18
Quoted 10 lines
Documentation/devicetree/bindings/iio/adc/adi,ad7768-1.yaml +6
-2description: | - Datasheet at: - https://www.analog.com/media/en/technical-documentation/data-sheets/ad7768-1.pdf + Analog Devices AD7768-1 24-Bit Single Channel Low Power sigma-delta ADC family + + https://www.analog.com/media/en/technical-documentation/data-sheets/ad7768-1.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/adaq7767-1.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/adaq7768-1.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/adaq7769-1.pdf
Only adding one property seems a bit incomplete give that the ADAQs have significantly more pins that the regular ADC.
E.g different/more power supplies; gain-gpios, fda-gpios (or don't allow gpio-controller if we can assume GAINx and FAx are always wired to back to the ADC and not coming from somewhere else).
Quoted 29 lines
Documentation/devicetree/bindings/iio/adc/adi,ad7768-1.yaml +18
-1properties: compatible: - const: adi,ad7768-1 + enum: + - adi,ad7768-1 + - adi,adaq7767-1 + - adi,adaq7768-1 + - adi,adaq7769-1 reg: maxItems: 1@@ -58,6 +66,19 @@ properties: description: ADC reference voltage supply + adi,aaf-gain-bp: + description: | + Specifies the gain applied by the Analog Anti-Aliasing Filter (AAF) + to the ADC input in basis points (one hundredth of a percent). + The hardware gain is determined by which input pin(s) the signal goes + through into the AAF. The possible connections are: + * For the ADAQ7767-1: Input connected to IN1±, IN2± or IN3±. + * For the ADAQ7769-1: OUT_PGA pin connected to IN1_AAF+, IN2_AAF+, + or IN3_AAF+. + $ref: /schemas/types.yaml#/definitions/uint16 + enum: [1430, 3640, 10000] + default: 10000 +
PATCH v3 2/4 iio: adc: ad7768-1: introduce chip info for future multidevice support
In reply to Jonathan SantosAdd Chip info struct in SPI device to store channel information for each supported part.
---
v3 Changes:
* ad7768_channel_masks removed along with available_masks element in ad7768_chip_info struct. It does not add anything for single channels, so not needed, at least for now.
* fixed inconsistency in spaces before \ in AD7768_CHAN macro.
v2 Changes:
* removed AD7768_CHAN_INFO_NONE macro.
* reordered fields in ad7768_chip_info struct.
* removed trailing comma.
--- drivers/iio/adc/ad7768-1.c | 67 +++++++++++++++++++++++++-------------
1 1 file changed, 44 insertions(+), 23 deletions(-)
drivers/iio/adc/ad7768-1.c +44 -23
@@ -213,6 +213,12 @@ static const struct iio_scan_type ad7768_scan_type[] = { }, }; +struct ad7768_chip_info { +const char *name; +const struct iio_chan_spec *channel_spec; +int num_channels; +}; +struct ad7768_state {struct spi_device *spi;struct regmap *regmap;
@@ -234,6 +240,7 @@ struct ad7768_state {struct gpio_desc *gpio_reset;const char *labels[AD7768_MAX_CHANNELS ];struct gpio_chip gpiochip; +const struct ad7768_chip_info *chip;bool en_spi_sync;/* * DMA (thus cache coherency maintenance) may require the
@@ -748,24 +755,27 @@ static const struct iio_chan_spec_ext_info ad7768_ext_info[] = { { } }; +#define AD7768_CHAN (_idx, _msk_avail) { \ + .type = IIO_VOLTAGE, \ + .info_mask_separate_available = _msk_avail, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) | \ + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ + .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .ext_info = ad7768_ext_info, \ + .indexed = 1, \ + .channel = _idx, \ + .scan_index = _idx, \ + .has_ext_scan_type = 1, \ + .ext_scan_type = ad7768_scan_type, \ + .num_ext_scan_type = ARRAY_SIZE(ad7768_scan_type), \ +} +static const struct iio_chan_spec ad7768_channels[] = { - { - .type =IIO_VOLTAGE , - .info_mask_separate =BIT (IIO_CHAN_INFO_RAW ), - .info_mask_shared_by_type =BIT (IIO_CHAN_INFO_SCALE ) | -BIT (IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY ) | -BIT (IIO_CHAN_INFO_OVERSAMPLING_RATIO ), - .info_mask_shared_by_type_available =BIT (IIO_CHAN_INFO_OVERSAMPLING_RATIO ), - .info_mask_shared_by_all =BIT (IIO_CHAN_INFO_SAMP_FREQ ), - .info_mask_shared_by_all_available =BIT (IIO_CHAN_INFO_SAMP_FREQ ), - .ext_info = ad7768_ext_info, - .indexed =1 , - .channel =0 , - .scan_index =0 , - .has_ext_scan_type =1 , - .ext_scan_type = ad7768_scan_type, - .num_ext_scan_type =ARRAY_SIZE (ad7768_scan_type), - }, +AD7768_CHAN (0 ,0 ), }; static int ad7768_read_raw(struct iio_dev *indio_dev,
@@ -1321,6 +1331,12 @@ static int ad7768_register_regulators(struct device *dev, struct ad7768_state *sreturn 0 ; } +static const struct ad7768_chip_info ad7768_chip_info = { + .name ="ad7768-1" , + .channel_spec = ad7768_channels, + .num_channels =ARRAY_SIZE (ad7768_channels), +}; +static int ad7768_probe (struct spi_device *spi) {struct ad7768_state *st;
@@ -1371,9 +1387,14 @@ static int ad7768_probe(struct spi_device *spi) st->mclk_freq =clk_get_rate (st->mclk); - indio_dev->channels = ad7768_channels; - indio_dev->num_channels =ARRAY_SIZE (ad7768_channels); - indio_dev->name =spi_get_device_id (spi)->name; + st->chip =spi_get_device_match_data (spi); +if (!st->chip) +return dev_err_probe (&spi->dev, -ENODEV , +"Could not find chip info data\n" ); + + indio_dev->channels = st->chip->channel_spec; + indio_dev->num_channels = st->chip->num_channels; + indio_dev->name = st->chip->name; indio_dev->info = &ad7768_info; indio_dev->modes =INDIO_DIRECT_MODE ;
@@ -1390,7 +1411,7 @@ static int ad7768_probe(struct spi_device *spi)init_completion (&st->completion); - ret =ad7768_set_channel_label (indio_dev,ARRAY_SIZE (ad7768_channels)); + ret =ad7768_set_channel_label (indio_dev, st->chip->num_channels);if (ret)return ret;
@@ -1409,13 +1430,13 @@ static int ad7768_probe(struct spi_device *spi) }static const struct spi_device_id ad7768_id_table[] = { - {"ad7768-1" ,0 }, + {"ad7768-1" , (kernel_ulong_t)&ad7768_chip_info }, { } };MODULE_DEVICE_TABLE (spi, ad7768_id_table);static const struct of_device_id ad7768_of_match[] = { - { .compatible ="adi,ad7768-1" }, + { .compatible ="adi,ad7768-1" , .data = &ad7768_chip_info }, { } };MODULE_DEVICE_TABLE (of, ad7768_of_match);
Signature · 1 line
2.34.1
Re: [PATCH v3 2/4] iio: adc: ad7768-1: introduce chip info for future multidevice support
Quoted 2 lines · Jonathan Santos
Add Chip info struct in SPI device to store channel information for each supported part.
...
Quoted 1 line
+#define
AD7768_CHAN(_idx, _msk_avail){ \
I consider slightly better to read
#define AD7768_CHAN(_idx, _msk_avail) \
{ \
drivers/iio/adc/ad7768-1.c static const struct iio_chan_spec_ext_info ad7768_ext_info[] = {
Quoted 7 lines
drivers/iio/adc/ad7768-1.c +6
-0+ .type = IIO_VOLTAGE, \ + .info_mask_separate_available = _msk_avail, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type =BIT (IIO_CHAN_INFO_SCALE ) | \ +BIT (IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY ) | \ + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
In the original code below indentation was not broken.
Quoted 11 lines
drivers/iio/adc/ad7768-1.c +11
-0+ .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .ext_info = ad7768_ext_info, \ + .indexed = 1, \ + .channel = _idx, \ + .scan_index = _idx, \ + .has_ext_scan_type = 1, \ + .ext_scan_type = ad7768_scan_type, \ + .num_ext_scan_type = ARRAY_SIZE(ad7768_scan_type), \ +}
...
drivers/iio/adc/ad7768-1.c static int ad7768_probe(struct spi_device *spi) · line 1393
Quoted 5 lines
drivers/iio/adc/ad7768-1.c +4
-0+ st->chip =spi_get_device_match_data (spi); +if (!st->chip) +return dev_err_probe (&spi->dev, -ENODEV , +"Could not find chip info data\n" );
Might be useful in some cases, but I don't see its value. Just always provide a chip_info and no need to care about this. Esp. this just shows that it's mandatory, but if absent, it will crash on the following line. Since it's about probe, one will notice it immediately, otherwise it will mean a submission of the code that has never been tested.
TL;DR: just drop this check.
Quoted 1 line
drivers/iio/adc/ad7768-1.c +1
-0+ indio_dev->channels = st->chip->channel_spec;
Signature · 2 lines
With Best Regards, Andy Shevchenko
David Lechner
reviewerRe: [PATCH v3 2/4] iio: adc: ad7768-1: introduce chip info for future multidevice support
In reply to Jonathan SantosQuoted 3 lines · Jonathan Santos
Add Chip info struct in SPI device to store channel information for each supported part.
...
drivers/iio/adc/ad7768-1.c static int ad7768_probe(struct spi_device *spi) · line 1390
Quoted 8 lines
drivers/iio/adc/ad7768-1.c +1
-3@@ -1371,9 +1387,14 @@ static int ad7768_probe(struct spi_device *spi) st->mclk_freq =clk_get_rate (st->mclk); - indio_dev->channels = ad7768_channels; - indio_dev->num_channels =ARRAY_SIZE (ad7768_channels); - indio_dev->name =spi_get_device_id (spi)->name; + st->chip =spi_get_device_match_data (spi);
Generally, we want this early in probe so that chip info is available as early as possible. Might not need it now, but would save us from having to move this later if we ever do.
Quoted 4 lines
drivers/iio/adc/ad7768-1.c +4
-0+if (!st->chip) +return dev_err_probe (&spi->dev, -ENODEV , +"Could not find chip info data\n" ); +
PATCH v3 3/4 math.h: Add 64-bit fractional numbers types
In reply to Jonathan SantosExtend fractional numbers types to include __u64 and __s64 data types.
---
v3 Changes:
* New patch.
* OBS: Andy suggested to support long types, but the macro was made for data types like __TYPE. So i have added the __u64 and __s64 types.
--- include/linux/math.h | 2 ++ 1 file changed, 2 insertions(+)
include/linux/math.h +2 -0
@@ -130,6 +130,8 @@ __STRUCT_FRACT(s16) __STRUCT_FRACT(u16) __STRUCT_FRACT(s32) __STRUCT_FRACT(u32) +__STRUCT_FRACT(s64) +__STRUCT_FRACT(u64) #undef __STRUCT_FRACT/* Calculate "x * n / d" without unnecessary overflow or loss of precision. */
Signature · 1 line
2.34.1
Re: [PATCH v3 3/4] math.h: Add 64-bit fractional numbers types
Quoted 1 line · Jonathan Santos
Extend fractional numbers types to include
__u64and__s64data types.
Signature · 2 lines
With Best Regards, Andy Shevchenko
PATCH v3 4/4 iio: adc: ad7768-1: add support for ADAQ776x-1 ADC Family
In reply to Jonathan SantosAdd support for ADAQ7767/68/69-1 series, which includes PGIA and Anti-aliasing filter (AAF) gains. Unlike the AD7768-1, they do not provide a VCM regulator interface.
The PGA gain is configured in run-time through the scale attribute, if supported by the device. PGA is enabled and controlled by the GPIO controller (GPIOs 0, 1 and 2) provided by the device with the SPI interface.
The AAF gain is defined by hardware connections and should be specified in the device tree.
---
v3 Changes:
* Fixed trailing comma issues.
* Addressed other minor issues related to dead code, variable declaration, etc.
* removed unnecessary comments and relocating some local variables.
* replaced mutex_init() with devm_mutex_init().
* adopted different variables for the input and output of rational_best_approximation(). Also used a u64_fract for the inputs, but kept the unsigned long for the outputs, because could not create a unsigned long fraction number type.
* ad7768_set_pga_gain(): removed the pgia enable check, relying on the regmap cache.
* Moved aaf gain parsing to its own function, and now returning after warning to avoid setting a variable when it shouldn't (avoid confusion).
* AAF gain is now in basis point units, so related multipliers and dividers are adjusted accordingly.
v2 Changes:
* Added more details to the commit message.
* Some devices does not provide VCM regulator, so a new field in the chip info struct was added to indicate this.
* Added 'select RATIONAL' to Kconfig. Kernel test robot pointed out compilation error due to undefined reference to rational_best_approximation().
* Added lock to protect PGA value access.
* precision in the PGA calculation is now dependent of the channel sign (signed or unsigned).
* went back to the original scale computation: (st->vref_uv * 2) / 2^n instead of st->vref_uv / 2^(n-1).
* rewrote AAF gain check and replaced error returns with warnings. I the AAF gain is not provided, a default value is used.
* Addressed other minor suggestions.
--- drivers/iio/adc/Kconfig | 1 + drivers/iio/adc/ad7768-1.c | 292 ++++++++++++++++++++++++++++++++++++- 2 files changed, 291 insertions(+), 2 deletions(-)
drivers/iio/adc/Kconfig +1 -0
@@ -374,6 +374,7 @@ config AD7768_1 depends on SPI select REGULATOR select REGMAP_SPI + select RATIONAL select IIO_BUFFER select IIO_TRIGGER select IIO_TRIGGERED_BUFFER
drivers/iio/adc/ad7768-1.c +290 -2
439 lines not on this page · raw message
Signature · 1 line
2.34.1
David Lechner
reviewerRe: [PATCH v3 4/4] iio: adc: ad7768-1: add support for ADAQ776x-1 ADC Family
Quoted 4 lines · Jonathan Santos
Add support for ADAQ7767/68/69-1 series, which includes PGIA and Anti-aliasing filter (AAF) gains. Unlike the AD7768-1, they do not provide a VCM regulator interface.
...
Quoted 20 lines
drivers/iio/adc/ad7768-1.c +20
-0+static void ad7768_fill_scale_tbl (struct iio_dev *dev) +{ +struct ad7768_state *st =iio_priv (dev); +const struct iio_scan_type *scan_type; +int val, val2, tmp0, tmp1, i; +struct u64_fract fract; +unsigned long n, d; +u64 tmp2; + + scan_type =iio_get_current_scan_type (dev, &dev->channels[0 ]); +if (scan_type->sign =='s' ) + val2 = scan_type->realbits -1 ; +else + val2 = scan_type->realbits; + +for (i =0 ; i < st->chip->num_pga_modes; i++) { +/* Convert gain to a fraction format */ + fract.numerator = st->chip->pga_gains[i]; + fract.denominator =MILLI ; +if (st->chip->has_variable_aaf) {
drivers/iio/adc/ad7768-1.c static int ad7768_reg_access(struct iio_dev *indio_dev, · line 563
Quoted 10 lines
drivers/iio/adc/ad7768-1.c +10
-0+ fract.numerator *= ad7768_aaf_gains_bp[st->aaf_gain]; + fract.denominator *=10000 ; + } + +rational_best_approximation (fract.numerator, fract.denominator, +INT_MAX ,INT_MAX , &n, &d); + + val =mult_frac (st->vref_uv, d, n); +/* Would multiply by NANO here, but value is already in milli */ + tmp2 =shift_right ((u64 )val *MICRO , val2);
shift_right() is only needed for signed values. Can just use >> since this is dealing with unsigned.
Quoted 6 lines
drivers/iio/adc/ad7768-1.c +6
-0+ tmp0 =div_u64_rem (tmp2,NANO , &tmp1); + st->scale_tbl[i][0 ] = tmp0;/* Integer part */ + st->scale_tbl[i][1 ] =abs (tmp1);/* Fractional part */ + } +} +
...
drivers/iio/adc/ad7768-1.c static int ad7768_configure_dig_fil(struct iio_dev *dev, · line 706
Quoted 9 lines
drivers/iio/adc/ad7768-1.c +9
-0+static int ad7768_set_pga_gain (struct ad7768_state *st, +int gain_mode) +{ +int pgia_pins_value =abs (gain_mode - st->chip->pgia_mode2pin_offset); +int ret; + +guard (mutex)(&st->pga_lock); + + ret =regmap_write (st->regmap,AD7768_REG_GPIO_CONTROL ,AD7768_GPIO_PGIA_EN );
Hiding multiple fields in a macro makes it harder to see what this is doing.
drivers/iio/adc/ad7768-1.c static int ad7768_configure_dig_fil(struct iio_dev *dev, · line 712
Quoted 6 lines
drivers/iio/adc/ad7768-1.c +6
-0+if (ret) +return ret; + +/* Write the respective gain values to GPIOs 0, 1, 2 */ + ret =regmap_write (st->regmap,AD7768_REG_GPIO_WRITE , +AD7768_GPIO_WRITE (pgia_pins_value));
Hiding the FIELD_PREP() in a macro makes this a bit harder to understand.
Quoted 28 lines
drivers/iio/adc/ad7768-1.c +13
-1+if (ret) +return ret; + + st->pga_gain_mode = gain_mode; + +return 0 ; +} +static int ad7768_gpio_direction_input (struct gpio_chip *chip,unsigned int offset) {struct iio_dev *indio_dev =gpiochip_get_data (chip);@@ -778,6 +925,10 @@ static const struct iio_chan_spec ad7768_channels[] = { AD7768_CHAN(0, 0), }; +static const struct iio_chan_spec adaq776x_channels[] = { +AD7768_CHAN (0 ,BIT (IIO_CHAN_INFO_SCALE )), +}; +static int ad7768_read_raw (struct iio_dev *indio_dev,struct iio_chan_spec const *chan,int *val,int *val2,long info)@@ -805,7 +956,19 @@ static int ad7768_read_raw(struct iio_dev *indio_dev,return IIO_VAL_INT ;case IIO_CHAN_INFO_SCALE : - *val = (st->vref_uv *2 ) /1000 ; +if (st->chip->has_pga) {
drivers/iio/adc/ad7768-1.c static int ad7768_read_raw(struct iio_dev *indio_dev, · line 969
Quoted 10 lines
drivers/iio/adc/ad7768-1.c +10
-0+guard (mutex)(&st->pga_lock); + + *val = st->scale_tbl[st->pga_gain_mode][0 ]; + *val2 = st->scale_tbl[st->pga_gain_mode][1 ]; +return IIO_VAL_INT_PLUS_NANO ; + } + + temp = (st->vref_uv *2 ) /1000 ; +if (st->chip->has_variable_aaf) + temp = (temp *10000 ) / ad7768_aaf_gains_bp[st->aaf_gain];
Should we add a BASIS_POINTS macro to units.h since we are calling this a standard unit?
Quoted 5 lines
drivers/iio/adc/ad7768-1.c +2
-0+ + *val = temp; *val2 = scan_type->realbits;return IIO_VAL_FRACTIONAL_LOG2 ;
...
drivers/iio/adc/ad7768-1.c static int ad7768_register_regulators(struct device *dev, struct ad7768_state *s · line 1540
Quoted 7 lines
drivers/iio/adc/ad7768-1.c +7
-0+static int ad7768_parse_aaf_gain (struct device *dev,struct ad7768_state *st) +{ +bool aaf_gain_provided; +u32 val; +int ret; + + st->aaf_gain =AD7768_AAF_IN1 ;
No sense in setting this if we return early on -EINVAL.
drivers/iio/adc/ad7768-1.c static int ad7768_register_regulators(struct device *dev, struct ad7768_state *s · line 1542
Quoted 2 lines
drivers/iio/adc/ad7768-1.c +2
-0+ ret =device_property_read_u32 (dev,"adi,aaf-gain-bp" , &val); + aaf_gain_provided = (ret ==0 );
Only -EINVAL means the property is not present. Other errors can be returned. Or add a comment explaining why we don't care about other errors.
drivers/iio/adc/ad7768-1.c static int ad7768_register_regulators(struct device *dev, struct ad7768_state *s · line 1544
Quoted 2 lines
drivers/iio/adc/ad7768-1.c +2
-0+if (!aaf_gain_provided && st->chip->has_variable_aaf) { +dev_warn (dev,"AAF gain not specified, using default\n" );
Using the default seems like a normal thing to do, so should not be a warning.
drivers/iio/adc/ad7768-1.c static int ad7768_register_regulators(struct device *dev, struct ad7768_state *s · line 1549
Quoted 5 lines
drivers/iio/adc/ad7768-1.c +5
-0+return 0 ; + } + +if (aaf_gain_provided && !st->chip->has_variable_aaf) { +dev_warn (dev,"AAF gain not supported for %s\n" , st->chip->name);
Returning error here would be senseible. Clearly there is something wrong with the devicetree. But it could be something else, like the wrong compaible string.
Quoted 23 lines
drivers/iio/adc/ad7768-1.c +23
-0+return 0 ; + } + +if (aaf_gain_provided) { +switch (val) { +case 10000 : + st->aaf_gain =AD7768_AAF_IN1 ; +break ; +case 3640 : + st->aaf_gain =AD7768_AAF_IN2 ; +break ; +case 1430 : + st->aaf_gain =AD7768_AAF_IN3 ; +break ; +default : +return dev_err_probe (dev, -EINVAL , +"Invalid firmware provided AAF gain\n" ); + } + } + +return 0 ; +} +
...
drivers/iio/adc/ad7768-1.c static int ad7768_probe(struct spi_device *spi) · line 1673
Quoted 8 lines
static int
ad7768_probe(struct spi_device *spi)drivers/iio/adc/ad7768-1.c +2
-1@@ -1399,7 +1669,13 @@ static int ad7768_probe(struct spi_device *spi) indio_dev->modes =INDIO_DIRECT_MODE ;/* Register VCM output regulator */ - ret =ad7768_register_regulators (&spi->dev, st, indio_dev); +if (st->chip->has_vcm_regulator) { + ret =ad7768_register_regulators (&spi->dev, st, indio_dev);
ad7768_register_regulators() now seems mis-named since it only handles VMC supply.
Quoted 8 lines
drivers/iio/adc/ad7768-1.c +5
-0+if (ret) +return ret; + } + + ret =ad7768_parse_aaf_gain (&spi->dev, st);if (ret)return ret;
Re: [PATCH v3 4/4] iio: adc: ad7768-1: add support for ADAQ776x-1 ADC Family
In reply to Jonathan SantosQuoted 11 lines · Jonathan Santos
Add support for ADAQ7767/68/69-1 series, which includes PGIA and Anti-aliasing filter (AAF) gains. Unlike the AD7768-1, they do not provide a VCM regulator interface.
The PGA gain is configured in run-time through the scale attribute, if supported by the device. PGA is enabled and controlled by the GPIO controller (GPIOs 0, 1 and 2) provided by the device with the SPI interface.
The AAF gain is defined by hardware connections and should be specified in the device tree.
...
drivers/iio/adc/ad7768-1.c static int ad7768_reg_access(struct iio_dev *indio_dev, · line 543
Quoted 10 lines
drivers/iio/adc/ad7768-1.c +10
-0+static void ad7768_fill_scale_tbl (struct iio_dev *dev) +{ +struct ad7768_state *st =iio_priv (dev); +const struct iio_scan_type *scan_type; +int val, val2, tmp0, tmp1, i; +struct u64_fract fract; +unsigned long n, d; +u64 tmp2; + + scan_type =iio_get_current_scan_type (dev, &dev->channels[0 ]);
Is it usual patter in IIO? Otherwise it can be written as
scan_type = iio_get_current_scan_type(dev, dev->channels);
drivers/iio/adc/ad7768-1.c static int ad7768_reg_access(struct iio_dev *indio_dev, · line 547
Quoted 4 lines
drivers/iio/adc/ad7768-1.c +4
-0+if (scan_type->sign =='s' ) + val2 = scan_type->realbits -1 ; +else + val2 = scan_type->realbits;
Wasn't smatch happy about this check?
drivers/iio/adc/ad7768-1.c static int ad7768_reg_access(struct iio_dev *indio_dev, · line 556
Quoted 8 lines
drivers/iio/adc/ad7768-1.c +8
-0+for (i =0 ; i < st->chip->num_pga_modes; i++) { +/* Convert gain to a fraction format */ + fract.numerator = st->chip->pga_gains[i]; + fract.denominator =MILLI ; +if (st->chip->has_variable_aaf) { + fract.numerator *= ad7768_aaf_gains_bp[st->aaf_gain]; + fract.denominator *=10000 ; + }
My question also was: Are these overflow u32? If not, the second patch is not needed. Otherwise, how is the previous version supposed to work with unsigned long type (if I am not mistaken) on 32-bit platforms?
Quoted 11 lines
drivers/iio/adc/ad7768-1.c +11
-0+rational_best_approximation (fract.numerator, fract.denominator, +INT_MAX ,INT_MAX , &n, &d); + + val =mult_frac (st->vref_uv, d, n); +/* Would multiply by NANO here, but value is already in milli */ + tmp2 =shift_right ((u64 )val *MICRO , val2); + tmp0 =div_u64_rem (tmp2,NANO , &tmp1); + st->scale_tbl[i][0 ] = tmp0;/* Integer part */ + st->scale_tbl[i][1 ] =abs (tmp1);/* Fractional part */ + } +}
...
drivers/iio/adc/ad7768-1.c static int ad7768_configure_dig_fil(struct iio_dev *dev, · line 691
Quoted 12 lines
drivers/iio/adc/ad7768-1.c +12
-0+static int ad7768_calc_pga_gain (struct ad7768_state *st,int gain_int, +int gain_fract,int precision) +{ +u64 gain_nano; +u32 tmp; + + gain_nano = gain_int *NANO + gain_fract; + gain_nano =clamp (gain_nano,0 ,ADAQ776X_GAIN_MAX_NANO ); + tmp =DIV_ROUND_CLOSEST_ULL (gain_nano << precision,NANO ); + gain_nano =DIV_ROUND_CLOSEST (st->vref_uv, tmp); +if (st->chip->has_variable_aaf) + gain_nano = DIV_ROUND_CLOSEST_ULL(gain_nano * 10000,
One space too many.
drivers/iio/adc/ad7768-1.c static int ad7768_configure_dig_fil(struct iio_dev *dev, · line 695
Quoted 4 lines
drivers/iio/adc/ad7768-1.c +4
-0+ ad7768_aaf_gains_bp[st->aaf_gain]); + +return find_closest (gain_nano, st->chip->pga_gains, + (int )st->chip->num_pga_modes);
Is casting needed?
Quoted 1 line
+}
...
drivers/iio/adc/ad7768-1.c static int __ad7768_write_raw(struct iio_dev *indio_dev, · line 1071
Quoted 1 line
drivers/iio/adc/ad7768-1.c +1
-0+case IIO_CHAN_INFO_SCALE : {
One space too many.
Quoted 14 lines
drivers/iio/adc/ad7768-1.c +14
-0+int gain_mode; + +if (!st->chip->has_pga) +return -EOPNOTSUPP ; + +if (scan_type->sign =='s' ) + gain_mode =ad7768_calc_pga_gain (st, val, val2, + scan_type->realbits -1 ); +else + gain_mode =ad7768_calc_pga_gain (st, val, val2, + scan_type->realbits); + +return ad7768_set_pga_gain (st, gain_mode); + }
...
drivers/iio/adc/ad7768-1.c static int ad7768_register_regulators(struct device *dev, struct ad7768_state *s · line 1542
Quoted 10 lines
drivers/iio/adc/ad7768-1.c +8
-0+static int ad7768_parse_aaf_gain (struct device *dev,struct ad7768_state *st) +{ +bool aaf_gain_provided; +u32 val; +int ret; + st->aaf_gain =AD7768_AAF_IN1 ; + ret =device_property_read_u32 (dev,"adi,aaf-gain-bp" , &val); + aaf_gain_provided = (ret ==0 );
Hmm... It seems rather incorrect check. You should actually return an error code in case it's provided but can't be read.
I would expect something like
ret = device_property_read_u32(dev, "adi,aaf-gain-bp", &val); if (ret == -EINVAL) _gain_provided = false; else if (ret) return dev_err_probe(...); else _gain_provided = true;
drivers/iio/adc/ad7768-1.c static int ad7768_register_regulators(struct device *dev, struct ad7768_state *s · line 1551
Quoted 9 lines
drivers/iio/adc/ad7768-1.c +9
-0+if (!aaf_gain_provided && st->chip->has_variable_aaf) { +dev_warn (dev,"AAF gain not specified, using default\n" ); +return 0 ; + } + +if (aaf_gain_provided && !st->chip->has_variable_aaf) { +dev_warn (dev,"AAF gain not supported for %s\n" , st->chip->name); +return 0 ; + }
We can refactor these to have one level indentation less for the switch-case.
if (aaf_gain_provided && !st->chip->has_variable_aaf) {
dev_warn(dev, "AAF gain not supported for %s\n", st->chip->name);
return 0;
}
if (!aaf_gain_provided) {
if (st->chip->has_variable_aaf)
dev_warn(dev, "AAF gain not specified, using default\n");
return 0;
}drivers/iio/adc/ad7768-1.c static int ad7768_register_regulators(struct device *dev, struct ad7768_state *s · line 1553
Quoted 1 line
drivers/iio/adc/ad7768-1.c +1
-0+if (aaf_gain_provided) {
So this one may be dropped.
Quoted 17 lines
drivers/iio/adc/ad7768-1.c +17
-0+switch (val) { +case 10000 : + st->aaf_gain =AD7768_AAF_IN1 ; +break ; +case 3640 : + st->aaf_gain =AD7768_AAF_IN2 ; +break ; +case 1430 : + st->aaf_gain =AD7768_AAF_IN3 ; +break ; +default : +return dev_err_probe (dev, -EINVAL , +"Invalid firmware provided AAF gain\n" ); + } + } +return 0 ; +}
Signature · 2 lines
With Best Regards, Andy Shevchenko
Re: [PATCH v3 4/4] iio: adc: ad7768-1: add support for ADAQ776x-1 ADC Family
Quoted 1 line · Andy Shevchenko
On Fri, Sep 05, 2025 at 06:49:42AM -0300, Jonathan Santos wrote:
...
Quoted 6 lines
drivers/iio/adc/ad7768-1.c static int ad7768_reg_access(struct iio_dev *indio_dev, · line 547
Quoted 4 lines
drivers/iio/adc/ad7768-1.c +4
-0+if (scan_type->sign =='s' ) + val2 = scan_type->realbits -1 ; +else + val2 = scan_type->realbits;Wasn't smatch happy about this check?
I meant unhappy
Signature · 2 lines
With Best Regards, Andy Shevchenko
Jonathan Cameron
maintainerRe: [PATCH v3 4/4] iio: adc: ad7768-1: add support for ADAQ776x-1 ADC Family
In reply to Andy ShevchenkoQuoted 14 lines
drivers/iio/adc/ad7768-1.c static int ad7768_reg_access(struct iio_dev *indio_dev, · line 543
Quoted 11 lines
drivers/iio/adc/ad7768-1.c +10
-0+static void ad7768_fill_scale_tbl (struct iio_dev *dev) +{ +struct ad7768_state *st =iio_priv (dev); +const struct iio_scan_type *scan_type; +int val, val2, tmp0, tmp1, i; +struct u64_fract fract; +unsigned long n, d; +u64 tmp2; + + scan_type =iio_get_current_scan_type (dev, &dev->channels[0 ]);Is it usual patter in IIO? Otherwise it can be written as
Quoted 1 line
scan_type = iio_get_current_scan_type(dev, dev->channels);
From a semantic / readability point of view I'd keep it referencing the first element. We are querying the scan type of one specific channel, rather than the array that is behind dev->channels.
Quoted 5 lines
Quoted 5 lines
drivers/iio/adc/ad7768-1.c +4
-0+if (scan_type->sign =='s' ) + val2 = scan_type->realbits -1 ; +else + val2 = scan_type->realbits;