* [PATCH v5 0/5] Add support for ADAQ776x-1 ADC Family
@ 2025-12-17 5:52 Jonathan Santos
2025-12-17 5:52 ` [PATCH v5 1/5] dt-bindings: iio: adc: ad7768-1: add new supported parts Jonathan Santos
` (4 more replies)
0 siblings, 5 replies; 11+ messages in thread
From: Jonathan Santos @ 2025-12-17 5:52 UTC (permalink / raw)
To: linux-iio, devicetree, linux-kernel
Cc: Jonathan Santos, lars, Michael.Hennerich, jic23, dlechner,
nuno.sa, andy, robh, krzk+dt, conor+dt, jonath4nns
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 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/cover.1764101647.git.Jonathan.Santos@analog.com/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/cover.1757001160.git.Jonathan.Santos@analog.com/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/cover.1754617360.git.Jonathan.Santos@analog.com/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 PERCENT and BASIS_POINTS macros
iio: adc: ad7768-1: squash __ad7768_write_raw() back to
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 | 428 ++++++++++++++++--
include/linux/units.h | 14 +
4 files changed, 453 insertions(+), 54 deletions(-)
base-commit: daea3a394a8b425a2dd206ab09eb37f0d1087d35
--
2.34.1
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v5 1/5] dt-bindings: iio: adc: ad7768-1: add new supported parts
2025-12-17 5:52 [PATCH v5 0/5] Add support for ADAQ776x-1 ADC Family Jonathan Santos
@ 2025-12-17 5:52 ` Jonathan Santos
2025-12-17 5:52 ` [PATCH v5 2/5] iio: adc: ad7768-1: introduce chip info for future multidevice support Jonathan Santos
` (3 subsequent siblings)
4 siblings, 0 replies; 11+ messages in thread
From: Jonathan Santos @ 2025-12-17 5:52 UTC (permalink / raw)
To: linux-iio, devicetree, linux-kernel
Cc: Jonathan Santos, lars, Michael.Hennerich, jic23, dlechner,
nuno.sa, andy, robh, krzk+dt, conor+dt, jonath4nns,
Krzysztof Kozlowski
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
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Jonathan Santos <Jonathan.Santos@analog.com>
---
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(-)
diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7768-1.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7768-1.yaml
index c06d0fc791d3..dfa2d7fa9fb3 100644
--- a/Documentation/devicetree/bindings/iio/adc/adi,ad7768-1.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7768-1.yaml
@@ -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 <michael.hennerich@analog.com>
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:
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v5 2/5] iio: adc: ad7768-1: introduce chip info for future multidevice support
2025-12-17 5:52 [PATCH v5 0/5] Add support for ADAQ776x-1 ADC Family Jonathan Santos
2025-12-17 5:52 ` [PATCH v5 1/5] dt-bindings: iio: adc: ad7768-1: add new supported parts Jonathan Santos
@ 2025-12-17 5:52 ` Jonathan Santos
2025-12-17 5:52 ` [PATCH v5 3/5] units: add PERCENT and BASIS_POINTS macros Jonathan Santos
` (2 subsequent siblings)
4 siblings, 0 replies; 11+ messages in thread
From: Jonathan Santos @ 2025-12-17 5:52 UTC (permalink / raw)
To: linux-iio, devicetree, linux-kernel
Cc: Jonathan Santos, lars, Michael.Hennerich, jic23, dlechner,
nuno.sa, andy, robh, krzk+dt, conor+dt, jonath4nns
Add Chip info struct in SPI device to store channel information for
each supported part.
Signed-off-by: Jonathan Santos <Jonathan.Santos@analog.com>
---
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(-)
diff --git a/drivers/iio/adc/ad7768-1.c b/drivers/iio/adc/ad7768-1.c
index d96802b7847a..89b0ca8f584c 100644
--- a/drivers/iio/adc/ad7768-1.c
+++ b/drivers/iio/adc/ad7768-1.c
@@ -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);
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v5 3/5] units: add PERCENT and BASIS_POINTS macros
2025-12-17 5:52 [PATCH v5 0/5] Add support for ADAQ776x-1 ADC Family Jonathan Santos
2025-12-17 5:52 ` [PATCH v5 1/5] dt-bindings: iio: adc: ad7768-1: add new supported parts Jonathan Santos
2025-12-17 5:52 ` [PATCH v5 2/5] iio: adc: ad7768-1: introduce chip info for future multidevice support Jonathan Santos
@ 2025-12-17 5:52 ` Jonathan Santos
2025-12-27 15:55 ` Jonathan Cameron
2025-12-17 5:52 ` [PATCH v5 4/5] iio: adc: ad7768-1: refactor ad7768_write_raw() Jonathan Santos
2025-12-17 5:53 ` [PATCH v5 5/5] iio: adc: ad7768-1: add support for ADAQ776x-1 ADC Family Jonathan Santos
4 siblings, 1 reply; 11+ messages in thread
From: Jonathan Santos @ 2025-12-17 5:52 UTC (permalink / raw)
To: linux-iio, devicetree, linux-kernel
Cc: Jonathan Santos, lars, Michael.Hennerich, jic23, dlechner,
nuno.sa, andy, robh, krzk+dt, conor+dt, jonath4nns
Add macros for percentage related units, with basis points defined as
1/100th of a percent. Basis points are commonly used in finance and
engineering to express small percentage changes with precision.
Signed-off-by: Jonathan Santos <Jonathan.Santos@analog.com>
---
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 | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/include/linux/units.h b/include/linux/units.h
index 00e15de33eca..9c2fbcf04c81 100644
--- a/include/linux/units.h
+++ b/include/linux/units.h
@@ -21,6 +21,20 @@
#define PICO 1000000000000ULL
#define FEMTO 1000000000000000ULL
+/*
+ * Percentage and basis point units
+ *
+ * Basis points are 1/100th of a percent (1/100), commonly used in finance,
+ * engineering or other applications that require precise percentage
+ * calculations.
+ *
+ * Examples:
+ * 100% = 10000 basis points = BASIS_POINTS
+ * 1% = 100 basis points = PERCENT
+ */
+#define PERCENT 100UL
+#define BASIS_POINTS 10000UL
+
#define NANOHZ_PER_HZ 1000000000UL
#define MICROHZ_PER_HZ 1000000UL
#define MILLIHZ_PER_HZ 1000UL
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v5 4/5] iio: adc: ad7768-1: refactor ad7768_write_raw()
2025-12-17 5:52 [PATCH v5 0/5] Add support for ADAQ776x-1 ADC Family Jonathan Santos
` (2 preceding siblings ...)
2025-12-17 5:52 ` [PATCH v5 3/5] units: add PERCENT and BASIS_POINTS macros Jonathan Santos
@ 2025-12-17 5:52 ` Jonathan Santos
2025-12-17 5:53 ` [PATCH v5 5/5] iio: adc: ad7768-1: add support for ADAQ776x-1 ADC Family Jonathan Santos
4 siblings, 0 replies; 11+ messages in thread
From: Jonathan Santos @ 2025-12-17 5:52 UTC (permalink / raw)
To: linux-iio, devicetree, linux-kernel
Cc: Jonathan Santos, lars, Michael.Hennerich, jic23, dlechner,
nuno.sa, andy, robh, krzk+dt, conor+dt, jonath4nns
Squash __ad7768_write_raw() back to ad7768_write_raw() to allow the
addition of new attributes without requiring a direct mode claim.
Signed-off-by: Jonathan Santos <Jonathan.Santos@analog.com>
---
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(-)
diff --git a/drivers/iio/adc/ad7768-1.c b/drivers/iio/adc/ad7768-1.c
index 89b0ca8f584c..bd4b2e090c5b 100644
--- a/drivers/iio/adc/ad7768-1.c
+++ b/drivers/iio/adc/ad7768-1.c
@@ -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)
{
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v5 5/5] iio: adc: ad7768-1: add support for ADAQ776x-1 ADC Family
2025-12-17 5:52 [PATCH v5 0/5] Add support for ADAQ776x-1 ADC Family Jonathan Santos
` (3 preceding siblings ...)
2025-12-17 5:52 ` [PATCH v5 4/5] iio: adc: ad7768-1: refactor ad7768_write_raw() Jonathan Santos
@ 2025-12-17 5:53 ` Jonathan Santos
2025-12-27 16:11 ` Jonathan Cameron
4 siblings, 1 reply; 11+ messages in thread
From: Jonathan Santos @ 2025-12-17 5:53 UTC (permalink / raw)
To: linux-iio, devicetree, linux-kernel
Cc: Jonathan Santos, lars, Michael.Hennerich, jic23, dlechner,
nuno.sa, andy, robh, krzk+dt, conor+dt, jonath4nns
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.
Signed-off-by: Jonathan Santos <Jonathan.Santos@analog.com>
---
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 | 316 ++++++++++++++++++++++++++++++++++++-
2 files changed, 313 insertions(+), 4 deletions(-)
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 9c4c1e23090a..e5794cb26da9 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -387,6 +387,7 @@ config AD7768_1
depends on SPI
select REGULATOR
select REGMAP_SPI
+ select RATIONAL
select IIO_BUFFER
select IIO_TRIGGER
select IIO_TRIGGERED_BUFFER
diff --git a/drivers/iio/adc/ad7768-1.c b/drivers/iio/adc/ad7768-1.c
index bd4b2e090c5b..beea64ad3b52 100644
--- a/drivers/iio/adc/ad7768-1.c
+++ b/drivers/iio/adc/ad7768-1.c
@@ -6,6 +6,7 @@
*/
#include <linux/array_size.h>
#include <linux/bitfield.h>
+#include <linux/cleanup.h>
#include <linux/clk.h>
#include <linux/completion.h>
#include <linux/delay.h>
@@ -14,8 +15,12 @@
#include <linux/gpio/driver.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
+#include <linux/limits.h>
+#include <linux/math.h>
#include <linux/minmax.h>
#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/rational.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/regulator/driver.h>
@@ -107,10 +112,15 @@
#define AD7768_VCM_OFF 0x07
+#define ADAQ776X_GAIN_MAX_NANO (128 * NANO)
+#define ADAQ776X_MAX_GAIN_MODES 8
+
#define AD7768_TRIGGER_SOURCE_SYNC_IDX 0
#define AD7768_MAX_CHANNELS 1
+#define ADAQ7768_PGA_PINS 3
+
enum ad7768_conv_mode {
AD7768_CONTINUOUS,
AD7768_ONE_SHOT,
@@ -153,6 +163,51 @@ enum ad7768_scan_type {
AD7768_SCAN_TYPE_HIGH_SPEED,
};
+enum {
+ AD7768_PGA_GAIN_0,
+ AD7768_PGA_GAIN_1,
+ AD7768_PGA_GAIN_2,
+ AD7768_PGA_GAIN_3,
+ AD7768_PGA_GAIN_4,
+ AD7768_PGA_GAIN_5,
+ AD7768_PGA_GAIN_6,
+ AD7768_PGA_GAIN_7,
+};
+
+enum {
+ AD7768_AAF_IN1,
+ AD7768_AAF_IN2,
+ AD7768_AAF_IN3,
+};
+
+/* PGA and AAF gains in V/V */
+static const int adaq7768_gains[] = {
+ [AD7768_PGA_GAIN_0] = 325, /* 0.325 */
+ [AD7768_PGA_GAIN_1] = 650, /* 0.650 */
+ [AD7768_PGA_GAIN_2] = 1300, /* 1.300 */
+ [AD7768_PGA_GAIN_3] = 2600, /* 2.600 */
+ [AD7768_PGA_GAIN_4] = 5200, /* 5.200 */
+ [AD7768_PGA_GAIN_5] = 10400, /* 10.400 */
+ [AD7768_PGA_GAIN_6] = 20800, /* 20.800 */
+};
+
+static const int adaq7769_gains[] = {
+ [AD7768_PGA_GAIN_0] = 1000, /* 1.000 */
+ [AD7768_PGA_GAIN_1] = 2000, /* 2.000 */
+ [AD7768_PGA_GAIN_2] = 4000, /* 4.000 */
+ [AD7768_PGA_GAIN_3] = 8000, /* 8.000 */
+ [AD7768_PGA_GAIN_4] = 16000, /* 16.000 */
+ [AD7768_PGA_GAIN_5] = 32000, /* 32.000 */
+ [AD7768_PGA_GAIN_6] = 64000, /* 64.000 */
+ [AD7768_PGA_GAIN_7] = 128000, /* 128.000 */
+};
+
+static const int ad7768_aaf_gains_bp[] = {
+ [AD7768_AAF_IN1] = 10000, /* 1.000 */
+ [AD7768_AAF_IN2] = 3640, /* 0.364 */
+ [AD7768_AAF_IN3] = 1430, /* 0.143 */
+};
+
/* -3dB cutoff frequency multipliers (relative to ODR) for each filter type. */
static const int ad7768_filter_3db_odr_multiplier[] = {
[AD7768_FILTER_SINC5] = 204, /* 0.204 */
@@ -217,6 +272,13 @@ struct ad7768_chip_info {
const char *name;
const struct iio_chan_spec *channel_spec;
int num_channels;
+ const int *pga_gains;
+ int num_pga_modes;
+ int default_pga_mode;
+ int pgia_mode2pin_offset;
+ bool has_pga;
+ bool has_variable_aaf;
+ bool has_vcm_regulator;
};
struct ad7768_state {
@@ -234,14 +296,19 @@ struct ad7768_state {
unsigned int samp_freq;
unsigned int samp_freq_avail[ARRAY_SIZE(ad7768_mclk_div_rates)];
unsigned int samp_freq_avail_len;
+ unsigned int pga_gain_mode;
+ unsigned int aaf_gain;
+ int scale_tbl[ADAQ776X_MAX_GAIN_MODES][2];
struct completion completion;
struct iio_trigger *trig;
+ struct gpio_descs *pga_gpios;
struct gpio_desc *gpio_sync_in;
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;
+ struct mutex pga_lock; /* protect device internal state (PGA) */
/*
* DMA (thus cache coherency maintenance) may require the
* transfer buffers to live in their own cache lines.
@@ -464,6 +531,42 @@ static int ad7768_reg_access(struct iio_dev *indio_dev,
return ret;
}
+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 *= BASIS_POINTS;
+ }
+
+ 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 */
+ }
+}
+
static int ad7768_set_sinc3_dec_rate(struct ad7768_state *st,
unsigned int dec_rate)
{
@@ -565,12 +668,66 @@ static int ad7768_configure_dig_fil(struct iio_dev *dev,
st->oversampling_ratio = ad7768_dec_rate_values[dec_rate_idx];
}
+ /* Update scale table: scale values vary according to the precision */
+ ad7768_fill_scale_tbl(dev);
+
ad7768_fill_samp_freq_tbl(st);
/* A sync-in pulse is required after every configuration change */
return ad7768_send_sync_pulse(st);
}
+static int ad7768_setup_pga(struct device *dev, struct ad7768_state *st)
+{
+ st->pga_gpios = devm_gpiod_get_array(dev, "pga", GPIOD_OUT_LOW);
+ if (IS_ERR(st->pga_gpios))
+ return dev_err_probe(dev, PTR_ERR(st->pga_gpios),
+ "Failed to get PGA gpios.\n");
+
+ if (st->pga_gpios->ndescs != ADAQ7768_PGA_PINS)
+ return dev_err_probe(dev, -EINVAL,
+ "Expected %d GPIOs for PGA control.\n",
+ ADAQ7768_PGA_PINS);
+ return 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 * BASIS_POINTS,
+ ad7768_aaf_gains_bp[st->aaf_gain]);
+
+ return find_closest(gain_nano, st->chip->pga_gains,
+ (int)st->chip->num_pga_modes);
+}
+
+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);
+ DECLARE_BITMAP(bitmap, ADAQ7768_PGA_PINS) = { };
+ int ret;
+
+ guard(mutex)(&st->pga_lock);
+
+ bitmap_write(bitmap, pgia_pins_value, 0, ADAQ7768_PGA_PINS);
+ ret = gpiod_multi_set_value_cansleep(st->pga_gpios, bitmap);
+ 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);
@@ -792,6 +949,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)
@@ -819,7 +980,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) {
+ 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 * BASIS_POINTS) / ad7768_aaf_gains_bp[st->aaf_gain];
+
+ *val = temp;
*val2 = scan_type->realbits;
return IIO_VAL_FRACTIONAL_LOG2;
@@ -875,18 +1048,39 @@ static int ad7768_read_avail(struct iio_dev *indio_dev,
*length = st->samp_freq_avail_len;
*type = IIO_VAL_INT;
return IIO_AVAIL_LIST;
+ case IIO_CHAN_INFO_SCALE:
+ *vals = (int *)st->scale_tbl;
+ *length = st->chip->num_pga_modes * 2;
+ *type = IIO_VAL_INT_PLUS_NANO;
+ return IIO_AVAIL_LIST;
default:
return -EINVAL;
}
}
+static int ad7768_write_raw_get_fmt(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, long mask)
+{
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ return IIO_VAL_INT_PLUS_NANO;
+ default:
+ return IIO_VAL_INT_PLUS_MICRO;
+ }
+}
+
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);
+ const struct iio_scan_type *scan_type;
int ret;
+ scan_type = iio_get_current_scan_type(indio_dev, chan);
+ if (IS_ERR(scan_type))
+ return PTR_ERR(scan_type);
+
switch (info) {
case IIO_CHAN_INFO_SAMP_FREQ:
if (!iio_device_claim_direct(indio_dev))
@@ -902,6 +1096,21 @@ static int ad7768_write_raw(struct iio_dev *indio_dev,
ret = ad7768_update_dec_rate(indio_dev, val);
iio_device_release_direct(indio_dev);
return ret;
+ case IIO_CHAN_INFO_SCALE: {
+ 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);
+ }
default:
return -EINVAL;
}
@@ -928,6 +1137,7 @@ static const struct iio_info ad7768_info = {
.read_raw = &ad7768_read_raw,
.read_avail = &ad7768_read_avail,
.write_raw = &ad7768_write_raw,
+ .write_raw_get_fmt = &ad7768_write_raw_get_fmt,
.read_label = ad7768_read_label,
.get_current_scan_type = &ad7768_get_current_scan_type,
.debugfs_reg_access = &ad7768_reg_access,
@@ -1311,8 +1521,9 @@ static const struct regulator_desc vcm_desc = {
.owner = THIS_MODULE,
};
-static int ad7768_register_regulators(struct device *dev, struct ad7768_state *st,
- struct iio_dev *indio_dev)
+static int ad7768_register_vcm_regulator(struct device *dev,
+ struct ad7768_state *st,
+ struct iio_dev *indio_dev)
{
struct regulator_config config = {
.dev = dev,
@@ -1334,10 +1545,82 @@ static int ad7768_register_regulators(struct device *dev, struct ad7768_state *s
return 0;
}
+static int ad7768_parse_aaf_gain(struct device *dev, struct ad7768_state *st)
+{
+ bool aaf_gain_provided;
+ u32 val;
+ int ret;
+
+ ret = device_property_read_u32(dev, "adi,aaf-gain-bp", &val);
+ if (ret == -EINVAL)
+ aaf_gain_provided = false;
+ else if (ret)
+ return dev_err_probe(dev, ret, "Failed to get AAF gain value\n");
+ else
+ aaf_gain_provided = true;
+
+ if (!aaf_gain_provided) {
+ if (st->chip->has_variable_aaf)
+ st->aaf_gain = AD7768_AAF_IN1;
+ return 0;
+ }
+
+ if (aaf_gain_provided && !st->chip->has_variable_aaf)
+ return dev_err_probe(dev, -EOPNOTSUPP,
+ "AAF gain not supported for %s\n", st->chip->name);
+
+ 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;
+}
+
static const struct ad7768_chip_info ad7768_chip_info = {
.name = "ad7768-1",
.channel_spec = ad7768_channels,
.num_channels = ARRAY_SIZE(ad7768_channels),
+ .has_vcm_regulator = true,
+};
+
+static const struct ad7768_chip_info adaq7767_chip_info = {
+ .name = "adaq7767-1",
+ .channel_spec = ad7768_channels,
+ .num_channels = ARRAY_SIZE(ad7768_channels),
+ .has_variable_aaf = true,
+};
+
+static const struct ad7768_chip_info adaq7768_chip_info = {
+ .name = "adaq7768-1",
+ .channel_spec = adaq776x_channels,
+ .num_channels = ARRAY_SIZE(adaq776x_channels),
+ .pga_gains = adaq7768_gains,
+ .default_pga_mode = AD7768_PGA_GAIN_2,
+ .num_pga_modes = ARRAY_SIZE(adaq7768_gains),
+ .pgia_mode2pin_offset = 6,
+ .has_pga = true,
+};
+
+static const struct ad7768_chip_info adaq7769_chip_info = {
+ .name = "adaq7769-1",
+ .channel_spec = adaq776x_channels,
+ .num_channels = ARRAY_SIZE(adaq776x_channels),
+ .pga_gains = adaq7769_gains,
+ .default_pga_mode = AD7768_PGA_GAIN_0,
+ .num_pga_modes = ARRAY_SIZE(adaq7769_gains),
+ .pgia_mode2pin_offset = 0,
+ .has_pga = true,
+ .has_variable_aaf = true,
};
static int ad7768_probe(struct spi_device *spi)
@@ -1398,7 +1681,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_vcm_regulator(&spi->dev, st, indio_dev);
+ if (ret)
+ return ret;
+ }
+
+ ret = ad7768_parse_aaf_gain(&spi->dev, st);
if (ret)
return ret;
@@ -1409,6 +1698,19 @@ static int ad7768_probe(struct spi_device *spi)
}
init_completion(&st->completion);
+ ret = devm_mutex_init(&spi->dev, &st->pga_lock);
+ if (ret)
+ return ret;
+
+ if (st->chip->has_pga) {
+ ret = ad7768_setup_pga(&spi->dev, st);
+ if (ret)
+ return ret;
+
+ ret = ad7768_set_pga_gain(st, st->chip->default_pga_mode);
+ if (ret)
+ return ret;
+ }
ret = ad7768_set_channel_label(indio_dev, st->chip->num_channels);
if (ret)
@@ -1430,12 +1732,18 @@ static int ad7768_probe(struct spi_device *spi)
static const struct spi_device_id ad7768_id_table[] = {
{ "ad7768-1", (kernel_ulong_t)&ad7768_chip_info },
+ { "adaq7767-1", (kernel_ulong_t)&adaq7767_chip_info },
+ { "adaq7768-1", (kernel_ulong_t)&adaq7768_chip_info },
+ { "adaq7769-1", (kernel_ulong_t)&adaq7769_chip_info },
{ }
};
MODULE_DEVICE_TABLE(spi, ad7768_id_table);
static const struct of_device_id ad7768_of_match[] = {
{ .compatible = "adi,ad7768-1", .data = &ad7768_chip_info },
+ { .compatible = "adi,adaq7767-1", .data = &adaq7767_chip_info },
+ { .compatible = "adi,adaq7768-1", .data = &adaq7768_chip_info },
+ { .compatible = "adi,adaq7769-1", .data = &adaq7769_chip_info },
{ }
};
MODULE_DEVICE_TABLE(of, ad7768_of_match);
--
2.34.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH v5 3/5] units: add PERCENT and BASIS_POINTS macros
2025-12-17 5:52 ` [PATCH v5 3/5] units: add PERCENT and BASIS_POINTS macros Jonathan Santos
@ 2025-12-27 15:55 ` Jonathan Cameron
2025-12-27 16:48 ` Andy Shevchenko
2025-12-27 16:52 ` Andy Shevchenko
0 siblings, 2 replies; 11+ messages in thread
From: Jonathan Cameron @ 2025-12-27 15:55 UTC (permalink / raw)
To: Jonathan Santos
Cc: linux-iio, devicetree, linux-kernel, lars, Michael.Hennerich,
dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt, jonath4nns
On Wed, 17 Dec 2025 02:52:45 -0300
Jonathan Santos <Jonathan.Santos@analog.com> wrote:
> Add macros for percentage related units, with basis points defined as
> 1/100th of a percent. Basis points are commonly used in finance and
> engineering to express small percentage changes with precision.
>
> Signed-off-by: Jonathan Santos <Jonathan.Santos@analog.com>
> ---
> 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 | 14 ++++++++++++++
> 1 file changed, 14 insertions(+)
>
> diff --git a/include/linux/units.h b/include/linux/units.h
> index 00e15de33eca..9c2fbcf04c81 100644
> --- a/include/linux/units.h
> +++ b/include/linux/units.h
> @@ -21,6 +21,20 @@
> #define PICO 1000000000000ULL
> #define FEMTO 1000000000000000ULL
>
> +/*
> + * Percentage and basis point units
> + *
> + * Basis points are 1/100th of a percent (1/100), commonly used in finance,
> + * engineering or other applications that require precise percentage
> + * calculations.
> + *
> + * Examples:
> + * 100% = 10000 basis points = BASIS_POINTS
> + * 1% = 100 basis points = PERCENT
I don't understand the final equality in these examples.
The top line is as it says 10000 basis points but you have it equal
to BASIS_POINTS?
> + */
> +#define PERCENT 100UL
> +#define BASIS_POINTS 10000UL
> +
> #define NANOHZ_PER_HZ 1000000000UL
> #define MICROHZ_PER_HZ 1000000UL
> #define MILLIHZ_PER_HZ 1000UL
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v5 5/5] iio: adc: ad7768-1: add support for ADAQ776x-1 ADC Family
2025-12-17 5:53 ` [PATCH v5 5/5] iio: adc: ad7768-1: add support for ADAQ776x-1 ADC Family Jonathan Santos
@ 2025-12-27 16:11 ` Jonathan Cameron
0 siblings, 0 replies; 11+ messages in thread
From: Jonathan Cameron @ 2025-12-27 16:11 UTC (permalink / raw)
To: Jonathan Santos
Cc: linux-iio, devicetree, linux-kernel, lars, Michael.Hennerich,
dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt, jonath4nns
On Wed, 17 Dec 2025 02:53:08 -0300
Jonathan Santos <Jonathan.Santos@analog.com> wrote:
> 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.
>
> Signed-off-by: Jonathan Santos <Jonathan.Santos@analog.com>
Hi Jonathan
I noted one minor area where I think the code could be slightly cleaner.
If we didn't have the outstanding question about the comment in the BP definitions
patch I'd just have merged it as it stands. I don't mind that much if you
prefer the current form.
Jonathan
>
> +static int ad7768_parse_aaf_gain(struct device *dev, struct ad7768_state *st)
> +{
> + bool aaf_gain_provided;
> + u32 val;
> + int ret;
> +
> + ret = device_property_read_u32(dev, "adi,aaf-gain-bp", &val);
> + if (ret == -EINVAL)
> + aaf_gain_provided = false;
> + else if (ret)
> + return dev_err_probe(dev, ret, "Failed to get AAF gain value\n");
> + else
> + aaf_gain_provided = true;
> +
> + if (!aaf_gain_provided) {
> + if (st->chip->has_variable_aaf)
> + st->aaf_gain = AD7768_AAF_IN1;
> + return 0;
> + }
> +
> + if (aaf_gain_provided && !st->chip->has_variable_aaf)
> + return dev_err_probe(dev, -EOPNOTSUPP,
> + "AAF gain not supported for %s\n", st->chip->name);
> +
Might be simpler if we just did the actions for aaf_gain at the point of detecting it.
if (ret == -EINVAL) {
/* If controllable, use default */
if (st->chip->has_variable_aaf)
st->aaf_gain = AD7768_AAF_IN1;
return 0;
}
if (ret)
return dev_err_probe(dev, ret, "Failed to get AAF gain value\n");
if (!st->chip->has_variable_aaf)
return dev_err_probe(dev,, -EOPNOTSUPP,
"AAF gain provided, but variable AFF gain not supported for %s\n", ...)
or maybe make the gain number obvious as the default by doing.
if (ret == -EINVAL) {
if (!st->chip->has_variable_aaf)
return 0;
val = 10000; /* Matches the default from DT */
} else if (ret) {
return dev_err_probe(dev, ret, "Failed to get AAF gain value\n");
} else if (!st->chip->has_variable_aaf) {
return dev_err_probe(dev,, -EOPNOTSUPP,
"AAF gain provided, but variable AFF gain not supported for %s\n", ...)
}
The first option is simpler, bu the second makes it easier to align with DT binding.
> + 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;
> +}
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v5 3/5] units: add PERCENT and BASIS_POINTS macros
2025-12-27 15:55 ` Jonathan Cameron
@ 2025-12-27 16:48 ` Andy Shevchenko
2025-12-27 16:52 ` Andy Shevchenko
1 sibling, 0 replies; 11+ messages in thread
From: Andy Shevchenko @ 2025-12-27 16:48 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Jonathan Santos, linux-iio, devicetree, linux-kernel, lars,
Michael.Hennerich, dlechner, nuno.sa, andy, robh, krzk+dt,
conor+dt, jonath4nns
On Sat, Dec 27, 2025 at 5:55 PM Jonathan Cameron <jic23@kernel.org> wrote:
> On Wed, 17 Dec 2025 02:52:45 -0300
> Jonathan Santos <Jonathan.Santos@analog.com> wrote:
...
> > +/*
> > + * Percentage and basis point units
> > + *
> > + * Basis points are 1/100th of a percent (1/100), commonly used in finance,
> > + * engineering or other applications that require precise percentage
> > + * calculations.
> > + *
> > + * Examples:
> > + * 100% = 10000 basis points = BASIS_POINTS
> > + * 1% = 100 basis points = PERCENT
>
> I don't understand the final equality in these examples.
> The top line is as it says 10000 basis points but you have it equal
> to BASIS_POINTS?
>
> > + */
> > +#define PERCENT 100UL
Be careful with UL. What would be 10% from -555 (minus five hundreds
fifty five)?
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v5 3/5] units: add PERCENT and BASIS_POINTS macros
2025-12-27 15:55 ` Jonathan Cameron
2025-12-27 16:48 ` Andy Shevchenko
@ 2025-12-27 16:52 ` Andy Shevchenko
2025-12-27 16:53 ` Andy Shevchenko
1 sibling, 1 reply; 11+ messages in thread
From: Andy Shevchenko @ 2025-12-27 16:52 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Jonathan Santos, linux-iio, devicetree, linux-kernel, lars,
Michael.Hennerich, dlechner, nuno.sa, andy, robh, krzk+dt,
conor+dt, jonath4nns
On Sat, Dec 27, 2025 at 5:55 PM Jonathan Cameron <jic23@kernel.org> wrote:
> On Wed, 17 Dec 2025 02:52:45 -0300
> Jonathan Santos <Jonathan.Santos@analog.com> wrote:
...
> > +/*
> > + * Percentage and basis point units
> > + *
> > + * Basis points are 1/100th of a percent (1/100), commonly used in finance,
> > + * engineering or other applications that require precise percentage
> > + * calculations.
> > + *
> > + * Examples:
> > + * 100% = 10000 basis points = BASIS_POINTS
> > + * 1% = 100 basis points = PERCENT
>
> I don't understand the final equality in these examples.
> The top line is as it says 10000 basis points but you have it equal
> to BASIS_POINTS?
Also there are pp (percentage points) and others like per mille
https://en.wikipedia.org/wiki/Percentage_point (see "Related units" section).
> > + */
> > +#define PERCENT 100UL
> > +#define BASIS_POINTS 10000UL
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v5 3/5] units: add PERCENT and BASIS_POINTS macros
2025-12-27 16:52 ` Andy Shevchenko
@ 2025-12-27 16:53 ` Andy Shevchenko
0 siblings, 0 replies; 11+ messages in thread
From: Andy Shevchenko @ 2025-12-27 16:53 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Jonathan Santos, linux-iio, devicetree, linux-kernel, lars,
Michael.Hennerich, dlechner, nuno.sa, andy, robh, krzk+dt,
conor+dt, jonath4nns
On Sat, Dec 27, 2025 at 6:52 PM Andy Shevchenko
<andy.shevchenko@gmail.com> wrote:
> On Sat, Dec 27, 2025 at 5:55 PM Jonathan Cameron <jic23@kernel.org> wrote:
> > On Wed, 17 Dec 2025 02:52:45 -0300
> > Jonathan Santos <Jonathan.Santos@analog.com> wrote:
...
> Also there are pp (percentage points) and others like per mille
>
> https://en.wikipedia.org/wiki/Percentage_point (see "Related units" section).
And given most of them are in the PER* namespace I would use those
names instead of variants.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2025-12-27 16:54 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-17 5:52 [PATCH v5 0/5] Add support for ADAQ776x-1 ADC Family Jonathan Santos
2025-12-17 5:52 ` [PATCH v5 1/5] dt-bindings: iio: adc: ad7768-1: add new supported parts Jonathan Santos
2025-12-17 5:52 ` [PATCH v5 2/5] iio: adc: ad7768-1: introduce chip info for future multidevice support Jonathan Santos
2025-12-17 5:52 ` [PATCH v5 3/5] units: add PERCENT and BASIS_POINTS macros Jonathan Santos
2025-12-27 15:55 ` Jonathan Cameron
2025-12-27 16:48 ` Andy Shevchenko
2025-12-27 16:52 ` Andy Shevchenko
2025-12-27 16:53 ` Andy Shevchenko
2025-12-17 5:52 ` [PATCH v5 4/5] iio: adc: ad7768-1: refactor ad7768_write_raw() Jonathan Santos
2025-12-17 5:53 ` [PATCH v5 5/5] iio: adc: ad7768-1: add support for ADAQ776x-1 ADC Family Jonathan Santos
2025-12-27 16:11 ` Jonathan Cameron
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).