* [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; 11+ 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] 11+ 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; 11+ 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] 11+ 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; 11+ 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] 11+ 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; 11+ 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] 11+ 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; 11+ 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] 11+ 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; 11+ 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] 11+ 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; 11+ 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] 11+ messages in thread
* Re: [PATCH 2/3] iio: adc: ad4130: introduce chip info for future multidevice support
@ 2026-03-05 19:45 kernel test robot
0 siblings, 0 replies; 11+ messages in thread
From: kernel test robot @ 2026-03-05 19:45 UTC (permalink / raw)
To: oe-kbuild; +Cc: lkp, Dan Carpenter
BCC: lkp@intel.com
CC: oe-kbuild-all@lists.linux.dev
In-Reply-To: <b95a029f836a1d2d125f5beccf5290cfcf32c725.1772078999.git.Jonathan.Santos@analog.com>
References: <b95a029f836a1d2d125f5beccf5290cfcf32c725.1772078999.git.Jonathan.Santos@analog.com>
TO: Jonathan Santos <Jonathan.Santos@analog.com>
TO: linux-iio@vger.kernel.org
TO: linux-kernel@vger.kernel.org
TO: devicetree@vger.kernel.org
CC: Jonathan Santos <Jonathan.Santos@analog.com>
CC: cosmin.tanislav@analog.com
CC: lars@metafoo.de
CC: Michael.Hennerich@analog.com
CC: jic23@kernel.org
CC: dlechner@baylibre.com
CC: nuno.sa@analog.com
CC: andy@kernel.org
CC: robh@kernel.org
CC: krzk+dt@kernel.org
CC: conor+dt@kernel.org
Hi Jonathan,
kernel test robot noticed the following build warnings:
[auto build test WARNING on jic23-iio/togreg]
[also build test WARNING on linus/master v7.0-rc2 next-20260305]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Jonathan-Santos/dt-bindings-iio-adc-ad4130-Add-new-supported-parts/20260303-002854
base: https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git togreg
patch link: https://lore.kernel.org/r/b95a029f836a1d2d125f5beccf5290cfcf32c725.1772078999.git.Jonathan.Santos%40analog.com
patch subject: [PATCH 2/3] iio: adc: ad4130: introduce chip info for future multidevice support
:::::: branch date: 3 days ago
:::::: commit date: 3 days ago
config: m68k-randconfig-r072-20260305 (https://download.01.org/0day-ci/archive/20260306/202603060334.Qy6YCwgJ-lkp@intel.com/config)
compiler: m68k-linux-gcc (GCC) 14.3.0
smatch: v0.5.0-9004-gb810ac53
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Reported-by: Dan Carpenter <error27@gmail.com>
| Closes: https://lore.kernel.org/r/202603060334.Qy6YCwgJ-lkp@intel.com/
New smatch warnings:
drivers/iio/adc/ad4130.c:1527 ad4130_validate_diff_channel() error: buffer overflow 'st->pins_fn' 16 <= 29
Old smatch warnings:
drivers/iio/adc/ad4130.c:1530 ad4130_validate_diff_channel() error: buffer overflow 'st->pins_fn' 16 <= 29
drivers/iio/adc/ad4130.c:1532 ad4130_validate_diff_channel() error: buffer overflow 'st->pins_fn' 16 <= 29
vim +1527 drivers/iio/adc/ad4130.c
62094060cf3aca Cosmin Tanislav 2022-10-21 1515
62094060cf3aca Cosmin Tanislav 2022-10-21 1516 static int ad4130_validate_diff_channel(struct ad4130_state *st, u32 pin)
62094060cf3aca Cosmin Tanislav 2022-10-21 1517 {
62094060cf3aca Cosmin Tanislav 2022-10-21 1518 struct device *dev = &st->spi->dev;
62094060cf3aca Cosmin Tanislav 2022-10-21 1519
62094060cf3aca Cosmin Tanislav 2022-10-21 1520 if (pin >= AD4130_MAX_DIFF_INPUTS)
62094060cf3aca Cosmin Tanislav 2022-10-21 1521 return dev_err_probe(dev, -EINVAL,
6abcb19e0a6a37 Colin Ian King 2022-11-04 1522 "Invalid differential channel %u\n", pin);
62094060cf3aca Cosmin Tanislav 2022-10-21 1523
9244a45dc94161 Jonathan Santos 2026-02-28 1524 if (pin >= st->chip_info->max_analog_pins)
62094060cf3aca Cosmin Tanislav 2022-10-21 1525 return 0;
62094060cf3aca Cosmin Tanislav 2022-10-21 1526
62094060cf3aca Cosmin Tanislav 2022-10-21 @1527 if (st->pins_fn[pin] == AD4130_PIN_FN_SPECIAL)
62094060cf3aca Cosmin Tanislav 2022-10-21 1528 return dev_err_probe(dev, -EINVAL,
62094060cf3aca Cosmin Tanislav 2022-10-21 1529 "Pin %u already used with fn %u\n", pin,
62094060cf3aca Cosmin Tanislav 2022-10-21 1530 st->pins_fn[pin]);
62094060cf3aca Cosmin Tanislav 2022-10-21 1531
62094060cf3aca Cosmin Tanislav 2022-10-21 1532 st->pins_fn[pin] |= AD4130_PIN_FN_DIFF;
62094060cf3aca Cosmin Tanislav 2022-10-21 1533
62094060cf3aca Cosmin Tanislav 2022-10-21 1534 return 0;
62094060cf3aca Cosmin Tanislav 2022-10-21 1535 }
62094060cf3aca Cosmin Tanislav 2022-10-21 1536
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 11+ 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; 11+ 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] 11+ 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; 11+ 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] 11+ 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; 11+ 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] 11+ messages in thread
end of thread, other threads:[~2026-03-07 17:01 UTC | newest]
Thread overview: 11+ 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
-- strict thread matches above, loose matches on Subject: below --
2026-03-05 19:45 [PATCH 2/3] iio: adc: ad4130: introduce chip info for future multidevice support kernel test robot
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.