All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 00/15] iio: adc: ad4134: Enable greater sample rate data capture
@ 2026-10-17  1:56 Marcelo Schmitt
  2026-10-17  1:56 ` [PATCH v5 01/15] iio: adc: ad4134: Adjust register map range Marcelo Schmitt
                   ` (14 more replies)
  0 siblings, 15 replies; 22+ messages in thread
From: Marcelo Schmitt @ 2026-10-17  1:56 UTC (permalink / raw)
  To: linux-iio, devicetree, linux-kernel, linux
  Cc: jic23, nuno.sa, dlechner, andy, Michael.Hennerich, robh, krzk+dt,
	conor+dt, corbet, skhan, marcelo.schmitt1

Extend AD4134 support to enable greater sample rate data capture. To achieve
that, provide control of digital filter type selection. The default filter
type on device power up only supports sample rates up to 374 kSPS. In addition
to that, enable interfacing with AD4134 in SPI 4-wire mode that can support
reading ADC sample data through multiple wires. Finally, use SPI offloading
to speed up data transfers at up to 1.49 MSPS.

Features being added:
- Data filter type selection.
- Triggered buffer data read.
- SPI 4-wire mode.
- High speed data capture with SPI offloading.
- Device tree doc updates.

Minor improvements (introduced before the new features):
- Sign extend sample data.
- Apply reset recovery wait time.
- Update include list to comply with IWYU principles.
- Serialize single-read operations.
- Run shorter transfers when CRC is disabled.
- Protect conventional device access from debug accesses [NEW PATCH]


Change log v4 -> v5:
[device tree]
- No changes in dt-doc.
[IIO]
- Initialized local variable with 0 to avoid build warns.
- Set max_register according to AD4134_NUM_CHANNELS.
- Apply reset recovery wait time. [NEW FIX PATCH]
- Protect conventional device access from debug accesses. [NEW PATCH]
- Re-arranged code so early function prototype declaration is no longer needed.
- Now using iio_for_each_active_channel() to iterate over IIO channels.
- Updated adi,spi-mode property handling.
- No longer selecting/deselecting multiplexer states when in minimum I/O mode.


Previous submissions:
  v1: https://lore.kernel.org/linux-iio/cover.1788368334.git.marcelo.schmitt@analog.com/
  v2: https://lore.kernel.org/linux-iio/cover.1789494473.git.marcelo.schmitt@analog.com/
  v3: https://lore.kernel.org/linux-iio/cover.1790719424.git.marcelo.schmitt@analog.com/
  v4: https://lore.kernel.org/linux-iio/cover.1791309733.git.marcelo.schmitt@analog.com/


Marcelo Schmitt (15):
  iio: adc: ad4134: Adjust register map range
  iio: adc: ad4134: Sign extend sample data
  iio: adc: ad4134: Apply reset recovery wait time
  iio: adc: ad4134: Update include list to comply with IWYU principles
  iio: adc: ad4134: Serialize single-read operations
  iio: adc: ad4134: Protect conventional device access from debug
    accesses
  iio: adc: ad4134: Run shorter transfers when CRC is disabled
  iio: adc: ad4134: Add support for digital filter type selection
  iio: adc: ad4134: Support buffered data read
  dt-bindings: iio: adc: adi,ad4134: Document SPI connection mode
  dt-bindings: iio: adc: adi,ad4134: Document external multiplexer usage
  iio: adc: ad4134: Support SPI 4-wire mode
  dt-bindings: iio: adc: adi,ad4134: Document PWM usage
  iio: adc: ad4134: Support high-speed data capture
  Docs: iio: Add AD4134

 .../bindings/iio/adc/adi,ad4134.yaml          | 110 ++-
 Documentation/iio/ad4134.rst                  | 127 +++
 Documentation/iio/index.rst                   |   1 +
 MAINTAINERS                                   |   1 +
 drivers/iio/adc/Kconfig                       |   8 +
 drivers/iio/adc/ad4134.c                      | 793 +++++++++++++++++-
 6 files changed, 987 insertions(+), 53 deletions(-)
 create mode 100644 Documentation/iio/ad4134.rst


base-commit: a22dc7ebb21a6bd4c8b63bc2c1dd46a24945aae7
-- 
2.53.0


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

* [PATCH v5 01/15] iio: adc: ad4134: Adjust register map range
  2026-10-17  1:56 [PATCH v5 00/15] iio: adc: ad4134: Enable greater sample rate data capture Marcelo Schmitt
@ 2026-10-17  1:56 ` Marcelo Schmitt
  2026-10-17  1:56 ` [PATCH v5 02/15] iio: adc: ad4134: Sign extend sample data Marcelo Schmitt
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Marcelo Schmitt @ 2026-10-17  1:56 UTC (permalink / raw)
  To: linux-iio, devicetree, linux-kernel, linux
  Cc: jic23, nuno.sa, dlechner, andy, Michael.Hennerich, robh, krzk+dt,
	conor+dt, corbet, skhan, marcelo.schmitt1

Due to a off-by-one mistake, privileged users would be able to read from an
unsupported register address when reading device registers through a debug
interface. Correct the off-by-one mistake at the high register map range to
prevent access of unsupported addresses.

Fixes: e0bc6d7e2584 ("iio: adc: Initial support for AD4134")
Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
---
Change log v4 -> v5
- Set max_register according to AD4134_NUM_CHANNELS.

 drivers/iio/adc/ad4134.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c
