Skip to contentSkip to conversation

Add support for ADAQ776x-1 ADC Family

PATCH In review Jonathan Santos 3 participants 11 messages Jan 14 – Jan 22

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

v6 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 v6:
* Use Pattern PER* for all percentage-related macros and include macros
for Per mille and per cent mille units.
* Refactored ad7768_parse_aaf_gain() to improve cleanliness and readability.
* Link to v5: https://lore.kernel.org/linux-iio/[email protected]/T/#t/

Changes in v5:
* Added PERCENT macro along with BASIS_POINTS in units.h.
* Added new patch to allow writing attributes without direct mode claim.
* Write scale attribute without direct mode claim to avoid deadlock
when using GPIOs from the device's own controller.
* Link to v4: https://lore.kernel.org/linux-iio/[email protected]/T/#t

Changes in v4:
* Removed u64_fract type patch, as it is not used. u32_fract is sufficient
for the PGA gain calculations.
* Added new patch adding BASIS_POINTS macro to units.h.
* Included pga-gpios property for parts that support PGA gain.
Before we were using the internal gpio controller to manage the PGA pins,
but still exposing the controller for external use (causing possible conflicts).
* Addressed other review comments, see individual patches.
* Link to v3: https://lore.kernel.org/linux-iio/[email protected]/T/#t

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 (5):
dt-bindings: iio: adc: ad7768-1: add new supported parts
iio: adc: ad7768-1: introduce chip info for future multidevice support
units: add conversion macros for percentage related units
iio: adc: ad7768-1: refactor ad7768_write_raw()
iio: adc: ad7768-1: add support for ADAQ776x-1 ADC Family

 .../bindings/iio/adc/adi,ad7768-1.yaml        |  64 ++-
 drivers/iio/adc/Kconfig                       |   1 +
 drivers/iio/adc/ad7768-1.c                    | 423 +++++++++++++++---
 include/linux/units.h                         |  19 +
 4 files changed, 453 insertions(+), 54 deletions(-)

base-commit: e0bc6d7e258486c10bb11e31fd4421c134063b1d

Signature · 1 line
2.34.1
#1 lore raw

PATCH v6 1/5 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, and for PGA gain, supported by ADAQ7768-1 and ADAQ7769-1:
adi,aaf-gain-bp
pga-gpios

---
v6 Changes:
* None.

v5 Changes:
* None.

v4 Changes:
* Inspired by [1], Included pga-gpios property for parts that support PGA gain. Before we were using the internal gpio controller to manage the PGA pins, but still exposing the controller for external use (causing possible conflicts). Using pga-gpios we can let the consumer define the pins to be used for PGA, even from the internal gpio controller (but not limited by that). The problem with that approach is the deadlock described in the last patch from this set.

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.

[1]: https://lore.kernel.org/linux-iio/318c31e023ebe30cc99b8743e87e869bf5e1f12b.1760984107.git.marcelo.schmitt@analog.com/

---
 .../bindings/iio/adc/adi,ad7768-1.yaml        | 64 +++++++++++++++++--
 1 file changed, 60 insertions(+), 4 deletions(-)
Documentation/devicetree/bindings/iio/adc/adi,ad7768-1.yaml +60 -4
index c06d0fc791d3..dfa2d7fa9fb3 100644
@@ -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,25 @@ 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+.
+    enum: [1430, 3640, 10000]
+    default: 10000
+
+  pga-gpios:
+    description:
+      GAIN 0, GAIN1 and GAIN2 pins for gain selection. For devices that have
+      PGA configuration input pins, pga-gpios must be defined.
+    minItems: 3
+    maxItems: 3
+
   adi,sync-in-gpios:
     maxItems: 1
     description:
@@ -147,6 +174,35 @@ 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
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - adi,adaq7768-1
+              - adi,adaq7769-1
+    then:
+      required:
+        - pga-gpios
+    else:
+      properties:
+        pga-gpios: false
+
 unevaluatedProperties: false
 
 examples:
Signature · 1 line
2.34.1
#2 lore raw

PATCH v6 2/5 iio: adc: ad7768-1: introduce chip info for future multidevice support

In reply to Jonathan Santos

Add Chip info struct in SPI device to store channel information for each supported part.

---
v6 Changes:
* None.

v5 Changes:
* None.

v4 Changes:
* Dropped chip info check and moved the st->chip assignment early in the probe function.
* Addressed indentation inconsistencies in AD7768_CHAN macro.

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 | 64 ++++++++++++++++++++++++--------------
 1 file changed, 41 insertions(+), 23 deletions(-)
