* [PATCH v1 00/13] iio: adc: ad4134: Enable greater sample rate data capture
@ 2026-09-02 17:21 Marcelo Schmitt
2026-09-02 17:21 ` [PATCH v1 01/13] iio: Fix typo in vendor name Marcelo Schmitt
` (12 more replies)
0 siblings, 13 replies; 21+ messages in thread
From: Marcelo Schmitt @ 2026-09-02 17:21 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 to reflect previously missing chip characteristics.
Minor improvements (introduced before the new features):
- Fix typo in vendor name.
- Drop import to empty name space.
- Update include list to comply with IWYU principles.
- Serialize single-read operations.
- Run shorter transfers when CRC is disabled.
Marcelo Schmitt (13):
iio: Fix typo in vendor name
iio: adc: ad4134: Drop import to empty name space
iio: adc: ad4134: Update include list to comply with IWYU principles
iio: adc: ad4134: Serialize single-read operations
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
iio: adc: ad4134: Support SPI 4-wire mode
dt-bindings: iio: adc: adi,ad4134: Document PWM usage
dt-bindings: iio: adc: adi,ad4134: Add high data throughput example
iio: adc: ad4134: Support high-speed data capture
Docs: iio: Add AD4134
.../bindings/iio/adc/adi,ad4134.yaml | 68 ++
Documentation/iio/ad4134.rst | 128 ++++
Documentation/iio/index.rst | 1 +
MAINTAINERS | 1 +
drivers/iio/adc/Kconfig | 20 +-
drivers/iio/adc/ad4134.c | 698 +++++++++++++++++-
drivers/iio/dac/ad3552r.c | 2 +-
7 files changed, 893 insertions(+), 25 deletions(-)
create mode 100644 Documentation/iio/ad4134.rst
base-commit: 8992f32c57607bdfaf5de2a2cd26b3b71f3a9d55
prerequisite-patch-id: a509ef662def60ff7a33b7dd949f26cd0eb1b8b7
prerequisite-patch-id: 6b5e2a61b7363b24fa9b9d2f6b20de57550415df
prerequisite-patch-id: 8dcffa92e3d7686214eda37a00a7c58d969d1bbf
prerequisite-patch-id: f84fc98c5728b8a2d401aa97507bed57e4748c7c
prerequisite-patch-id: fc9dcff6eae8019f0e0c38409cfafe020d5aaa05
prerequisite-patch-id: 578583880ef301e0901be4b23d05de5a1ccca926
prerequisite-patch-id: a2a4b770f7b76b965a2eaac95a7d8d1b6c956a7c
prerequisite-patch-id: c42fead7b0d37866757d55679ec2252bc67e9679
prerequisite-patch-id: 851fddf35c3e7cf142a0274879f7bfe354c44b48
prerequisite-patch-id: bcbffeedc3004ae7c7d38e0968248379a2cc11d3
prerequisite-patch-id: 29da6bee42ad3a8a1c1ab3cfa7196e3da8c255a5
prerequisite-patch-id: 24b9fc5c9f8f5e39454a714b6119bcc66c68c332
prerequisite-patch-id: 17ef931c5e720671a4ad3d245c530c3b225a11d2
prerequisite-patch-id: d6c8f2b172bcdf33f3e26cce3aa257cd6abde8f3
prerequisite-patch-id: 5362999f38f6c7db8c232815719d62864cdf9bb4
prerequisite-patch-id: 3c45895d15347202dcb333f4b75589defda6c8bd
prerequisite-patch-id: aa612ba587be22841cbaf1e817afc037a53bdb6e
prerequisite-patch-id: abd9264f4a8ce712fc02a6759cd984591e080714
prerequisite-patch-id: 2305923b790db41e048b4eadd2751837ee356e0f
prerequisite-patch-id: 99eba606a73a31f9cd8edf9efe43f353fa4c6dc1
prerequisite-patch-id: a6821645307265ecb3e8a9192a7ca75ff4ef4c25
prerequisite-patch-id: 3d73401e6137ec3f4b9a2c74aa8bde5ac73c7f43
prerequisite-patch-id: 980b5343a5ed0d38dc3deb50168dffd9a3aa94e5
prerequisite-patch-id: b6ad0c491dffc778949b689a82ae881bd73a7e70
prerequisite-patch-id: a180b3ed7c48d6917291db69f2c737d5f0ae54ef
prerequisite-patch-id: 206d438356ef9752c5409ef2ad6c8abcb4561bfe
prerequisite-patch-id: 0c21540845530f357bd1f0ecd5acb6933396b011
prerequisite-patch-id: 83d82a4a7da474a2be230c938cd01a8654db4b76
prerequisite-patch-id: 7a7bbfcead00fbe85dbcc9717a322dd394c115ff
prerequisite-patch-id: 56fb22d293ed8d1f00446bab19ddd3eab5927a22
prerequisite-patch-id: a54d660597db7fb3f916e8a3c9cf7efa401ae7df
prerequisite-patch-id: b9520c10d63f34769b18ac2034dbfe86e21444aa
prerequisite-patch-id: 2d3f13c29a14be6612de58b0ff45de3f25fec6a2
prerequisite-patch-id: 04fc520dd6f9ab1cf21b50d9052fe42072481407
prerequisite-patch-id: 98aa7964283264e9fb272303f020d96e9d2a6b58
prerequisite-patch-id: a5affc1602a01d0591824a7d11411774fcd381e1
prerequisite-patch-id: 9d8e457f7f9922a6b966193f207332efce7a2259
prerequisite-patch-id: e242d91086a77f3405497a0aee5ddafa971e735e
prerequisite-patch-id: 54e443d84b2f92b602b98d4a0cb902fd83c86691
prerequisite-patch-id: 36db49f322d7859248ae7a51f48f6c9a9986c86e
prerequisite-patch-id: 7dd860477d9c68f12baf74013c7c9b217086ea52
prerequisite-patch-id: aacc247928434df5d0017b6e96e6e8ccab4fd98e
prerequisite-patch-id: 60ea842bf051438047cc6d4383de237bbd7d57a1
prerequisite-patch-id: 1bdde9ce22e6b2818245ab8441fc22a203c116d0
prerequisite-patch-id: 9013dbccb132763b987e40e41d0a2141a4732144
prerequisite-patch-id: fa77c324defdf995d708ab78b46d03e4c456a046
prerequisite-patch-id: fe533cbe9cf454eef8d50aa340b21e1052458f17
--
2.53.0
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v1 01/13] iio: Fix typo in vendor name
2026-09-02 17:21 [PATCH v1 00/13] iio: adc: ad4134: Enable greater sample rate data capture Marcelo Schmitt
@ 2026-09-02 17:21 ` Marcelo Schmitt
2026-09-03 6:22 ` Andy Shevchenko
2026-09-02 17:21 ` [PATCH v1 02/13] iio: adc: ad4134: Drop import to empty name space Marcelo Schmitt
` (11 subsequent siblings)
12 siblings, 1 reply; 21+ messages in thread
From: Marcelo Schmitt @ 2026-09-02 17:21 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
Correct a typo in vendor company name: "Analog Device" -> "Analog Devices".
Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
---
Now
find drivers/iio/ -type f | xargs grep -i "Analog Device "
finds no leftover occurrence of such typo.
Also,
grep -nrIi drivers/iio/ -e "Analog Device" | wc -l
and
grep -nrIi drivers/iio/ -e "Analog Devices" | wc -l
both count the same number of lines.
drivers/iio/adc/Kconfig | 12 ++++++------
drivers/iio/dac/ad3552r.c | 2 +-
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 38e212a6f789..02f189e90c30 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -105,7 +105,7 @@ config AD4080
called ad4080.
config AD4130
- tristate "Analog Device AD4130 ADC Driver"
+ tristate "Analog Devices AD4130 ADC Driver"
depends on SPI
depends on GPIOLIB
select IIO_BUFFER
@@ -121,7 +121,7 @@ config AD4130
called ad4130.
config AD4134
- tristate "Analog Device AD4134 ADC Driver"
+ tristate "Analog Devices AD4134 ADC Driver"
depends on SPI
select REGMAP_SPI
select CRC8
@@ -133,7 +133,7 @@ config AD4134
called ad4134_spi.
config AD4170_4
- tristate "Analog Device AD4170-4 ADC Driver"
+ tristate "Analog Devices AD4170-4 ADC Driver"
depends on SPI
select REGMAP_SPI
select IIO_BUFFER
@@ -164,7 +164,7 @@ config AD4691
called ad4691.
config AD4695
- tristate "Analog Device AD4695 ADC Driver"
+ tristate "Analog Devices AD4695 ADC Driver"
depends on SPI
select IIO_BUFFER
select IIO_BUFFER_DMAENGINE
@@ -179,7 +179,7 @@ config AD4695
called ad4695.
config AD4851
- tristate "Analog Device AD4851 DAS Driver"
+ tristate "Analog Devices AD4851 DAS Driver"
depends on SPI
depends on PWM
select REGMAP_SPI
@@ -347,7 +347,7 @@ config AD7380
called ad7380.
config AD7405
- tristate "Analog Device AD7405 ADC Driver"
+ tristate "Analog Devices AD7405 ADC Driver"
depends on IIO_BACKEND
help
Say yes here to build support for Analog Devices AD7405, ADUM7701,
diff --git a/drivers/iio/dac/ad3552r.c b/drivers/iio/dac/ad3552r.c
index 16db94fef9d4..039af514adde 100644
--- a/drivers/iio/dac/ad3552r.c
+++ b/drivers/iio/dac/ad3552r.c
@@ -696,6 +696,6 @@ static struct spi_driver ad3552r_driver = {
module_spi_driver(ad3552r_driver);
MODULE_AUTHOR("Mihail Chindris <mihail.chindris@analog.com>");
-MODULE_DESCRIPTION("Analog Device AD3552R DAC");
+MODULE_DESCRIPTION("Analog Devices AD3552R DAC");
MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS("IIO_AD3552R");
--
2.53.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v1 02/13] iio: adc: ad4134: Drop import to empty name space
2026-09-02 17:21 [PATCH v1 00/13] iio: adc: ad4134: Enable greater sample rate data capture Marcelo Schmitt
2026-09-02 17:21 ` [PATCH v1 01/13] iio: Fix typo in vendor name Marcelo Schmitt
@ 2026-09-02 17:21 ` Marcelo Schmitt
2026-09-02 17:22 ` [PATCH v1 03/13] iio: adc: ad4134: Update include list to comply with IWYU principles Marcelo Schmitt
` (10 subsequent siblings)
12 siblings, 0 replies; 21+ messages in thread
From: Marcelo Schmitt @ 2026-09-02 17:21 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
Drop unused name space that somehow remained being included by the device
driver.
Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
---
drivers/iio/adc/ad4134.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c
index 0490218bb0e9..70f80bf1825f 100644
--- a/drivers/iio/adc/ad4134.c
+++ b/drivers/iio/adc/ad4134.c
@@ -496,4 +496,3 @@ 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_AD4134");
--
2.53.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v1 03/13] iio: adc: ad4134: Update include list to comply with IWYU principles
2026-09-02 17:21 [PATCH v1 00/13] iio: adc: ad4134: Enable greater sample rate data capture Marcelo Schmitt
2026-09-02 17:21 ` [PATCH v1 01/13] iio: Fix typo in vendor name Marcelo Schmitt
2026-09-02 17:21 ` [PATCH v1 02/13] iio: adc: ad4134: Drop import to empty name space Marcelo Schmitt
@ 2026-09-02 17:22 ` Marcelo Schmitt
2026-09-03 6:26 ` Andy Shevchenko
2026-09-02 17:22 ` [PATCH v1 04/13] iio: adc: ad4134: Serialize single-read operations Marcelo Schmitt
` (9 subsequent siblings)
12 siblings, 1 reply; 21+ messages in thread
From: Marcelo Schmitt @ 2026-09-02 17:22 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 includes that were missing (according to include-what-you-use tool)
to comply with include what is used principles. Namely, add bits.h for
BIT and GENMASK, and 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.
Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
---
drivers/iio/adc/ad4134.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c
index 70f80bf1825f..7a3b05aacc74 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/bits.h>
#include <linux/clk.h>
#include <linux/crc8.h>
#include <linux/delay.h>
@@ -14,18 +15,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] 21+ messages in thread
* [PATCH v1 04/13] iio: adc: ad4134: Serialize single-read operations
2026-09-02 17:21 [PATCH v1 00/13] iio: adc: ad4134: Enable greater sample rate data capture Marcelo Schmitt
` (2 preceding siblings ...)
2026-09-02 17:22 ` [PATCH v1 03/13] iio: adc: ad4134: Update include list to comply with IWYU principles Marcelo Schmitt
@ 2026-09-02 17:22 ` Marcelo Schmitt
2026-09-03 6:27 ` Andy Shevchenko
2026-09-02 17:23 ` [PATCH v1 05/13] iio: adc: ad4134: Run shorter transfers when CRC is disabled Marcelo Schmitt
` (8 subsequent siblings)
12 siblings, 1 reply; 21+ messages in thread
From: Marcelo Schmitt @ 2026-09-02 17:22 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
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.
Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
---
drivers/iio/adc/ad4134.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c
index 7a3b05aacc74..3460ecf4cafd 100644
--- a/drivers/iio/adc/ad4134.c
+++ b/drivers/iio/adc/ad4134.c
@@ -8,6 +8,7 @@
#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/bits.h>
+#include <linux/cleanup.h>
#include <linux/clk.h>
#include <linux/crc8.h>
#include <linux/delay.h>
@@ -16,6 +17,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>
@@ -100,6 +102,11 @@ struct ad4134_state {
unsigned long sys_clk_hz;
struct gpio_desc *odr_gpio;
int refin_mv;
+ /*
+ * Synchronize access to members the of driver state, and ensure
+ * atomicity of consecutive register access operations.
+ */
+ struct mutex lock;
/*
* DMA (thus cache coherency maintenance) requires the transfer buffers
* to live in their own cache lines.
@@ -257,6 +264,7 @@ static int ad4134_read_raw(struct iio_dev *indio_dev,
switch (info) {
case IIO_CHAN_INFO_RAW:
+ guard(mutex)(&st->lock);
gpiod_set_value_cansleep(st->odr_gpio, 1);
/*
* For slave mode gated DCLK (data sheet page 11), the minimum
@@ -443,6 +451,10 @@ static int ad4134_probe(struct spi_device *spi)
crc8_populate_msb(ad4134_spi_crc_table, AD4134_SPI_CRC_POLYNOM);
+ ret = devm_mutex_init(dev, &st->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] 21+ messages in thread
* [PATCH v1 05/13] iio: adc: ad4134: Run shorter transfers when CRC is disabled
2026-09-02 17:21 [PATCH v1 00/13] iio: adc: ad4134: Enable greater sample rate data capture Marcelo Schmitt
` (3 preceding siblings ...)
2026-09-02 17:22 ` [PATCH v1 04/13] iio: adc: ad4134: Serialize single-read operations Marcelo Schmitt
@ 2026-09-02 17:23 ` Marcelo Schmitt
2026-09-02 17:23 ` [PATCH v1 06/13] iio: adc: ad4134: Add support for digital filter type selection Marcelo Schmitt
` (7 subsequent siblings)
12 siblings, 0 replies; 21+ messages in thread
From: Marcelo Schmitt @ 2026-09-02 17:23 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.
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 3460ecf4cafd..7da6734d4609 100644
--- a/drivers/iio/adc/ad4134.c
+++ b/drivers/iio/adc/ad4134.c
@@ -102,6 +102,7 @@ struct ad4134_state {
unsigned long sys_clk_hz;
struct gpio_desc *odr_gpio;
int refin_mv;
+ bool crc_en;
/*
* Synchronize access to members the of driver state, and ensure
* atomicity of consecutive register access operations.
@@ -160,7 +161,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;
@@ -170,7 +171,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;
@@ -216,7 +217,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;
@@ -231,7 +232,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;
@@ -310,6 +311,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] 21+ messages in thread
* [PATCH v1 06/13] iio: adc: ad4134: Add support for digital filter type selection
2026-09-02 17:21 [PATCH v1 00/13] iio: adc: ad4134: Enable greater sample rate data capture Marcelo Schmitt
` (4 preceding siblings ...)
2026-09-02 17:23 ` [PATCH v1 05/13] iio: adc: ad4134: Run shorter transfers when CRC is disabled Marcelo Schmitt
@ 2026-09-02 17:23 ` Marcelo Schmitt
2026-09-03 6:31 ` Andy Shevchenko
2026-09-02 17:23 ` [PATCH v1 07/13] iio: adc: ad4134: Support buffered data read Marcelo Schmitt
` (6 subsequent siblings)
12 siblings, 1 reply; 21+ messages in thread
From: Marcelo Schmitt @ 2026-09-02 17:23 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>
---
drivers/iio/adc/ad4134.c | 80 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 80 insertions(+)
diff --git a/drivers/iio/adc/ad4134.c b/drivers/iio/adc/ad4134.c
index 7da6734d4609..a1474316e330 100644
--- a/drivers/iio/adc/ad4134.c
+++ b/drivers/iio/adc/ad4134.c
@@ -64,6 +64,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
@@ -81,12 +84,48 @@
#define AD4134_SPI_CRC_INIT_VALUE 0xA5
static unsigned char ad4134_spi_crc_table[CRC8_TABLE_SIZE];
+enum ad4134_filter_type {
+ AD4134_WIDEBAND,
+ AD4134_SINC6,
+ AD4134_SINC3,
+ AD4134_SINC3_REJ60,
+};
+
+static const char * const ad4134_filt_names[] = {
+ [AD4134_WIDEBAND] = "wideband",
+ [AD4134_SINC6] = "sinc6",
+ [AD4134_SINC3] = "sinc3",
+ [AD4134_SINC3_REJ60] = "sinc3+rej60",
+};
+
+static int ad4134_get_filter_type(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan);
+
+static int ad4134_set_filter_type(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ unsigned int 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[] = {
@@ -116,6 +155,47 @@ 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->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);
+ enum ad4134_filter_type f_type;
+ 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, ®_val);
+ if (ret)
+ return ret;
+
+ mask = AD4134_CHAN_DIG_FILTER_SEL_CH_MASK(chan->channel);
+ f_type = field_get(mask, reg_val);
+
+ return f_type;
+}
+
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] 21+ messages in thread
* [PATCH v1 07/13] iio: adc: ad4134: Support buffered data read
2026-09-02 17:21 [PATCH v1 00/13] iio: adc: ad4134: Enable greater sample rate data capture Marcelo Schmitt
` (5 preceding siblings ...)
2026-09-02 17:23 ` [PATCH v1 06/13] iio: adc: ad4134: Add support for digital filter type selection Marcelo Schmitt
@ 2026-09-02 17:23 ` Marcelo Schmitt
2026-09-02 17:24 ` [PATCH v1 08/13] dt-bindings: iio: adc: adi,ad4134: Document SPI connection mode Marcelo Schmitt
` (5 subsequent siblings)
12 siblings, 0 replies; 21+ messages in thread
From: Marcelo Schmitt @ 2026-09-02 17:23 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>
---
drivers/iio/adc/Kconfig | 2 ++
drivers/iio/adc/ad4134.c | 59 ++++++++++++++++++++++++++++++++++++++--
2 files changed, 59 insertions(+), 2 deletions(-)
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 02f189e90c30..584251a3f45c 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 a1474316e330..0751b89dec8f 100644
--- a/drivers/iio/adc/ad4134.c
+++ b/drivers/iio/adc/ad4134.c
@@ -27,7 +27,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)
@@ -126,6 +129,14 @@ 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, \
+ .shift = 8, \
+ .endianness = IIO_BE, \
+ }, \
}
static const struct iio_chan_spec ad4134_chan_set[] = {
@@ -133,6 +144,7 @@ static const struct iio_chan_spec ad4134_chan_set[] = {
AD4134_CHANNEL(1),
AD4134_CHANNEL(2),
AD4134_CHANNEL(3),
+ IIO_CHAN_SOFT_TIMESTAMP(4),
};
struct ad4134_state {
@@ -151,7 +163,8 @@ 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);
+ u32 scan[AD4134_NUM_CHANNELS] __aligned(IIO_DMA_MINALIGN);
+ u8 rx_buf[AD4134_SPI_MAX_XFER_LEN];
u8 tx_buf[AD4134_SPI_MAX_XFER_LEN];
};
@@ -336,6 +349,36 @@ static const struct regmap_config ad4134_regmap_config = {
.max_register = AD4134_CH_VREG(ARRAY_SIZE(ad4134_chan_set)),
};
+static irqreturn_t ad4134_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct ad4134_state *st = iio_priv(indio_dev);
+ unsigned int i = 0;
+ int ret;
+
+ gpiod_set_value_cansleep(st->odr_gpio, 1);
+ fsleep(1);
+ gpiod_set_value_cansleep(st->odr_gpio, 0);
+
+ for (unsigned int ch = 0; ch < iio_get_masklength(indio_dev); ch++) {
+ ret = spi_write_then_read(st->spi, NULL, 0, &st->scan[ch],
+ BITS_TO_BYTES(AD4134_CHAN_PRECISION_BITS));
+ if (ret)
+ goto err_out;
+
+ if (test_bit(ch, indio_dev->active_scan_mask))
+ memcpy(&st->scan[i++], &st->scan[ch], sizeof(st->scan[ch]));
+ }
+
+ iio_push_to_buffers_with_ts(indio_dev, &st->scan, sizeof(st->scan),
+ pf->timestamp);
+
+err_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)
@@ -344,7 +387,11 @@ static int ad4134_read_raw(struct iio_dev *indio_dev,
int ret;
switch (info) {
- case IIO_CHAN_INFO_RAW:
+ case IIO_CHAN_INFO_RAW: {
+ IIO_DEV_ACQUIRE_DIRECT_MODE(indio_dev, claim);
+ if (IIO_DEV_ACQUIRE_FAILED(claim))
+ return -EBUSY;
+
guard(mutex)(&st->lock);
gpiod_set_value_cansleep(st->odr_gpio, 1);
/*
@@ -364,6 +411,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;
@@ -547,6 +595,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] 21+ messages in thread
* [PATCH v1 08/13] dt-bindings: iio: adc: adi,ad4134: Document SPI connection mode
2026-09-02 17:21 [PATCH v1 00/13] iio: adc: ad4134: Enable greater sample rate data capture Marcelo Schmitt
` (6 preceding siblings ...)
2026-09-02 17:23 ` [PATCH v1 07/13] iio: adc: ad4134: Support buffered data read Marcelo Schmitt
@ 2026-09-02 17:24 ` Marcelo Schmitt
2026-09-03 18:14 ` Conor Dooley
2026-09-02 17:24 ` [PATCH v1 09/13] iio: adc: ad4134: Support SPI 4-wire mode Marcelo Schmitt
` (4 subsequent siblings)
12 siblings, 1 reply; 21+ messages in thread
From: Marcelo Schmitt @ 2026-09-02 17:24 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
Document how AD4134 chips are connected to the host SPI controller
according to different wiring configurations.
Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
---
.../bindings/iio/adc/adi,ad4134.yaml | 22 +++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml
index ea6d7e026419..d843c02a394a 100644
--- a/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml
@@ -131,6 +131,28 @@ 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 ]
+ description: |
+ This property indicates the SPI wiring configuration.
+
+ When this property is omitted, it is assumed that the device is using
+ 'no-cs' wiring. When this property is present, it indicates that the
+ device is using one of the following wiring configurations:
+
+ * 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.
+
required:
- compatible
- reg
--
2.53.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v1 09/13] iio: adc: ad4134: Support SPI 4-wire mode
2026-09-02 17:21 [PATCH v1 00/13] iio: adc: ad4134: Enable greater sample rate data capture Marcelo Schmitt
` (7 preceding siblings ...)
2026-09-02 17:24 ` [PATCH v1 08/13] dt-bindings: iio: adc: adi,ad4134: Document SPI connection mode Marcelo Schmitt
@ 2026-09-02 17:24 ` Marcelo Schmitt
2026-09-03 6:39 ` Andy Shevchenko
2026-09-02 17:24 ` [PATCH v1 10/13] dt-bindings: iio: adc: adi,ad4134: Document PWM usage Marcelo Schmitt
` (3 subsequent siblings)
12 siblings, 1 reply; 21+ messages in thread
From: Marcelo Schmitt @ 2026-09-02 17:24 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
optimal 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>
---
The reason for the input multiplexer is enable both register access and
multi-lane read. Before coming to the current solution, we tried the following
configuration.
+-----------------------+ +-----------------+
| AD4134 | | SPI Controller |
| | | |
| SPI interface | | |
| for register SCLK |<--------------------------| SCLK |
| access CS |<--------------------------| CS |
| SDI |<--------------------------| SDO |
| SDO |---+ | |
| | | | |
| Data interface DOUT0 |---+---------------------->| SDI0 |
| for ADC data DOUT1 |-------------------------->| SDI1 |
| read back DOUT2 |-------------------------->| SDI2 |
| DOUT3 |-------------------------->| SDI3 |
| DCLK |<--------------------------| DCLK
| ODR |<------------------+ +->| Offload Trigger |
+-----------------------+ | | +-----------------+
| +--| PWM1 |
+-------| PWM0 |
+-------| GPIO |
+-----------------+
Though, because DOUT0 never goes high-Z, the DOUT0 pin keeps driving the data
line, causing register read to fail (always get 0xFF). Another solution would be
to connect SDO to SDI0 and DOUT pins to SDI1, SDI2, SDI3, SDI4. That would then
require a special multi-lane mode.
Please, see patch 13 for a better view of how the proposed setup works.
drivers/iio/adc/Kconfig | 1 +
drivers/iio/adc/ad4134.c | 162 +++++++++++++++++++++++++++++++++++++--
2 files changed, 158 insertions(+), 5 deletions(-)
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 584251a3f45c..ef77ee60df4e 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 0751b89dec8f..8453b44ef368 100644
--- a/drivers/iio/adc/ad4134.c
+++ b/drivers/iio/adc/ad4134.c
@@ -18,6 +18,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>
@@ -73,6 +75,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
@@ -87,6 +92,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,
@@ -154,11 +170,17 @@ struct ad4134_state {
struct gpio_desc *odr_gpio;
int refin_mv;
bool crc_en;
+ enum ad4134_spi_mode spi_mode;
+ struct mux_state *mux_st[2];
/*
* Synchronize access to members the of driver state, and ensure
* atomicity of consecutive register access operations.
*/
struct mutex lock;
+ /*
+ * Ensure atomicity of access mode switch operations.
+ */
+ struct mutex access_mode_lock;
/*
* DMA (thus cache coherency maintenance) requires the transfer buffers
* to live in their own cache lines.
@@ -233,6 +255,73 @@ static const struct regmap_access_table ad4134_regmap_wr_table = {
.n_yes_ranges = ARRAY_SIZE(ad4134_regmap_wr_range),
};
+/*
+ * When AD4134 SDO and DOUT0 pins are multiplexed, this function changes the
+ * multiplexer state to route SDO to the SPI controller.
+ */
+static int ad4134_set_register_access(struct ad4134_state *st)
+{
+ int ret;
+
+ guard(mutex)(&st->access_mode_lock);
+ st->spi->mode = SPI_MODE_0;
+ ret = spi_setup(st->spi);
+ if (ret)
+ return ret;
+
+ ret = mux_state_deselect(st->mux_st[AD4134_DOUT0_INPUT]);
+ if (ret)
+ dev_err(&st->spi->dev, "error on DOUT0 deselect: %d\n", ret);
+
+ ret = mux_state_try_select(st->mux_st[AD4134_SDO_INPUT]);
+ if (ret && ret != -EBUSY)
+ return ret;
+
+ return 0;
+}
+
+/*
+ * When AD4134 SDO and DOUT0 pins are multiplexed, this function changes the
+ * multiplexer state to route DOUT0 to the SPI controller. On failure, fall
+ * back to routing SDO to the controller and return an errno.
+ */
+static int ad4134_set_sample_access(struct ad4134_state *st)
+{
+ int ret, ret2;
+
+ guard(mutex)(&st->access_mode_lock);
+ ret = mux_state_deselect(st->mux_st[AD4134_SDO_INPUT]);
+ if (ret)
+ dev_err(&st->spi->dev, "error on SDO deselect: %d\n", ret);
+
+ ret = mux_state_try_select(st->mux_st[AD4134_DOUT0_INPUT]);
+ if (ret) {
+ dev_err(&st->spi->dev, "error on DOUT0 select: %d\n", ret);
+ return mux_state_select(st->mux_st[AD4134_SDO_INPUT]);
+ }
+
+ /*
+ * Data output on the DOUT lines is sampled on the falling edge
+ * (SPI mode 1).
+ */
+ st->spi->mode = SPI_MODE_1;
+ ret = spi_setup(st->spi);
+ if (ret) {
+ dev_err(&st->spi->dev, "failed to setup SPI mode 1: %d\n", ret);
+ ret2 = mux_state_deselect(st->mux_st[AD4134_DOUT0_INPUT]);
+ if (ret2)
+ dev_err(&st->spi->dev, "error on DOUT0 deselect: %d\n", ret2);
+
+ ret2 = mux_state_select(st->mux_st[AD4134_SDO_INPUT]);
+ if (ret2)
+ dev_err(&st->spi->dev, "error on SDO select: %d\n", ret2);
+
+ return ret;
+ }
+
+ return 0;
+}
+
static int ad4134_calc_spi_crc(u8 inst, u8 data)
{
u8 buf[] = { inst, data };
@@ -334,9 +423,25 @@ static int ad4134_register_read(struct ad4134_state *st, unsigned int reg,
static int ad4134_reg_read(void *context, unsigned int reg, unsigned int *val)
{
struct ad4134_state *st = context;
+ int ret, ret2;
- if (reg >= AD4134_CH_VREG(0))
- return ad4134_data_read(st, reg, val);
+ if (reg >= AD4134_CH_VREG(0)) {
+ if (st->spi_mode == AD4134_SPI_MODE_4_WIRE) {
+ ret = ad4134_set_sample_access(st);
+ if (ret)
+ return ret;
+ }
+
+ ret = ad4134_data_read(st, reg, val);
+
+ if (st->spi_mode == AD4134_SPI_MODE_4_WIRE) {
+ ret2 = ad4134_set_register_access(st);
+ if (ret2)
+ dev_err(&st->spi->dev, "access mode error: %d\n", ret2);
+ }
+
+ return ret;
+ }
return ad4134_register_read(st, reg, val);
}
@@ -379,6 +484,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_set_sample_access(iio_priv(indio_dev));
+}
+
+static int ad4134_buffer_predisable(struct iio_dev *indio_dev)
+{
+ return ad4134_set_register_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)
@@ -590,10 +710,42 @@ 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)
+ ret = device_property_match_property_string(dev, "adi,spi-mode",
+ ad4134_spi_modes,
+ ARRAY_SIZE(ad4134_spi_modes));
+ /* Default to "no-cs" mode if adi,spi-mode is not specified */
+ if (ret == -EINVAL)
+ st->spi_mode = AD4134_SPI_MODE_NO_CS;
+ else if (ret < 0)
return dev_err_probe(dev, ret,
- "failed to setup minimum I/O mode\n");
+ "getting adi,spi-mode property failed\n");
+ else
+ st->spi_mode = ret;
+
+ if (st->spi_mode == AD4134_SPI_MODE_NO_CS) {
+ 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 {
+ st->mux_st[AD4134_SDO_INPUT] = devm_mux_state_get_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");
+
+ 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;
+ }
ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
iio_pollfunc_store_time,
--
2.53.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v1 10/13] dt-bindings: iio: adc: adi,ad4134: Document PWM usage
2026-09-02 17:21 [PATCH v1 00/13] iio: adc: ad4134: Enable greater sample rate data capture Marcelo Schmitt
` (8 preceding siblings ...)
2026-09-02 17:24 ` [PATCH v1 09/13] iio: adc: ad4134: Support SPI 4-wire mode Marcelo Schmitt
@ 2026-09-02 17:24 ` Marcelo Schmitt
2026-09-02 17:25 ` [PATCH v1 11/13] dt-bindings: iio: adc: adi,ad4134: Add high data throughput example Marcelo Schmitt
` (2 subsequent siblings)
12 siblings, 0 replies; 21+ messages in thread
From: Marcelo Schmitt @ 2026-09-02 17:24 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
Advenced setups may connect a PWM signal to AD4134 ODR pin for faster
output data rates.
Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
---
Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml
index d843c02a394a..34043f89730b 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
+
adi,asrc-mode:
$ref: /schemas/types.yaml#/definitions/string
description:
--
2.53.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v1 11/13] dt-bindings: iio: adc: adi,ad4134: Add high data throughput example
2026-09-02 17:21 [PATCH v1 00/13] iio: adc: ad4134: Enable greater sample rate data capture Marcelo Schmitt
` (9 preceding siblings ...)
2026-09-02 17:24 ` [PATCH v1 10/13] dt-bindings: iio: adc: adi,ad4134: Document PWM usage Marcelo Schmitt
@ 2026-09-02 17:25 ` Marcelo Schmitt
2026-09-02 17:25 ` [PATCH v1 12/13] iio: adc: ad4134: Support high-speed data capture Marcelo Schmitt
2026-09-02 17:25 ` [PATCH v1 13/13] Docs: iio: Add AD4134 Marcelo Schmitt
12 siblings, 0 replies; 21+ messages in thread
From: Marcelo Schmitt @ 2026-09-02 17:25 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 device tree example for AD4134 operation in 4-wire SPI mode with 4
lines to transfer data samples to the host controller.
Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
---
The reason for the input multiplexer is enable both register access and
multi-lane read. Before coming to the current solution, we tried the following
configuration.
+-----------------------+ +-----------------+
| AD4134 | | SPI Controller |
| | | |
| SPI interface | | |
| for register SCLK |<--------------------------| SCLK |
| access CS |<--------------------------| CS |
| SDI |<--------------------------| SDO |
| SDO |---+ | |
| | | | |
| Data interface DOUT0 |---+---------------------->| SDI0 |
| for ADC data DOUT1 |-------------------------->| SDI1 |
| read back DOUT2 |-------------------------->| SDI2 |
| DOUT3 |-------------------------->| SDI3 |
| DCLK |<--------------------------| DCLK
| ODR |<------------------+ +->| Offload Trigger |
+-----------------------+ | | +-----------------+
| +--| PWM1 |
+-------| PWM0 |
+-------| GPIO |
+-----------------+
Though, because DOUT0 never goes high-Z, the DOUT0 pin keeps driving the data
line, causing register read to fail (always get 0xFF). Another solution would be
to connect SDO to SDI0 and DOUT pins to SDI1, SDI2, SDI3, SDI4. That would then
require a special multi-lane mode.
Please, see patch 13 for a better view of how the proposed setup works.
.../bindings/iio/adc/adi,ad4134.yaml | 42 +++++++++++++++++++
1 file changed, 42 insertions(+)
diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml
index 34043f89730b..6f0b4346426a 100644
--- a/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml
@@ -214,4 +214,46 @@ examples:
};
};
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ ad4134_sdo_dout0_mux: mux-controller {
+ compatible = "gpio-mux";
+ #mux-state-cells = <1>;
+ mux-gpios = <&gpio0 100 GPIO_ACTIVE_HIGH>;
+ };
+
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ adc@0 {
+ compatible = "adi,ad4134";
+ reg = <0>;
+
+ spi-max-frequency = <1000000>;
+ spi-rx-bus-width = <1>, <1>, <1>, <1>; /* 4 lanes of 1 bit each */
+
+ pwms = <&ad4134_odr_generator 1 1000000 0>;
+ reset-gpios = <&gpio0 86 GPIO_ACTIVE_LOW>;
+ odr-gpios = <&gpio0 87 GPIO_ACTIVE_HIGH>;
+ 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] 21+ messages in thread
* [PATCH v1 12/13] iio: adc: ad4134: Support high-speed data capture
2026-09-02 17:21 [PATCH v1 00/13] iio: adc: ad4134: Enable greater sample rate data capture Marcelo Schmitt
` (10 preceding siblings ...)
2026-09-02 17:25 ` [PATCH v1 11/13] dt-bindings: iio: adc: adi,ad4134: Add high data throughput example Marcelo Schmitt
@ 2026-09-02 17:25 ` Marcelo Schmitt
2026-09-03 7:00 ` Andy Shevchenko
2026-09-02 17:25 ` [PATCH v1 13/13] Docs: iio: Add AD4134 Marcelo Schmitt
12 siblings, 1 reply; 21+ messages in thread
From: Marcelo Schmitt @ 2026-09-02 17:25 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 | 379 ++++++++++++++++++++++++++++++++++++++-
2 files changed, 375 insertions(+), 9 deletions(-)
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index ef77ee60df4e..369cc0659073 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 8453b44ef368..cf84d2b24417 100644
--- a/drivers/iio/adc/ad4134.c
+++ b/drivers/iio/adc/ad4134.c
@@ -13,6 +13,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>
@@ -20,9 +21,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>
@@ -30,11 +34,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
@@ -65,6 +74,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
@@ -117,6 +127,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,
+};
+
static int ad4134_get_filter_type(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan);
@@ -163,6 +177,39 @@ 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_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .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),
+};
+
struct ad4134_state {
struct spi_device *spi;
struct regmap *regmap;
@@ -172,6 +219,14 @@ struct ad4134_state {
bool crc_en;
enum ad4134_spi_mode spi_mode;
struct mux_state *mux_st[2];
+ struct spi_transfer xfers;
+ struct spi_message msg;
+ struct spi_offload *offload;
+ struct spi_offload_trigger *offload_trigger;
+ struct spi_offload_trigger_config offload_trigger_config;
+ struct pwm_device *odr_pwm;
+ struct pwm_waveform odr_wf;
+ unsigned int odr_hz;
/*
* Synchronize access to members the of driver state, and ensure
* atomicity of consecutive register access operations.
@@ -454,6 +509,90 @@ static const struct regmap_config ad4134_regmap_config = {
.max_register = AD4134_CH_VREG(ARRAY_SIZE(ad4134_chan_set)),
};
+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 = 10;
+ int ret;
+
+ if (!in_range(freq_Hz, AD4134_MIN_ODR_FREQ_HZ, AD4134_MAX_ODR_FREQ_HZ))
+ 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);
+ count = 100;
+ do {
+ odr_wf.duty_length_ns = target;
+ ret = pwm_round_waveform_might_sleep(st->odr_pwm, &odr_wf);
+ if (ret)
+ return ret;
+ target += 10; /* Increment by PWM duty cycle period */
+ } 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)
{
struct iio_poll_func *pf = p;
@@ -537,6 +676,42 @@ 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->lock);
+ switch (mask) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ return ad4134_update_conversion_rate(st, val);
default:
return -EINVAL;
}
@@ -588,6 +763,176 @@ 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 = roundup_pow_of_two(BITS_TO_BYTES(AD4134_CHAN_PRECISION_BITS));
+ unsigned int bpw = AD4134_CHAN_PRECISION_BITS;
+
+ st->xfers.cs_off = 1;
+ st->xfers.bits_per_word = bpw;
+ st->xfers.len = base_len * st->spi->num_rx_lanes;
+ 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, ret2;
+
+ if (st->spi_mode == AD4134_SPI_MODE_4_WIRE) {
+ ret = ad4134_set_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_set_register_input;
+
+ 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_set_register_input:
+ ret2 = ad4134_set_register_access(st);
+ if (ret2)
+ dev_err(&st->spi->dev, "reg input select error: %d\n", ret2);
+
+ return ret;
+}
+
+static int ad4134_offload_buffer_predisable(struct iio_dev *indio_dev)
+{
+ struct ad4134_state *st = iio_priv(indio_dev);
+ int ret = 0;
+
+ spi_offload_trigger_disable(st->offload, st->offload_trigger);
+
+ if (st->spi_mode == AD4134_SPI_MODE_4_WIRE)
+ ret = ad4134_set_register_access(st);
+
+ spi_unoptimize_message(&st->msg);
+
+ return ret;
+}
+
+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[] = {
+ GENMASK(3, 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);
+ }
+
+ return 0;
+}
+
static const char * const ad4143_required_regulators[] = {
"avdd5", "dvdd5", "iovdd",
};
@@ -681,10 +1026,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)
@@ -747,12 +1089,30 @@ static int ad4134_probe(struct spi_device *spi)
indio_dev->setup_ops = &ad4134_buffer_setup_ops;
}
- ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
- iio_pollfunc_store_time,
- ad4134_trigger_handler,
- NULL);
- if (ret)
- return ret;
+ 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) {
+ 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,
+ NULL);
+ if (ret)
+ return ret;
+ } else if (ret) {
+ return dev_err_probe(dev, ret, "failed to get offload\n");
+ } else {
+ 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,
@@ -798,3 +1158,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] 21+ messages in thread
* [PATCH v1 13/13] Docs: iio: Add AD4134
2026-09-02 17:21 [PATCH v1 00/13] iio: adc: ad4134: Enable greater sample rate data capture Marcelo Schmitt
` (11 preceding siblings ...)
2026-09-02 17:25 ` [PATCH v1 12/13] iio: adc: ad4134: Support high-speed data capture Marcelo Schmitt
@ 2026-09-02 17:25 ` Marcelo Schmitt
12 siblings, 0 replies; 21+ messages in thread
From: Marcelo Schmitt @ 2026-09-02 17:25 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 | 128 +++++++++++++++++++++++++++++++++++
Documentation/iio/index.rst | 1 +
MAINTAINERS | 1 +
3 files changed, 130 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..4e93d670e2db
--- /dev/null
+++ b/Documentation/iio/ad4134.rst
@@ -0,0 +1,128 @@
+.. 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 | | |
+ | for register SCLK |<------------------------| SCLK |
+ | access CS |<------------------------| CS |
+ | SDI |<------------------------| SDO |
+ | SDO |------->|¯¯¯¯\ | |
+ | Data interface | |MUX >--------->| SDI |
+ | for ADC sample DOUT0 |------->|____/ | |
+ | data read | ^ | |
+ | | +--------------| GPIO |
+ | 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 througput rate can be achieved by reading 4 input lines simultaneously.::
+
+ +-----------------------+ +-----------------+
+ | AD4134 | | SPI Controller |
+ | | | |
+ | SPI interface | | |
+ | for register SCLK |<------------------------| SCLK |
+ | access CS |<------------------------| CS |
+ | SDI |<------------------------| SDO |
+ | SDO |------->|¯¯¯¯\ | |
+ | Data interface | |MUX >--------->| SDI0 |
+ | for ADC sample DOUT0 |------->|____/<--------- | GPIO |
+ | 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 b02b879b053a..e4ec8a05dded 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 f3be900e5b9d..7b972c1f9833 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1514,6 +1514,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] 21+ messages in thread
* Re: [PATCH v1 01/13] iio: Fix typo in vendor name
2026-09-02 17:21 ` [PATCH v1 01/13] iio: Fix typo in vendor name Marcelo Schmitt
@ 2026-09-03 6:22 ` Andy Shevchenko
0 siblings, 0 replies; 21+ messages in thread
From: Andy Shevchenko @ 2026-09-03 6:22 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 Wed, Sep 02, 2026 at 02:21:34PM -0300, Marcelo Schmitt wrote:
> ---
> Now
> find drivers/iio/ -type f | xargs grep -i "Analog Device "
> finds no leftover occurrence of such typo.
>
> Also,
> grep -nrIi drivers/iio/ -e "Analog Device" | wc -l
> and
> grep -nrIi drivers/iio/ -e "Analog Devices" | wc -l
> both count the same number of lines.
Why not `git grep ...`?
...
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
But you also want to fix possessive suffix usage
$ git grep -n 'Analog Device[^s]'
Documentation/iio/ade9000.rst:7:This driver supports Analog Device's ADE9000 and ADE9078 energy measurement
Documentation/iio/adis16475.rst:7:This driver supports Analog Device's IMUs on SPI bus.
Documentation/iio/adis16480.rst:7:This driver supports Analog Device's IMUs on SPI bus.
Documentation/iio/adis16550.rst:7:This driver supports Analog Device's IMUs on SPI bus.
Documentation/iio/adxl313.rst:7:This driver supports Analog Device's ADXL313 on SPI/I2C bus.
Documentation/iio/adxl345.rst:7:This driver supports Analog Device's ADXL345/375 on SPI/I2C bus.
Documentation/iio/adxl380.rst:7:This driver supports Analog Device's ADXL380/382 on SPI/I2C bus.
drivers/iio/adc/Kconfig:108: tristate "Analog Device AD4130 ADC Driver"
drivers/iio/adc/Kconfig:124: tristate "Analog Device AD4134 ADC Driver"
drivers/iio/adc/Kconfig:136: tristate "Analog Device AD4170-4 ADC Driver"
drivers/iio/adc/Kconfig:167: tristate "Analog Device AD4695 ADC Driver"
drivers/iio/adc/Kconfig:182: tristate "Analog Device AD4851 DAS Driver"
drivers/iio/adc/Kconfig:350: tristate "Analog Device AD7405 ADC Driver"
drivers/iio/dac/ad3552r.c:699:MODULE_DESCRIPTION("Analog Device AD3552R DAC");
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v1 03/13] iio: adc: ad4134: Update include list to comply with IWYU principles
2026-09-02 17:22 ` [PATCH v1 03/13] iio: adc: ad4134: Update include list to comply with IWYU principles Marcelo Schmitt
@ 2026-09-03 6:26 ` Andy Shevchenko
0 siblings, 0 replies; 21+ messages in thread
From: Andy Shevchenko @ 2026-09-03 6:26 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 Wed, Sep 02, 2026 at 02:22:16PM -0300, Marcelo Schmitt wrote:
> Add includes that were missing (according to include-what-you-use tool)
> to comply with include what is used principles. Namely, add bits.h for
> BIT and GENMASK, and 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.
...
> @@ -7,6 +7,7 @@
> #include <linux/array_size.h>
> #include <linux/bitfield.h>
> #include <linux/bitops.h>
> +#include <linux/bits.h>
No need, bitops.h implies it.
...
With that being addressed
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v1 04/13] iio: adc: ad4134: Serialize single-read operations
2026-09-02 17:22 ` [PATCH v1 04/13] iio: adc: ad4134: Serialize single-read operations Marcelo Schmitt
@ 2026-09-03 6:27 ` Andy Shevchenko
0 siblings, 0 replies; 21+ messages in thread
From: Andy Shevchenko @ 2026-09-03 6:27 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 Wed, Sep 02, 2026 at 02:22:41PM -0300, Marcelo Schmitt wrote:
> 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.
...
> case IIO_CHAN_INFO_RAW:
> + guard(mutex)(&st->lock);
Always delimit guard()() with a blank line.
> gpiod_set_value_cansleep(st->odr_gpio, 1);
...
With blank line added
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v1 06/13] iio: adc: ad4134: Add support for digital filter type selection
2026-09-02 17:23 ` [PATCH v1 06/13] iio: adc: ad4134: Add support for digital filter type selection Marcelo Schmitt
@ 2026-09-03 6:31 ` Andy Shevchenko
0 siblings, 0 replies; 21+ messages in thread
From: Andy Shevchenko @ 2026-09-03 6:31 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 Wed, Sep 02, 2026 at 02:23:22PM -0300, Marcelo Schmitt wrote:
> 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.
...
> +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),
Make it a single line (it's only 82 characters).
> + { }
> +};
...
> +static int ad4134_get_filter_type(struct iio_dev *indio_dev,
> + struct iio_chan_spec const *chan)
int
> +{
> + struct ad4134_state *st = iio_priv(indio_dev);
> + enum ad4134_filter_type f_type;
enum
> + 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, ®_val);
> + if (ret)
> + return ret;
> +
> + mask = AD4134_CHAN_DIG_FILTER_SEL_CH_MASK(chan->channel);
> + f_type = field_get(mask, reg_val);
> +
> + return f_type;
field_get() macro...
I think you can get rid of temporary variable if it's not used afterwards.
> +}
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v1 09/13] iio: adc: ad4134: Support SPI 4-wire mode
2026-09-02 17:24 ` [PATCH v1 09/13] iio: adc: ad4134: Support SPI 4-wire mode Marcelo Schmitt
@ 2026-09-03 6:39 ` Andy Shevchenko
0 siblings, 0 replies; 21+ messages in thread
From: Andy Shevchenko @ 2026-09-03 6:39 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 Wed, Sep 02, 2026 at 02:24:25PM -0300, Marcelo Schmitt wrote:
> 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
> optimal for high-throughput data acquisition.
>
> Extend AD4134 support to enable interfacing in SPI 4-wire configuration.
...
> struct ad4134_state {
I hope on each stage you run `pahole` to confirm that this is the optimal
layout.
> struct gpio_desc *odr_gpio;
> int refin_mv;
> bool crc_en;
> + enum ad4134_spi_mode spi_mode;
> + struct mux_state *mux_st[2];
> /*
> * Synchronize access to members the of driver state, and ensure
> * atomicity of consecutive register access operations.
> */
> struct mutex lock;
> + /*
> + * Ensure atomicity of access mode switch operations.
> + */
> + struct mutex access_mode_lock;
> };
...
> +static int ad4134_set_register_access(struct ad4134_state *st)
> +{
> + int ret;
> +
> + guard(mutex)(&st->access_mode_lock);
+ blank line.
> + st->spi->mode = SPI_MODE_0;
> + ret = spi_setup(st->spi);
> + if (ret)
> + return ret;
> +
> + ret = mux_state_deselect(st->mux_st[AD4134_DOUT0_INPUT]);
> + if (ret)
> + dev_err(&st->spi->dev, "error on DOUT0 deselect: %d\n", ret);
> + ret = mux_state_try_select(st->mux_st[AD4134_SDO_INPUT]);
> + if (ret && ret != -EBUSY)
> + return ret;
Reading this without a comment about EBUSY is difficult. Interpreting BUSY as
occupied mux channel, why do we return success?
> + return 0;
> +}
...
> +static int ad4134_set_sample_access(struct ad4134_state *st)
> +{
struct device *dev = &st->spi->dev;
> + int ret, ret2;
I would go with
int mux_state_ret;
int ret;
> + guard(mutex)(&st->access_mode_lock);
> + ret = mux_state_deselect(st->mux_st[AD4134_SDO_INPUT]);
> + if (ret)
> + dev_err(&st->spi->dev, "error on SDO deselect: %d\n", ret);
> +
> + ret = mux_state_try_select(st->mux_st[AD4134_DOUT0_INPUT]);
> + if (ret) {
> + dev_err(&st->spi->dev, "error on DOUT0 select: %d\n", ret);
> + return mux_state_select(st->mux_st[AD4134_SDO_INPUT]);
> + }
> +
> + /*
> + * Data output on the DOUT lines is sampled on the falling edge
> + * (SPI mode 1).
> + */
> + st->spi->mode = SPI_MODE_1;
> + ret = spi_setup(st->spi);
> + if (ret) {
> + dev_err(&st->spi->dev, "failed to setup SPI mode 1: %d\n", ret);
> + ret2 = mux_state_deselect(st->mux_st[AD4134_DOUT0_INPUT]);
> + if (ret2)
> + dev_err(&st->spi->dev, "error on DOUT0 deselect: %d\n", ret2);
> +
> + ret2 = mux_state_select(st->mux_st[AD4134_SDO_INPUT]);
> + if (ret2)
> + dev_err(&st->spi->dev, "error on SDO select: %d\n", ret2);
> +
> + return ret;
> + }
> +
> + return 0;
> +}
...
> static int ad4134_reg_read(void *context, unsigned int reg, unsigned int *val)
> {
> struct ad4134_state *st = context;
> + int ret, ret2;
>
> - if (reg >= AD4134_CH_VREG(0))
> - return ad4134_data_read(st, reg, val);
> + if (reg >= AD4134_CH_VREG(0)) {
> + if (st->spi_mode == AD4134_SPI_MODE_4_WIRE) {
> + ret = ad4134_set_sample_access(st);
> + if (ret)
> + return ret;
> + }
> +
> + ret = ad4134_data_read(st, reg, val);
> +
> + if (st->spi_mode == AD4134_SPI_MODE_4_WIRE) {
> + ret2 = ad4134_set_register_access(st);
> + if (ret2)
> + dev_err(&st->spi->dev, "access mode error: %d\n", ret2);
> + }
I would go with duplication of _data_read() call but better flow
if (...) {
_set_sample_()
ret = _data_read();
_set_register_()
} else {
ret = _data_read();
}
> + return ret;
> + }
...
> + ret = device_property_match_property_string(dev, "adi,spi-mode",
> + ad4134_spi_modes,
> + ARRAY_SIZE(ad4134_spi_modes));
> + /* Default to "no-cs" mode if adi,spi-mode is not specified */
> + if (ret == -EINVAL)
No, use device_property_present() instead.
> + st->spi_mode = AD4134_SPI_MODE_NO_CS;
> + else if (ret < 0)
> return dev_err_probe(dev, ret,
> - "failed to setup minimum I/O mode\n");
> + "getting adi,spi-mode property failed\n");
> + else
> + st->spi_mode = ret;
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v1 12/13] iio: adc: ad4134: Support high-speed data capture
2026-09-02 17:25 ` [PATCH v1 12/13] iio: adc: ad4134: Support high-speed data capture Marcelo Schmitt
@ 2026-09-03 7:00 ` Andy Shevchenko
0 siblings, 0 replies; 21+ messages in thread
From: Andy Shevchenko @ 2026-09-03 7:00 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 Wed, Sep 02, 2026 at 02:25:26PM -0300, Marcelo Schmitt wrote:
> Make use of SPI transfer offloading to speed up data capture, enabling data
> acquisition at faster sample rates (up to 1.496 MSPS).
...
> +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 = 10;
Split assignment and move it closer to its first user.
> + int ret;
> +
> + if (!in_range(freq_Hz, AD4134_MIN_ODR_FREQ_HZ, AD4134_MAX_ODR_FREQ_HZ))
> + 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 = 0;
> + count = 100;
> + do {
target += 10; /* Increment by PWM duty cycle period */
> + odr_wf.duty_length_ns = target;
> + ret = pwm_round_waveform_might_sleep(st->odr_pwm, &odr_wf);
> + if (ret)
> + return ret;
> + target += 10; /* Increment by PWM duty cycle period */
In the above way I think it clarifies the initial setting to 10.
Shouldn't be target named as target_ns? Can we use odr_wf.duty_length_ns
directly?
> + } 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;
Does this need the similar comment as per above?
> + } 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 int ad4134_offload_buffer_postenable(struct iio_dev *indio_dev)
> +{
> + struct ad4134_state *st = iio_priv(indio_dev);
> + int ret, ret2;
These ret2:s in the cases of _set_register_() can be named accordingly.
> + if (st->spi_mode == AD4134_SPI_MODE_4_WIRE) {
> + ret = ad4134_set_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_set_register_input;
> +
> + 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_set_register_input:
> + ret2 = ad4134_set_register_access(st);
> + if (ret2)
> + dev_err(&st->spi->dev, "reg input select error: %d\n", ret2);
> +
> + return ret;
> +}
...
> +/* The chip converts and outputs all 4 channels on each sample request */
> +static const unsigned long ad4134_scan_masks[] = {
> + GENMASK(3, 0),
IIRC Jonathan wants to see this as BIT(x) | BIT(y) | ... to clarify that each
bit is semantically independent.
> + 0
> +};
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v1 08/13] dt-bindings: iio: adc: adi,ad4134: Document SPI connection mode
2026-09-02 17:24 ` [PATCH v1 08/13] dt-bindings: iio: adc: adi,ad4134: Document SPI connection mode Marcelo Schmitt
@ 2026-09-03 18:14 ` Conor Dooley
0 siblings, 0 replies; 21+ messages in thread
From: Conor Dooley @ 2026-09-03 18:14 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
[-- Attachment #1: Type: text/plain, Size: 2635 bytes --]
On Wed, Sep 02, 2026 at 02:24:02PM -0300, Marcelo Schmitt wrote:
> Document how AD4134 chips are connected to the host SPI controller
> according to different wiring configurations.
>
> Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
> ---
> .../bindings/iio/adc/adi,ad4134.yaml | 22 +++++++++++++++++++
> 1 file changed, 22 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml
> index ea6d7e026419..d843c02a394a 100644
> --- a/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml
> +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml
> @@ -131,6 +131,28 @@ 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 ]
> + description: |
> + This property indicates the SPI wiring configuration.
> +
> + When this property is omitted, it is assumed that the device is using
> + 'no-cs' wiring. When this property is present, it indicates that the
> + device is using one of the following wiring configurations:
"default: no-cs" and drop the text about the default, but there's some
pretty interesting comments from Sashiko about #daisy-chained-devices
(used for ad7944), although I'm not sure how that'd work for the
two-channel-chain case.
I'd also really appreciate a dts example for a system
with one-channel-chain or two-channel-chain looks, given the second
device may require different supplies etc. I have no impression in my
head of how the dt would be constructed, so I'd like to see wht you have
in mind.
> +
> + * 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.
> +
> required:
> - compatible
> - reg
> --
> 2.53.0
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2026-09-03 18:14 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-02 17:21 [PATCH v1 00/13] iio: adc: ad4134: Enable greater sample rate data capture Marcelo Schmitt
2026-09-02 17:21 ` [PATCH v1 01/13] iio: Fix typo in vendor name Marcelo Schmitt
2026-09-03 6:22 ` Andy Shevchenko
2026-09-02 17:21 ` [PATCH v1 02/13] iio: adc: ad4134: Drop import to empty name space Marcelo Schmitt
2026-09-02 17:22 ` [PATCH v1 03/13] iio: adc: ad4134: Update include list to comply with IWYU principles Marcelo Schmitt
2026-09-03 6:26 ` Andy Shevchenko
2026-09-02 17:22 ` [PATCH v1 04/13] iio: adc: ad4134: Serialize single-read operations Marcelo Schmitt
2026-09-03 6:27 ` Andy Shevchenko
2026-09-02 17:23 ` [PATCH v1 05/13] iio: adc: ad4134: Run shorter transfers when CRC is disabled Marcelo Schmitt
2026-09-02 17:23 ` [PATCH v1 06/13] iio: adc: ad4134: Add support for digital filter type selection Marcelo Schmitt
2026-09-03 6:31 ` Andy Shevchenko
2026-09-02 17:23 ` [PATCH v1 07/13] iio: adc: ad4134: Support buffered data read Marcelo Schmitt
2026-09-02 17:24 ` [PATCH v1 08/13] dt-bindings: iio: adc: adi,ad4134: Document SPI connection mode Marcelo Schmitt
2026-09-03 18:14 ` Conor Dooley
2026-09-02 17:24 ` [PATCH v1 09/13] iio: adc: ad4134: Support SPI 4-wire mode Marcelo Schmitt
2026-09-03 6:39 ` Andy Shevchenko
2026-09-02 17:24 ` [PATCH v1 10/13] dt-bindings: iio: adc: adi,ad4134: Document PWM usage Marcelo Schmitt
2026-09-02 17:25 ` [PATCH v1 11/13] dt-bindings: iio: adc: adi,ad4134: Add high data throughput example Marcelo Schmitt
2026-09-02 17:25 ` [PATCH v1 12/13] iio: adc: ad4134: Support high-speed data capture Marcelo Schmitt
2026-09-03 7:00 ` Andy Shevchenko
2026-09-02 17:25 ` [PATCH v1 13/13] Docs: iio: Add AD4134 Marcelo Schmitt
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).