index 70f80bf1825f..8400c3934925 100644
--- a/drivers/iio/adc/ad4134.c
+++ b/drivers/iio/adc/ad4134.c
@@ -111,7 +111,7 @@ static const struct regmap_range ad4134_regmap_rd_range[] = {
 	regmap_reg_range(AD4134_IFACE_CONFIG_A_REG, AD4134_SILICON_REV_REG),
 	regmap_reg_range(AD4134_SCRATCH_PAD_REG, AD4134_PW_DOWN_CTRL_REG),
 	regmap_reg_range(AD4134_DEVICE_STATUS_REG, AD4134_AIN_OR_ERROR_REG),
-	regmap_reg_range(AD4134_CH_VREG(0), AD4134_CH_VREG(AD4134_NUM_CHANNELS)),
+	regmap_reg_range(AD4134_CH_VREG(0), AD4134_CH_VREG(AD4134_NUM_CHANNELS - 1)),
 };
 
 static const struct regmap_range ad4134_regmap_wr_range[] = {
@@ -244,7 +244,7 @@ static const struct regmap_config ad4134_regmap_config = {
 	.reg_write = ad4134_reg_write,
 	.rd_table = &ad4134_regmap_rd_table,
 	.wr_table = &ad4134_regmap_wr_table,
-	.max_register = AD4134_CH_VREG(ARRAY_SIZE(ad4134_chan_set)),
+	.max_register = AD4134_CH_VREG(AD4134_NUM_CHANNELS - 1),
 };
 
 static int ad4134_read_raw(struct iio_dev *indio_dev,
-- 
2.53.0


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

* [PATCH v5 02/15] iio: adc: ad4134: Sign extend sample data
  2026-10-17  1:56 [PATCH v5 00/15] iio: adc: ad4134: Enable greater sample rate data capture Marcelo Schmitt
  2026-10-17  1:56 ` [PATCH v5 01/15] iio: adc: ad4134: Adjust register map range Marcelo Schmitt
@ 2026-10-17  1:56 ` Marcelo Schmitt
  2026-10-17  1:57 ` [PATCH v5 03/15] iio: adc: ad4134: Apply reset recovery wait time Marcelo Schmitt
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Marcelo Schmitt @ 2026-10-17  1:56 UTC (permalink / raw)
  To: linux-iio, devicetree, linux-kernel, linux
  Cc: jic23, nuno.sa, dlechner, andy, Michael.Hennerich, robh, krzk+dt,
	conor+dt, corbet, skhan, marcelo.schmitt1, Joshua Crofts

Sign extend ADC sample data for correct delivery of negative ADC input
difference.

Reviewed-by: Nuno Sá <nuno.sa@analog.com>
Reviewed-by: Joshua Crofts <joshua.crofts1@gmail.com>
Fixes: e0bc6d7e2584 ("iio: adc: Initial support for AD4134")
Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
---
Change log v5
- Initialized local variable with 0 to avoid build warns.

 drivers/iio/adc/ad4134.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c
index 8400c3934925..40b27b01f126 100644
--- a/drivers/iio/adc/ad4134.c
+++ b/drivers/iio/adc/ad4134.c
@@ -172,6 +172,7 @@ static int ad4134_data_read(struct ad4134_state *st, unsigned int reg,
 			    unsigned int *val)
 {
 	unsigned int i;
+	u32 sample = 0;
 	int ret;
 
 	/*
@@ -196,8 +197,9 @@ static int ad4134_data_read(struct ad4134_state *st, unsigned int reg,
 		 * Clock out data from all channels to avoid that.
 		 */
 		if (i == AD4134_VREG_CH(reg))
-			*val = get_unaligned_be24(st->rx_buf);
+			sample = get_unaligned_be24(st->rx_buf);
 	}
+	*val = sign_extend32(sample, AD4134_CHAN_PRECISION_BITS - 1);
 
 	return 0;
 }
-- 
2.53.0


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

* [PATCH v5 03/15] iio: adc: ad4134: Apply reset recovery wait time
  2026-10-17  1:56 [PATCH v5 00/15] iio: adc: ad4134: Enable greater sample rate data capture Marcelo Schmitt
  2026-10-17  1:56 ` [PATCH v5 01/15] iio: adc: ad4134: Adjust register map range Marcelo Schmitt
  2026-10-17  1:56 ` [PATCH v5 02/15] iio: adc: ad4134: Sign extend sample data Marcelo Schmitt
@ 2026-10-17  1:57 ` Marcelo Schmitt
  2026-10-17  2:05   ` sashiko-bot
  2026-10-17  5:55   ` Joshua Crofts
  2026-10-17  1:57 ` [PATCH v5 04/15] iio: adc: ad4134: Update include list to comply with IWYU principles Marcelo Schmitt
                   ` (11 subsequent siblings)
  14 siblings, 2 replies; 22+ messages in thread
From: Marcelo Schmitt @ 2026-10-17  1:57 UTC (permalink / raw)
  To: linux-iio, devicetree, linux-kernel, linux
  Cc: jic23, nuno.sa, dlechner, andy, Michael.Hennerich, robh, krzk+dt,
	conor+dt, corbet, skhan, marcelo.schmitt1

Add a reset recovery wait time to avoid any SPI transfer from running too
soon during device probe.

Fixes: e0bc6d7e2584 ("iio: adc: Initial support for AD4134")
Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
---
New patch in v5.

 drivers/iio/adc/ad4134.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c
index 40b27b01f126..d555874b4959 100644
--- a/drivers/iio/adc/ad4134.c
+++ b/drivers/iio/adc/ad4134.c
@@ -442,6 +442,7 @@ static int ad4134_probe(struct spi_device *spi)
 		return dev_err_probe(dev, PTR_ERR(rst),
 				     "failed to get and deassert reset\n");
 
+	fsleep(AD4134_RESET_TIME_US);
 	crc8_populate_msb(ad4134_spi_crc_table, AD4134_SPI_CRC_POLYNOM);
 
 	st->regmap = devm_regmap_init(dev, NULL, st, &ad4134_regmap_config);
-- 
2.53.0


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

* [PATCH v5 04/15] iio: adc: ad4134: Update include list to comply with IWYU principles
  2026-10-17  1:56 [PATCH v5 00/15] iio: adc: ad4134: Enable greater sample rate data capture Marcelo Schmitt
                   ` (2 preceding siblings ...)
  2026-10-17  1:57 ` [PATCH v5 03/15] iio: adc: ad4134: Apply reset recovery wait time Marcelo Schmitt
@ 2026-10-17  1:57 ` Marcelo Schmitt
  2026-10-17  1:57 ` [PATCH v5 05/15] iio: adc: ad4134: Serialize single-read operations Marcelo Schmitt
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Marcelo Schmitt @ 2026-10-17  1:57 UTC (permalink / raw)
  To: linux-iio, devicetree, linux-kernel, linux
  Cc: jic23, nuno.sa, dlechner, andy, Michael.Hennerich, robh, krzk+dt,
	conor+dt, corbet, skhan, marcelo.schmitt1, Andy Shevchenko

Add includes that were missing (according to include-what-you-use tool)
to comply with include what is used principles. Namely, add time64.h for
USEC_PER_SEC.

Remove time.h which is covered by time64.h and iio/types.h which is
covered by iio/iio.h.

While updating the list, organize it to follow current IIO include list
convention.

Reviewed-by: Nuno Sá <nuno.sa@analog.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
---
 drivers/iio/adc/ad4134.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c
index d555874b4959..dc2b32c73a3a 100644
--- a/drivers/iio/adc/ad4134.c
+++ b/drivers/iio/adc/ad4134.c
@@ -14,18 +14,18 @@
 #include <linux/err.h>
 #include <linux/export.h>
 #include <linux/gpio/consumer.h>
-#include <linux/iio/iio.h>
-#include <linux/iio/types.h>
 #include <linux/module.h>
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/reset.h>
 #include <linux/spi/spi.h>
-#include <linux/time.h>
+#include <linux/time64.h>
 #include <linux/types.h>
 #include <linux/unaligned.h>
 #include <linux/units.h>
 
+#include <linux/iio/iio.h>
+
 #define AD4134_RESET_TIME_US			(10 * USEC_PER_SEC)
 
 #define AD4134_REG_READ_MASK			BIT(7)
-- 
2.53.0


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

* [PATCH v5 05/15] iio: adc: ad4134: Serialize single-read operations
  2026-10-17  1:56 [PATCH v5 00/15] iio: adc: ad4134: Enable greater sample rate data capture Marcelo Schmitt
                   ` (3 preceding siblings ...)
  2026-10-17  1:57 ` [PATCH v5 04/15] iio: adc: ad4134: Update include list to comply with IWYU principles Marcelo Schmitt
@ 2026-10-17  1:57 ` Marcelo Schmitt
  2026-10-17  1:58 ` [PATCH v5 06/15] iio: adc: ad4134: Protect conventional device access from debug accesses Marcelo Schmitt
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Marcelo Schmitt @ 2026-10-17  1:57 UTC (permalink / raw)
  To: linux-iio, devicetree, linux-kernel, linux
  Cc: jic23, nuno.sa, dlechner, andy, Michael.Hennerich, robh, krzk+dt,
	conor+dt, corbet, skhan, marcelo.schmitt1, Andy Shevchenko

Protect single-sample read operations from going wrong if two or more of
them run concurrently. Serialize the data read operation so to avoid
single-sample read requests disrupting each other.

Reviewed-by: Nuno Sá <nuno.sa@analog.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
---
 drivers/iio/adc/ad4134.c | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c
index dc2b32c73a3a..dc4d801490db 100644
--- a/drivers/iio/adc/ad4134.c
+++ b/drivers/iio/adc/ad4134.c
@@ -7,6 +7,7 @@
 #include <linux/array_size.h>
 #include <linux/bitfield.h>
 #include <linux/bitops.h>
+#include <linux/cleanup.h>
 #include <linux/clk.h>
 #include <linux/crc8.h>
 #include <linux/delay.h>
@@ -15,6 +16,7 @@
 #include <linux/export.h>
 #include <linux/gpio/consumer.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/reset.h>
@@ -98,6 +100,11 @@ struct ad4134_state {
 	struct regmap *regmap;
 	unsigned long sys_clk_hz;
 	struct gpio_desc *odr_gpio;
+	/*
+	 * Synchronize access to device state fields and ensure atomicity of
+	 * consecutive register access operations.
+	 */
+	struct mutex sync_lock;
 	int refin_mv;
 	/*
 	 * DMA (thus cache coherency maintenance) requires the transfer buffers
@@ -257,7 +264,9 @@ static int ad4134_read_raw(struct iio_dev *indio_dev,
 	int ret;
 
 	switch (info) {
-	case IIO_CHAN_INFO_RAW:
+	case IIO_CHAN_INFO_RAW: {
+		guard(mutex)(&st->sync_lock);
+
 		gpiod_set_value_cansleep(st->odr_gpio, 1);
 		/*
 		 * For slave mode gated DCLK (data sheet page 11), the minimum
@@ -276,6 +285,7 @@ static int ad4134_read_raw(struct iio_dev *indio_dev,
 			return ret;
 
 		return IIO_VAL_INT;
+	}
 	case IIO_CHAN_INFO_SCALE:
 		*val = st->refin_mv;
 		*val2 = AD4134_CHAN_PRECISION_BITS - 1;
@@ -445,6 +455,10 @@ static int ad4134_probe(struct spi_device *spi)
 	fsleep(AD4134_RESET_TIME_US);
 	crc8_populate_msb(ad4134_spi_crc_table, AD4134_SPI_CRC_POLYNOM);
 
+	ret = devm_mutex_init(dev, &st->sync_lock);
+	if (ret)
+		return ret;
+
 	st->regmap = devm_regmap_init(dev, NULL, st, &ad4134_regmap_config);
 	if (IS_ERR(st->regmap))
 		return dev_err_probe(dev, PTR_ERR(st->regmap),
-- 
2.53.0


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

* [PATCH v5 06/15] iio: adc: ad4134: Protect conventional device access from debug accesses
  2026-10-17  1:56 [PATCH v5 00/15] iio: adc: ad4134: Enable greater sample rate data capture Marcelo Schmitt
                   ` (4 preceding siblings ...)
  2026-10-17  1:57 ` [PATCH v5 05/15] iio: adc: ad4134: Serialize single-read operations Marcelo Schmitt
@ 2026-10-17  1:58 ` Marcelo Schmitt
  2026-10-17  1:58 ` [PATCH v5 07/15] iio: adc: ad4134: Run shorter transfers when CRC is disabled Marcelo Schmitt
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Marcelo Schmitt @ 2026-10-17  1:58 UTC (permalink / raw)
  To: linux-iio, devicetree, linux-kernel, linux
  Cc: jic23, nuno.sa, dlechner, andy, Michael.Hennerich, robh, krzk+dt,
	conor+dt, corbet, skhan, marcelo.schmitt1

Require debug access to acquire device synchronization locks before
allowing any transfer from the debug interface so to avoid disrupting
operations issued from usual (non-debug) interfaces.

Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
---
New patch in v5.

I'm not sure about this one and have no strong opinion about it.
Providing it according to suggestion from Nuno.
https://lore.kernel.org/linux-iio/179199692826.658576.4841754843069240356.b4-review@b4/
From previous discussions I guess this patch might not be welcome.
https://lore.kernel.org/linux-iio/20250421142359.11fb483f@jic23-huawei/
In that case, completely fine with it being dropped.

 drivers/iio/adc/ad4134.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c
index dc4d801490db..42a1272c2894 100644
--- a/drivers/iio/adc/ad4134.c
+++ b/drivers/iio/adc/ad4134.c
@@ -302,6 +302,12 @@ static int ad4134_debugfs_reg_access(struct iio_dev *indio_dev,
 {
 	struct ad4134_state *st = iio_priv(indio_dev);
 
+	IIO_DEV_ACQUIRE_DIRECT_MODE(indio_dev, claim);
+	if (IIO_DEV_ACQUIRE_FAILED(claim))
+		return -EBUSY;
+
+	guard(mutex)(&st->sync_lock);
+
 	if (readval)
 		return regmap_read(st->regmap, reg, readval);
 
-- 
2.53.0


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

* [PATCH v5 07/15] iio: adc: ad4134: Run shorter transfers when CRC is disabled
  2026-10-17  1:56 [PATCH v5 00/15] iio: adc: ad4134: Enable greater sample rate data capture Marcelo Schmitt
                   ` (5 preceding siblings ...)
  2026-10-17  1:58 ` [PATCH v5 06/15] iio: adc: ad4134: Protect conventional device access from debug accesses Marcelo Schmitt
@ 2026-10-17  1:58 ` Marcelo Schmitt
  2026-10-17  1:58 ` [PATCH v5 08/15] iio: adc: ad4134: Add support for digital filter type selection Marcelo Schmitt
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Marcelo Schmitt @ 2026-10-17  1:58 UTC (permalink / raw)
  To: linux-iio, devicetree, linux-kernel, linux
  Cc: jic23, nuno.sa, dlechner, andy, Michael.Hennerich, robh, krzk+dt,
	conor+dt, corbet, skhan, marcelo.schmitt1

When AD4134 has its SPI CRC feature enabled, one extra byte (the CRC code)
is sent through SPI for both ends to verify the integrity of data
transfers. Though, when CRC is not enabled, SPI transfers can be shorter.

Reviewed-by: Nuno Sá <nuno.sa@analog.com>
Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
---
 drivers/iio/adc/ad4134.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c
index 42a1272c2894..91a7c2107770 100644
--- a/drivers/iio/adc/ad4134.c
+++ b/drivers/iio/adc/ad4134.c
@@ -106,6 +106,7 @@ struct ad4134_state {
 	 */
 	struct mutex sync_lock;
 	int refin_mv;
+	bool crc_en;
 	/*
 	 * DMA (thus cache coherency maintenance) requires the transfer buffers
 	 * to live in their own cache lines.
@@ -159,7 +160,7 @@ static int ad4134_reg_write(void *context, unsigned int reg, unsigned int val)
 	struct spi_transfer xfer = {
 		.tx_buf = st->tx_buf,
 		.rx_buf = st->rx_buf,
-		.len = AD4134_SPI_MAX_XFER_LEN,
+		.len = st->crc_en ? AD4134_SPI_MAX_XFER_LEN : 2,
 	};
 	int ret;
 
@@ -169,7 +170,7 @@ static int ad4134_reg_write(void *context, unsigned int reg, unsigned int val)
 	if (ret)
 		return ret;
 
-	if (st->rx_buf[2] != st->tx_buf[2])
+	if (st->crc_en && st->rx_buf[2] != st->tx_buf[2])
 		dev_dbg(&st->spi->dev, "reg write CRC check failed\n");
 
 	return 0;
@@ -217,7 +218,7 @@ static int ad4134_register_read(struct ad4134_state *st, unsigned int reg,
 	struct spi_transfer xfer = {
 		.tx_buf = st->tx_buf,
 		.rx_buf = st->rx_buf,
-		.len = AD4134_SPI_MAX_XFER_LEN,
+		.len = st->crc_en ? AD4134_SPI_MAX_XFER_LEN : 2,
 	};
 	unsigned int inst;
 	int ret;
@@ -232,7 +233,7 @@ static int ad4134_register_read(struct ad4134_state *st, unsigned int reg,
 	*val = st->rx_buf[1];
 
 	/* Check CRC */
-	if (st->rx_buf[2] != st->tx_buf[2])
+	if (st->crc_en && st->rx_buf[2] != st->tx_buf[2])
 		dev_dbg(&st->spi->dev, "reg read CRC check failed\n");
 
 	return 0;
@@ -319,6 +320,7 @@ static int ad4134_min_io_mode_setup(struct ad4134_state *st)
 	struct device *dev = &st->spi->dev;
 	int ret;
 
+	st->crc_en = true; /* In minimum I/O mode CRC cannot be disabled */
 	st->odr_gpio = devm_gpiod_get(dev, "odr", GPIOD_OUT_LOW);
 	if (IS_ERR(st->odr_gpio))
 		return dev_err_probe(dev, PTR_ERR(st->odr_gpio),
-- 
2.53.0


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

* [PATCH v5 08/15] iio: adc: ad4134: Add support for digital filter type selection
  2026-10-17  1:56 [PATCH v5 00/15] iio: adc: ad4134: Enable greater sample rate data capture Marcelo Schmitt
                   ` (6 preceding siblings ...)
  2026-10-17  1:58 ` [PATCH v5 07/15] iio: adc: ad4134: Run shorter transfers when CRC is disabled Marcelo Schmitt
@ 2026-10-17  1:58 ` Marcelo Schmitt
  2026-10-17  2:16   ` sashiko-bot
  2026-10-17  1:59 ` [PATCH v5 09/15] iio: adc: ad4134: Support buffered data read Marcelo Schmitt
                   ` (6 subsequent siblings)
  14 siblings, 1 reply; 22+ messages in thread
From: Marcelo Schmitt @ 2026-10-17  1:58 UTC (permalink / raw)
  To: linux-iio, devicetree, linux-kernel, linux
  Cc: jic23, nuno.sa, dlechner, andy, Michael.Hennerich, robh, krzk+dt,
	conor+dt, corbet, skhan, marcelo.schmitt1

AD4134 supports four types of programmable digital filters that allow users
to choose between different output data rates and input bandwidths. Enable
basic digital filter configuration by providing a way to select which
filter type is activated for each channel.

Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
---
Change log v4 -> v5
- Re-arranged code so early function prototype declaration is no longer needed.

 drivers/iio/adc/ad4134.c | 93 ++++++++++++++++++++++++++++++++++------
 1 file changed, 81 insertions(+), 12 deletions(-)

diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c
index 91a7c2107770..b245001d4551 100644
--- a/drivers/iio/adc/ad4134.c
+++ b/drivers/iio/adc/ad4134.c
@@ -63,6 +63,9 @@
 #define AD4134_PW_DOWN_CTRL_REG			0x13
 #define AD4134_DEVICE_STATUS_REG		0x15
 #define AD4134_ODR_VAL_INT_LSB_REG		0x16
+#define AD4134_CHAN_DIG_FILTER_SEL_REG		0x1E
+#define AD4134_CHAN_DIG_FILTER_SEL_CH_MASK(ch)	(GENMASK(1, 0) << 2 * (ch))
+
 #define AD4134_CH3_OFFSET_MSB_REG		0x3E
 #define AD4134_AIN_OR_ERROR_REG			0x48
 
@@ -80,19 +83,18 @@
 #define AD4134_SPI_CRC_INIT_VALUE		0xA5
 static unsigned char ad4134_spi_crc_table[CRC8_TABLE_SIZE];
 
-#define AD4134_CHANNEL(_index) {						\
-	.type = IIO_VOLTAGE,							\
-	.indexed = 1,								\
-	.channel = (_index),							\
-	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),				\
-	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),			\
-}
+enum ad4134_filter_type {
+	AD4134_WIDEBAND,
+	AD4134_SINC6,
+	AD4134_SINC3,
+	AD4134_SINC3_REJ60,
+};
 
-static const struct iio_chan_spec ad4134_chan_set[] = {
-	AD4134_CHANNEL(0),
-	AD4134_CHANNEL(1),
-	AD4134_CHANNEL(2),
-	AD4134_CHANNEL(3),
+static const char * const ad4134_filt_names[] = {
+	[AD4134_WIDEBAND] = "wideband",
+	[AD4134_SINC6] = "sinc6",
+	[AD4134_SINC3] = "sinc3",
+	[AD4134_SINC3_REJ60] = "sinc3+rej60",
 };
 
 struct ad4134_state {
@@ -115,6 +117,73 @@ struct ad4134_state {
 	u8 tx_buf[AD4134_SPI_MAX_XFER_LEN];
 };
 
+static int ad4134_set_filter_type(struct iio_dev *indio_dev,
+				  struct iio_chan_spec const *chan,
+				  unsigned int val)
+{
+	struct ad4134_state *st = iio_priv(indio_dev);
+	unsigned int mask, reg_val;
+
+	IIO_DEV_ACQUIRE_DIRECT_MODE(indio_dev, claim);
+	if (IIO_DEV_ACQUIRE_FAILED(claim))
+		return -EBUSY;
+
+	guard(mutex)(&st->sync_lock);
+
+	mask = AD4134_CHAN_DIG_FILTER_SEL_CH_MASK(chan->channel);
+	reg_val = field_prep(mask, val);
+	return regmap_update_bits(st->regmap, AD4134_CHAN_DIG_FILTER_SEL_REG,
+				  mask, reg_val);
+}
+
+static int ad4134_get_filter_type(struct iio_dev *indio_dev,
+				  struct iio_chan_spec const *chan)
+{
+	struct ad4134_state *st = iio_priv(indio_dev);
+	unsigned int mask, reg_val;
+	int ret;
+
+	IIO_DEV_ACQUIRE_DIRECT_MODE(indio_dev, claim);
+	if (IIO_DEV_ACQUIRE_FAILED(claim))
+		return -EBUSY;
+
+	ret = regmap_read(st->regmap, AD4134_CHAN_DIG_FILTER_SEL_REG, &reg_val);
+	if (ret)
+		return ret;
+
+	mask = AD4134_CHAN_DIG_FILTER_SEL_CH_MASK(chan->channel);
+	return field_get(mask, reg_val);
+}
+
+static const struct iio_enum ad4134_filter_type_enum = {
+	.items = ad4134_filt_names,
+	.num_items = ARRAY_SIZE(ad4134_filt_names),
+	.get = ad4134_get_filter_type,
+	.set = ad4134_set_filter_type,
+};
+
+static const struct iio_chan_spec_ext_info ad4134_filter_type_ext_info[] = {
+	IIO_ENUM("filter_type", IIO_SEPARATE, &ad4134_filter_type_enum),
+	IIO_ENUM_AVAILABLE("filter_type", IIO_SEPARATE, &ad4134_filter_type_enum),
+	{ }
+};
+
+#define AD4134_CHANNEL(_index) {						\
+	.type = IIO_VOLTAGE,							\
+	.indexed = 1,								\
+	.channel = (_index),							\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),				\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),			\
+	.ext_info = ad4134_filter_type_ext_info,				\
+}
+
+static const struct iio_chan_spec ad4134_chan_set[] = {
+	AD4134_CHANNEL(0),
+	AD4134_CHANNEL(1),
+	AD4134_CHANNEL(2),
+	AD4134_CHANNEL(3),
+};
+
 static const struct regmap_range ad4134_regmap_rd_range[] = {
 	regmap_reg_range(AD4134_IFACE_CONFIG_A_REG, AD4134_SILICON_REV_REG),
 	regmap_reg_range(AD4134_SCRATCH_PAD_REG, AD4134_PW_DOWN_CTRL_REG),
-- 
2.53.0


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

* [PATCH v5 09/15] iio: adc: ad4134: Support buffered data read
  2026-10-17  1:56 [PATCH v5 00/15] iio: adc: ad4134: Enable greater sample rate data capture Marcelo Schmitt
                   ` (7 preceding siblings ...)
  2026-10-17  1:58 ` [PATCH v5 08/15] iio: adc: ad4134: Add support for digital filter type selection Marcelo Schmitt
@ 2026-10-17  1:59 ` Marcelo Schmitt
  2026-10-17  5:59   ` Joshua Crofts
  2026-10-17  1:59 ` [PATCH v5 10/15] dt-bindings: iio: adc: adi,ad4134: Document SPI connection mode Marcelo Schmitt
                   ` (5 subsequent siblings)
  14 siblings, 1 reply; 22+ messages in thread
From: Marcelo Schmitt @ 2026-10-17  1:59 UTC (permalink / raw)
  To: linux-iio, devicetree, linux-kernel, linux
  Cc: jic23, nuno.sa, dlechner, andy, Michael.Hennerich, robh, krzk+dt,
	conor+dt, corbet, skhan, marcelo.schmitt1

Enable users to run buffered data captures triggered by IIO trigger device.
Add an IIO timestamp channel so each data scan is provided with measurement
time information. Require single-read operations to be in IIO device direct
access mode to prevent buffered and single-shot data captures to disrupt
each other.

Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
---
Change log v4 -> v5
- Now using iio_for_each_active_channel() to iterate over IIO channels.

 drivers/iio/adc/Kconfig  |  2 ++
 drivers/iio/adc/ad4134.c | 61 ++++++++++++++++++++++++++++++++++++++--
 2 files changed, 61 insertions(+), 2 deletions(-)

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 02de4809ae31..d625f36a0283 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -125,6 +125,8 @@ config AD4134
 	depends on SPI
 	select REGMAP_SPI
 	select CRC8
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
 	help
 	  Say yes here to build support for Analog Devices AD4134 SPI analog to
 	  digital converters (ADC).
diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c
index b245001d4551..eaf5bb55f25b 100644
--- a/drivers/iio/adc/ad4134.c
+++ b/drivers/iio/adc/ad4134.c
@@ -26,7 +26,10 @@
 #include <linux/unaligned.h>
 #include <linux/units.h>
 
+#include <linux/iio/buffer.h>
 #include <linux/iio/iio.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/trigger_consumer.h>
 
 #define AD4134_RESET_TIME_US			(10 * USEC_PER_SEC)
 
@@ -113,7 +116,7 @@ struct ad4134_state {
 	 * DMA (thus cache coherency maintenance) requires the transfer buffers
 	 * to live in their own cache lines.
 	 */
-	u8 rx_buf[AD4134_SPI_MAX_XFER_LEN] __aligned(IIO_DMA_MINALIGN);
+	u8 rx_buf[AD4134_SPI_MAX_XFER_LEN * AD4134_NUM_CHANNELS] __aligned(IIO_DMA_MINALIGN);
 	u8 tx_buf[AD4134_SPI_MAX_XFER_LEN];
 };
 
@@ -175,6 +178,13 @@ static const struct iio_chan_spec_ext_info ad4134_filter_type_ext_info[] = {
 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),				\
 	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),			\
 	.ext_info = ad4134_filter_type_ext_info,				\