drivers/iio/adc/ad7768-1.c +41 -23
index d96802b7847a..89b0ca8f584c 100644
@@ -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,28 @@ 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 +1332,12 @@ static int ad7768_register_regulators(struct device *dev, struct ad7768_state *s
 	return 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;
@@ -1347,6 +1364,7 @@ static int ad7768_probe(struct spi_device *spi)
 			return ret;
 	}
 
+	st->chip = spi_get_device_match_data(spi);
 	st->spi = spi;
 
 	st->regmap = devm_regmap_init_spi(spi, &ad7768_regmap_config);
@@ -1371,9 +1389,9 @@ 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;
+	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 +1408,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 +1427,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
#3 lore raw

PATCH v6 3/5 units: add conversion macros for percentage related units

In reply to Jonathan Santos

Add macros to convert between ratio and percentage related units, including percent (1/100), permille (1/1,000), permyriad (1/10,000, also equivalent to one Basis point) and per cent mille (1/100,000). Those are Used for precise fractional calculations in engineering, finance, and measurement applications.

---
v6 Changes:
* Use Pattern PER* for all percentage-related macros. BASIS_POINTS is now PERMYRIAD.
* Include macros for Per mille and per cent mille units.

v5 Changes:
* Included PERCENT macro along with BASIS_POINTS.
* Adjusted commit description and comment in the code to add more context and examples.

v4 Changes:
* New patch.

---
 include/linux/units.h | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
include/linux/units.h +19 -0
index 00e15de33eca..3471c5a38dcf 100644
@@ -21,6 +21,25 @@
 #define PICO	1000000000000ULL
 #define FEMTO	1000000000000000ULL
 
+/*
+ * Percentage and related scaling units
+ *
+ * These macros define scaling factors used to convert between ratio and
+ * percentage-based representations with different decimal resolutions.
+ * They are used for precise fractional calculations in engineering, finance,
+ * and measurement applications.
+ *
+ * Examples:
+ *   1%     = 0.01    = 1 / PERCENT
+ *   0.1%   = 0.001   = 1 / PERMILLE
+ *   0.01%  = 0.0001  = 1 / PERMYRIAD (1 basis point)
+ *   0.001% = 0.00001 = 1 / PERCENTMILLE
+ */
+#define PERCENT		100
+#define PERMILLE	1000
+#define PERMYRIAD	10000
+#define PERCENTMILLE	100000
+
 #define NANOHZ_PER_HZ		1000000000UL
 #define MICROHZ_PER_HZ		1000000UL
 #define MILLIHZ_PER_HZ		1000UL
Signature · 1 line
2.34.1
Reviewed-by on v6 3/5
#4 lore raw

Re: [PATCH v6 3/5] units: add conversion macros for percentage related units

Quoted 5 lines · Jonathan Santos

Add macros to convert between ratio and percentage related units, including percent (1/100), permille (1/1,000), permyriad (1/10,000, also equivalent to one Basis point) and per cent mille (1/100,000). Those are Used for precise fractional calculations in engineering, finance, and measurement applications.

This version LGTM,

Signature · 2 lines
With Best Regards,
Andy Shevchenko
#5 lore raw

Re: [PATCH v6 3/5] units: add conversion macros for percentage related units

Quoted 9 lines · Andy Shevchenko
Quoted 5 lines · Jonathan Santos

Add macros to convert between ratio and percentage related units, including percent (1/100), permille (1/1,000), permyriad (1/10,000, also equivalent to one Basis point) and per cent mille (1/100,000). Those are Used for precise fractional calculations in engineering, finance, and measurement applications.

This version LGTM,

FWIW, we have one dup drivers/net/wireless/realtek/rtw89/phy.h:93:#define PERCENT 100

But since the type and value is the same it can be addressed later on.

Signature · 2 lines
With Best Regards,
Andy Shevchenko
#6 lore raw

PATCH v6 4/5 iio: adc: ad7768-1: refactor ad7768_write_raw()

In reply to Jonathan Santos

Squash __ad7768_write_raw() back to ad7768_write_raw() to allow the addition of new attributes without requiring a direct mode claim.

---
v6 Changes:
* None.

v5 Changes:
* new patch suggested by Jonathan Cameron to allow attributes without the direct mode claim, necessary for fixing the deadlock issue reported in v4.

---
 drivers/iio/adc/ad7768-1.c | 50 ++++++++++++++++++++------------------
 1 file changed, 26 insertions(+), 24 deletions(-)
drivers/iio/adc/ad7768-1.c +26 -24
index 89b0ca8f584c..bd4b2e090c5b 100644
@@ -742,6 +742,19 @@ static int ad7768_get_filter_type_attr(struct iio_dev *dev,
 	return ad7768_filter_regval_to_type[FIELD_GET(mask, mode)];
 }
 
