public inbox for devicetree@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] iio: adc: ad4130: Add support for AD4129-4/8, AD4130-4, and AD4131-4/8
@ 2026-02-28 12:38 Jonathan Santos
  2026-02-28 12:38 ` [PATCH 1/3] dt-bindings: iio: adc: ad4130: Add new supported parts Jonathan Santos
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Jonathan Santos @ 2026-02-28 12:38 UTC (permalink / raw)
  To: linux-iio, linux-kernel, devicetree
  Cc: Jonathan Santos, cosmin.tanislav, lars, Michael.Hennerich, jic23,
	dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt

This patch series extends the AD4130 driver to support additional variants
in the AD4130 family: AD4129-4/8, AD4130-4, and AD4131-4/8.

The series introduces a chip info architecture to handle device-specific
differences. The AD4129 series provides 16-bit resolution with FIFO
support, while the AD4131 series offers 24-bit resolution but without
FIFO capability, requiring triggered buffer implementation. The 4-channel
variants feature reduced analog inputs, fewer GPIOs, and sparse pin
mappings.

Jonathan Santos (3):
  dt-bindings: iio: adc: ad4130: Add new supported parts
  iio: adc: ad4130: introduce chip info for future multidevice support
  iio: adc: ad4130: add new supported parts

 .../bindings/iio/adc/adi,ad4130.yaml          |  15 +-
 drivers/iio/adc/ad4130.c                      | 485 +++++++++++++++---
 2 files changed, 415 insertions(+), 85 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/3] dt-bindings: iio: adc: ad4130: Add new supported parts
  2026-02-28 12:38 [PATCH 0/3] iio: adc: ad4130: Add support for AD4129-4/8, AD4130-4, and AD4131-4/8 Jonathan Santos
@ 2026-02-28 12:38 ` Jonathan Santos
  2026-03-03  6:50   ` Krzysztof Kozlowski
  2026-02-28 12:38 ` [PATCH 2/3] iio: adc: ad4130: introduce chip info for future multidevice support Jonathan Santos
  2026-02-28 12:39 ` [PATCH 3/3] iio: adc: ad4130: add new supported parts Jonathan Santos
  2 siblings, 1 reply; 10+ messages in thread
From: Jonathan Santos @ 2026-02-28 12:38 UTC (permalink / raw)
  To: linux-iio, linux-kernel, devicetree
  Cc: Jonathan Santos, cosmin.tanislav, lars, Michael.Hennerich, jic23,
	dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt

Extend driver support for AD4129-4/8, AD4130-4, and AD4131-4/8 ADC
variants.

Signed-off-by: Jonathan Santos <Jonathan.Santos@analog.com>
---
 .../devicetree/bindings/iio/adc/adi,ad4130.yaml   | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad4130.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad4130.yaml
index d00690a8d3fb..075ce62cb4e7 100644
--- a/Documentation/devicetree/bindings/iio/adc/adi,ad4130.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ad4130.yaml
@@ -5,19 +5,30 @@
 $id: http://devicetree.org/schemas/iio/adc/adi,ad4130.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
-title: Analog Devices AD4130 ADC device driver
+title: Analog Devices AD4130 family ADC device driver
 
 maintainers:
   - Cosmin Tanislav <cosmin.tanislav@analog.com>
 
 description: |
-  Bindings for the Analog Devices AD4130 ADC. Datasheet can be found here:
+  Bindings for the Analog Devices AD4130 family ADCs.
+  Datasheets can be found here:
+    https://www.analog.com/media/en/technical-documentation/data-sheets/AD4129-4.pdf
+    https://www.analog.com/media/en/technical-documentation/data-sheets/AD4129-8.pdf
+    https://www.analog.com/media/en/technical-documentation/data-sheets/AD4130-4.pdf
     https://www.analog.com/media/en/technical-documentation/data-sheets/AD4130-8.pdf
+    https://www.analog.com/media/en/technical-documentation/data-sheets/AD4131-4.pdf
+    https://www.analog.com/media/en/technical-documentation/data-sheets/AD4131-8.pdf
 
 properties:
   compatible:
     enum:
+      - adi,ad4129-4
+      - adi,ad4129-8
+      - adi,ad4130-4
       - adi,ad4130
+      - adi,ad4131-4
+      - adi,ad4131-8
 
   reg:
     maxItems: 1
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/3] iio: adc: ad4130: introduce chip info for future multidevice support
  2026-02-28 12:38 [PATCH 0/3] iio: adc: ad4130: Add support for AD4129-4/8, AD4130-4, and AD4131-4/8 Jonathan Santos
  2026-02-28 12:38 ` [PATCH 1/3] dt-bindings: iio: adc: ad4130: Add new supported parts Jonathan Santos