+	.scan_index = (_index),							\
+	.scan_type = {								\
+		.format = IIO_SCAN_FORMAT_SIGNED_INT,				\
+		.realbits = AD4134_CHAN_PRECISION_BITS,				\
+		.storagebits = 32,						\
+		.endianness = IIO_CPU,						\
+	},									\
 }
 
 static const struct iio_chan_spec ad4134_chan_set[] = {
@@ -182,6 +192,7 @@ static const struct iio_chan_spec ad4134_chan_set[] = {
 	AD4134_CHANNEL(1),
 	AD4134_CHANNEL(2),
 	AD4134_CHANNEL(3),
+	IIO_CHAN_SOFT_TIMESTAMP(4),
 };
 
 static const struct regmap_range ad4134_regmap_rd_range[] = {
@@ -262,7 +273,7 @@ static int ad4134_data_read(struct ad4134_state *st, unsigned int reg,
 	 * interface. Now we read data from all channels but keep only the bits
 	 * from the requested one.
 	 */
-	for (i = 0; i < ARRAY_SIZE(ad4134_chan_set); i++) {
+	for (i = 0; i < AD4134_NUM_CHANNELS; i++) {
 		ret = spi_write_then_read(st->spi, NULL, 0, st->rx_buf,
 					  BITS_TO_BYTES(AD4134_CHAN_PRECISION_BITS));
 		if (ret)
@@ -326,6 +337,41 @@ static const struct regmap_config ad4134_regmap_config = {
 	.max_register = AD4134_CH_VREG(AD4134_NUM_CHANNELS - 1),
 };
 
+static irqreturn_t ad4134_trigger_handler(int irq, void *p)
+{
+	IIO_DECLARE_BUFFER_WITH_TS(u32, channels, AD4134_NUM_CHANNELS) = { };
+	unsigned int chan_bytes = BITS_TO_BYTES(AD4134_CHAN_PRECISION_BITS);
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct ad4134_state *st = iio_priv(indio_dev);
+	struct spi_transfer xfer = {
+		.rx_buf = st->rx_buf,
+		.cs_off = true,
+		.len = chan_bytes * AD4134_NUM_CHANNELS,
+	};
+	unsigned int ch, i = 0;
+	int ret;
+
+	gpiod_set_value_cansleep(st->odr_gpio, 1);
+	fsleep(1);
+	gpiod_set_value_cansleep(st->odr_gpio, 0);
+
+	/* Run enough DCLK cycles to match the data frame length. */
+	ret = spi_sync_transfer(st->spi, &xfer, 1);
+	if (ret)
+		goto out;
+
+	iio_for_each_active_channel(indio_dev, ch)
+		channels[i++] = get_unaligned_be24(&st->rx_buf[ch * chan_bytes]);
+
+	iio_push_to_buffers_with_ts(indio_dev, channels, sizeof(channels),
+				    pf->timestamp);
+
+out:
+	iio_trigger_notify_done(indio_dev->trig);
+	return IRQ_HANDLED;
+}
+
 static int ad4134_read_raw(struct iio_dev *indio_dev,
 			   struct iio_chan_spec const *chan,
 			   int *val, int *val2, long info)
@@ -335,6 +381,10 @@ static int ad4134_read_raw(struct iio_dev *indio_dev,
 
 	switch (info) {
 	case IIO_CHAN_INFO_RAW: {
+		IIO_DEV_ACQUIRE_DIRECT_MODE(indio_dev, claim);
+		if (IIO_DEV_ACQUIRE_FAILED(claim))
+			return -EBUSY;
+
 		guard(mutex)(&st->sync_lock);
 
 		gpiod_set_value_cansleep(st->odr_gpio, 1);
@@ -546,6 +596,13 @@ static int ad4134_probe(struct spi_device *spi)
 		return dev_err_probe(dev, ret,
 				     "failed to setup minimum I/O mode\n");
 
+	ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
+					      iio_pollfunc_store_time,
+					      ad4134_trigger_handler,
+					      NULL);
+	if (ret)
+		return ret;
+
 	/* Bump precision to 24-bit */
 	ret = regmap_update_bits(st->regmap, AD4134_DATA_PACKET_CONFIG_REG,
 				 AD4134_DATA_PACKET_CONFIG_FRAME_MASK,
-- 
2.53.0


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

* [PATCH v5 10/15] dt-bindings: iio: adc: adi,ad4134: Document SPI connection mode
  2026-10-17  1:56 [PATCH v5 00/15] iio: adc: ad4134: Enable greater sample rate data capture Marcelo Schmitt
                   ` (8 preceding siblings ...)
  2026-10-17  1:59 ` [PATCH v5 09/15] iio: adc: ad4134: Support buffered data read Marcelo Schmitt
@ 2026-10-17  1:59 ` Marcelo Schmitt
  2026-10-17  1:59 ` [PATCH v5 11/15] dt-bindings: iio: adc: adi,ad4134: Document external multiplexer usage Marcelo Schmitt
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Marcelo Schmitt @ 2026-10-17  1:59 UTC (permalink / raw)
  To: linux-iio, devicetree, linux-kernel, linux
  Cc: jic23, nuno.sa, dlechner, andy, Michael.Hennerich, robh, krzk+dt,
	conor+dt, corbet, skhan, marcelo.schmitt1, Conor Dooley

Document how AD4134 chips are connected to the host SPI controller
according to different wiring configurations.

Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
---
No changes in v5.

 .../bindings/iio/adc/adi,ad4134.yaml          | 57 ++++++++++++++++---
 1 file changed, 50 insertions(+), 7 deletions(-)

diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml
index ea6d7e026419..970e7adb2405 100644
--- a/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml
@@ -131,6 +131,26 @@ properties:
     enum: [ free-running, gated ]
     default: gated
 
+  adi,spi-mode:
+    $ref: /schemas/types.yaml#/definitions/string
+    enum: [ no-cs, 4-wire, one-channel-chain, two-channel-chain ]
+    default: no-cs
+    description: |
+      This property indicates the SPI wiring configuration.
+      * no-cs: The datasheet calls this "minimum I/O mode". In this mode, the CS
+        line is not used (tied to GND).
+      * 4-wire: Specifies a conventional SPI wiring configuration.
+      * one-channel-chain: In this mode, the DOUT0 line of one chip is connected
+        to DOUT2 of the next chip upstream in the chain. Only the data interface
+        of the upmost device in the stream is in direct connection with the
+        digital host.
+      * two-channel-chain: In this mode, the DOUT0 and DOUT1 lines of one chip
+        are respectively connected to DOUT2 and DOUT3 of the next chip upstream
+        in the chain. Only the data interface of the upmost device in the stream
+        is in direct connection with the digital host.
+
+  '#daisy-chained-devices': true
+
 required:
   - compatible
   - reg
@@ -141,13 +161,36 @@ required:
   - clocks
   - clock-names
 
-oneOf:
-  - required:
-      - ldoin-supply
-  - required:
-      - avdd1v8-supply
-      - dvdd1v8-supply
-      - clkvdd-supply
+allOf:
+  - oneOf:
+      - required:
+          - ldoin-supply
+      - required:
+          - avdd1v8-supply
+          - dvdd1v8-supply
+          - clkvdd-supply
+
+  - oneOf:
+      - required: ['adi,spi-mode', '#daisy-chained-devices']
+        properties:
+          adi,spi-mode:
+            const: one-channel-chain
+          spi-rx-bus-width:
+            const: 1
+      - required: ['adi,spi-mode', '#daisy-chained-devices']
+        properties:
+          adi,spi-mode:
+            const: two-channel-chain
+          spi-rx-bus-width:
+            items:
+              - const: 1
+              - const: 1
+      - properties:
+          '#daisy-chained-devices': false
+          adi,spi-mode:
+            enum:
+              - no-cs
+              - 4-wire
 
 unevaluatedProperties: false
 
-- 
2.53.0


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

* [PATCH v5 11/15] dt-bindings: iio: adc: adi,ad4134: Document external multiplexer usage
  2026-10-17  1:56 [PATCH v5 00/15] iio: adc: ad4134: Enable greater sample rate data capture Marcelo Schmitt
                   ` (9 preceding siblings ...)
  2026-10-17  1:59 ` [PATCH v5 10/15] dt-bindings: iio: adc: adi,ad4134: Document SPI connection mode Marcelo Schmitt
@ 2026-10-17  1:59 ` Marcelo Schmitt
  2026-10-17  1:59 ` [PATCH v5 12/15] iio: adc: ad4134: Support SPI 4-wire mode Marcelo Schmitt
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 22+ messages in thread
From: Marcelo Schmitt @ 2026-10-17  1:59 UTC (permalink / raw)
  To: linux-iio, devicetree, linux-kernel, linux
  Cc: jic23, nuno.sa, dlechner, andy, Michael.Hennerich, robh, krzk+dt,
	conor+dt, corbet, skhan, marcelo.schmitt1

The AD4134 design has two data interfaces. One interface allows register
access for device configuration while the other (separate interface)
provides ADC sample data. One way of handling both peripheral interfaces is
to merge them into a single SPI interface by switching between register
access and sample access according to device user requests. Though, such
solution requires extra hardware, external to the ADC chip. The access mode
switch can be done with an external multiplexer selecting either AD4134 SDO
or AD4134 DOUT0 to connect to the controller. The external multiplexer
becomes part of hardware requested for AD4134 device operation and thus
must be provided for operating the peripheral in such merged interface
schema. Still, there are alternative ways of handling the two AD4134 data
interfaces so the multiplexer is not always required.

Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
---
No changes in v5.

Detailed reasoning for the external multiplexer usage.

Before coming to the current solution, the following configuration was tried.

  +-----------------------+                           +-----------------+
  |       AD4134          |                           | SPI Controller  |
  |                       |                           |                 |
  | SPI interface    SCLK |<--------------------------| SCLK            |
  | for register       CS |<--------------------------| CS              |
  | access            SDI |<--------------------------| SDO             |
  |                   SDO |---+                       |                 |
  |                       |   |                       |                 |
  | Data interface  DOUT0 |---+---------------------->| SDI0            |
  | for ADC sample  DOUT1 |-------------------------->| SDI1            |
  | data read       DOUT2 |-------------------------->| SDI2            |
  |                 DOUT3 |-------------------------->| SDI3            |
  |                 DCLK  |<--------------------------| DCLK
  |                 ODR   |<------------------+    +->| Offload Trigger |
  +-----------------------+                   |    |  +-----------------+
                                              |    +--| PWM1            |
                                              +-------| PWM0            |
                                                      +-----------------+

Though, because DOUT0 never goes high-Z, the DOUT0 pin keeps driving the data
line, causing register reads to fail.

Alternatively, we could have something like

  +-----------------------+                           +-----------------+
  |       AD4134          |                           | SPI Controller  |
  |                       |                           |                 |
  | SPI interface    SCLK |<--------------------------| SCLK            |
  | for register       CS |<--------------------------| CS              |
  | access            SDI |<--------------------------| SDO             |
  |                   SDO |-------------------------->| SDI0            |
  |                       |                           |                 |
  | Data interface  DOUT0 |-------------------------->| SDI1            |
  | for ADC sample  DOUT1 |-------------------------->| SDI2            |
  | data read       DOUT2 |-------------------------->| SDI3            |
  |                 DOUT3 |-------------------------->| SDI4            |
  |                 DCLK  |<--------------------------| DCLK
  |                 ODR   |<------------------+    +->| Offload Trigger |
  +-----------------------+                   |    |  +-----------------+
                                              |    +--| PWM1            |
                                              +-------| PWM0            |
                                                      +-----------------+

The downside of the above is the peripheral would need fine-grained config of
controller SDI lines to only read SDI0 for register access, and only read SDI1,
SDI2, SDI3, SDI4 for ADC sample data (currently available
SPI_MULTI_LANE_MODE_STRIPE reads from all SDI lines).

The currently proposed solution looks like the following

  +-----------------------+                         +-----------------+
  |         AD4134        |                         | SPI Controller  |
  |                       |                         |                 |
  | SPI interface    SCLK |<------------------------| SCLK            |
  | for register       CS |<------------------------| CS              |
  | access            SDI |<------------------------| SDO             |
  |                   SDO |------->|¯¯¯¯\           |                 |
  |                       |        |MUX  >--------->| SDI0            |
  | Data interface  DOUT0 |------->|____/           |                 |
  | for ADC sample        |          ^              |                 |
  | data read       DOUT1 |------------------------>| SDI1            |
  |                 DOUT2 |------------------------>| SDI2            |
  |                 DOUT3 |------------------------>| SDI3            |
  |                  DCLK |<------------------------| DCLK            |
  |                   ODR |<----------------+    +->| Offload Trigger |
  +-----------------------+          |      |    |  +-----------------+
                                     |      |    +--| PWM1            |
                                     |      +-------| PWM0            |
                                     +--------------| GPIO            |
                                                    +-----------------+

By being able to mux between AD4134 SDO and AD4134 DOUT0, the peripheral can be
connected to a single bus such that controllers able to read from multiple lines
will be able to gather ADC sample data from all SDI lines (SPI_MULTI_LANE_MODE_STRIPE).
With that, AD4134 maximum data throughput can be supported with what is already
available from the SPI core. See additional details on the AD4134 IIO
documentation (patch 15).

Yet another possibility would be to have the peripheral sitting in two buses.

  +-----------------------+                           +-----------------+
  |       AD4134          |                           | SPI Controller A|
  |                       |                           |                 |
  | SPI interface    SCLK |<--------------------------| SCLK            |
  | for register       CS |<--------------------------| CS              |
  | access            SDI |<--------------------------| SDO             |
  |                   SDO |-------------------------->| SDI             |
  |                       |                           +-----------------+
  |                       |                           | SPI Controller B|
  |                       |                           |                 |
  | Data interface  DOUT0 |-------------------------->| SDI0            |
  | for ADC sample  DOUT1 |-------------------------->| SDI1            |
  | data read       DOUT2 |-------------------------->| SDI2            |
  |                 DOUT3 |-------------------------->| SDI3            |
  |                 DCLK  |<--------------------------| DCLK            |
  |                 ODR   |<------------------+    +->| Offload Trigger |
  +-----------------------+                   |    |  +-----------------+
                                              |    +--| PWM1            |
                                              +-------| PWM0            |
                                                      +-----------------+

That may be a fallback option if what's currently being proposed fails to comply
to Linux code standards.



 .../bindings/iio/adc/adi,ad4134.yaml          | 47 +++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml
index 970e7adb2405..c70b9113cd67 100644
--- a/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml
@@ -104,6 +104,20 @@ properties:
       GPIO connected to ODR pin. Used to sample ADC data in minimum I/O mode.
     maxItems: 1
 
+  mux-states:
+    description:
+      mux controller node to route SDO and DOUT0 signals from peripheral to
+      controller.
+    maxItems: 2
+
+  mux-state-names:
+    description:
+      mux state names for routing SDO and DOUT0 signals from peripheral to
+      controller.
+    items:
+      - const: data_read
+      - const: reg_access
+
   adi,asrc-mode:
     $ref: /schemas/types.yaml#/definitions/string
     description:
@@ -231,4 +245,37 @@ examples:
 
         };
     };
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+
+    spi {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        adc@0 {
+            compatible = "adi,ad4134";
+            reg = <0>;
+
+            spi-max-frequency = <1000000>;
+
+            reset-gpios = <&gpio0 86 GPIO_ACTIVE_LOW>;
+            powerdown-gpios = <&gpio0 88 GPIO_ACTIVE_LOW>;
+
+            clocks = <&sys_clk>;
+            clock-names = "clkin";
+
+            avdd5-supply = <&avdd5>;
+            dvdd5-supply = <&dvdd5>;
+            iovdd-supply = <&iovdd>;
+            refin-supply = <&refin>;
+            avdd1v8-supply = <&avdd1v8>;
+            dvdd1v8-supply = <&dvdd1v8>;
+            clkvdd-supply = <&clkvdd>;
+
+            mux-states = <&ad4134_sdo_dout0_mux 0>, <&ad4134_sdo_dout0_mux 1>;
+            mux-state-names = "data_read", "reg_access";
+
+            adi,spi-mode = "4-wire";
+        };
+    };
 ...
-- 
2.53.0


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

* [PATCH v5 12/15] iio: adc: ad4134: Support SPI 4-wire mode
  2026-10-17  1:56 [PATCH v5 00/15] iio: adc: ad4134: Enable greater sample rate data capture Marcelo Schmitt
                   ` (10 preceding siblings ...)
  2026-10-17  1:59 ` [PATCH v5 11/15] dt-bindings: iio: adc: adi,ad4134: Document external multiplexer usage Marcelo Schmitt
@ 2026-10-17  1:59 ` Marcelo Schmitt
  2026-10-17  2:19   ` sashiko-bot
  2026-10-17  2:00 ` [PATCH v5 13/15] dt-bindings: iio: adc: adi,ad4134: Document PWM usage Marcelo Schmitt
                   ` (2 subsequent siblings)
  14 siblings, 1 reply; 22+ messages in thread
From: Marcelo Schmitt @ 2026-10-17  1:59 UTC (permalink / raw)
  To: linux-iio, devicetree, linux-kernel, linux
  Cc: jic23, nuno.sa, dlechner, andy, Michael.Hennerich, robh, krzk+dt,
	conor+dt, corbet, skhan, marcelo.schmitt1

AD4134 devices can be wired in a few different ways. So far, only minimum
I/O mode was supported. While minimum I/O mode allows interfacing with
AD4134 with a reduced number of wires, that wiring configuration is not
suitable for high-throughput data acquisition.

Extend AD4134 support to enable interfacing in SPI 4-wire configuration.

Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
---
Change log v4 -> v5
- Updated adi,spi-mode property handling.
- No longer selecting/deselecting multiplexer states when in minimum I/O mode.

Detailed reasoning for the external multiplexer usage.

Before coming to the current solution, the following configuration was tried.

  +-----------------------+                           +-----------------+
  |       AD4134          |                           | SPI Controller  |
  |                       |                           |                 |
  | SPI interface    SCLK |<--------------------------| SCLK            |
  | for register       CS |<--------------------------| CS              |
  | access            SDI |<--------------------------| SDO             |
  |                   SDO |---+                       |                 |
  |                       |   |                       |                 |
  | Data interface  DOUT0 |---+---------------------->| SDI0            |
  | for ADC sample  DOUT1 |-------------------------->| SDI1            |
  | data read       DOUT2 |-------------------------->| SDI2            |
  |                 DOUT3 |-------------------------->| SDI3            |
  |                 DCLK  |<--------------------------| DCLK
  |                 ODR   |<------------------+    +->| Offload Trigger |
  +-----------------------+                   |    |  +-----------------+
                                              |    +--| PWM1            |
                                              +-------| PWM0            |
                                                      +-----------------+

Though, because DOUT0 never goes high-Z, the DOUT0 pin keeps driving the data
line, causing register reads to fail.

Alternatively, we could have something like

  +-----------------------+                           +-----------------+
  |       AD4134          |                           | SPI Controller  |
  |                       |                           |                 |
  | SPI interface    SCLK |<--------------------------| SCLK            |
  | for register       CS |<--------------------------| CS              |
  | access            SDI |<--------------------------| SDO             |
  |                   SDO |-------------------------->| SDI0            |
  |                       |                           |                 |
  | Data interface  DOUT0 |-------------------------->| SDI1            |
  | for ADC sample  DOUT1 |-------------------------->| SDI2            |
  | data read       DOUT2 |-------------------------->| SDI3            |
  |                 DOUT3 |-------------------------->| SDI4            |
  |                 DCLK  |<--------------------------| DCLK
  |                 ODR   |<------------------+    +->| Offload Trigger |
  +-----------------------+                   |    |  +-----------------+
                                              |    +--| PWM1            |
                                              +-------| PWM0            |
                                                      +-----------------+

The downside of the above is the peripheral would need fine-grained config of
controller SDI lines to only read SDI0 for register access, and only read SDI1,
SDI2, SDI3, SDI4 for ADC sample data (currently available
SPI_MULTI_LANE_MODE_STRIPE reads from all SDI lines).

The currently proposed solution looks like the following

  +-----------------------+                         +-----------------+
  |         AD4134        |                         | SPI Controller  |
  |                       |                         |                 |
  | SPI interface    SCLK |<------------------------| SCLK            |
  | for register       CS |<------------------------| CS              |
  | access            SDI |<------------------------| SDO             |
  |                   SDO |------->|¯¯¯¯\           |                 |
  |                       |        |MUX  >--------->| SDI0            |
  | Data interface  DOUT0 |------->|____/           |                 |
  | for ADC sample        |          ^              |                 |
  | data read       DOUT1 |------------------------>| SDI1            |
  |                 DOUT2 |------------------------>| SDI2            |
  |                 DOUT3 |------------------------>| SDI3            |
  |                  DCLK |<------------------------| DCLK            |
  |                   ODR |<----------------+    +->| Offload Trigger |
  +-----------------------+          |      |    |  +-----------------+
                                     |      |    +--| PWM1            |
                                     |      +-------| PWM0            |
                                     +--------------| GPIO            |
                                                    +-----------------+

By being able to mux between AD4134 SDO and AD4134 DOUT0, the peripheral can be
connected to a single bus such that controllers able to read from multiple lines
will be able to gather ADC sample data from all SDI lines (SPI_MULTI_LANE_MODE_STRIPE).
With that, AD4134 maximum data throughput can be supported with what is already
available from the SPI core. See additional details on the AD4134 IIO
documentation (patch 15).

Yet another possibility would be to have the peripheral sitting in two buses.

  +-----------------------+                           +-----------------+
  |       AD4134          |                           | SPI Controller A|
  |                       |                           |                 |
  | SPI interface    SCLK |<--------------------------| SCLK            |
  | for register       CS |<--------------------------| CS              |
  | access            SDI |<--------------------------| SDO             |
  |                   SDO |-------------------------->| SDI             |
  |                       |                           +-----------------+
  |                       |                           | SPI Controller B|
  |                       |                           |                 |
  | Data interface  DOUT0 |-------------------------->| SDI0            |
  | for ADC sample  DOUT1 |-------------------------->| SDI1            |
  | data read       DOUT2 |-------------------------->| SDI2            |
  |                 DOUT3 |-------------------------->| SDI3            |
  |                 DCLK  |<--------------------------| DCLK            |
  |                 ODR   |<------------------+    +->| Offload Trigger |
  +-----------------------+                   |    |  +-----------------+
                                              |    +--| PWM1            |
                                              +-------| PWM0            |
                                                      +-----------------+

That may be a fallback option if what's currently being proposed fails to comply
to Linux code standards.


 drivers/iio/adc/Kconfig  |   1 +
 drivers/iio/adc/ad4134.c | 221 +++++++++++++++++++++++++++++++++++----
 2 files changed, 204 insertions(+), 18 deletions(-)

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index d625f36a0283..10f3c804df9a 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -127,6 +127,7 @@ config AD4134
 	select CRC8
 	select IIO_BUFFER
 	select IIO_TRIGGERED_BUFFER
+	select MULTIPLEXER
 	help
 	  Say yes here to build support for Analog Devices AD4134 SPI analog to
 	  digital converters (ADC).
diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c
index eaf5bb55f25b..6b05e40f7aeb 100644
--- a/drivers/iio/adc/ad4134.c
+++ b/drivers/iio/adc/ad4134.c
@@ -17,6 +17,8 @@
 #include <linux/gpio/consumer.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/mux/consumer.h>
+#include <linux/property.h>
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/reset.h>
@@ -72,6 +74,9 @@
 #define AD4134_CH3_OFFSET_MSB_REG		0x3E
 #define AD4134_AIN_OR_ERROR_REG			0x48
 
+#define AD4134_SDO_INPUT			0
+#define AD4134_DOUT0_INPUT			1
+
 /*
  * AD4134 register map ends at address 0x48 and there is no register for
  * retrieving ADC sample data. Though, to make use of Linux regmap API both
@@ -86,6 +91,17 @@
 #define AD4134_SPI_CRC_INIT_VALUE		0xA5
 static unsigned char ad4134_spi_crc_table[CRC8_TABLE_SIZE];
 
+enum ad4134_spi_mode {
+	AD4134_SPI_MODE_NO_CS, /* datasheet calls this "minimum I/O mode" */
+	AD4134_SPI_MODE_4_WIRE,
+};
+
+/* maps adi,spi-mode property value to enum */
+static const char * const ad4134_spi_modes[] = {
+	[AD4134_SPI_MODE_NO_CS] = "no-cs",
+	[AD4134_SPI_MODE_4_WIRE] = "4-wire",
+};
+
 enum ad4134_filter_type {
 	AD4134_WIDEBAND,
 	AD4134_SINC6,
@@ -110,6 +126,8 @@ struct ad4134_state {
 	 * consecutive register access operations.
 	 */
 	struct mutex sync_lock;
+	struct mux_state *mux_st[2]; /* For external multiplexer control */
+	enum ad4134_spi_mode spi_mode;
 	int refin_mv;
 	bool crc_en;
 	/*
@@ -219,6 +237,85 @@ static const struct regmap_access_table ad4134_regmap_wr_table = {
 	.n_yes_ranges = ARRAY_SIZE(ad4134_regmap_wr_range),
 };
 
+/*
+ * When operating in modes other than minimum I/O mode, AD4134 register data on
+ * the SDO line is sampled on SCLK rising edge (SPI mode 0). In addition to
+ * that, when AD4134 SDO and DOUT0 pins are multiplexed by hardware OUTSIDE
+ * AD4134 SILICON, the multiplexer state must be set to route SDO to the SPI
+ * controller. With both SPI mode and multiplexer state properly set, register
+ * access runs as usual. Successful calls to this function must be balanced with
+ * calls to ad4134_release_reg_access() so to release the mux state lock. See
+ * AD4134 IIO documentation for details.
+ */
+static int ad4134_claim_reg_access(struct ad4134_state *st)
+{
+	unsigned int cur_mode = st->spi->mode & SPI_MODE_X_MASK;
+	int ret;
+
+	if (st->spi_mode != AD4134_SPI_MODE_NO_CS && cur_mode != SPI_MODE_0) {
+		st->spi->mode &= ~SPI_MODE_X_MASK;
+		st->spi->mode |= SPI_MODE_0;
+		ret = spi_setup(st->spi);
+		if (ret)
+			return ret;
+	}
+
+	if (st->spi_mode != AD4134_SPI_MODE_NO_CS && st->mux_st[AD4134_SDO_INPUT])
+		return mux_state_select(st->mux_st[AD4134_SDO_INPUT]);
+
+	return 0;
+}
+
+/*
+ * Must be balanced with successful calls to ad4134_claim_reg_access().
+ */
+static int ad4134_release_reg_access(struct ad4134_state *st)
+{
+	if (st->spi_mode != AD4134_SPI_MODE_NO_CS && st->mux_st[AD4134_SDO_INPUT])
+		return mux_state_deselect(st->mux_st[AD4134_SDO_INPUT]);
+
+	return 0;
+}
+
+/*
+ * When operating in modes other than minimum I/O mode, AD4134 ADC sample data
+ * on the DOUT lines is sampled on SCLK falling edge (SPI mode 1). In addition
+ * to that, when AD4134 SDO and DOUT0 pins are multiplexed by hardware OUTSIDE
+ * AD4134 SILICON, the multiplexer state must be set to route DOUT0 to the SPI
+ * controller. With both SPI mode and multiplexer state properly set, ADC
+ * samples can be read normally. Successful call to this function must be paired
+ * with a call to ad4134_release_sample_access().
+ */
+static int ad4134_claim_sample_access(struct ad4134_state *st)
+{
+	unsigned int cur_mode = st->spi->mode & SPI_MODE_X_MASK;
+	int ret;
+
+	if (st->spi_mode != AD4134_SPI_MODE_NO_CS && cur_mode != SPI_MODE_1) {
+		st->spi->mode &= ~SPI_MODE_X_MASK;
+		st->spi->mode |= SPI_MODE_1;
+		ret = spi_setup(st->spi);
+		if (ret)
+			return ret;
+	}
+
+	if (st->spi_mode != AD4134_SPI_MODE_NO_CS && st->mux_st[AD4134_DOUT0_INPUT])
+		return mux_state_select(st->mux_st[AD4134_DOUT0_INPUT]);
+
+	return 0;
+}
+
+/*
+ * Must be balanced with successful calls to ad4134_claim_sample_access().
+ */
+static int ad4134_release_sample_access(struct ad4134_state *st)
+{
+	if (st->spi_mode != AD4134_SPI_MODE_NO_CS && st->mux_st[AD4134_DOUT0_INPUT])
+		return mux_state_deselect(st->mux_st[AD4134_DOUT0_INPUT]);
+
+	return 0;
+}
+
 static int ad4134_calc_spi_crc(u8 inst, u8 data)
 {
 	u8 buf[] = { inst, data };
@@ -242,18 +339,27 @@ static int ad4134_reg_write(void *context, unsigned int reg, unsigned int val)
 		.rx_buf = st->rx_buf,
 		.len = st->crc_en ? AD4134_SPI_MAX_XFER_LEN : 2,
 	};
-	int ret;
+	int access_ret, ret;
+
+	ret = ad4134_claim_reg_access(st);
+	if (ret)
+		return ret;
 
 	ad4134_prepare_spi_tx_buf(reg, val, st->tx_buf);
 
 	ret = spi_sync_transfer(st->spi, &xfer, 1);
 	if (ret)
-		return ret;
+		goto out_write_release;
 
 	if (st->crc_en && st->rx_buf[2] != st->tx_buf[2])
 		dev_dbg(&st->spi->dev, "reg write CRC check failed\n");
 
-	return 0;
+out_write_release:
+	access_ret = ad4134_release_reg_access(st);
+	if (access_ret)
+		dev_err(&st->spi->dev, "error on access release: %d\n", access_ret);
+
+	return ret;
 }
 
 static int ad4134_data_read(struct ad4134_state *st, unsigned int reg,
@@ -261,7 +367,11 @@ static int ad4134_data_read(struct ad4134_state *st, unsigned int reg,
 {
 	unsigned int i;
 	u32 sample = 0;
-	int ret;
+	int access_ret, ret;
+
+	ret = ad4134_claim_sample_access(st);
+	if (ret)
+		return ret;
 
 	/*
 	 * To be able to read data from all 4 channels through a single line, we
@@ -277,7 +387,7 @@ static int ad4134_data_read(struct ad4134_state *st, unsigned int reg,
 		ret = spi_write_then_read(st->spi, NULL, 0, st->rx_buf,
 					  BITS_TO_BYTES(AD4134_CHAN_PRECISION_BITS));
 		if (ret)
-			return ret;
+			goto out_data_read_release;
 
 		/*
 		 * AD4134 has a built-in feature that flags when data transfers
@@ -289,7 +399,12 @@ static int ad4134_data_read(struct ad4134_state *st, unsigned int reg,
 	}
 	*val = sign_extend32(sample, AD4134_CHAN_PRECISION_BITS - 1);
 
-	return 0;
+out_data_read_release:
+	access_ret = ad4134_release_sample_access(st);
+	if (access_ret)
+		dev_err(&st->spi->dev, "error on access release: %d\n", access_ret);
+
+	return ret;
 }
 
 static int ad4134_register_read(struct ad4134_state *st, unsigned int reg,
@@ -301,14 +416,18 @@ static int ad4134_register_read(struct ad4134_state *st, unsigned int reg,
 		.len = st->crc_en ? AD4134_SPI_MAX_XFER_LEN : 2,
 	};
 	unsigned int inst;
-	int ret;
+	int access_ret, ret;
+
+	ret = ad4134_claim_reg_access(st);
+	if (ret)
+		return ret;
 
 	inst = AD4134_REG_READ_MASK | reg;
 	ad4134_prepare_spi_tx_buf(inst, 0, st->tx_buf);
 
 	ret = spi_sync_transfer(st->spi, &xfer, 1);
 	if (ret)
-		return ret;
+		goto out_read_release;
 
 	*val = st->rx_buf[1];
 
@@ -316,7 +435,12 @@ static int ad4134_register_read(struct ad4134_state *st, unsigned int reg,
 	if (st->crc_en && st->rx_buf[2] != st->tx_buf[2])
 		dev_dbg(&st->spi->dev, "reg read CRC check failed\n");
 
-	return 0;
+out_read_release:
+	access_ret = ad4134_release_reg_access(st);
+	if (access_ret)
+		dev_err(&st->spi->dev, "error on access release: %d\n", access_ret);
+
+	return ret;
 }
 
 static int ad4134_reg_read(void *context, unsigned int reg, unsigned int *val)
@@ -372,6 +496,21 @@ static irqreturn_t ad4134_trigger_handler(int irq, void *p)
 	return IRQ_HANDLED;
 }
 
+static int ad4134_buffer_postenable(struct iio_dev *indio_dev)
+{
+	return ad4134_claim_sample_access(iio_priv(indio_dev));
+}
+
+static int ad4134_buffer_predisable(struct iio_dev *indio_dev)
+{
+	return ad4134_release_sample_access(iio_priv(indio_dev));
+}
+
+static const struct iio_buffer_setup_ops ad4134_buffer_setup_ops = {
+	.postenable = &ad4134_buffer_postenable,
+	.predisable = &ad4134_buffer_predisable,
+};
+
 static int ad4134_read_raw(struct iio_dev *indio_dev,
 			   struct iio_chan_spec const *chan,
 			   int *val, int *val2, long info)
@@ -440,11 +579,6 @@ static int ad4134_min_io_mode_setup(struct ad4134_state *st)
 	int ret;
 
 	st->crc_en = true; /* In minimum I/O mode CRC cannot be disabled */
-	st->odr_gpio = devm_gpiod_get(dev, "odr", GPIOD_OUT_LOW);
-	if (IS_ERR(st->odr_gpio))
-		return dev_err_probe(dev, PTR_ERR(st->odr_gpio),
-				     "failed to get ODR GPIO\n");
-
 	ret = regmap_update_bits(st->regmap, AD4134_DIG_IF_CFG_REG,
 				 AD4134_DIF_IF_CFG_FORMAT_MASK,
 				 FIELD_PREP(AD4134_DIF_IF_CFG_FORMAT_MASK,
@@ -591,10 +725,61 @@ static int ad4134_probe(struct spi_device *spi)
 		return dev_err_probe(dev, PTR_ERR(st->regmap),
 				     "failed to initialize regmap");
 
-	ret = ad4134_min_io_mode_setup(st);
-	if (ret)
-		return dev_err_probe(dev, ret,
-				     "failed to setup minimum I/O mode\n");
+	if (device_property_present(dev, "adi,spi-mode")) {
+		ret = device_property_match_property_string(dev, "adi,spi-mode",
+							    ad4134_spi_modes,
+							    ARRAY_SIZE(ad4134_spi_modes));
+		if (ret < 0)
+			return dev_err_probe(dev, ret,
+					     "getting adi,spi-mode property failed\n");
+
+		st->spi_mode = ret;
+	} else {
+		/* Default to no-cs mode if adi,spi-mode is not specified */
+		st->spi_mode = AD4134_SPI_MODE_NO_CS;
+	}
+
+	if (st->spi_mode == AD4134_SPI_MODE_NO_CS) {
+		/*
+		 * The support hardware for AD4134 may have a multiplexer for
+		 * selecting between AD4134 SDO and AD4134 DOUT0. If that mux
+		 * is set but the user still wants to run AD4134 in minimum I/O
+		 * mode, then DOUT0 is not used and the multiplexer OUTSIDE OF
+		 * AD4134 SILICON must be set to select AD4134 SDO. See AD4134
+		 * IIO documentation for details.
+		 */
+		st->mux_st[AD4134_SDO_INPUT] =
+			devm_mux_state_get_optional_selected(dev, "reg_access");
+		if (IS_ERR(st->mux_st[AD4134_SDO_INPUT]))
+			return dev_err_probe(dev, PTR_ERR(st->mux_st[AD4134_SDO_INPUT]),
+					     "failed to get reg_access mux-state\n");
+
+		ret = ad4134_min_io_mode_setup(st);
+		if (ret)
+			return dev_err_probe(dev, ret,
+					     "failed to setup minimum I/O mode\n");
+	} else {
+		/*
+		 * This controls a multiplexer OUTSIDE OF AD4134 SILICON.
+		 * See AD4134 IIO documentation for details.
+		 */
+		st->mux_st[AD4134_SDO_INPUT] = devm_mux_state_get(dev, "reg_access");
+		if (IS_ERR(st->mux_st[AD4134_SDO_INPUT]))
+			return dev_err_probe(dev, PTR_ERR(st->mux_st[AD4134_SDO_INPUT]),
+					     "failed to get reg_access mux-state\n");
+
+		st->mux_st[AD4134_DOUT0_INPUT] = devm_mux_state_get(dev, "data_read");
+		if (IS_ERR(st->mux_st[AD4134_DOUT0_INPUT]))
+			return dev_err_probe(dev, PTR_ERR(st->mux_st[AD4134_DOUT0_INPUT]),
+					     "failed to get data_read mux-state\n");
+
+		indio_dev->setup_ops = &ad4134_buffer_setup_ops;
+	}
+
+	st->odr_gpio = devm_gpiod_get(dev, "odr", GPIOD_OUT_LOW);
+	if (IS_ERR(st->odr_gpio))
+		return dev_err_probe(dev, PTR_ERR(st->odr_gpio),
+				     "failed to get ODR GPIO\n");
 
 	ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
 					      iio_pollfunc_store_time,
-- 
2.53.0


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

* [PATCH v5 13/15] dt-bindings: iio: adc: adi,ad4134: Document PWM usage
  2026-10-17  1:56 [PATCH v5 00/15] iio: adc: ad4134: Enable greater sample rate data capture Marcelo Schmitt
                   ` (11 preceding siblings ...)
  2026-10-17  1:59 ` [PATCH v5 12/15] iio: adc: ad4134: Support SPI 4-wire mode Marcelo Schmitt
@ 2026-10-17  2:00 ` Marcelo Schmitt
  2026-10-17  2:00 ` [PATCH v5 14/15] iio: adc: ad4134: Support high-speed data capture Marcelo Schmitt
  2026-10-17  2:00 ` [PATCH v5 15/15] Docs: iio: Add AD4134 Marcelo Schmitt
  14 siblings, 0 replies; 22+ messages in thread
From: Marcelo Schmitt @ 2026-10-17  2:00 UTC (permalink / raw)
  To: linux-iio, devicetree, linux-kernel, linux
  Cc: jic23, nuno.sa, dlechner, andy, Michael.Hennerich, robh, krzk+dt,
	conor+dt, corbet, skhan, marcelo.schmitt1, Conor Dooley

Advanced setups may connect a PWM signal to AD4134 ODR pin for faster
output data rates.

Acked-by: Conor Dooley <conor.dooley@microchip.com>
Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
---
 Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml
index c70b9113cd67..6a190b7a9311 100644
--- a/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml
@@ -104,6 +104,10 @@ properties:
       GPIO connected to ODR pin. Used to sample ADC data in minimum I/O mode.
     maxItems: 1
 
+  pwms:
+    description: PWM signal connected to the ODR pin.
+    maxItems: 1
+
   mux-states:
     description:
       mux controller node to route SDO and DOUT0 signals from peripheral to
@@ -257,9 +261,11 @@ examples:
             reg = <0>;
 
             spi-max-frequency = <1000000>;
+            spi-rx-bus-width = <1>, <1>, <1>, <1>; /* 4 lanes of 1 bit each */
 
             reset-gpios = <&gpio0 86 GPIO_ACTIVE_LOW>;
             powerdown-gpios = <&gpio0 88 GPIO_ACTIVE_LOW>;
+            pwms = <&ad4134_odr_generator 1 1000000 0>;
 
             clocks = <&sys_clk>;
             clock-names = "clkin";
-- 
2.53.0


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

* [PATCH v5 14/15] iio: adc: ad4134: Support high-speed data capture
  2026-10-17  1:56 [PATCH v5 00/15] iio: adc: ad4134: Enable greater sample rate data capture Marcelo Schmitt
                   ` (12 preceding siblings ...)
  2026-10-17  2:00 ` [PATCH v5 13/15] dt-bindings: iio: adc: adi,ad4134: Document PWM usage Marcelo Schmitt
@ 2026-10-17  2:00 ` Marcelo Schmitt
  2026-10-17  2:21   ` sashiko-bot
  2026-10-17  2:00 ` [PATCH v5 15/15] Docs: iio: Add AD4134 Marcelo Schmitt
  14 siblings, 1 reply; 22+ messages in thread
From: Marcelo Schmitt @ 2026-10-17  2:00 UTC (permalink / raw)
  To: linux-iio, devicetree, linux-kernel, linux
  Cc: jic23, nuno.sa, dlechner, andy, Michael.Hennerich, robh, krzk+dt,
	conor+dt, corbet, skhan, marcelo.schmitt1

Make use of SPI transfer offloading to speed up data capture, enabling data
acquisition at faster sample rates (up to 1.496 MSPS).

Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
---
 drivers/iio/adc/Kconfig  |   5 +
 drivers/iio/adc/ad4134.c | 391 +++++++++++++++++++++++++++++++++++++--
 2 files changed, 383 insertions(+), 13 deletions(-)

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 10f3c804df9a..f2bbaef88a5a 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -123,9 +123,14 @@ config AD4130
 config AD4134
 	tristate "Analog Devices AD4134 ADC Driver"
 	depends on SPI
+	depends on PWM
 	select REGMAP_SPI
+	select SPI_OFFLOAD
+	select SPI_OFFLOAD_TRIGGER_PWM
 	select CRC8
 	select IIO_BUFFER
+	select IIO_BUFFER_DMA
+	select IIO_BUFFER_DMAENGINE
 	select IIO_TRIGGERED_BUFFER
 	select MULTIPLEXER
 	help
diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c
index 6b05e40f7aeb..21e8039b3411 100644
--- a/drivers/iio/adc/ad4134.c
+++ b/drivers/iio/adc/ad4134.c
@@ -12,6 +12,7 @@
 #include <linux/crc8.h>
 #include <linux/delay.h>
 #include <linux/dev_printk.h>
+#include <linux/dmaengine.h>
 #include <linux/err.h>
 #include <linux/export.h>
 #include <linux/gpio/consumer.h>
@@ -19,9 +20,12 @@
 #include <linux/mutex.h>
 #include <linux/mux/consumer.h>
 #include <linux/property.h>
+#include <linux/pwm.h>
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/reset.h>
+#include <linux/spi/offload/consumer.h>
+#include <linux/spi/offload/types.h>
 #include <linux/spi/spi.h>
 #include <linux/time64.h>
 #include <linux/types.h>
@@ -29,11 +33,16 @@
 #include <linux/units.h>
 
 #include <linux/iio/buffer.h>
+#include <linux/iio/buffer-dma.h>
+#include <linux/iio/buffer-dmaengine.h>
 #include <linux/iio/iio.h>
 #include <linux/iio/triggered_buffer.h>
 #include <linux/iio/trigger_consumer.h>
 
 #define AD4134_RESET_TIME_US			(10 * USEC_PER_SEC)
+#define AD4134_DCLK_RISING_OFFSET_NS		8
+#define AD4134_MIN_ODR_FREQ_HZ			10
+#define AD4134_MAX_ODR_FREQ_HZ			(1496 * HZ_PER_KHZ)
 
 #define AD4134_REG_READ_MASK			BIT(7)
 #define AD4134_SPI_MAX_XFER_LEN			3
@@ -64,6 +73,7 @@
 #define AD4134_DIG_IF_CFG_REG			0x12
 #define AD4134_DIF_IF_CFG_FORMAT_MASK		GENMASK(1, 0)
 #define AD4134_DATA_FORMAT_SINGLE_CH_MODE	0x0
+#define AD4134_DATA_FORMAT_QUAD_CH_PARALLEL	0x2
 
 #define AD4134_PW_DOWN_CTRL_REG			0x13
 #define AD4134_DEVICE_STATUS_REG		0x15
@@ -116,6 +126,10 @@ static const char * const ad4134_filt_names[] = {
 	[AD4134_SINC3_REJ60] = "sinc3+rej60",
 };
 
+static const int ad4134_max_samp_freq_range_Hz[3] = {
+	AD4134_MIN_ODR_FREQ_HZ, 1, AD4134_MAX_ODR_FREQ_HZ,
+};
+
 struct ad4134_state {
 	struct spi_device *spi;
 	struct regmap *regmap;
@@ -129,6 +143,14 @@ struct ad4134_state {
 	struct mux_state *mux_st[2]; /* For external multiplexer control */
 	enum ad4134_spi_mode spi_mode;
 	int refin_mv;
+	struct spi_message msg;
+	struct spi_transfer xfers;
+	struct spi_offload_trigger_config offload_trigger_config;
+	struct spi_offload_trigger *offload_trigger;
+	struct spi_offload *offload;
+	struct pwm_waveform odr_wf;
+	struct pwm_device *odr_pwm;
+	unsigned int odr_hz;
 	bool crc_en;
 	/*
 	 * DMA (thus cache coherency maintenance) requires the transfer buffers
@@ -213,6 +235,38 @@ static const struct iio_chan_spec ad4134_chan_set[] = {
 	IIO_CHAN_SOFT_TIMESTAMP(4),
 };
 
+/*
+ * Hardcoded 32-bit storagebits and CPU endianness because the currently
+ * available HDL only supports that configuration.
+ */
+#define AD4134_OFFLOAD_CHANNEL(_index) {					\
+	.type = IIO_VOLTAGE,							\
+	.indexed = 1,								\
+	.channel = (_index),							\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |			\
+				    BIT(IIO_CHAN_INFO_SAMP_FREQ),		\
+	.info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ),	\
+	.ext_info = ad4134_filter_type_ext_info,				\
+	.scan_index = (_index),							\
+	.scan_type = {								\
+		.format = IIO_SCAN_FORMAT_SIGNED_INT,				\
+		.realbits = AD4134_CHAN_PRECISION_BITS,				\
+		.storagebits = 32,						\
+		.endianness = IIO_CPU,						\
+	},									\
+}
+
+/*
+ * It's not possible for software to record when offloaded SPI transfers run so
+ * no additional timestamp channel is added.
+ */
+static const struct iio_chan_spec ad4134_offload_chan_set[] = {
+	AD4134_OFFLOAD_CHANNEL(0),
+	AD4134_OFFLOAD_CHANNEL(1),
+	AD4134_OFFLOAD_CHANNEL(2),
+	AD4134_OFFLOAD_CHANNEL(3),
+};
+
 static const struct regmap_range ad4134_regmap_rd_range[] = {
 	regmap_reg_range(AD4134_IFACE_CONFIG_A_REG, AD4134_SILICON_REV_REG),
 	regmap_reg_range(AD4134_SCRATCH_PAD_REG, AD4134_PW_DOWN_CTRL_REG),
@@ -461,6 +515,92 @@ static const struct regmap_config ad4134_regmap_config = {
 	.max_register = AD4134_CH_VREG(AD4134_NUM_CHANNELS - 1),
 };
 
+static int ad4134_update_conversion_rate(struct ad4134_state *st,
+					 unsigned int freq_Hz)
+{
+	struct spi_offload_trigger_config config = st->offload_trigger_config;
+	struct pwm_waveform odr_wf = { };
+	u64 offload_period_ns;
+	u64 offload_offset_ns;
+	u64 odr_high_time_ns;
+	unsigned int count;
+	u64 target_ns;
+	int ret;
+
+	if (!in_range(freq_Hz, AD4134_MIN_ODR_FREQ_HZ,
+		      AD4134_MAX_ODR_FREQ_HZ - AD4134_MIN_ODR_FREQ_HZ + 1))
+		return -ERANGE;
+
+	odr_wf.period_length_ns = DIV_ROUND_UP_ULL(NSEC_PER_SEC, freq_Hz);
+	/*
+	 * Set the PWM duty cycle to keep ODR high for at least minimum required
+	 * time. If the rounded PWM's value is less than the minimum required,
+	 * increase the target value by 10 and attempt to round the waveform
+	 * again, until the minimum (or try count limit) is reached.
+	 */
+	odr_high_time_ns = div64_ul(6ULL * NSEC_PER_SEC, st->sys_clk_hz);
+	target_ns = 0;
+	count = 100;
+	do {
+		target_ns += 10; /* Increment by PWM duty cycle period */
+		odr_wf.duty_length_ns = target_ns;
+		ret = pwm_round_waveform_might_sleep(st->odr_pwm, &odr_wf);
+		if (ret)
+			return ret;
+	} while (--count && odr_wf.duty_length_ns < odr_high_time_ns);
+
+	/* Check the minimum ODR high time is met */
+	if (odr_wf.duty_length_ns < odr_high_time_ns)
+		return -EDOM;
+
+	if (odr_wf.period_length_ns < 2 * odr_high_time_ns)
+		return -EDOM;
+
+	/*
+	 * Configure SPI offload PWM trigger.
+	 * For gated DCLK, the minimum required time between ODR rising edge
+	 * and DCLK rising edge is the sum of ODR high time and ODR falling
+	 * edge to DCLK rising edge time. Delay the offload trigger for at least
+	 * that amount of time so the ADC sample data will be available when the
+	 * SPI transfer begin.
+	 *
+	 * Use the same period as ODR PWM to avoid timing issues.
+	 * Convert back from period to frequency for the SPI offload API.
+	 */
+	offload_period_ns = odr_wf.period_length_ns;
+	config.periodic.frequency_hz = DIV_ROUND_UP_ULL(HZ_PER_GHZ, offload_period_ns);
+	offload_offset_ns = odr_high_time_ns + AD4134_DCLK_RISING_OFFSET_NS;
+	count = 100;
+	do {
+		config.periodic.offset_ns = offload_offset_ns;
+		ret = spi_offload_trigger_validate(st->offload_trigger, &config);
+		if (ret)
+			return ret;
+
+		offload_offset_ns += 10;
+	} while (--count && config.periodic.offset_ns < odr_high_time_ns +
+							AD4134_DCLK_RISING_OFFSET_NS);
+
+	/* Check the minimum ODR to DCLK delay is met */
+	if (config.periodic.offset_ns < odr_high_time_ns + AD4134_DCLK_RISING_OFFSET_NS)
+		return -EDOM;
+
+	/* Check the PWM periods remain the same */
+	offload_period_ns = DIV_ROUND_UP_ULL(HZ_PER_GHZ, config.periodic.frequency_hz);
+	if (odr_wf.period_length_ns != offload_period_ns)
+		return -EDOM;
+
+	ret = pwm_set_waveform_might_sleep(st->odr_pwm, &odr_wf, false);
+	if (ret)
+		return ret;
+
+	st->offload_trigger_config = config;
+	st->odr_wf = odr_wf;
+	st->odr_hz = DIV_ROUND_UP_ULL(NSEC_PER_SEC, odr_wf.period_length_ns);
+
+	return 0;
+}
+
 static irqreturn_t ad4134_trigger_handler(int irq, void *p)
 {
 	IIO_DECLARE_BUFFER_WITH_TS(u32, channels, AD4134_NUM_CHANNELS) = { };
@@ -520,6 +660,9 @@ static int ad4134_read_raw(struct iio_dev *indio_dev,
 
 	switch (info) {
 	case IIO_CHAN_INFO_RAW: {
+		if (!IS_ERR_OR_NULL(st->offload))
+			return -EPROTONOSUPPORT;
+
 		IIO_DEV_ACQUIRE_DIRECT_MODE(indio_dev, claim);
 		if (IIO_DEV_ACQUIRE_FAILED(claim))
 			return -EBUSY;
@@ -550,6 +693,44 @@ static int ad4134_read_raw(struct iio_dev *indio_dev,
 		*val2 = AD4134_CHAN_PRECISION_BITS - 1;
 
 		return IIO_VAL_FRACTIONAL_LOG2;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		*val = st->odr_hz;
+		return IIO_VAL_INT;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int ad4134_read_avail(struct iio_dev *indio_dev,
+			     struct iio_chan_spec const *chan,
+			     const int **vals, int *type, int *length,
+			     long info)
+{
+	switch (info) {
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		*vals = (int *)ad4134_max_samp_freq_range_Hz;
+		*type = IIO_VAL_INT;
+		return IIO_AVAIL_RANGE;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int ad4134_write_raw(struct iio_dev *indio_dev,
+			    struct iio_chan_spec const *chan,
+			    int val, int val2, long mask)
+{
+	struct ad4134_state *st = iio_priv(indio_dev);
+
+	IIO_DEV_ACQUIRE_DIRECT_MODE(indio_dev, claim);
+	if (IIO_DEV_ACQUIRE_FAILED(claim))
+		return -EBUSY;
+
+	guard(mutex)(&st->sync_lock);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		return ad4134_update_conversion_rate(st, val);
 	default:
 		return -EINVAL;
 	}
@@ -602,6 +783,166 @@ static const struct iio_info ad4134_info = {
 	.debugfs_reg_access = ad4134_debugfs_reg_access,
 };
 
+static const struct iio_info ad4134_offload_info = {
+	.read_raw = ad4134_read_raw,
+	.read_avail = ad4134_read_avail,
+	.write_raw = ad4134_write_raw,
+	.debugfs_reg_access = ad4134_debugfs_reg_access,
+};
+
+static void ad4134_prepare_offload_msg(struct iio_dev *indio_dev)
+{
+	struct ad4134_state *st = iio_priv(indio_dev);
+	unsigned int base_len = spi_bpw_to_bytes(AD4134_CHAN_PRECISION_BITS);
+
+	st->xfers.cs_off = 1;
+	st->xfers.bits_per_word = AD4134_CHAN_PRECISION_BITS;
+	st->xfers.len = base_len * AD4134_NUM_CHANNELS;
+	if (st->spi->num_rx_lanes > 1)
+		st->xfers.multi_lane_mode = SPI_MULTI_LANE_MODE_STRIPE;
+
+	st->xfers.offload_flags = SPI_OFFLOAD_XFER_RX_STREAM;
+
+	spi_message_init_with_transfers(&st->msg, &st->xfers, 1);
+}
+
+static int ad4134_offload_buffer_postenable(struct iio_dev *indio_dev)
+{
+	struct ad4134_state *st = iio_priv(indio_dev);
+	int ret, access_ret;
+
+	ret = ad4134_claim_sample_access(st);
+	if (ret)
+		return ret;
+
+	ad4134_prepare_offload_msg(indio_dev);
+	st->msg.offload = st->offload;
+	ret = spi_optimize_message(st->spi, &st->msg);
+	if (ret)
+		goto out_offload_release;
+
+	ret = spi_offload_trigger_enable(st->offload, st->offload_trigger,
+					 &st->offload_trigger_config);
+	if (ret)
+		goto out_unoptimize;
+
+	return 0;
+
+out_unoptimize:
+	spi_unoptimize_message(&st->msg);
+
+out_offload_release:
+	access_ret = ad4134_release_sample_access(st);
+	if (access_ret)
+		dev_err(&st->spi->dev, "reg input select error: %d\n", access_ret);
+
+	return ret;
+}
+
+static int ad4134_offload_buffer_predisable(struct iio_dev *indio_dev)
+{
+	struct ad4134_state *st = iio_priv(indio_dev);
+
+	spi_offload_trigger_disable(st->offload, st->offload_trigger);
+	spi_unoptimize_message(&st->msg);
+
+	return ad4134_release_sample_access(st);
+}
+
+static const struct iio_buffer_setup_ops ad4134_offload_buffer_setup_ops = {
+	.postenable = &ad4134_offload_buffer_postenable,
+	.predisable = &ad4134_offload_buffer_predisable,
+};
+
+static int ad4134_pwm_get(struct ad4134_state *st)
+{
+	struct device *dev = &st->spi->dev;
+
+	st->odr_pwm = devm_pwm_get(dev, NULL);
+	if (IS_ERR(st->odr_pwm))
+		return dev_err_probe(dev, PTR_ERR(st->odr_pwm),
+				     "failed to get ODR PWM\n");
+
+	return 0;
+}
+
+static const struct spi_offload_config ad4134_offload_config = {
+	.capability_flags = SPI_OFFLOAD_CAP_TRIGGER |
+			    SPI_OFFLOAD_CAP_RX_STREAM_DMA,
+};
+
+static int ad4134_offload_buffer_setup(struct iio_dev *indio_dev, struct spi_device *spi)
+{
+	struct ad4134_state *st = iio_priv(indio_dev);
+	struct device *dev = &spi->dev;
+	struct dma_chan *rx_dma;
+
+	st->offload_trigger = devm_spi_offload_trigger_get(dev, st->offload,
+							   SPI_OFFLOAD_TRIGGER_PERIODIC);
+	if (IS_ERR(st->offload_trigger))
+		return dev_err_probe(dev, PTR_ERR(st->offload_trigger),
+				     "failed to get offload trigger\n");
+
+	st->offload_trigger_config.type = SPI_OFFLOAD_TRIGGER_PERIODIC;
+
+	rx_dma = devm_spi_offload_rx_stream_request_dma_chan(dev, st->offload);
+	if (IS_ERR(rx_dma))
+		return dev_err_probe(dev, PTR_ERR(rx_dma),
+				     "failed to get offload RX DMA\n");
+
+	return devm_iio_dmaengine_buffer_setup_with_handle(dev, indio_dev, rx_dma,
+							   IIO_BUFFER_DIRECTION_IN);
+}
+
+/* The chip converts and outputs all 4 channels on each sample request */
+static const unsigned long ad4134_scan_masks[] = {
+	BIT(3) | BIT(2) | BIT(1) | BIT(0),
+	0
+};
+
+static int ad4134_offload_setup(struct iio_dev *indio_dev, struct ad4134_state *st)
+{
+	struct device *dev = &st->spi->dev;
+	int ret;
+
+	ret = ad4134_pwm_get(st);
+	if (ret)
+		return ret;
+
+	ret = ad4134_offload_buffer_setup(indio_dev, st->spi);
+	if (ret)
+		return ret;
+
+	/*
+	 * Start with a sampling rate slower than 374 kSPS because that is the
+	 * maximum rate supported with wideband filter (default on power up).
+	 */
+	st->odr_hz = 250 * HZ_PER_KHZ;
+	ret = ad4134_update_conversion_rate(st, st->odr_hz);
+	if (ret)
+		return dev_err_probe(dev, ret, "failed to set sampling freq\n");
+
+	indio_dev->setup_ops = &ad4134_offload_buffer_setup_ops;
+	indio_dev->available_scan_masks = ad4134_scan_masks;
+
+	switch (st->spi->num_rx_lanes) {
+	case 1:
+		return regmap_update_bits(st->regmap, AD4134_DIG_IF_CFG_REG,
+					  AD4134_DIF_IF_CFG_FORMAT_MASK,
+					  FIELD_PREP(AD4134_DIF_IF_CFG_FORMAT_MASK,
+						     AD4134_DATA_FORMAT_SINGLE_CH_MODE));
+	case 4:
+		return regmap_update_bits(st->regmap, AD4134_DIG_IF_CFG_REG,
+					  AD4134_DIF_IF_CFG_FORMAT_MASK,
+					  FIELD_PREP(AD4134_DIF_IF_CFG_FORMAT_MASK,
+						     AD4134_DATA_FORMAT_QUAD_CH_PARALLEL));
+	default:
+		return dev_err_probe(dev, -EINVAL,
+			"unsupported number of spi-rx-bus-width elements: %d\n",
+			st->spi->num_rx_lanes);
+	}
+}
+
 static const char * const ad4143_required_regulators[] = {
 	"avdd5", "dvdd5", "iovdd",
 };
@@ -676,6 +1017,9 @@ static int ad4134_clock_select(struct ad4134_state *st)
 		dev_warn(dev, "invalid external clock frequency %lu\n",
 			 st->sys_clk_hz);
 
+	if (!st->sys_clk_hz)
+		return dev_err_probe(dev, -EINVAL, "0 Hz external clock\n");
+
 	return 0;
 }
 
@@ -695,10 +1039,7 @@ static int ad4134_probe(struct spi_device *spi)
 	st->spi = spi;
 
 	indio_dev->name = "ad4134";
-	indio_dev->channels = ad4134_chan_set;
-	indio_dev->num_channels = ARRAY_SIZE(ad4134_chan_set);
 	indio_dev->modes = INDIO_DIRECT_MODE;
-	indio_dev->info = &ad4134_info;
 
 	ret = ad4134_regulator_setup(st);
 	if (ret)
@@ -776,17 +1117,40 @@ static int ad4134_probe(struct spi_device *spi)
 		indio_dev->setup_ops = &ad4134_buffer_setup_ops;
 	}
 
-	st->odr_gpio = devm_gpiod_get(dev, "odr", GPIOD_OUT_LOW);
-	if (IS_ERR(st->odr_gpio))
-		return dev_err_probe(dev, PTR_ERR(st->odr_gpio),
-				     "failed to get ODR GPIO\n");
+	st->offload = devm_spi_offload_get(dev, spi, &ad4134_offload_config);
+	ret = PTR_ERR_OR_ZERO(st->offload);
+	/* Fall back to low speed usage when no SPI offload is available. */
+	if (ret == -ENODEV) {
+		st->odr_gpio = devm_gpiod_get(dev, "odr", GPIOD_OUT_LOW);
+		if (IS_ERR(st->odr_gpio))
+			return dev_err_probe(dev, PTR_ERR(st->odr_gpio),
+					     "failed to get ODR GPIO\n");
 
-	ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
-					      iio_pollfunc_store_time,
-					      ad4134_trigger_handler,
-					      NULL);
-	if (ret)
-		return ret;
+		indio_dev->info = &ad4134_info;
+		indio_dev->channels = ad4134_chan_set;
+		indio_dev->num_channels = ARRAY_SIZE(ad4134_chan_set);
+		ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
+						      iio_pollfunc_store_time,
+						      ad4134_trigger_handler,
+						      st->spi_mode != AD4134_SPI_MODE_NO_CS ?
+						      &ad4134_buffer_setup_ops : NULL);
+		if (ret)
+			return ret;
+	} else if (ret) {
+		return dev_err_probe(dev, ret, "failed to get offload\n");
+	} else {
+		if (st->spi_mode == AD4134_SPI_MODE_NO_CS)
+			return dev_err_probe(dev, -EPROTONOSUPPORT,
+					     "Unsupported min I/O + offload config\n");
+
+		indio_dev->info = &ad4134_offload_info;
+		indio_dev->channels = ad4134_offload_chan_set;
+		indio_dev->num_channels = ARRAY_SIZE(ad4134_offload_chan_set);
+		ret = ad4134_offload_setup(indio_dev, st);
+		if (ret)
+			return dev_err_probe(dev, ret,
+					     "failed to setup SPI offload\n");
+	}
 
 	/* Bump precision to 24-bit */
 	ret = regmap_update_bits(st->regmap, AD4134_DATA_PACKET_CONFIG_REG,
@@ -832,3 +1196,4 @@ module_spi_driver(ad4134_driver);
 MODULE_AUTHOR("Marcelo Schmitt <marcelo.schmitt@analog.com>");
 MODULE_DESCRIPTION("Analog Devices AD4134 SPI driver");
 MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_DMAENGINE_BUFFER");
-- 
2.53.0


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

* [PATCH v5 15/15] Docs: iio: Add AD4134
  2026-10-17  1:56 [PATCH v5 00/15] iio: adc: ad4134: Enable greater sample rate data capture Marcelo Schmitt
                   ` (13 preceding siblings ...)
  2026-10-17  2:00 ` [PATCH v5 14/15] iio: adc: ad4134: Support high-speed data capture Marcelo Schmitt
@ 2026-10-17  2:00 ` Marcelo Schmitt
  14 siblings, 0 replies; 22+ messages in thread
From: Marcelo Schmitt @ 2026-10-17  2:00 UTC (permalink / raw)
  To: linux-iio, devicetree, linux-kernel, linux
  Cc: jic23, nuno.sa, dlechner, andy, Michael.Hennerich, robh, krzk+dt,
	conor+dt, corbet, skhan, marcelo.schmitt1

Add initial documentation for the ad4134 IIO driver.

Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
---
 Documentation/iio/ad4134.rst | 127 +++++++++++++++++++++++++++++++++++
 Documentation/iio/index.rst  |   1 +
 MAINTAINERS                  |   1 +
 3 files changed, 129 insertions(+)
 create mode 100644 Documentation/iio/ad4134.rst

diff --git a/Documentation/iio/ad4134.rst b/Documentation/iio/ad4134.rst
new file mode 100644
index 000000000000..c0889a21cd77
--- /dev/null
+++ b/Documentation/iio/ad4134.rst
@@ -0,0 +1,127 @@
+.. SPDX-License-Identifier: GPL-2.0-only
+
+=============
+AD4134 driver
+=============
+
+Device driver for Analog Devices Inc. AD4134 and similar ADCs.
+
+Supported devices
+=================
+
+* `AD4134 <https://www.analog.com/AD4134>`_
+* `AD7134 <https://www.analog.com/AD7134>`_
+
+Wiring connections
+------------------
+
+AD4134 and similar ADCs can operate in a few different wiring configurations.
+Because AD4134 also supports control modes other than through SPI protocol,
+the following pins must be statically set for all of the wiring modes described
+below.
+
++----------------------------+----------------------+--------------------+
+| Pin Function               |         Level        | Description        |
++============================+======================+====================+
+| PIN/SPI                    |         High         | SPI control mode   |
++----------------------------+----------------------+--------------------+
+| MODE                       |         Low          | ASRC slave mode    |
++----------------------------+----------------------+--------------------+
+| DEC0/DCLKI                 |         Low          | DCLK input         |
++----------------------------+----------------------+--------------------+
+| DEC1/DCLKMODE              |         Low          | Gated DCLK         |
++----------------------------+----------------------+--------------------+
+
+Minimum I/O mode
+^^^^^^^^^^^^^^^^
+
+The minimum I/O mode wiring allows AD4134 register and data access with the
+conventional set of SPI bus lines. In this mode, the peripheral CS pin must be
+tied to GND. A possible connection schema that sets AD4134 digital interface for
+minimum I/O mode is::
+
+      +------------+         +-------------+
+      |  AD4134    |         | SPI         |
+      |            |         | Controller  |
+      |       DCLK |<--+     |             |
+      |       SCLK |<--+---- | SCLK        |
+      |        SDI |<--------| SDO         |
+      |        SDO |-------->| SDI         |
+      |        ODR |<--------| GPIO        |
+      |         CS |----+    |             |
+      +------------+    |    +-------------+
+                        V
+                       GND
+
+Set ``adi,spi-mode = "no-cs"`` in device tree to indicate the device is
+connected in minimum I/O wiring configuration.
+
+SPI 4-wire mode - single lane
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The conventional SPI 4-wire configuration except a multiplexer is used to
+select between SDO (for register data) and DOUT0 (for ADC sample data).::
+
+  +-----------------------+                         +-----------------+
+  |         AD4134        |                         | SPI Controller  |
+  |                       |                         |                 |
+  | SPI interface    SCLK |<------------------------| SCLK            |
+  | for register       CS |<------------------------| CS              |
+  | access            SDI |<------------------------| SDO             |
+  |                   SDO |------->|¯¯¯¯\           |                 |
+  |                       |        |MUX  >--------->| SDI             |
+  | Data interface DOUT0  |------->|____/           |                 |
+  | for ADC sample        |          ^              |                 |
+  | data read             |          |              |                 |
+  |                  DCLK |<------------------------| DCLK            |
+  |                   ODR |<----------------+    +->| Offload Trigger |
+  +-----------------------+          |      |    |  +-----------------+
+                                     |      |    +--| PWM1            |
+                                     |      +-------| PWM0            |
+                                     +--------------| GPIO            |
+                                                    +-----------------+
+
+Set ``adi,spi-mode = "4-wire"`` in device tree to indicate the device is
+connected in SPI 4-wire configuration.
+
+For SPI offload operation, a PWM is connected to the ADC ODR pin. The ``pwms``
+firmware property specifies the PWM that is connected to the ADC. The SPI
+offload will have a ``trigger-sources`` property to indicate the SPI offload
+(PWM) trigger source.
+
+To achieve high sample rates while meeting ADC timing requirements, an offset
+must be added between the rising edges of PWM0 and PWM1 to delay the SPI
+transfer until ADC sample data is available. This requires a specialized PWM
+controller that can provide such an offset.  The `AD4134-FMC HDL project`_, for
+example, can be configured to sample AD4134 at high speed sample rates.
+
+.. _AD4134-FMC HDL project: https://analogdevicesinc.github.io/hdl/projects/ad4134_fmc/index.html
+
+SPI 4-wire mode - multi-lane
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Maximum throughput rate can be achieved by reading 4 input lines simultaneously.::
+
+  +-----------------------+                         +-----------------+
+  |         AD4134        |                         | SPI Controller  |
+  |                       |                         |                 |
+  | SPI interface    SCLK |<------------------------| SCLK            |
+  | for register       CS |<------------------------| CS              |
+  | access            SDI |<------------------------| SDO             |
+  |                   SDO |------->|¯¯¯¯\           |                 |
+  |                       |        |MUX  >--------->| SDI0            |
+  | Data interface  DOUT0 |------->|____/           |                 |
+  | for ADC sample        |          ^              |                 |
+  | data read       DOUT1 |------------------------>| SDI1            |
+  |                 DOUT2 |------------------------>| SDI2            |
+  |                 DOUT3 |------------------------>| SDI3            |
+  |                  DCLK |<------------------------| DCLK            |
+  |                   ODR |<----------------+    +->| Offload Trigger |
+  +-----------------------+          |      |    |  +-----------------+
+                                     |      |    +--| PWM1            |
+                                     |      +-------| PWM0            |
+                                     +--------------| GPIO            |
+                                                    +-----------------+
+
+Each of SDI0 to SDI3 connect to a different SPI controller deserializer
+(``spi-rx-bus-width = <1>, <1>, <1>, <1>``).
diff --git a/Documentation/iio/index.rst b/Documentation/iio/index.rst
index d0fb32f4b80f..3a49e08a2366 100644
--- a/Documentation/iio/index.rst
+++ b/Documentation/iio/index.rst
@@ -23,6 +23,7 @@ Industrial I/O Kernel Drivers
    ad4000
    ad4030
    ad4062
+   ad4134
    ad4691
    ad4695
    ad7191
diff --git a/MAINTAINERS b/MAINTAINERS
index 3a2dfd1a4fd8..82a810ac788e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1533,6 +1533,7 @@ L:	linux-iio@vger.kernel.org
 S:	Supported
 W:	https://ez.analog.com/linux-software-drivers
 F:	Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml
+F:	Documentation/iio/ad4134.rst
 F:	drivers/iio/adc/ad4134.c
 
 ANALOG DEVICES INC AD4170-4 DRIVER
-- 
2.53.0


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

* Re: [PATCH v5 03/15] iio: adc: ad4134: Apply reset recovery wait time
  2026-10-17  1:57 ` [PATCH v5 03/15] iio: adc: ad4134: Apply reset recovery wait time Marcelo Schmitt
@ 2026-10-17  2:05   ` sashiko-bot
  2026-10-17  5:55   ` Joshua Crofts
  1 sibling, 0 replies; 22+ messages in thread
From: sashiko-bot @ 2026-10-17  2:05 UTC (permalink / raw)
  To: Marcelo Schmitt, devicetree; +Cc: robh, conor+dt

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] iio: adc: ad4134: 10-second sleep in ad4134_probe() due to USEC_PER_SEC
--

commit 3488776492f80838a5517d1bec747527ca957473
Author: Marcelo Schmitt <marcelo.schmitt@analog.com>

iio: adc: ad4134: Apply reset recovery wait time

This commit adds an fsleep() call after deasserting reset in ad4134_probe()
to wait for reset recovery before starting SPI transfers.

> diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c
> index 40b27b01f1260..d555874b49597 100644
> --- a/drivers/iio/adc/ad4134.c
> +++ b/drivers/iio/adc/ad4134.c
> @@ -442,6 +442,7 @@ static int ad4134_probe(struct spi_device *spi)
>  		return dev_err_probe(dev, PTR_ERR(rst),
>  				     "failed to get and deassert reset\n");
>  
> +	fsleep(AD4134_RESET_TIME_US);
>  	crc8_populate_msb(ad4134_spi_crc_table, AD4134_SPI_CRC_POLYNOM);
>  
>  	st->regmap = devm_regmap_init(dev, NULL, st, &ad4134_regmap_config);

[Severity: Medium]
Does calling fsleep(AD4134_RESET_TIME_US) here in ad4134_probe() cause the
probe path to stall for 10 seconds?

Earlier in drivers/iio/adc/ad4134.c, AD4134_RESET_TIME_US is defined using
USEC_PER_SEC:

    #define AD4134_RESET_TIME_US			(10 * USEC_PER_SEC)

This evaluates to 10,000,000 microseconds (10 seconds), causing fsleep() to
invoke msleep(10000) every time devm_reset_control_get_optional_exclusive_deasserted()
succeeds during probe. Should AD4134_RESET_TIME_US be defined with
USEC_PER_MSEC for a 10 millisecond recovery delay instead?

титься

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1792200021.git.marcelo.schmitt@analog.com?part=3

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

* Re: [PATCH v5 08/15] iio: adc: ad4134: Add support for digital filter type selection
  2026-10-17  1:58 ` [PATCH v5 08/15] iio: adc: ad4134: Add support for digital filter type selection Marcelo Schmitt
@ 2026-10-17  2:16   ` sashiko-bot
  0 siblings, 0 replies; 22+ messages in thread
From: sashiko-bot @ 2026-10-17  2:16 UTC (permalink / raw)
  To: Marcelo Schmitt, devicetree; +Cc: robh, conor+dt

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] iio: adc: ad4134: undocumented sinc6 filter_type and sysfs ABI attributes
--

commit f7364f2a84e232ee97a6956a54b434e35fd7f79d
Author: Marcelo Schmitt <marcelo.schmitt@analog.com>

iio: adc: ad4134: Add support for digital filter type selection

This commit adds per-channel digital filter type configuration for the AD4134
ADC by exposing filter_type and filter_type_available sysfs attributes via
IIO_ENUM.

> diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c
> index 91a7c21077709..b245001d45517 100644
> --- a/drivers/iio/adc/ad4134.c
> +++ b/drivers/iio/adc/ad4134.c
[ ... ]
> @@ -80,19 +83,18 @@
[ ... ]
> +enum ad4134_filter_type {
> +	AD4134_WIDEBAND,
> +	AD4134_SINC6,
> +	AD4134_SINC3,
> +	AD4134_SINC3_REJ60,
> +};
>  
> -static const struct iio_chan_spec ad4134_chan_set[] = {
> -	AD4134_CHANNEL(0),
> -	AD4134_CHANNEL(1),
> -	AD4134_CHANNEL(2),
> -	AD4134_CHANNEL(3),
> +static const char * const ad4134_filt_names[] = {
> +	[AD4134_WIDEBAND] = "wideband",
> +	[AD4134_SINC6] = "sinc6",
> +	[AD4134_SINC3] = "sinc3",
> +	[AD4134_SINC3_REJ60] = "sinc3+rej60",
>  };
>  
>  struct ad4134_state {
> @@ -115,6 +117,73 @@ struct ad4134_state {
>  	u8 tx_buf[AD4134_SPI_MAX_XFER_LEN];
>  };
>  
[ ... ]
> +static const struct iio_enum ad4134_filter_type_enum = {
> +	.items = ad4134_filt_names,
> +	.num_items = ARRAY_SIZE(ad4134_filt_names),
> +	.get = ad4134_get_filter_type,
> +	.set = ad4134_set_filter_type,
> +};
> +
> +static const struct iio_chan_spec_ext_info ad4134_filter_type_ext_info[] = {
> +	IIO_ENUM("filter_type", IIO_SEPARATE, &ad4134_filter_type_enum),
> +	IIO_ENUM_AVAILABLE("filter_type", IIO_SEPARATE, &ad4134_filter_type_enum),
> +	{ }
> +};
> +
> +#define AD4134_CHANNEL(_index) {						\
> +	.type = IIO_VOLTAGE,							\
> +	.indexed = 1,								\
> +	.channel = (_index),							\
> +	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),				\
> +	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),			\
> +	.ext_info = ad4134_filter_type_ext_info,				\
> +}

[Severity: Low]
In drivers/iio/adc/ad4134.c, ad4134_filt_names[] introduces "sinc6" as a new
filter_type string option when the driver probes and registers
ad4134_chan_set[].

In addition, attaching ad4134_filter_type_ext_info[] with IIO_SEPARATE to
indexed non-differential IIO_VOLTAGE channels in AD4134_CHANNEL() exposes
/sys/bus/iio/devices/iio:deviceX/in_voltageY_filter_type and
/sys/bus/iio/devices/iio:deviceX/in_voltageY_filter_type_available to
userspace.

Currently, Documentation/ABI/testing/sysfs-bus-iio only lists What entries
for filter_type, in_voltageY-voltageZ_filter_type, filter_type_available, and
in_voltage-voltage_filter_type_available, and its list of valid filter types
does not include "sinc6".

Should Documentation/ABI/testing/sysfs-bus-iio be updated to document the
"sinc6" filter option and the in_voltageY_filter_type and
in_voltageY_filter_type_available attributes?

> +
> +static const struct iio_chan_spec ad4134_chan_set[] = {
> +	AD4134_CHANNEL(0),
> +	AD4134_CHANNEL(1),
> +	AD4134_CHANNEL(2),
> +	AD4134_CHANNEL(3),
> +};

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1792200021.git.marcelo.schmitt@analog.com?part=8

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

* Re: [PATCH v5 12/15] iio: adc: ad4134: Support SPI 4-wire mode
  2026-10-17  1:59 ` [PATCH v5 12/15] iio: adc: ad4134: Support SPI 4-wire mode Marcelo Schmitt
@ 2026-10-17  2:19   ` sashiko-bot
  0 siblings, 0 replies; 22+ messages in thread
From: sashiko-bot @ 2026-10-17  2:19 UTC (permalink / raw)
  To: Marcelo Schmitt, devicetree; +Cc: robh, conor+dt

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [Medium] iio: adc: ad4134: race with trigger handler in ad4134_buffer_setup_ops
- [Medium] iio: adc: ad4134: missing DOUT0 format config and cs_off in 4-wire mode
- [Medium] iio: adc: ad4134: spi_setup() ordering and mode desync in claim helpers
--

commit 8eb548670148a37e8ad1ee608a1ea7bc67bedb0c
Author: Marcelo Schmitt <marcelo.schmitt@analog.com>

iio: adc: ad4134: Support SPI 4-wire mode

This commit extends the AD4134 ADC driver to support SPI 4-wire mode in
addition to minimum I/O mode by switching SPI clock phase and controlling
an external SDO/DOUT0 multiplexer between register and sample accesses.

> diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c
> index eaf5bb55f25ba..6b05e40f7aeb7 100644
> --- a/drivers/iio/adc/ad4134.c
> +++ b/drivers/iio/adc/ad4134.c

[ ... ]

> @@ -219,6 +237,85 @@ static const struct regmap_access_table ad4134_regmap_wr_table = {
>  	.n_yes_ranges = ARRAY_SIZE(ad4134_regmap_wr_range),
>  };
>  
> +/*
> + * When operating in modes other than minimum I/O mode, AD4134 register data on
> + * the SDO line is sampled on SCLK rising edge (SPI mode 0). In addition to
> + * that, when AD4134 SDO and DOUT0 pins are multiplexed by hardware OUTSIDE
> + * AD4134 SILICON, the multiplexer state must be set to route SDO to the SPI
> + * controller. With both SPI mode and multiplexer state properly set, register
> + * access runs as usual. Successful calls to this function must be balanced with
> + * calls to ad4134_release_reg_access() so to release the mux state lock. See
> + * AD4134 IIO documentation for details.
> + */
> +static int ad4134_claim_reg_access(struct ad4134_state *st)
> +{
> +	unsigned int cur_mode = st->spi->mode & SPI_MODE_X_MASK;
> +	int ret;
> +
> +	if (st->spi_mode != AD4134_SPI_MODE_NO_CS && cur_mode != SPI_MODE_0) {
> +		st->spi->mode &= ~SPI_MODE_X_MASK;
> +		st->spi->mode |= SPI_MODE_0;
> +		ret = spi_setup(st->spi);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	if (st->spi_mode != AD4134_SPI_MODE_NO_CS && st->mux_st[AD4134_SDO_INPUT])
> +		return mux_state_select(st->mux_st[AD4134_SDO_INPUT]);
> +
> +	return 0;
> +}

[Severity: Medium]
In ad4134_claim_reg_access() and ad4134_claim_sample_access(), can
mutating st->spi->mode and calling spi_setup() before mux_state_select()
leave the SPI mode out of sync or reconfigure the controller during an
active capture?

If spi_setup(st->spi) fails, st->spi->mode is not restored to cur_mode. On
the next call to the same claim helper, cur_mode already matches the
target mode, so spi_setup() is skipped while the SPI controller remains
configured in the previous mode.

Similarly, because spi_setup() runs before mux_state_select() acquires the
mux lock, if mux_state_select() fails (for example with -EINTR while
waiting in down_killable()), st->spi->mode and the SPI controller remain in
the new mode on an error return. In addition, if a register read occurs via
regmap debugfs while buffered capture holds the mux lock in SPI_MODE_1,
ad4134_claim_reg_access() will call spi_setup() to switch the controller to
SPI_MODE_0 before blocking on mux_state_select().

Should mux_state_select() be called before changing st->spi->mode and
calling spi_setup(), with st->spi->mode restored and the mux deselected if
spi_setup() fails?

[ ... ]

> @@ -261,7 +367,11 @@ static int ad4134_data_read(struct ad4134_state *st, unsigned int reg,
>  {
>  	unsigned int i;
>  	u32 sample = 0;
> -	int ret;
> +	int access_ret, ret;
> +
> +	ret = ad4134_claim_sample_access(st);
> +	if (ret)
> +		return ret;
>  
>  	/*
>  	 * To be able to read data from all 4 channels through a single line, we
> @@ -277,7 +387,7 @@ static int ad4134_data_read(struct ad4134_state *st, unsigned int reg,
>  		ret = spi_write_then_read(st->spi, NULL, 0, st->rx_buf,
>  					  BITS_TO_BYTES(AD4134_CHAN_PRECISION_BITS));
>  		if (ret)
> -			return ret;
> +			goto out_data_read_release;

[ ... ]

> @@ -372,6 +496,21 @@ static irqreturn_t ad4134_trigger_handler(int irq, void *p)
>  	return IRQ_HANDLED;
>  }
>  
> +static int ad4134_buffer_postenable(struct iio_dev *indio_dev)
> +{
> +	return ad4134_claim_sample_access(iio_priv(indio_dev));
> +}
> +
> +static int ad4134_buffer_predisable(struct iio_dev *indio_dev)
> +{
> +	return ad4134_release_sample_access(iio_priv(indio_dev));
> +}
> +
> +static const struct iio_buffer_setup_ops ad4134_buffer_setup_ops = {
> +	.postenable = &ad4134_buffer_postenable,
> +	.predisable = &ad4134_buffer_predisable,
> +};

[Severity: Medium]
Can using .postenable and .predisable in ad4134_buffer_setup_ops race with
ad4134_trigger_handler() in 4-wire mode?

In drivers/iio/industrialio-buffer.c, iio_enable_buffers() attaches the
trigger pollfunc before running .postenable:

	if (iio_dev_opaque->currentmode == INDIO_BUFFER_TRIGGERED) {
		ret = iio_trigger_attach_poll_func(indio_dev->trig,
						   indio_dev->pollfunc);
		if (ret)
			goto err_disable_buffers;
	}

	if (indio_dev->setup_ops->postenable) {
		ret = indio_dev->setup_ops->postenable(indio_dev);

Because iio_trigger_attach_poll_func() requests the threaded IRQ and enables
the external trigger, ad4134_trigger_handler() can start running
spi_sync_transfer() before or concurrently with ad4134_buffer_postenable()
calling ad4134_claim_sample_access() to update st->spi->mode, call
spi_setup(), and select st->mux_st[AD4134_DOUT0_INPUT].

Symmetrically, iio_disable_buffers() runs .predisable before detaching the
trigger pollfunc:

	if (indio_dev->setup_ops->predisable) {
		ret2 = indio_dev->setup_ops->predisable(indio_dev);
		if (ret2 && !ret)
			ret = ret2;
	}

	if (iio_dev_opaque->currentmode == INDIO_BUFFER_TRIGGERED) {
		iio_trigger_detach_poll_func(indio_dev->trig,
					     indio_dev->pollfunc);
	}

This allows ad4134_buffer_predisable() to deselect the DOUT0 mux state
before iio_trigger_detach_poll_func() disables the trigger and frees the
pollfunc IRQ.

(Note also that in this commit, indio_dev->setup_ops is overwritten with
NULL by the subsequent devm_iio_triggered_buffer_setup(..., NULL) call in
ad4134_probe() until a later commit in the series passes
&ad4134_buffer_setup_ops to devm_iio_triggered_buffer_setup().)

Should ad4134_buffer_setup_ops use .preenable and .postdisable instead of
.postenable and .predisable?

[ ... ]

> @@ -591,10 +725,61 @@ static int ad4134_probe(struct spi_device *spi)
>  		return dev_err_probe(dev, PTR_ERR(st->regmap),
>  				     "failed to initialize regmap");
>  
> -	ret = ad4134_min_io_mode_setup(st);
> -	if (ret)
> -		return dev_err_probe(dev, ret,
> -				     "failed to setup minimum I/O mode\n");
> +	if (device_property_present(dev, "adi,spi-mode")) {
> +		ret = device_property_match_property_string(dev, "adi,spi-mode",
> +							    ad4134_spi_modes,
> +							    ARRAY_SIZE(ad4134_spi_modes));
> +		if (ret < 0)
> +			return dev_err_probe(dev, ret,
> +					     "getting adi,spi-mode property failed\n");
> +
> +		st->spi_mode = ret;
> +	} else {
> +		/* Default to no-cs mode if adi,spi-mode is not specified */
> +		st->spi_mode = AD4134_SPI_MODE_NO_CS;
> +	}
> +
> +	if (st->spi_mode == AD4134_SPI_MODE_NO_CS) {
> +		/*
> +		 * The support hardware for AD4134 may have a multiplexer for
> +		 * selecting between AD4134 SDO and AD4134 DOUT0. If that mux
> +		 * is set but the user still wants to run AD4134 in minimum I/O
> +		 * mode, then DOUT0 is not used and the multiplexer OUTSIDE OF
> +		 * AD4134 SILICON must be set to select AD4134 SDO. See AD4134
> +		 * IIO documentation for details.
> +		 */
> +		st->mux_st[AD4134_SDO_INPUT] =
> +			devm_mux_state_get_optional_selected(dev, "reg_access");
> +		if (IS_ERR(st->mux_st[AD4134_SDO_INPUT]))
> +			return dev_err_probe(dev, PTR_ERR(st->mux_st[AD4134_SDO_INPUT]),
> +					     "failed to get reg_access mux-state\n");
> +
> +		ret = ad4134_min_io_mode_setup(st);
> +		if (ret)
> +			return dev_err_probe(dev, ret,
> +					     "failed to setup minimum I/O mode\n");
> +	} else {
> +		/*
> +		 * This controls a multiplexer OUTSIDE OF AD4134 SILICON.
> +		 * See AD4134 IIO documentation for details.
> +		 */
> +		st->mux_st[AD4134_SDO_INPUT] = devm_mux_state_get(dev, "reg_access");
> +		if (IS_ERR(st->mux_st[AD4134_SDO_INPUT]))
> +			return dev_err_probe(dev, PTR_ERR(st->mux_st[AD4134_SDO_INPUT]),
> +					     "failed to get reg_access mux-state\n");
> +
> +		st->mux_st[AD4134_DOUT0_INPUT] = devm_mux_state_get(dev, "data_read");
> +		if (IS_ERR(st->mux_st[AD4134_DOUT0_INPUT]))
> +			return dev_err_probe(dev, PTR_ERR(st->mux_st[AD4134_DOUT0_INPUT]),
> +					     "failed to get data_read mux-state\n");
> +
> +		indio_dev->setup_ops = &ad4134_buffer_setup_ops;
> +	}

[Severity: Medium]
When st->spi_mode is AD4134_SPI_MODE_4_WIRE (and without SPI offload in the
later high-speed data capture commit), how does sample readout work in
ad4134_data_read() and ad4134_trigger_handler()?

Both ad4134_data_read() and ad4134_trigger_handler() read all 4 channels
sequentially over DOUT0, which requires AD4134_DIG_IF_CFG_REG to be set to
AD4134_DATA_FORMAT_SINGLE_CH_MODE. However, that register update is only
performed inside ad4134_min_io_mode_setup() when st->spi_mode is
AD4134_SPI_MODE_NO_CS (and in ad4134_offload_setup() for 1-lane offload in
the later commit), leaving AD4134_DIG_IF_CFG_REG unconfigured in non-offload
4-wire mode.

In addition, while ad4134_trigger_handler() sets .cs_off = true on its
spi_transfer, ad4134_data_read() uses spi_write_then_read(), which asserts
CS during each 3-byte read while transmitting 0x00 on SDI. In 4-wire mode,
CS is wired to the register SPI interface and st->crc_en is false, so won't
asserting CS while clocking SCLK perform an unintended write to
AD4134_IFACE_CONFIG_A_REG (0x00)?

Should AD4134_DIG_IF_CFG_REG also be configured for single-channel DOUT0
output in 4-wire mode, and should ad4134_data_read() use a spi_transfer
with .cs_off = true?

> +
> +	st->odr_gpio = devm_gpiod_get(dev, "odr", GPIOD_OUT_LOW);
> +	if (IS_ERR(st->odr_gpio))
> +		return dev_err_probe(dev, PTR_ERR(st->odr_gpio),
> +				     "failed to get ODR GPIO\n");
>  
>  	ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
>  					      iio_pollfunc_store_time,

[ ... ]

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1792200021.git.marcelo.schmitt@analog.com?part=12

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

* Re: [PATCH v5 14/15] iio: adc: ad4134: Support high-speed data capture
  2026-10-17  2:00 ` [PATCH v5 14/15] iio: adc: ad4134: Support high-speed data capture Marcelo Schmitt
@ 2026-10-17  2:21   ` sashiko-bot
  0 siblings, 0 replies; 22+ messages in thread
From: sashiko-bot @ 2026-10-17  2:21 UTC (permalink / raw)
  To: Marcelo Schmitt, devicetree; +Cc: robh, conor+dt

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [High] iio: adc: ad4134: positive return from pwm_round_waveform_might_sleep()
- [High] iio: adc: ad4134: ODR PWM enabled in probe and never disabled
- [Medium] iio: adc: ad4134: period rounding drift in ad4134_update_conversion_rate()
- [Medium] iio: adc: ad4134: trigger offset uses unrounded ODR high time
--

commit 08608ae1b3f8617876d1b47ec67b7654d5a033e9
Author: Marcelo Schmitt <marcelo.schmitt@analog.com>

iio: adc: ad4134: Support high-speed data capture

This commit adds SPI transfer offload support to the ad4134 ADC driver,
using a periodic PWM trigger and DMA engine buffer to capture samples at
rates up to 1.496 MSPS.

> diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c
> index 6b05e40f7aeb7..21e8039b34116 100644
> --- a/drivers/iio/adc/ad4134.c
> +++ b/drivers/iio/adc/ad4134.c
[ ... ]
> @@ -461,6 +515,92 @@ static const struct regmap_config ad4134_regmap_config = {
>  	.max_register = AD4134_CH_VREG(AD4134_NUM_CHANNELS - 1),
>  };
>  
> +static int ad4134_update_conversion_rate(struct ad4134_state *st,
> +					 unsigned int freq_Hz)
> +{
> +	struct spi_offload_trigger_config config = st->offload_trigger_config;
> +	struct pwm_waveform odr_wf = { };
> +	u64 offload_period_ns;
> +	u64 offload_offset_ns;
> +	u64 odr_high_time_ns;
> +	unsigned int count;
> +	u64 target_ns;
> +	int ret;
> +
> +	if (!in_range(freq_Hz, AD4134_MIN_ODR_FREQ_HZ,
> +		      AD4134_MAX_ODR_FREQ_HZ - AD4134_MIN_ODR_FREQ_HZ + 1))
> +		return -ERANGE;
> +
> +	odr_wf.period_length_ns = DIV_ROUND_UP_ULL(NSEC_PER_SEC, freq_Hz);
> +	/*
> +	 * Set the PWM duty cycle to keep ODR high for at least minimum required
> +	 * time. If the rounded PWM's value is less than the minimum required,
> +	 * increase the target value by 10 and attempt to round the waveform
> +	 * again, until the minimum (or try count limit) is reached.
> +	 */
> +	odr_high_time_ns = div64_ul(6ULL * NSEC_PER_SEC, st->sys_clk_hz);
> +	target_ns = 0;
> +	count = 100;
> +	do {
> +		target_ns += 10; /* Increment by PWM duty cycle period */
> +		odr_wf.duty_length_ns = target_ns;
> +		ret = pwm_round_waveform_might_sleep(st->odr_pwm, &odr_wf);
> +		if (ret)
> +			return ret;
> +	} while (--count && odr_wf.duty_length_ns < odr_high_time_ns);

[Severity: High]
In ad4134_update_conversion_rate(), pwm_round_waveform_might_sleep() returns
0 on exact or downward rounding, 1 when a waveform value had to be rounded up,
or a negative errno on failure:

drivers/pwm/core.c:
 * Returns: 0 on success, 1 if at least one value had to be rounded up or a
 * negative errno.
 * Context: May sleep.
 */
int pwm_round_waveform_might_sleep(struct pwm_device *pwm, struct pwm_waveform *wf)

Because target_ns starts at 0 (requesting 10 ns on the first iteration) and
the return value is checked with if (ret) instead of if (ret < 0), won't any
upward rounding cause ad4134_update_conversion_rate() to abort and return +1
to ad4134_offload_setup() -> ad4134_probe() or ad4134_write_raw()?

Also, since target_ns starts at 0 and only increments up to 1000 ns across
100 iterations rather than starting at odr_high_time_ns, this performs
unnecessary rounding calls at the nominal 48 MHz clock (where
odr_high_time_ns is 125 ns) and will always exhaust count and fail with
-EDOM if st->sys_clk_hz < 6 MHz. Should target_ns start at odr_high_time_ns
and check if (ret < 0)?

> +
> +	/* Check the minimum ODR high time is met */
> +	if (odr_wf.duty_length_ns < odr_high_time_ns)
> +		return -EDOM;
> +
> +	if (odr_wf.period_length_ns < 2 * odr_high_time_ns)
> +		return -EDOM;
> +
> +	/*
> +	 * Configure SPI offload PWM trigger.
> +	 * For gated DCLK, the minimum required time between ODR rising edge
> +	 * and DCLK rising edge is the sum of ODR high time and ODR falling
> +	 * edge to DCLK rising edge time. Delay the offload trigger for at least
> +	 * that amount of time so the ADC sample data will be available when the
> +	 * SPI transfer begin.
> +	 *
> +	 * Use the same period as ODR PWM to avoid timing issues.
> +	 * Convert back from period to frequency for the SPI offload API.
> +	 */
> +	offload_period_ns = odr_wf.period_length_ns;
> +	config.periodic.frequency_hz = DIV_ROUND_UP_ULL(HZ_PER_GHZ, offload_period_ns);
> +	offload_offset_ns = odr_high_time_ns + AD4134_DCLK_RISING_OFFSET_NS;
> +	count = 100;
> +	do {
> +		config.periodic.offset_ns = offload_offset_ns;
> +		ret = spi_offload_trigger_validate(st->offload_trigger, &config);
> +		if (ret)
> +			return ret;
> +
> +		offload_offset_ns += 10;
> +	} while (--count && config.periodic.offset_ns < odr_high_time_ns +
> +							AD4134_DCLK_RISING_OFFSET_NS);
> +
> +	/* Check the minimum ODR to DCLK delay is met */
> +	if (config.periodic.offset_ns < odr_high_time_ns + AD4134_DCLK_RISING_OFFSET_NS)
> +		return -EDOM;

[Severity: Medium]
Here in ad4134_update_conversion_rate(), offload_offset_ns and the loop
termination checks use the theoretical minimum odr_high_time_ns rather than
the actual rounded ODR pulse width odr_wf.duty_length_ns.

If pwm_round_waveform_might_sleep() rounds odr_wf.duty_length_ns up above
odr_high_time_ns (for example, to 140 ns or 150 ns when odr_high_time_ns is
125 ns), the ODR falling edge occurs at odr_wf.duty_length_ns. Validating
config.periodic.offset_ns against odr_high_time_ns +
AD4134_DCLK_RISING_OFFSET_NS (133 ns) allows the SPI offload trigger to fire
less than 8 ns after (or simultaneously with) the actual ODR falling edge.

Should offload_offset_ns and the post-validation checks use
odr_wf.duty_length_ns + AD4134_DCLK_RISING_OFFSET_NS instead?

> +
> +	/* Check the PWM periods remain the same */
> +	offload_period_ns = DIV_ROUND_UP_ULL(HZ_PER_GHZ, config.periodic.frequency_hz);
> +	if (odr_wf.period_length_ns != offload_period_ns)
> +		return -EDOM;

[Severity: Medium]
Can this period equality check in ad4134_update_conversion_rate() reject valid
sampling frequencies in the [10, 1496000] Hz range with -EDOM?

In spi_offload_trigger_pwm_validate(), config.periodic.frequency_hz is
converted back to a period via DIV_ROUND_UP_ULL(NSEC_PER_SEC,
periodic->frequency_hz), rounded down by the PWM hardware, and written back to
periodic->frequency_hz:

drivers/spi/spi-offload-trigger-pwm.c:spi_offload_trigger_pwm_validate() {
	wf.period_length_ns = DIV_ROUND_UP_ULL(NSEC_PER_SEC, periodic->frequency_hz);
	...
	ret = pwm_round_waveform_might_sleep(st->pwm, &wf);
	if (ret < 0)
		return ret;

	periodic->frequency_hz = DIV_ROUND_UP_ULL(NSEC_PER_SEC, wf.period_length_ns);
	periodic->offset_ns = wf.duty_offset_ns;
}

When odr_wf.period_length_ns is converted to an integer frequency_hz via
DIV_ROUND_UP_ULL(HZ_PER_GHZ, offload_period_ns), any period where
ceil(10^9 / ceil(10^9 / P)) != P (such as almost all frequencies below
31.6 kHz, e.g., 60 Hz or 19200 Hz) produces a smaller wf.period_length_ns in
spi_offload_trigger_pwm_validate().

In addition, because config.periodic.frequency_hz is set outside the do-while
loop and modified in-place by spi_offload_trigger_validate(), each loop
iteration feeds the rounded-up frequency_hz back into
spi_offload_trigger_validate(), causing the trigger period to shrink further
across iterations and fail the odr_wf.period_length_ns != offload_period_ns
check.

> +
> +	ret = pwm_set_waveform_might_sleep(st->odr_pwm, &odr_wf, false);
> +	if (ret)
> +		return ret;
> +
> +	st->offload_trigger_config = config;
> +	st->odr_wf = odr_wf;
> +	st->odr_hz = DIV_ROUND_UP_ULL(NSEC_PER_SEC, odr_wf.period_length_ns);
> +
> +	return 0;
> +}
[ ... ]
> @@ -602,6 +783,166 @@ static const struct iio_info ad4134_info = {
>  	.debugfs_reg_access = ad4134_debugfs_reg_access,
>  };
[ ... ]
> +static int ad4134_offload_buffer_postenable(struct iio_dev *indio_dev)
> +{
> +	struct ad4134_state *st = iio_priv(indio_dev);
> +	int ret, access_ret;
> +
> +	ret = ad4134_claim_sample_access(st);
> +	if (ret)
> +		return ret;
> +
> +	ad4134_prepare_offload_msg(indio_dev);
> +	st->msg.offload = st->offload;
> +	ret = spi_optimize_message(st->spi, &st->msg);
> +	if (ret)
> +		goto out_offload_release;
> +
> +	ret = spi_offload_trigger_enable(st->offload, st->offload_trigger,
> +					 &st->offload_trigger_config);
> +	if (ret)
> +		goto out_unoptimize;
> +
> +	return 0;
> +
> +out_unoptimize:
> +	spi_unoptimize_message(&st->msg);
> +
> +out_offload_release:
> +	access_ret = ad4134_release_sample_access(st);
> +	if (access_ret)
> +		dev_err(&st->spi->dev, "reg input select error: %d\n", access_ret);
> +
> +	return ret;
> +}
> +
> +static int ad4134_offload_buffer_predisable(struct iio_dev *indio_dev)
> +{
> +	struct ad4134_state *st = iio_priv(indio_dev);
> +
> +	spi_offload_trigger_disable(st->offload, st->offload_trigger);
> +	spi_unoptimize_message(&st->msg);
> +
> +	return ad4134_release_sample_access(st);
> +}
> +
> +static const struct iio_buffer_setup_ops ad4134_offload_buffer_setup_ops = {
> +	.postenable = &ad4134_offload_buffer_postenable,
> +	.predisable = &ad4134_offload_buffer_predisable,
> +};
> +
> +static int ad4134_pwm_get(struct ad4134_state *st)
> +{
> +	struct device *dev = &st->spi->dev;
> +
> +	st->odr_pwm = devm_pwm_get(dev, NULL);
> +	if (IS_ERR(st->odr_pwm))
> +		return dev_err_probe(dev, PTR_ERR(st->odr_pwm),
> +				     "failed to get ODR PWM\n");
> +
> +	return 0;
> +}

[Severity: High]
How is the lifecycle of st->odr_pwm managed?

During probe, ad4134_offload_setup() calls ad4134_update_conversion_rate(),
which calls pwm_set_waveform_might_sleep(st->odr_pwm, &odr_wf, false) with a
non-zero duty cycle and period. This immediately enables the ODR PWM output
before the AD4134 registers are configured.

Furthermore, st->odr_wf is saved in ad4134_update_conversion_rate() but never
used, and neither ad4134_offload_buffer_predisable() nor any devm cleanup
action ever disables st->odr_pwm. Because devm_pwm_get() only releases the
PWM reference without stopping hardware output, won't st->odr_pwm remain
running continuously when the buffer is disabled, or after late probe failure
and driver unbind (driving the ODR pin after the ADC's clocks and regulators
have been disabled)?

[ ... ]

> +static int ad4134_offload_setup(struct iio_dev *indio_dev, struct ad4134_state *st)
> +{
> +	struct device *dev = &st->spi->dev;
> +	int ret;
> +
> +	ret = ad4134_pwm_get(st);
> +	if (ret)
> +		return ret;
> +
> +	ret = ad4134_offload_buffer_setup(indio_dev, st->spi);
> +	if (ret)
> +		return ret;
> +
> +	/*
> +	 * Start with a sampling rate slower than 374 kSPS because that is the
> +	 * maximum rate supported with wideband filter (default on power up).
> +	 */
> +	st->odr_hz = 250 * HZ_PER_KHZ;
> +	ret = ad4134_update_conversion_rate(st, st->odr_hz);
> +	if (ret)
> +		return dev_err_probe(dev, ret, "failed to set sampling freq\n");

[ ... ]

> +}

[ ... ]

> @@ -776,17 +1117,40 @@ static int ad4134_probe(struct spi_device *spi)

[ ... ]

> +	st->offload = devm_spi_offload_get(dev, spi, &ad4134_offload_config);
> +	ret = PTR_ERR_OR_ZERO(st->offload);
> +	/* Fall back to low speed usage when no SPI offload is available. */
> +	if (ret == -ENODEV) {

[ ... ]

> +	} else if (ret) {
> +		return dev_err_probe(dev, ret, "failed to get offload\n");
> +	} else {
> +		if (st->spi_mode == AD4134_SPI_MODE_NO_CS)
> +			return dev_err_probe(dev, -EPROTONOSUPPORT,
> +					     "Unsupported min I/O + offload config\n");
> +
> +		indio_dev->info = &ad4134_offload_info;
> +		indio_dev->channels = ad4134_offload_chan_set;
> +		indio_dev->num_channels = ARRAY_SIZE(ad4134_offload_chan_set);
> +		ret = ad4134_offload_setup(indio_dev, st);
> +		if (ret)
> +			return dev_err_probe(dev, ret,
> +					     "failed to setup SPI offload\n");
> +	}

[ ... ]

>  	return devm_iio_device_register(dev, indio_dev);
>  }

[ ... ]

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1792200021.git.marcelo.schmitt@analog.com?part=14

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

* Re: [PATCH v5 03/15] iio: adc: ad4134: Apply reset recovery wait time
  2026-10-17  1:57 ` [PATCH v5 03/15] iio: adc: ad4134: Apply reset recovery wait time Marcelo Schmitt
  2026-10-17  2:05   ` sashiko-bot
@ 2026-10-17  5:55   ` Joshua Crofts
  1 sibling, 0 replies; 22+ messages in thread
From: Joshua Crofts @ 2026-10-17  5:55 UTC (permalink / raw)
  To: Marcelo Schmitt
  Cc: linux-iio, devicetree, linux-kernel, linux, jic23, nuno.sa,
	dlechner, andy, Michael.Hennerich, robh, krzk+dt, conor+dt,
	corbet, skhan, marcelo.schmitt1

On Fri, 16 Oct 2026 22:57:08 -0300
Marcelo Schmitt <marcelo.schmitt@analog.com> wrote:

> Add a reset recovery wait time to avoid any SPI transfer from running too
> soon during device probe.
> 
> Fixes: e0bc6d7e2584 ("iio: adc: Initial support for AD4134")
> Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
> ---
> New patch in v5.
> 
>  drivers/iio/adc/ad4134.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c
> index 40b27b01f126..d555874b4959 100644
> --- a/drivers/iio/adc/ad4134.c
> +++ b/drivers/iio/adc/ad4134.c
> @@ -442,6 +442,7 @@ static int ad4134_probe(struct spi_device *spi)
>  		return dev_err_probe(dev, PTR_ERR(rst),
>  				     "failed to get and deassert reset\n");
>  
> +	fsleep(AD4134_RESET_TIME_US);
>  	crc8_populate_msb(ad4134_spi_crc_table, AD4134_SPI_CRC_POLYNOM);
>  
>  	st->regmap = devm_regmap_init(dev, NULL, st, &ad4134_regmap_config);

Reviewed-by: Joshua Crofts <joshua.crofts1@gmail.com>

-- 
Kind regards,
Joshua Crofts

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

* Re: [PATCH v5 09/15] iio: adc: ad4134: Support buffered data read
  2026-10-17  1:59 ` [PATCH v5 09/15] iio: adc: ad4134: Support buffered data read Marcelo Schmitt
@ 2026-10-17  5:59   ` Joshua Crofts
  0 siblings, 0 replies; 22+ messages in thread
From: Joshua Crofts @ 2026-10-17  5:59 UTC (permalink / raw)
  To: Marcelo Schmitt
  Cc: linux-iio, devicetree, linux-kernel, linux, jic23, nuno.sa,
	dlechner, andy, Michael.Hennerich, robh, krzk+dt, conor+dt,
	corbet, skhan, marcelo.schmitt1

On Fri, 16 Oct 2026 22:59:00 -0300
Marcelo Schmitt <marcelo.schmitt@analog.com> wrote:

> Enable users to run buffered data captures triggered by IIO trigger device.
> Add an IIO timestamp channel so each data scan is provided with measurement
> time information. Require single-read operations to be in IIO device direct
> access mode to prevent buffered and single-shot data captures to disrupt
> each other.
> 
> Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
> ---

Reviewed-by: Joshua Crofts <joshua.crofts1@gmail.com>

-- 
Kind regards,
Joshua Crofts

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

end of thread, other threads:[~2026-10-17  5:59 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-17  1:56 [PATCH v5 00/15] iio: adc: ad4134: Enable greater sample rate data capture Marcelo Schmitt
2026-10-17  1:56 ` [PATCH v5 01/15] iio: adc: ad4134: Adjust register map range Marcelo Schmitt
2026-10-17  1:56 ` [PATCH v5 02/15] iio: adc: ad4134: Sign extend sample data Marcelo Schmitt
2026-10-17  1:57 ` [PATCH v5 03/15] iio: adc: ad4134: Apply reset recovery wait time Marcelo Schmitt
2026-10-17  2:05   ` sashiko-bot
2026-10-17  5:55   ` Joshua Crofts
2026-10-17  1:57 ` [PATCH v5 04/15] iio: adc: ad4134: Update include list to comply with IWYU principles Marcelo Schmitt
2026-10-17  1:57 ` [PATCH v5 05/15] iio: adc: ad4134: Serialize single-read operations Marcelo Schmitt
2026-10-17  1:58 ` [PATCH v5 06/15] iio: adc: ad4134: Protect conventional device access from debug accesses Marcelo Schmitt
2026-10-17  1:58 ` [PATCH v5 07/15] iio: adc: ad4134: Run shorter transfers when CRC is disabled Marcelo Schmitt
2026-10-17  1:58 ` [PATCH v5 08/15] iio: adc: ad4134: Add support for digital filter type selection Marcelo Schmitt
2026-10-17  2:16   ` sashiko-bot
2026-10-17  1:59 ` [PATCH v5 09/15] iio: adc: ad4134: Support buffered data read Marcelo Schmitt
2026-10-17  5:59   ` Joshua Crofts
2026-10-17  1:59 ` [PATCH v5 10/15] dt-bindings: iio: adc: adi,ad4134: Document SPI connection mode Marcelo Schmitt
2026-10-17  1:59 ` [PATCH v5 11/15] dt-bindings: iio: adc: adi,ad4134: Document external multiplexer usage Marcelo Schmitt
2026-10-17  1:59 ` [PATCH v5 12/15] iio: adc: ad4134: Support SPI 4-wire mode Marcelo Schmitt
2026-10-17  2:19   ` sashiko-bot
2026-10-17  2:00 ` [PATCH v5 13/15] dt-bindings: iio: adc: adi,ad4134: Document PWM usage Marcelo Schmitt
2026-10-17  2:00 ` [PATCH v5 14/15] iio: adc: ad4134: Support high-speed data capture Marcelo Schmitt
2026-10-17  2:21   ` sashiko-bot
2026-10-17  2:00 ` [PATCH v5 15/15] Docs: iio: Add AD4134 Marcelo Schmitt

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.