+static int ad7768_update_dec_rate(struct iio_dev *dev, unsigned int dec_rate)
+{
+	struct ad7768_state *st = iio_priv(dev);
+	int ret;
+
+	ret = ad7768_configure_dig_fil(dev, st->filter_type, dec_rate);
+	if (ret)
+		return ret;
+
+	/* Update sampling frequency */
+	return ad7768_set_freq(st, st->samp_freq);
+}
+
 static const struct iio_enum ad7768_filter_type_iio_enum = {
 	.items = ad7768_filter_enum,
 	.num_items = ARRAY_SIZE(ad7768_filter_enum),
@@ -867,44 +880,33 @@ static int ad7768_read_avail(struct iio_dev *indio_dev,
 	}
 }
 
-static int __ad7768_write_raw(struct iio_dev *indio_dev,
-			      struct iio_chan_spec const *chan,
-			      int val, int val2, long info)
+static int ad7768_write_raw(struct iio_dev *indio_dev,
+			    struct iio_chan_spec const *chan,
+			    int val, int val2, long info)
 {
 	struct ad7768_state *st = iio_priv(indio_dev);
 	int ret;
 
 	switch (info) {
 	case IIO_CHAN_INFO_SAMP_FREQ:
-		return ad7768_set_freq(st, val);
+		if (!iio_device_claim_direct(indio_dev))
+			return -EBUSY;
 
+		ret = ad7768_set_freq(st, val);
+		iio_device_release_direct(indio_dev);
+		return ret;
 	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
-		ret = ad7768_configure_dig_fil(indio_dev, st->filter_type, val);
-		if (ret)
-			return ret;
+		if (!iio_device_claim_direct(indio_dev))
+			return -EBUSY;
 
-		/* Update sampling frequency */
-		return ad7768_set_freq(st, st->samp_freq);
+		ret = ad7768_update_dec_rate(indio_dev, val);
+		iio_device_release_direct(indio_dev);
+		return ret;
 	default:
 		return -EINVAL;
 	}
 }
 
-static int ad7768_write_raw(struct iio_dev *indio_dev,
-			    struct iio_chan_spec const *chan,
-			    int val, int val2, long info)
-{
-	int ret;
-
-	if (!iio_device_claim_direct(indio_dev))
-		return -EBUSY;
-
-	ret = __ad7768_write_raw(indio_dev, chan, val, val2, info);
-	iio_device_release_direct(indio_dev);
-
-	return ret;
-}
-
 static int ad7768_read_label(struct iio_dev *indio_dev,
 	const struct iio_chan_spec *chan, char *label)
 {
Signature · 1 line
2.34.1
#7 lore raw

PATCH v6 5/5 iio: adc: ad7768-1: add support for ADAQ776x-1 ADC Family

In reply to 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 controlled by GPIOs provided in the device tree.

The AAF gain is defined by hardware connections and should be specified in the device tree.

---
v6 Changes:
* Refactored ad7768_parse_aaf_gain() to improve cleanliness and readability.

v5 Changes:
* Write scale attribute without direct mode claim to avoid deadlock when using GPIOs from the device's own controller.

v4 Changes:
* replaced shift_right() with '>>' operator in the ad7768_fill_scale_tbl() function.
* Refactored ad7768_parse_aaf_gain () as requested.
* renamed ad7768_register_regulators() to ad7768_register_vcm_regulator() to better reflect its purpose (not sure if this is ok to do).
* Replaced u64_fract with u32_fract -> after reviewing the numbers again, I realized that u32_fract is sufficient for these calculations.
* addressed minor suggestions.
* Adopted a new approach to manage the PGA GPIOs, using pga-gpios property. This avoids possible conflicts when the internal gpio controller is used externally (and also allows hardwiring, as soon as the gpio interface supports it). However, using GPIOs from the device's own controller causes a deadlock when claiming direct mode in the ad7768_gpio_get() function. This happens because the direct mode remains locked by the ad7768_write_raw() function. I have kept this approach for now to discuss a way around this problem. It would be good to have the flexibility provided by pga-gpios property.

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 | 311 ++++++++++++++++++++++++++++++++++++-
 2 files changed, 308 insertions(+), 4 deletions(-)
drivers/iio/adc/Kconfig +1 -0
index b4295aa415bf..60038ae8dfc4 100644
@@ -411,6 +411,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 +307 -4

461 lines not on this page · raw message

Signature · 1 line
2.34.1
maintainer
#8 lore raw

Re: [PATCH v6 5/5] iio: adc: ad7768-1: add support for ADAQ776x-1 ADC Family

Quoted 4 lines · On Wed, 14 Jan 2026 06:27:29 -0300 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 8 lines

The PGA gain is configured in run-time through the scale attribute, if supported by the device. PGA is controlled by GPIOs provided in the device tree.

The AAF gain is defined by hardware connections and should be specified in the device tree.

Hi Jonathan,

See inline. One small thing I am fine fixing up whilst applying if nothing else comes up.

thanks,

Jonathan

Quoted 29 lines

---

drivers/iio/adc/ad7768-1.c +23 -0
index bd4b2e090c5b..980c079ab41a 100644
+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 u32_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) {
+			fract.numerator *= ad7768_aaf_gains_bp[st->aaf_gain];
+			fract.denominator *= PERMYRIAD;
+		}