@ 2026-02-28 12:38 ` Jonathan Santos
  2026-03-02 12:39   ` Andy Shevchenko
  2026-02-28 12:39 ` [PATCH 3/3] iio: adc: ad4130: add new supported parts Jonathan Santos
  2 siblings, 1 reply; 10+ messages in thread
From: Jonathan Santos @ 2026-02-28 12:38 UTC (permalink / raw)
  To: linux-iio, linux-kernel, devicetree
  Cc: Jonathan Santos, cosmin.tanislav, lars, Michael.Hennerich, jic23,
	dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt

Introduce a chip_info structure to abstract device-specific parameters
and prepare the driver for supporting multiple AD4130 family variants.

Signed-off-by: Jonathan Santos <Jonathan.Santos@analog.com>
---
 drivers/iio/adc/ad4130.c | 48 ++++++++++++++++++++++++++++++----------
 1 file changed, 36 insertions(+), 12 deletions(-)

diff --git a/drivers/iio/adc/ad4130.c b/drivers/iio/adc/ad4130.c
index 5567ae5dee88..138fc0b99d81 100644
--- a/drivers/iio/adc/ad4130.c
+++ b/drivers/iio/adc/ad4130.c
@@ -224,6 +224,14 @@ enum ad4130_pin_function {
 	AD4130_PIN_FN_VBIAS = BIT(3),
 };
 
+struct ad4130_chip_info {
+	const char *name;
+	unsigned int max_analog_pins;
+	const struct iio_info *info;
+	const unsigned int *reg_size;
+	const unsigned int reg_size_length;
+};
+
 /*
  * If you make adaptations in this struct, you most likely also have to adapt
  * ad4130_setup_info_eq(), too.
@@ -268,6 +276,7 @@ struct ad4130_state {
 	struct regmap			*regmap;
 	struct spi_device		*spi;
 	struct clk			*mclk;
+	const struct ad4130_chip_info	*chip_info;
 	struct regulator_bulk_data	regulators[4];
 	u32				irq_trigger;
 	u32				inv_irq_trigger;
@@ -394,10 +403,10 @@ static const char * const ad4130_filter_types_str[] = {
 static int ad4130_get_reg_size(struct ad4130_state *st, unsigned int reg,
 			       unsigned int *size)
 {
-	if (reg >= ARRAY_SIZE(ad4130_reg_size))
+	if (reg >= st->chip_info->reg_size_length)
 		return -EINVAL;
 
-	*size = ad4130_reg_size[reg];
+	*size = st->chip_info->reg_size[reg];
 
 	return 0;
 }
@@ -1291,6 +1300,14 @@ static const struct iio_info ad4130_info = {
 	.debugfs_reg_access = ad4130_reg_access,
 };
 
+static const struct ad4130_chip_info ad4130_8_chip_info = {
+	.name = "ad4130-8",
+	.max_analog_pins = 16,
+	.info = &ad4130_info,
+	.reg_size = ad4130_reg_size,
+	.reg_size_length = ARRAY_SIZE(ad4130_reg_size),
+};
+
 static int ad4130_buffer_postenable(struct iio_dev *indio_dev)
 {
 	struct ad4130_state *st = iio_priv(indio_dev);
@@ -1504,7 +1521,7 @@ static int ad4130_validate_diff_channel(struct ad4130_state *st, u32 pin)
 		return dev_err_probe(dev, -EINVAL,
 				     "Invalid differential channel %u\n", pin);
 
-	if (pin >= AD4130_MAX_ANALOG_PINS)
+	if (pin >= st->chip_info->max_analog_pins)
 		return 0;
 
 	if (st->pins_fn[pin] == AD4130_PIN_FN_SPECIAL)
@@ -1536,7 +1553,7 @@ static int ad4130_validate_excitation_pin(struct ad4130_state *st, u32 pin)
 {
 	struct device *dev = &st->spi->dev;
 
-	if (pin >= AD4130_MAX_ANALOG_PINS)
+	if (pin >= st->chip_info->max_analog_pins)
 		return dev_err_probe(dev, -EINVAL,
 				     "Invalid excitation pin %u\n", pin);
 
@@ -1554,7 +1571,7 @@ static int ad4130_validate_vbias_pin(struct ad4130_state *st, u32 pin)
 {
 	struct device *dev = &st->spi->dev;
 
-	if (pin >= AD4130_MAX_ANALOG_PINS)
+	if (pin >= st->chip_info->max_analog_pins)
 		return dev_err_probe(dev, -EINVAL, "Invalid vbias pin %u\n",
 				     pin);
 
@@ -1730,7 +1747,7 @@ static int ad4310_parse_fw(struct iio_dev *indio_dev)
 
 	ret = device_property_count_u32(dev, "adi,vbias-pins");
 	if (ret > 0) {
-		if (ret > AD4130_MAX_ANALOG_PINS)
+		if (ret > st->chip_info->max_analog_pins)
 			return dev_err_probe(dev, -EINVAL,
 					     "Too many vbias pins %u\n", ret);
 
@@ -1994,6 +2011,8 @@ static int ad4130_probe(struct spi_device *spi)
 
 	st = iio_priv(indio_dev);
 
+	st->chip_info = device_get_match_data(dev);
+
 	memset(st->reset_buf, 0xff, sizeof(st->reset_buf));
 	init_completion(&st->completion);
 	mutex_init(&st->lock);
@@ -2011,9 +2030,9 @@ static int ad4130_probe(struct spi_device *spi)
 	spi_message_init_with_transfers(&st->fifo_msg, st->fifo_xfer,
 					ARRAY_SIZE(st->fifo_xfer));
 
-	indio_dev->name = AD4130_NAME;
+	indio_dev->name = st->chip_info->name;
 	indio_dev->modes = INDIO_DIRECT_MODE;
-	indio_dev->info = &ad4130_info;
+	indio_dev->info = st->chip_info->info;
 
 	st->regmap = devm_regmap_init(dev, NULL, st, &ad4130_regmap_config);
 	if (IS_ERR(st->regmap))
@@ -2056,7 +2075,7 @@ static int ad4130_probe(struct spi_device *spi)
 	ad4130_fill_scale_tbls(st);
 
 	st->gc.owner = THIS_MODULE;
-	st->gc.label = AD4130_NAME;
+	st->gc.label = st->chip_info->name;
 	st->gc.base = -1;
 	st->gc.ngpio = AD4130_MAX_GPIOS;
 	st->gc.parent = dev;
@@ -2102,19 +2121,24 @@ static int ad4130_probe(struct spi_device *spi)
 }
 
 static const struct of_device_id ad4130_of_match[] = {
-	{
-		.compatible = "adi,ad4130",
-	},
+	{ .compatible = "adi,ad4130", .data = &ad4130_8_chip_info },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, ad4130_of_match);
 
+static const struct spi_device_id ad4130_id_table[] = {
+	{ "ad4130", (kernel_ulong_t)&ad4130_8_chip_info },
+	{ }
+};
+MODULE_DEVICE_TABLE(spi, ad4130_id_table);
+
 static struct spi_driver ad4130_driver = {
 	.driver = {
 		.name = AD4130_NAME,
 		.of_match_table = ad4130_of_match,
 	},
 	.probe = ad4130_probe,
+	.id_table = ad4130_id_table,
 };
 module_spi_driver(ad4130_driver);
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/3] iio: adc: ad4130: add new supported parts
  2026-02-28 12:38 [PATCH 0/3] iio: adc: ad4130: Add support for AD4129-4/8, AD4130-4, and AD4131-4/8 Jonathan Santos
  2026-02-28 12:38 ` [PATCH 1/3] dt-bindings: iio: adc: ad4130: Add new supported parts Jonathan Santos
  2026-02-28 12:38 ` [PATCH 2/3] iio: adc: ad4130: introduce chip info for future multidevice support Jonathan Santos
@ 2026-02-28 12:39 ` Jonathan Santos
  2026-03-02 12:51   ` Andy Shevchenko
  2026-03-07 14:20   ` Jonathan Cameron
  2 siblings, 2 replies; 10+ messages in thread
From: Jonathan Santos @ 2026-02-28 12:39 UTC (permalink / raw)
  To: linux-iio, linux-kernel, devicetree
  Cc: Jonathan Santos, cosmin.tanislav, lars, Michael.Hennerich, jic23,
	dlechner, nuno.sa, andy, robh, krzk+dt, conor+dt

Add support for AD4129-4/8, AD4130-4, and AD4131-4/8 variants.

The AD4129 series supports the same FIFO interface as the AD4130 but with
reduced resolution (16-bit). The AD4131 series lacks FIFO support, so
triggered buffer functionality is introduced.

The 4-channel variants feature fewer analog inputs, GPIOs, and sparse pin
mappings for VBIAS, analog inputs, and excitation currents. The driver now
handles these differences with chip-specific configurations, including pin
mappings and GPIO counts.

Signed-off-by: Jonathan Santos <Jonathan.Santos@analog.com>
---
 drivers/iio/adc/ad4130.c | 435 ++++++++++++++++++++++++++++++++-------
 1 file changed, 365 insertions(+), 70 deletions(-)

diff --git a/drivers/iio/adc/ad4130.c b/drivers/iio/adc/ad4130.c
index 138fc0b99d81..e3a3b373e99d 100644
--- a/drivers/iio/adc/ad4130.c
+++ b/drivers/iio/adc/ad4130.c
@@ -9,6 +9,7 @@
 #include <linux/cleanup.h>
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/completion.h>
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/err.h>
@@ -21,6 +22,7 @@
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/spi/spi.h>
+#include <linux/types.h>
 #include <linux/units.h>
 
 #include <asm/div64.h>
@@ -30,6 +32,9 @@
 #include <linux/iio/iio.h>
 #include <linux/iio/kfifo_buf.h>
 #include <linux/iio/sysfs.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
 
 #define AD4130_NAME				"ad4130"
 
@@ -40,6 +45,7 @@
 #define AD4130_ADC_CONTROL_REG			0x01
 #define AD4130_ADC_CONTROL_BIPOLAR_MASK		BIT(14)
 #define AD4130_ADC_CONTROL_INT_REF_VAL_MASK	BIT(13)
+#define AD4130_ADC_CONTROL_CONT_READ_MASK	BIT(11)
 #define AD4130_INT_REF_2_5V			2500000
 #define AD4130_INT_REF_1_25V			1250000
 #define AD4130_ADC_CONTROL_CSB_EN_MASK		BIT(9)
@@ -54,7 +60,9 @@
 #define AD4130_IO_CONTROL_REG			0x03
 #define AD4130_IO_CONTROL_INT_PIN_SEL_MASK	GENMASK(9, 8)
 #define AD4130_IO_CONTROL_GPIO_DATA_MASK	GENMASK(7, 4)
+#define AD4130_4_IO_CONTROL_GPIO_DATA_MASK	GENMASK(7, 6)
 #define AD4130_IO_CONTROL_GPIO_CTRL_MASK	GENMASK(3, 0)
+#define AD4130_4_IO_CONTROL_GPIO_CTRL_MASK	GENMASK(3, 2)
 
 #define AD4130_VBIAS_REG			0x04
 