drivers/iio/adc/ad7768-1.c static int ad7768_reg_access(struct iio_dev *indio_dev, · line 566

Quoted 10 lines
drivers/iio/adc/ad7768-1.c +10 -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 = ((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 */

How does remainder from div_u64_rem() end up other than positive? That divides a u64 by a u32 and takes a u32 * for that final parameter. Changing the type of tmp1 to u32 should do the job. Given we do the divisor is big enough, this can't be something subtle with the top bit set (if it were it would need a comment!)

If nothing else comes up I can do that whilst applying
(I'll wait on Andy having a chance to sanity check the PERMYRIAD stuff anyway).

Quoted 3 lines
drivers/iio/adc/ad7768-1.c +3 -0
+	}
+}
+
#9 lore raw

Re: [PATCH v6 5/5] iio: adc: ad7768-1: add support for ADAQ776x-1 ADC Family

Quoted 2 lines · Jonathan Cameron

On Wed, 14 Jan 2026 06:27:29 -0300
Jonathan Santos <[email protected]> wrote:

...

Quoted 2 lines

If nothing else comes up I can do that whilst applying
(I'll wait on Andy having a chance to sanity check the PERMYRIAD stuff anyway).

Fine with me, just one more thought about it, perhaps it's good to add a reference to Wikipedia article in the comment there as well:

...
*
* See details on https://en.wikipedia.org/wiki/Percentage.
*
...

Signature · 2 lines
With Best Regards,
Andy Shevchenko
maintainer
#10 lore raw
In reply to Jonathan Santos
Quoted 53 lines · On Wed, 14 Jan 2026 06:26:22 -0300 Jonathan Santos…

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 v6:
* Use Pattern PER* for all percentage-related macros and include macros
for Per mille and per cent mille units.
* Refactored ad7768_parse_aaf_gain() to improve cleanliness and readability.
* Link to v5: https://lore.kernel.org/linux-iio/[email protected]/T/#t/

Changes in v5:
* Added PERCENT macro along with BASIS_POINTS in units.h.
* Added new patch to allow writing attributes without direct mode claim.
* Write scale attribute without direct mode claim to avoid deadlock
when using GPIOs from the device's own controller.
* Link to v4: https://lore.kernel.org/linux-iio/[email protected]/T/#t

Changes in v4:
* Removed u64_fract type patch, as it is not used. u32_fract is sufficient
for the PGA gain calculations.
* Added new patch adding BASIS_POINTS macro to units.h.
* Included pga-gpios property for parts that support PGA gain.
Before we were using the internal gpio controller to manage the PGA pins,
but still exposing the controller for external use (causing possible conflicts).
* Addressed other review comments, see individual patches.
* Link to v3: https://lore.kernel.org/linux-iio/[email protected]/T/#t

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

Quoted 6 lines

Jonathan Santos (5):
dt-bindings: iio: adc: ad7768-1: add new supported parts
iio: adc: ad7768-1: introduce chip info for future multidevice support
units: add conversion macros for percentage related units
iio: adc: ad7768-1: refactor ad7768_write_raw()
iio: adc: ad7768-1: add support for ADAQ776x-1 ADC Family

Applied with this diff to last patch. Will first push out as testing to let 0-day take a look.

Shout if the change is a problem.

drivers/iio/adc/ad7768-1.c +3 -2
index 980c079ab41a..dc5be3d14664 100644
@@ -535,9 +535,10 @@ 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;
+       int val, val2, tmp0, i;
        struct u32_fract fract;
        unsigned long n, d;
+       u32 tmp1;
        u64 tmp2;
 
        scan_type = iio_get_current_scan_type(dev, &dev->channels[0]);
@@ -563,7 +564,7 @@ static void ad7768_fill_scale_tbl(struct iio_dev *dev)
                tmp2 = ((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 */
+               st->scale_tbl[i][1] = tmp1; /* Fractional part */
        }
 }
 
Quoted 9 lines
 .../bindings/iio/adc/adi,ad7768-1.yaml        |  64 ++-
 drivers/iio/adc/Kconfig                       |   1 +
 drivers/iio/adc/ad7768-1.c                    | 423 +++++++++++++++---
 include/linux/units.h                         |  19 +
 4 files changed, 453 insertions(+), 54 deletions(-)

base-commit: e0bc6d7e258486c10bb11e31fd4421c134063b1d