@@ -125,6 +133,28 @@
 
 #define AD4130_INVALID_SLOT			-1
 
+static const unsigned int ad4129_reg_size[] = {
+	[AD4130_STATUS_REG] = 1,
+	[AD4130_ADC_CONTROL_REG] = 2,
+	[AD4130_DATA_REG] = 2,
+	[AD4130_IO_CONTROL_REG] = 2,
+	[AD4130_VBIAS_REG] = 2,
+	[AD4130_ID_REG] = 1,
+	[AD4130_ERROR_REG] = 2,
+	[AD4130_ERROR_EN_REG] = 2,
+	[AD4130_MCLK_COUNT_REG] = 1,
+	[AD4130_CHANNEL_X_REG(0) ... AD4130_CHANNEL_X_REG(AD4130_MAX_CHANNELS - 1)] = 3,
+	[AD4130_CONFIG_X_REG(0) ... AD4130_CONFIG_X_REG(AD4130_MAX_SETUPS - 1)] = 2,
+	[AD4130_FILTER_X_REG(0) ... AD4130_FILTER_X_REG(AD4130_MAX_SETUPS - 1)] = 3,
+	[AD4130_OFFSET_X_REG(0) ... AD4130_OFFSET_X_REG(AD4130_MAX_SETUPS - 1)] = 2,
+	[AD4130_GAIN_X_REG(0) ... AD4130_GAIN_X_REG(AD4130_MAX_SETUPS - 1)] = 2,
+	[AD4130_MISC_REG] = 2,
+	[AD4130_FIFO_CONTROL_REG] = 3,
+	[AD4130_FIFO_STATUS_REG] = 1,
+	[AD4130_FIFO_THRESHOLD_REG] = 3,
+	[AD4130_FIFO_DATA_REG] = 2,
+};
+
 static const unsigned int ad4130_reg_size[] = {
 	[AD4130_STATUS_REG] = 1,
 	[AD4130_ADC_CONTROL_REG] = 2,
@@ -147,6 +177,24 @@ static const unsigned int ad4130_reg_size[] = {
 	[AD4130_FIFO_DATA_REG] = 3,
 };
 
+static const unsigned int ad4131_reg_size[] = {
+	[AD4130_STATUS_REG] = 1,
+	[AD4130_ADC_CONTROL_REG] = 2,
+	[AD4130_DATA_REG] = 2,
+	[AD4130_IO_CONTROL_REG] = 2,
+	[AD4130_VBIAS_REG] = 2,
+	[AD4130_ID_REG] = 1,
+	[AD4130_ERROR_REG] = 2,
+	[AD4130_ERROR_EN_REG] = 2,
+	[AD4130_MCLK_COUNT_REG] = 1,
+	[AD4130_CHANNEL_X_REG(0) ... AD4130_CHANNEL_X_REG(AD4130_MAX_CHANNELS - 1)] = 3,
+	[AD4130_CONFIG_X_REG(0) ... AD4130_CONFIG_X_REG(AD4130_MAX_SETUPS - 1)] = 2,
+	[AD4130_FILTER_X_REG(0) ... AD4130_FILTER_X_REG(AD4130_MAX_SETUPS - 1)] = 3,
+	[AD4130_OFFSET_X_REG(0) ... AD4130_OFFSET_X_REG(AD4130_MAX_SETUPS - 1)] = 2,
+	[AD4130_GAIN_X_REG(0) ... AD4130_GAIN_X_REG(AD4130_MAX_SETUPS - 1)] = 2,
+	[AD4130_MISC_REG] = 2,
+};
+
 enum ad4130_int_ref_val {
 	AD4130_INT_REF_VAL_2_5V,
 	AD4130_INT_REF_VAL_1_25V,
@@ -224,12 +272,32 @@ enum ad4130_pin_function {
 	AD4130_PIN_FN_VBIAS = BIT(3),
 };
 
+/* Map logical pins to register value */
+static const u8 ad4130_4_pin_map[] = {
+	0x00, /* AIN0/VBIAS_0 */
+	0x01, /* AIN1/VBIAS_1 */
+	0x04, /* AIN2/VBIAS_2 */
+	0x05, /* AIN3/VBIAS_3 */
+	0x0A, /* AIN4/VBIAS_4 */
+	0x0B, /* AIN5/VBIAS_5 */
+	0x0E, /* AIN6/VBIAS_6 */
+	0x0F, /* AIN7/VBIAS_7 */
+};
+
+static const u8 ad4130_8_pin_map[] = {
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* AIN0/VBIAS_0-AIN7/VBIAS_7 */
+	0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* AIN8/VBIAS_8-AIN15/VBIAS_15 */
+};
+
 struct ad4130_chip_info {
 	const char *name;
 	unsigned int max_analog_pins;
+	unsigned int num_gpios;
 	const struct iio_info *info;
 	const unsigned int *reg_size;
 	const unsigned int reg_size_length;
+	const u8 *pin_map;
+	bool has_fifo;
 };
 
 /*
@@ -303,6 +371,7 @@ struct ad4130_state {
 	u32			mclk_sel;
 	bool			int_ref_en;
 	bool			bipolar;
+	bool			buffer_wait_for_irq;
 
 	unsigned int		num_enabled_channels;
 	unsigned int		effective_watermark;
@@ -310,6 +379,7 @@ struct ad4130_state {
 
 	struct spi_message	fifo_msg;
 	struct spi_transfer	fifo_xfer[2];
+	struct iio_trigger	*trig;
 
 	/*
 	 * DMA (thus cache coherency maintenance) requires any transfer
@@ -324,6 +394,12 @@ struct ad4130_state {
 	u8			fifo_tx_buf[2];
 	u8			fifo_rx_buf[AD4130_FIFO_SIZE *
 					    AD4130_FIFO_MAX_SAMPLE_SIZE];
+
+	/* Triggered buffer data structure */
+	struct {
+		u32 channels[AD4130_MAX_CHANNELS];
+		s64 timestamp;
+	} scan __aligned(8);
 };
 
 static const char * const ad4130_int_pin_names[] = {
@@ -514,7 +590,8 @@ static int ad4130_gpio_init_valid_mask(struct gpio_chip *gc,
 
 	/*
 	 * Output-only GPIO functionality is available on pins AIN2 through
-	 * AIN5. If these pins are used for anything else, do not expose them.
+	 * AIN5 for some parts and AIN2 through AIN3 for others. If these pins
+	 * are used for anything else, do not expose them.
 	 */
 	for (i = 0; i < ngpios; i++) {
 		unsigned int pin = i + AD4130_AIN2_P1;
@@ -535,8 +612,14 @@ static int ad4130_gpio_set(struct gpio_chip *gc, unsigned int offset,
 			   int value)
 {
 	struct ad4130_state *st = gpiochip_get_data(gc);
-	unsigned int mask = FIELD_PREP(AD4130_IO_CONTROL_GPIO_DATA_MASK,
-				       BIT(offset));
+	unsigned int mask;
+
+	if (st->chip_info->num_gpios == AD4130_MAX_GPIOS)
+		mask = FIELD_PREP(AD4130_IO_CONTROL_GPIO_DATA_MASK,
+				  BIT(offset));
+	else
+		mask = FIELD_PREP(AD4130_4_IO_CONTROL_GPIO_DATA_MASK,
+				  BIT(offset));
 
 	return regmap_update_bits(st->regmap, AD4130_IO_CONTROL_REG, mask,
 				  value ? mask : 0);
@@ -597,10 +680,43 @@ static irqreturn_t ad4130_irq_handler(int irq, void *private)
 	struct iio_dev *indio_dev = private;
 	struct ad4130_state *st = iio_priv(indio_dev);
 
-	if (iio_buffer_enabled(indio_dev))
-		ad4130_push_fifo_data(indio_dev);
-	else
+	if (iio_buffer_enabled(indio_dev)) {
+		if (st->chip_info->has_fifo)
+			ad4130_push_fifo_data(indio_dev);
+		else if (st->buffer_wait_for_irq)
+			complete(&st->completion);
+		else
+			iio_trigger_poll(st->trig);
+	} else {
 		complete(&st->completion);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t ad4130_trigger_handler(int irq, void *p)
+{
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct ad4130_state *st = iio_priv(indio_dev);
+	unsigned int data_reg_size = ad4130_data_reg_size(st);
+	unsigned int num_en_chn = bitmap_weight(indio_dev->active_scan_mask,
+						iio_get_masklength(indio_dev));
+	struct spi_transfer xfer = {
+		.rx_buf = st->scan.channels,
+		.len = data_reg_size * num_en_chn,
+	};
+	int ret;
+
+	ret = spi_sync_transfer(st->spi, &xfer, 1);
+	if (ret < 0)
+		goto err_unlock;
+
+	iio_push_to_buffers_with_timestamp(indio_dev, &st->scan,
+					   iio_get_time_ns(indio_dev));
+
+err_unlock:
+	iio_trigger_notify_done(indio_dev->trig);
 
 	return IRQ_HANDLED;
 }
@@ -1300,12 +1416,77 @@ static const struct iio_info ad4130_info = {
 	.debugfs_reg_access = ad4130_reg_access,
 };
 
+static const struct iio_info ad4131_info = {
+	.read_raw = ad4130_read_raw,
+	.read_avail = ad4130_read_avail,
+	.write_raw_get_fmt = ad4130_write_raw_get_fmt,
+	.write_raw = ad4130_write_raw,
+	.update_scan_mode = ad4130_update_scan_mode,
+	.debugfs_reg_access = ad4130_reg_access,
+};
+
+static const struct ad4130_chip_info ad4129_4_chip_info = {
+	.name = "ad4129-4",
+	.max_analog_pins = 8,
+	.num_gpios = 2,
+	.info = &ad4130_info,
+	.reg_size = ad4129_reg_size,
+	.reg_size_length = ARRAY_SIZE(ad4129_reg_size),
+	.has_fifo = true,
+	.pin_map = ad4130_4_pin_map,
+};
+
+static const struct ad4130_chip_info ad4129_8_chip_info = {
+	.name = "ad4129-8",
+	.max_analog_pins = 16,
+	.num_gpios = 4,
+	.info = &ad4130_info,
+	.reg_size = ad4129_reg_size,
+	.reg_size_length = ARRAY_SIZE(ad4129_reg_size),
+	.has_fifo = true,
+	.pin_map = ad4130_8_pin_map,
+};
+
+static const struct ad4130_chip_info ad4130_4_chip_info = {
+	.name = "ad4130-4",
+	.max_analog_pins = 16,
+	.num_gpios = 2,
+	.info = &ad4130_info,
+	.reg_size = ad4130_reg_size,
+	.reg_size_length = ARRAY_SIZE(ad4130_reg_size),
+	.has_fifo = true,
+	.pin_map = ad4130_4_pin_map,
+};
+
 static const struct ad4130_chip_info ad4130_8_chip_info = {
 	.name = "ad4130-8",
 	.max_analog_pins = 16,
+	.num_gpios = 4,
 	.info = &ad4130_info,
 	.reg_size = ad4130_reg_size,
 	.reg_size_length = ARRAY_SIZE(ad4130_reg_size),
+	.has_fifo = true,
+	.pin_map = ad4130_8_pin_map,
+};
+
+static const struct ad4130_chip_info ad4131_4_chip_info = {
+	.name = "ad4131-4",
+	.max_analog_pins = 8,
+	.num_gpios = 2,
+	.info = &ad4131_info,
+	.reg_size = ad4131_reg_size,
+	.reg_size_length = ARRAY_SIZE(ad4131_reg_size),
+	.pin_map = ad4130_4_pin_map,
+};
+
+static const struct ad4130_chip_info ad4131_8_chip_info = {
+	.name = "ad4131-8",
+	.max_analog_pins = 16,
+	.num_gpios = 4,
+	.info = &ad4131_info,
+	.reg_size = ad4131_reg_size,
+	.reg_size_length = ARRAY_SIZE(ad4131_reg_size),
+	.pin_map = ad4130_8_pin_map,
 };
 
 static int ad4130_buffer_postenable(struct iio_dev *indio_dev)
@@ -1315,44 +1496,91 @@ static int ad4130_buffer_postenable(struct iio_dev *indio_dev)
 
 	guard(mutex)(&st->lock);
 
-	ret = ad4130_set_watermark_interrupt_en(st, true);
-	if (ret)
-		return ret;
+	if (st->chip_info->has_fifo) {
+		ret = ad4130_set_watermark_interrupt_en(st, true);
+		if (ret)
+			return ret;
 
-	ret = irq_set_irq_type(st->spi->irq, st->inv_irq_trigger);
-	if (ret)
-		return ret;
+		ret = irq_set_irq_type(st->spi->irq, st->inv_irq_trigger);
+		if (ret)
+			return ret;
+
+		ret = ad4130_set_fifo_mode(st, AD4130_FIFO_MODE_WM);
+		if (ret)
+			return ret;
+	}
 
-	ret = ad4130_set_fifo_mode(st, AD4130_FIFO_MODE_WM);
+	ret = ad4130_set_mode(st, AD4130_MODE_CONTINUOUS);
 	if (ret)
 		return ret;
 
-	return ad4130_set_mode(st, AD4130_MODE_CONTINUOUS);
+	/*
+	 * When using triggered buffer, Entering continuous read mode must
+	 * be the last command sent. No configuration changes are allowed until
+	 * exiting this mode.
+	 */
+	if (!st->chip_info->has_fifo) {
+		ret = regmap_update_bits(st->regmap, AD4130_ADC_CONTROL_REG,
+					 AD4130_ADC_CONTROL_CONT_READ_MASK,
+					 FIELD_PREP(AD4130_ADC_CONTROL_CONT_READ_MASK, 1));
+		if (ret)
+			return ret;
+	}
+
+	return 0;
 }
 
 static int ad4130_buffer_predisable(struct iio_dev *indio_dev)
 {
 	struct ad4130_state *st = iio_priv(indio_dev);
 	unsigned int i;
+	u32 temp;
 	int ret;
 
 	guard(mutex)(&st->lock);
 
+	if (!st->chip_info->has_fifo) {
+		temp = 0x42;
+		reinit_completion(&st->completion);
+
+		/*
+		 * In continuous read mode, when all samples are read, the data
+		 * ready signal returns high until the next conversion result is
+		 * ready. To exit this mode, the command must be sent when data
+		 * ready is low. In order to ensure that condition, wait for the
+		 * next interrupt (when the new conversion is finished), allowing
+		 * data ready to return low before sending the exit command.
+		 */
+		st->buffer_wait_for_irq = true;
+		ret = wait_for_completion_timeout(&st->completion,
+						  msecs_to_jiffies(1000));
+		st->buffer_wait_for_irq = false;
+		if (!ret)
+			dev_warn(&st->spi->dev, "Conversion timed out\n");
+
+		/* Perform a read data command to exit continuous read mode (0x42) */
+		ret = spi_write(st->spi, &temp, 1);
+		if (ret)
+			return ret;
+	}
+
 	ret = ad4130_set_mode(st, AD4130_MODE_IDLE);
 	if (ret)
 		return ret;
 
-	ret = irq_set_irq_type(st->spi->irq, st->irq_trigger);
-	if (ret)
-		return ret;
+	if (st->chip_info->has_fifo) {
+		ret = irq_set_irq_type(st->spi->irq, st->irq_trigger);
+		if (ret)
+			return ret;
 
-	ret = ad4130_set_fifo_mode(st, AD4130_FIFO_MODE_DISABLED);
-	if (ret)
-		return ret;
+		ret = ad4130_set_fifo_mode(st, AD4130_FIFO_MODE_DISABLED);
+		if (ret)
+			return ret;
 
-	ret = ad4130_set_watermark_interrupt_en(st, false);
-	if (ret)
-		return ret;
+		ret = ad4130_set_watermark_interrupt_en(st, false);
+		if (ret)
+			return ret;
+	}
 
 	/*
 	 * update_scan_mode() is not called in the disable path, disable all
@@ -1427,6 +1655,34 @@ static const struct iio_dev_attr *ad4130_fifo_attributes[] = {
 	NULL
 };
 
+static const struct iio_trigger_ops ad4130_trigger_ops = {
+	.validate_device = iio_trigger_validate_own_device,
+};
+
+static int ad4130_triggered_buffer_setup(struct iio_dev *indio_dev)
+{
+	struct ad4130_state *st = iio_priv(indio_dev);
+	int ret;
+
+	st->trig = devm_iio_trigger_alloc(indio_dev->dev.parent, "%s-dev%d",
+					  indio_dev->name, iio_device_id(indio_dev));
+	if (!st->trig)
+		return -ENOMEM;
+
+	st->trig->ops = &ad4130_trigger_ops;
+	iio_trigger_set_drvdata(st->trig, indio_dev);
+	ret = devm_iio_trigger_register(indio_dev->dev.parent, st->trig);
+	if (ret)
+		return ret;
+
+	indio_dev->trig = iio_trigger_get(st->trig);
+
+	return devm_iio_triggered_buffer_setup(indio_dev->dev.parent, indio_dev,
+					       &iio_pollfunc_store_time,
+					       &ad4130_trigger_handler,
+					       &ad4130_buffer_ops);
+}
+
 static int _ad4130_find_table_index(const unsigned int *tbl, size_t len,
 				    unsigned int val)
 {
@@ -1513,6 +1769,17 @@ static int ad4130_parse_fw_setup(struct ad4130_state *st,
 	return 0;
 }
 
+static unsigned int ad4130_translate_pin(struct ad4130_state *st,
+					 unsigned int logical_pin)
+{
+	/* For analog input pins, use the chip-specific pin mapping */
+	if (logical_pin < st->chip_info->max_analog_pins)
+		return st->chip_info->pin_map[logical_pin];
+
+	/* For internal channels, pass through unchanged */
+	return logical_pin;
+}
+
 static int ad4130_validate_diff_channel(struct ad4130_state *st, u32 pin)
 {
 	struct device *dev = &st->spi->dev;
@@ -1931,9 +2198,14 @@ static int ad4130_setup(struct iio_dev *indio_dev)
 	 * function of P2 takes priority over the GPIO out function.
 	 */
 	val = 0;
-	for (i = 0; i < AD4130_MAX_GPIOS; i++)
-		if (st->pins_fn[i + AD4130_AIN2_P1] == AD4130_PIN_FN_NONE)
-			val |= FIELD_PREP(AD4130_IO_CONTROL_GPIO_CTRL_MASK, BIT(i));
+	for (i = 0; i < st->chip_info->num_gpios; i++) {
+		if (st->pins_fn[i + AD4130_AIN2_P1] == AD4130_PIN_FN_NONE) {
+			if (st->chip_info->num_gpios == 2)
+				val |= FIELD_PREP(AD4130_4_IO_CONTROL_GPIO_CTRL_MASK, BIT(i));
+			else
+				val |= FIELD_PREP(AD4130_IO_CONTROL_GPIO_CTRL_MASK, BIT(i));
+		}
+	}
 
 	val |= FIELD_PREP(AD4130_IO_CONTROL_INT_PIN_SEL_MASK, st->int_pin_sel);
 
@@ -1943,21 +2215,23 @@ static int ad4130_setup(struct iio_dev *indio_dev)
 
 	val = 0;
 	for (i = 0; i < st->num_vbias_pins; i++)
-		val |= BIT(st->vbias_pins[i]);
+		val |= BIT(ad4130_translate_pin(st, st->vbias_pins[i]));
 
 	ret = regmap_write(st->regmap, AD4130_VBIAS_REG, val);
 	if (ret)
 		return ret;
 
-	ret = regmap_clear_bits(st->regmap, AD4130_FIFO_CONTROL_REG,
-				AD4130_FIFO_CONTROL_HEADER_MASK);
-	if (ret)
-		return ret;
+	if (st->chip_info->has_fifo) {
+		ret = regmap_clear_bits(st->regmap, AD4130_FIFO_CONTROL_REG,
+					AD4130_FIFO_CONTROL_HEADER_MASK);
+		if (ret)
+			return ret;
 
-	/* FIFO watermark interrupt starts out as enabled, disable it. */
-	ret = ad4130_set_watermark_interrupt_en(st, false);
-	if (ret)
-		return ret;
+		/* FIFO watermark interrupt starts out as enabled, disable it. */
+		ret = ad4130_set_watermark_interrupt_en(st, false);
+		if (ret)
+			return ret;
+	}
 
 	/* Setup channels. */
 	for (i = 0; i < indio_dev->num_channels; i++) {
@@ -1965,10 +2239,14 @@ static int ad4130_setup(struct iio_dev *indio_dev)
 		struct iio_chan_spec *chan = &st->chans[i];
 		unsigned int val;
 
-		val = FIELD_PREP(AD4130_CHANNEL_AINP_MASK, chan->channel) |
-		      FIELD_PREP(AD4130_CHANNEL_AINM_MASK, chan->channel2) |
-		      FIELD_PREP(AD4130_CHANNEL_IOUT1_MASK, chan_info->iout0) |
-		      FIELD_PREP(AD4130_CHANNEL_IOUT2_MASK, chan_info->iout1);
+		val = FIELD_PREP(AD4130_CHANNEL_AINP_MASK,
+				 ad4130_translate_pin(st, chan->channel)) |
+		      FIELD_PREP(AD4130_CHANNEL_AINM_MASK,
+				 ad4130_translate_pin(st, chan->channel2)) |
+		      FIELD_PREP(AD4130_CHANNEL_IOUT1_MASK,
+				 ad4130_translate_pin(st, chan_info->iout0)) |
+		      FIELD_PREP(AD4130_CHANNEL_IOUT2_MASK,
+				 ad4130_translate_pin(st, chan_info->iout1));
 
 		ret = regmap_write(st->regmap, AD4130_CHANNEL_X_REG(i), val);
 		if (ret)
@@ -2018,17 +2296,19 @@ static int ad4130_probe(struct spi_device *spi)
 	mutex_init(&st->lock);
 	st->spi = spi;
 
-	/*
-	 * Xfer:   [ XFR1 ] [         XFR2         ]
-	 * Master:  0x7D N   ......................
-	 * Slave:   ......   DATA1 DATA2 ... DATAN
-	 */
-	st->fifo_tx_buf[0] = AD4130_COMMS_READ_MASK | AD4130_FIFO_DATA_REG;
-	st->fifo_xfer[0].tx_buf = st->fifo_tx_buf;
-	st->fifo_xfer[0].len = sizeof(st->fifo_tx_buf);
-	st->fifo_xfer[1].rx_buf = st->fifo_rx_buf;
-	spi_message_init_with_transfers(&st->fifo_msg, st->fifo_xfer,
-					ARRAY_SIZE(st->fifo_xfer));
+	if (st->chip_info->has_fifo) {
+		/*
+		 * Xfer:   [ XFR1 ] [         XFR2         ]
+		 * Master:  0x7D N   ......................
+		 * Slave:   ......   DATA1 DATA2 ... DATAN
+		 */
+		st->fifo_tx_buf[0] = AD4130_COMMS_READ_MASK | AD4130_FIFO_DATA_REG;
+		st->fifo_xfer[0].tx_buf = st->fifo_tx_buf;
+		st->fifo_xfer[0].len = sizeof(st->fifo_tx_buf);
+		st->fifo_xfer[1].rx_buf = st->fifo_rx_buf;
+		spi_message_init_with_transfers(&st->fifo_msg, st->fifo_xfer,
+						ARRAY_SIZE(st->fifo_xfer));
+	}
 
 	indio_dev->name = st->chip_info->name;
 	indio_dev->modes = INDIO_DIRECT_MODE;
@@ -2077,7 +2357,7 @@ static int ad4130_probe(struct spi_device *spi)
 	st->gc.owner = THIS_MODULE;
 	st->gc.label = st->chip_info->name;
 	st->gc.base = -1;
-	st->gc.ngpio = AD4130_MAX_GPIOS;
+	st->gc.ngpio = st->chip_info->num_gpios;
 	st->gc.parent = dev;
 	st->gc.can_sleep = true;
 	st->gc.init_valid_mask = ad4130_gpio_init_valid_mask;
@@ -2088,9 +2368,12 @@ static int ad4130_probe(struct spi_device *spi)
 	if (ret)
 		return ret;
 
-	ret = devm_iio_kfifo_buffer_setup_ext(dev, indio_dev,
-					      &ad4130_buffer_ops,
-					      ad4130_fifo_attributes);
+	if (st->chip_info->has_fifo)
+		ret = devm_iio_kfifo_buffer_setup_ext(dev, indio_dev,
+						      &ad4130_buffer_ops,
+						      ad4130_fifo_attributes);
+	else
+		ret = ad4130_triggered_buffer_setup(indio_dev);
 	if (ret)
 		return ret;
 
@@ -2100,34 +2383,46 @@ static int ad4130_probe(struct spi_device *spi)
 	if (ret)
 		return dev_err_probe(dev, ret, "Failed to request irq\n");
 
-	/*
-	 * When the chip enters FIFO mode, IRQ polarity is inverted.
-	 * When the chip exits FIFO mode, IRQ polarity returns to normal.
-	 * See datasheet pages: 65, FIFO Watermark Interrupt section,
-	 * and 71, Bit Descriptions for STATUS Register, RDYB.
-	 * Cache the normal and inverted IRQ triggers to set them when
-	 * entering and exiting FIFO mode.
-	 */
-	st->irq_trigger = irq_get_trigger_type(spi->irq);
-	if (st->irq_trigger & IRQF_TRIGGER_RISING)
-		st->inv_irq_trigger = IRQF_TRIGGER_FALLING;
-	else if (st->irq_trigger & IRQF_TRIGGER_FALLING)
-		st->inv_irq_trigger = IRQF_TRIGGER_RISING;
-	else
-		return dev_err_probe(dev, -EINVAL, "Invalid irq flags: %u\n",
-				     st->irq_trigger);
+	if (st->chip_info->has_fifo) {
+		/*
+		 * When the chip enters FIFO mode, IRQ polarity is inverted.
+		 * When the chip exits FIFO mode, IRQ polarity returns to normal.
+		 * See datasheet pages: 65, FIFO Watermark Interrupt section,
+		 * and 71, Bit Descriptions for STATUS Register, RDYB.
+		 * Cache the normal and inverted IRQ triggers to set them when
+		 * entering and exiting FIFO mode.
+		 */
+		st->irq_trigger = irq_get_trigger_type(spi->irq);
+		if (st->irq_trigger & IRQF_TRIGGER_RISING)
+			st->inv_irq_trigger = IRQF_TRIGGER_FALLING;
+		else if (st->irq_trigger & IRQF_TRIGGER_FALLING)
+			st->inv_irq_trigger = IRQF_TRIGGER_RISING;
+		else
+			return dev_err_probe(dev, -EINVAL, "Invalid irq flags: %u\n",
+					     st->irq_trigger);
+	}
 
 	return devm_iio_device_register(dev, indio_dev);
 }
 
 static const struct of_device_id ad4130_of_match[] = {
+	{ .compatible = "adi,ad4129-4", .data = &ad4129_4_chip_info },
+	{ .compatible = "adi,ad4129-8", .data = &ad4129_8_chip_info },
+	{ .compatible = "adi,ad4130-4", .data = &ad4130_4_chip_info },
 	{ .compatible = "adi,ad4130", .data = &ad4130_8_chip_info },
+	{ .compatible = "adi,ad4131-4", .data = &ad4131_4_chip_info },
+	{ .compatible = "adi,ad4131-8", .data = &ad4131_8_chip_info },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, ad4130_of_match);
 
 static const struct spi_device_id ad4130_id_table[] = {
+	{ "ad4129-4", (kernel_ulong_t)&ad4129_4_chip_info },
+	{ "ad4129-8", (kernel_ulong_t)&ad4129_8_chip_info },
+	{ "ad4130-4", (kernel_ulong_t)&ad4130_4_chip_info },
 	{ "ad4130", (kernel_ulong_t)&ad4130_8_chip_info },
+	{ "ad4131-4", (kernel_ulong_t)&ad4131_4_chip_info },
+	{ "ad4131-8", (kernel_ulong_t)&ad4131_8_chip_info },
 	{ }
 };
 MODULE_DEVICE_TABLE(spi, ad4130_id_table);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/3] iio: adc: ad4130: introduce chip info for future multidevice support
  2026-02-28 12:38 ` [PATCH 2/3] iio: adc: ad4130: introduce chip info for future multidevice support Jonathan Santos
@ 2026-03-02 12:39   ` Andy Shevchenko
  0 siblings, 0 replies; 10+ messages in thread
From: Andy Shevchenko @ 2026-03-02 12:39 UTC (permalink / raw)
  To: Jonathan Santos
  Cc: linux-iio, linux-kernel, devicetree, cosmin.tanislav, lars,
	Michael.Hennerich, jic23, dlechner, nuno.sa, andy, robh, krzk+dt,
	conor+dt

On Sat, Feb 28, 2026 at 09:38:53AM -0300, Jonathan Santos wrote:
> Introduce a chip_info structure to abstract device-specific parameters
> and prepare the driver for supporting multiple AD4130 family variants.

...

> +struct ad4130_chip_info {
> +	const char *name;
> +	unsigned int max_analog_pins;
> +	const struct iio_info *info;
> +	const unsigned int *reg_size;
> +	const unsigned int reg_size_length;
> +};

Is `pahole` okay with the chosen layout?

...

>  static const struct of_device_id ad4130_of_match[] = {
> -	{
> -		.compatible = "adi,ad4130",
> -	},
> +	{ .compatible = "adi,ad4130", .data = &ad4130_8_chip_info },

Why touching the rest? Isn't just fine to add

		.data = ...,

?

>  	{ }
>  };

...

> +static const struct spi_device_id ad4130_id_table[] = {
> +	{ "ad4130", (kernel_ulong_t)&ad4130_8_chip_info },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(spi, ad4130_id_table);

> +	.id_table = ad4130_id_table,

Strictly speaking this can be a precursor change, while here you just add a
driver_data to it.


-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 3/3] iio: adc: ad4130: add new supported parts
  2026-02-28 12:39 ` [PATCH 3/3] iio: adc: ad4130: add new supported parts Jonathan Santos
@ 2026-03-02 12:51   ` Andy Shevchenko
  2026-03-07 16:27     ` David Lechner
  2026-03-07 14:20   ` Jonathan Cameron
  1 sibling, 1 reply; 10+ messages in thread
From: Andy Shevchenko @ 2026-03-02 12:51 UTC (permalink / raw)
  To: Jonathan Santos
  Cc: linux-iio, linux-kernel, devicetree, cosmin.tanislav, lars,
	Michael.Hennerich, jic23, dlechner, nuno.sa, andy, robh, krzk+dt,
	conor+dt

On Sat, Feb 28, 2026 at 09:39:04AM -0300, Jonathan Santos wrote:
> Add support for AD4129-4/8, AD4130-4, and AD4131-4/8 variants.
> 
> The AD4129 series supports the same FIFO interface as the AD4130 but with
> reduced resolution (16-bit). The AD4131 series lacks FIFO support, so
> triggered buffer functionality is introduced.
> 
> The 4-channel variants feature fewer analog inputs, GPIOs, and sparse pin
> mappings for VBIAS, analog inputs, and excitation currents. The driver now
> handles these differences with chip-specific configurations, including pin
> mappings and GPIO counts.

...

> +static const unsigned int ad4129_reg_size[] = {
> +	[AD4130_STATUS_REG] = 1,
> +	[AD4130_ADC_CONTROL_REG] = 2,
> +	[AD4130_DATA_REG] = 2,
> +	[AD4130_IO_CONTROL_REG] = 2,
> +	[AD4130_VBIAS_REG] = 2,
> +	[AD4130_ID_REG] = 1,
> +	[AD4130_ERROR_REG] = 2,
> +	[AD4130_ERROR_EN_REG] = 2,
> +	[AD4130_MCLK_COUNT_REG] = 1,
> +	[AD4130_CHANNEL_X_REG(0) ... AD4130_CHANNEL_X_REG(AD4130_MAX_CHANNELS - 1)] = 3,
> +	[AD4130_CONFIG_X_REG(0) ... AD4130_CONFIG_X_REG(AD4130_MAX_SETUPS - 1)] = 2,
> +	[AD4130_FILTER_X_REG(0) ... AD4130_FILTER_X_REG(AD4130_MAX_SETUPS - 1)] = 3,
> +	[AD4130_OFFSET_X_REG(0) ... AD4130_OFFSET_X_REG(AD4130_MAX_SETUPS - 1)] = 2,
> +	[AD4130_GAIN_X_REG(0) ... AD4130_GAIN_X_REG(AD4130_MAX_SETUPS - 1)] = 2,
> +	[AD4130_MISC_REG] = 2,
> +	[AD4130_FIFO_CONTROL_REG] = 3,
> +	[AD4130_FIFO_STATUS_REG] = 1,
> +	[AD4130_FIFO_THRESHOLD_REG] = 3,
> +	[AD4130_FIFO_DATA_REG] = 2,
> +};

I hope this passes `make W=1` builds for both clang and GCC.

...

> +static const u8 ad4130_8_pin_map[] = {
> +	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* AIN0/VBIAS_0-AIN7/VBIAS_7 */
> +	0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* AIN8/VBIAS_8-AIN15/VBIAS_15 */

These comments are hard to follow. Much better is

> +};

/* Pin mapping for AIN0..AIN15, VBIAS_0..VBIAS_15 */
static const u8 ad4130_8_pin_map[] = {
	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,	/* 0 -  7 */
	0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,	/* 8 - 15 */
};

...

>  struct ad4130_chip_info {
>  	const char *name;
>  	unsigned int max_analog_pins;
> +	unsigned int num_gpios;
>  	const struct iio_info *info;
>  	const unsigned int *reg_size;
>  	const unsigned int reg_size_length;
> +	const u8 *pin_map;
> +	bool has_fifo;

Ah, okay, so we fill the potential 4-byte gap from the previous patch.

>  };


...

> +	/* Triggered buffer data structure */
> +	struct {
> +		u32 channels[AD4130_MAX_CHANNELS];
> +		s64 timestamp;

Use aligned_s64 type...

> +	} scan __aligned(8);

...instead of this.

...

> +static irqreturn_t ad4130_trigger_handler(int irq, void *p)
> +{
> +	struct iio_poll_func *pf = p;
> +	struct iio_dev *indio_dev = pf->indio_dev;
> +	struct ad4130_state *st = iio_priv(indio_dev);
> +	unsigned int data_reg_size = ad4130_data_reg_size(st);

> +	unsigned int num_en_chn = bitmap_weight(indio_dev->active_scan_mask,
> +						iio_get_masklength(indio_dev));

Split this assignment. It's harder to read in the current form.

> +	struct spi_transfer xfer = {
> +		.rx_buf = st->scan.channels,
> +		.len = data_reg_size * num_en_chn,
> +	};
> +	int ret;
> +
> +	ret = spi_sync_transfer(st->spi, &xfer, 1);
> +	if (ret < 0)
> +		goto err_unlock;
> +
> +	iio_push_to_buffers_with_timestamp(indio_dev, &st->scan,
> +					   iio_get_time_ns(indio_dev));
> +
> +err_unlock:
> +	iio_trigger_notify_done(indio_dev->trig);
>  
>  	return IRQ_HANDLED;
>  }

...

> +		/*
> +		 * In continuous read mode, when all samples are read, the data
> +		 * ready signal returns high until the next conversion result is
> +		 * ready. To exit this mode, the command must be sent when data
> +		 * ready is low. In order to ensure that condition, wait for the
> +		 * next interrupt (when the new conversion is finished), allowing
> +		 * data ready to return low before sending the exit command.
> +		 */
> +		st->buffer_wait_for_irq = true;
> +		ret = wait_for_completion_timeout(&st->completion,
> +						  msecs_to_jiffies(1000));
> +		st->buffer_wait_for_irq = false;
> +		if (!ret)
> +			dev_warn(&st->spi->dev, "Conversion timed out\n");

Usage of 'ret' for semantically different (and IIRC unsigned) case is
confusing, perhaps

		st->buffer_wait_for_irq = true;
		if (wait_for_completion_timeout(&st->completion, msecs_to_jiffies(1000))
			dev_warn(&st->spi->dev, "Conversion timed out\n");
		st->buffer_wait_for_irq = false;

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/3] dt-bindings: iio: adc: ad4130: Add new supported parts
  2026-02-28 12:38 ` [PATCH 1/3] dt-bindings: iio: adc: ad4130: Add new supported parts Jonathan Santos
@ 2026-03-03  6:50   ` Krzysztof Kozlowski
  0 siblings, 0 replies; 10+ messages in thread
From: Krzysztof Kozlowski @ 2026-03-03  6:50 UTC (permalink / raw)
  To: Jonathan Santos
  Cc: linux-iio, linux-kernel, devicetree, cosmin.tanislav, lars,
	Michael.Hennerich, jic23, dlechner, nuno.sa, andy, robh, krzk+dt,
	conor+dt

On Sat, Feb 28, 2026 at 09:38:43AM -0300, Jonathan Santos wrote:
> Extend driver support for AD4129-4/8, AD4130-4, and AD4131-4/8 ADC
> variants.
> 
> Signed-off-by: Jonathan Santos <Jonathan.Santos@analog.com>
> ---
>  .../devicetree/bindings/iio/adc/adi,ad4130.yaml   | 15 +++++++++++++--
>  1 file changed, 13 insertions(+), 2 deletions(-)

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 3/3] iio: adc: ad4130: add new supported parts
  2026-02-28 12:39 ` [PATCH 3/3] iio: adc: ad4130: add new supported parts Jonathan Santos
  2026-03-02 12:51   ` Andy Shevchenko
@ 2026-03-07 14:20   ` Jonathan Cameron
  1 sibling, 0 replies; 10+ messages in thread
From: Jonathan Cameron @ 2026-03-07 14:20 UTC (permalink / raw)
  To: Jonathan Santos
  Cc: linux-iio, linux-kernel, devicetree, cosmin.tanislav, lars,
	Michael.Hennerich, dlechner, nuno.sa, andy, robh, krzk+dt,
	conor+dt

On Sat, 28 Feb 2026 09:39:04 -0300
Jonathan Santos <Jonathan.Santos@analog.com> wrote:

> Add support for AD4129-4/8, AD4130-4, and AD4131-4/8 variants.
> 
> The AD4129 series supports the same FIFO interface as the AD4130 but with
> reduced resolution (16-bit). The AD4131 series lacks FIFO support, so
> triggered buffer functionality is introduced.
> 
> The 4-channel variants feature fewer analog inputs, GPIOs, and sparse pin
> mappings for VBIAS, analog inputs, and excitation currents. The driver now
> handles these differences with chip-specific configurations, including pin
> mappings and GPIO counts.
> 
> Signed-off-by: Jonathan Santos <Jonathan.Santos@analog.com>
A couple of things inline.

> +static irqreturn_t ad4130_trigger_handler(int irq, void *p)
> +{
> +	struct iio_poll_func *pf = p;
> +	struct iio_dev *indio_dev = pf->indio_dev;
> +	struct ad4130_state *st = iio_priv(indio_dev);
> +	unsigned int data_reg_size = ad4130_data_reg_size(st);
> +	unsigned int num_en_chn = bitmap_weight(indio_dev->active_scan_mask,
> +						iio_get_masklength(indio_dev));
> +	struct spi_transfer xfer = {
> +		.rx_buf = st->scan.channels,
> +		.len = data_reg_size * num_en_chn,
> +	};
> +	int ret;
> +
> +	ret = spi_sync_transfer(st->spi, &xfer, 1);
> +	if (ret < 0)
> +		goto err_unlock;
> +
> +	iio_push_to_buffers_with_timestamp(indio_dev, &st->scan,
> +					   iio_get_time_ns(indio_dev));
> +
> +err_unlock:

Needs a rename seeing as no locks involved.

> +	iio_trigger_notify_done(indio_dev->trig);
>  
>  	return IRQ_HANDLED;
>  }
> @@ -1300,12 +1416,77 @@ static const struct iio_info ad4130_info = {
>  	.debugfs_reg_access = ad4130_reg_access,
>  };

> @@ -2100,34 +2383,46 @@ static int ad4130_probe(struct spi_device *spi)
>  	if (ret)
>  		return dev_err_probe(dev, ret, "Failed to request irq\n");
>  
> -	/*
> -	 * When the chip enters FIFO mode, IRQ polarity is inverted.
> -	 * When the chip exits FIFO mode, IRQ polarity returns to normal.
> -	 * See datasheet pages: 65, FIFO Watermark Interrupt section,
> -	 * and 71, Bit Descriptions for STATUS Register, RDYB.
> -	 * Cache the normal and inverted IRQ triggers to set them when
> -	 * entering and exiting FIFO mode.
> -	 */
> -	st->irq_trigger = irq_get_trigger_type(spi->irq);
> -	if (st->irq_trigger & IRQF_TRIGGER_RISING)
> -		st->inv_irq_trigger = IRQF_TRIGGER_FALLING;
> -	else if (st->irq_trigger & IRQF_TRIGGER_FALLING)
> -		st->inv_irq_trigger = IRQF_TRIGGER_RISING;
> -	else
> -		return dev_err_probe(dev, -EINVAL, "Invalid irq flags: %u\n",
> -				     st->irq_trigger);
> +	if (st->chip_info->has_fifo) {
> +		/*
> +		 * When the chip enters FIFO mode, IRQ polarity is inverted.
> +		 * When the chip exits FIFO mode, IRQ polarity returns to normal.
> +		 * See datasheet pages: 65, FIFO Watermark Interrupt section,
> +		 * and 71, Bit Descriptions for STATUS Register, RDYB.
> +		 * Cache the normal and inverted IRQ triggers to set them when
> +		 * entering and exiting FIFO mode.

That's special.   The binding doc needs an update to say which state we are
expecting an irq description for.  Obviously not a result of this
series but nice to add that none the less!

> +		 */
> +		st->irq_trigger = irq_get_trigger_type(spi->irq);
> +		if (st->irq_trigger & IRQF_TRIGGER_RISING)
> +			st->inv_irq_trigger = IRQF_TRIGGER_FALLING;
> +		else if (st->irq_trigger & IRQF_TRIGGER_FALLING)
> +			st->inv_irq_trigger = IRQF_TRIGGER_RISING;
> +		else
> +			return dev_err_probe(dev, -EINVAL, "Invalid irq flags: %u\n",
> +					     st->irq_trigger);
> +	}
>  
>  	return devm_iio_device_register(dev, indio_dev);
>  }

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 3/3] iio: adc: ad4130: add new supported parts
  2026-03-02 12:51   ` Andy Shevchenko
@ 2026-03-07 16:27     ` David Lechner
  2026-03-07 17:01       ` Jonathan Cameron
  0 siblings, 1 reply; 10+ messages in thread
From: David Lechner @ 2026-03-07 16:27 UTC (permalink / raw)
  To: Andy Shevchenko, Jonathan Santos
  Cc: linux-iio, linux-kernel, devicetree, cosmin.tanislav, lars,
	Michael.Hennerich, jic23, nuno.sa, andy, robh, krzk+dt, conor+dt

On 3/2/26 6:51 AM, Andy Shevchenko wrote:
> On Sat, Feb 28, 2026 at 09:39:04AM -0300, Jonathan Santos wrote:
>> Add support for AD4129-4/8, AD4130-4, and AD4131-4/8 variants.
>>

...

> 
>> +	/* Triggered buffer data structure */
>> +	struct {
>> +		u32 channels[AD4130_MAX_CHANNELS];
>> +		s64 timestamp;
> 
> Use aligned_s64 type...
> 
>> +	} scan __aligned(8);
> 
> ...instead of this.
> 

This is used with SPI, so it actually needs to be:

	IIO_DECLARE_DMA_BUFFER_WITH_TS(u32, channels, AD4130_MAX_CHANNELS);

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 3/3] iio: adc: ad4130: add new supported parts
  2026-03-07 16:27     ` David Lechner
@ 2026-03-07 17:01       ` Jonathan Cameron
  0 siblings, 0 replies; 10+ messages in thread
From: Jonathan Cameron @ 2026-03-07 17:01 UTC (permalink / raw)
  To: David Lechner
  Cc: Andy Shevchenko, Jonathan Santos, linux-iio, linux-kernel,
	devicetree, cosmin.tanislav, lars, Michael.Hennerich, nuno.sa,
	andy, robh, krzk+dt, conor+dt

On Sat, 7 Mar 2026 10:27:41 -0600
David Lechner <dlechner@baylibre.com> wrote:

> On 3/2/26 6:51 AM, Andy Shevchenko wrote:
> > On Sat, Feb 28, 2026 at 09:39:04AM -0300, Jonathan Santos wrote:  
> >> Add support for AD4129-4/8, AD4130-4, and AD4131-4/8 variants.
> >>  
> 
> ...
> 
> >   
> >> +	/* Triggered buffer data structure */
> >> +	struct {
> >> +		u32 channels[AD4130_MAX_CHANNELS];
> >> +		s64 timestamp;  
> > 
> > Use aligned_s64 type...
> >   
> >> +	} scan __aligned(8);  
> > 
> > ...instead of this.
> >   
> 
> This is used with SPI, so it actually needs to be:
> 
> 	IIO_DECLARE_DMA_BUFFER_WITH_TS(u32, channels, AD4130_MAX_CHANNELS);
Whilst you are correct, that reasoning is partial.

We could have marked it as sufficiently aligned.
The buffer part make sense because we may have only a few channels enabled
so the timestamp may be much earlier in memory than the structure suggests.

Thanks,

J

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2026-03-07 17:01 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-28 12:38 [PATCH 0/3] iio: adc: ad4130: Add support for AD4129-4/8, AD4130-4, and AD4131-4/8 Jonathan Santos
2026-02-28 12:38 ` [PATCH 1/3] dt-bindings: iio: adc: ad4130: Add new supported parts Jonathan Santos
2026-03-03  6:50   ` Krzysztof Kozlowski
2026-02-28 12:38 ` [PATCH 2/3] iio: adc: ad4130: introduce chip info for future multidevice support Jonathan Santos
2026-03-02 12:39   ` Andy Shevchenko
2026-02-28 12:39 ` [PATCH 3/3] iio: adc: ad4130: add new supported parts Jonathan Santos
2026-03-02 12:51   ` Andy Shevchenko
2026-03-07 16:27     ` David Lechner
2026-03-07 17:01       ` Jonathan Cameron
2026-03-07 14:20   ` Jonathan Cameron

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox