[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <027a198b8dea771601d7dcfa9827e7204e873741.1770309522.git.marcelo.schmitt@analog.com>
Date: Thu, 5 Feb 2026 13:49:37 -0300
From: Marcelo Schmitt <marcelo.schmitt@...log.com>
To: <linux-iio@...r.kernel.org>, <devicetree@...r.kernel.org>,
<linux-doc@...r.kernel.org>, <linux-kernel@...r.kernel.org>
CC: <jic23@...nel.org>, <michael.hennerich@...log.com>, <nuno.sa@...log.com>,
<eblanc@...libre.com>, <dlechner@...libre.com>, <andy@...nel.org>,
<robh@...nel.org>, <krzk+dt@...nel.org>, <conor+dt@...nel.org>,
<corbet@....net>, <marcelo.schmitt1@...il.com>
Subject: [PATCH v7 8/8] iio: adc: ad4030: Support common-mode channels with SPI offloading
AD4030 and similar devices can read common-mode voltage together with
ADC sample data. When enabled, common-mode voltage data is provided in a
separate IIO channel since it measures something other than the primary
ADC input signal and requires separate scaling to convert to voltage
units. The initial SPI offload support patch for AD4030 only provided
differential channels. Now, extend the AD4030 driver to also provide
common-mode IIO channels when setup with SPI offloading capability.
Signed-off-by: Marcelo Schmitt <marcelo.schmitt@...log.com>
---
Change log v6 -> v7
- No changes.
drivers/iio/adc/ad4030.c | 49 ++++++++++++++++++++++++++++++++--------
1 file changed, 40 insertions(+), 9 deletions(-)
diff --git a/drivers/iio/adc/ad4030.c b/drivers/iio/adc/ad4030.c
index 4f521fe787d9..b2b3cd8ff38a 100644
--- a/drivers/iio/adc/ad4030.c
+++ b/drivers/iio/adc/ad4030.c
@@ -192,7 +192,7 @@ struct ad4030_state {
unsigned int avg_log2;
enum ad4030_out_mode mode;
/* Offload sampling */
- struct spi_transfer offload_xfer;
+ struct spi_transfer offload_xfer[2];
struct spi_message offload_msg;
struct spi_offload *offload;
struct spi_offload_trigger *offload_trigger;
@@ -237,7 +237,7 @@ struct ad4030_state {
* - _idx - _ch * 2 + _ch gives the channel number for this specific common-mode
* channel
*/
-#define AD4030_CHAN_CMO(_idx, _ch) { \
+#define __AD4030_CHAN_CMO(_idx, _ch, _offload) { \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_SCALE), \
.type = IIO_VOLTAGE, \
@@ -247,12 +247,18 @@ struct ad4030_state {
.scan_index = (_idx), \
.scan_type = { \
.sign = 'u', \
- .storagebits = 8, \
+ .storagebits = (_offload ? 32 : 8), \
.realbits = 8, \
- .endianness = IIO_BE, \
+ .endianness = (_offload ? IIO_CPU : IIO_BE), \
}, \
}
+#define AD4030_CHAN_CMO(_idx, _ch) \
+ __AD4030_CHAN_CMO(_idx, _ch, 0)
+
+#define AD4030_OFFLOAD_CHAN_CMO(_idx, _ch) \
+ __AD4030_CHAN_CMO(_idx, _ch, 1)
+
/*
* For a chip with 2 hardware channel this will be used to create 2 differential
* channels:
@@ -1180,6 +1186,7 @@ static const struct iio_buffer_setup_ops ad4030_buffer_setup_ops = {
static void ad4030_prepare_offload_msg(struct iio_dev *indio_dev)
{
struct ad4030_state *st = iio_priv(indio_dev);
+ bool common_mode;
u8 offload_bpw;
if (st->mode == AD4030_OUT_DATA_MD_30_AVERAGED_DIFF)
@@ -1187,10 +1194,22 @@ static void ad4030_prepare_offload_msg(struct iio_dev *indio_dev)
else
offload_bpw = st->chip->precision_bits;
- st->offload_xfer.bits_per_word = offload_bpw;
- st->offload_xfer.len = spi_bpw_to_bytes(offload_bpw);
- st->offload_xfer.offload_flags = SPI_OFFLOAD_XFER_RX_STREAM;
- spi_message_init_with_transfers(&st->offload_msg, &st->offload_xfer, 1);
+ st->offload_xfer[0].bits_per_word = offload_bpw;
+ st->offload_xfer[0].len = spi_bpw_to_bytes(offload_bpw);
+ st->offload_xfer[0].offload_flags = SPI_OFFLOAD_XFER_RX_STREAM;
+
+ common_mode = st->mode == AD4030_OUT_DATA_MD_24_DIFF_8_COM ||
+ st->mode == AD4030_OUT_DATA_MD_16_DIFF_8_COM;
+
+ if (common_mode) {
+ offload_bpw = 8;
+ st->offload_xfer[1].bits_per_word = offload_bpw;
+ st->offload_xfer[1].len = spi_bpw_to_bytes(offload_bpw);
+ st->offload_xfer[1].offload_flags = SPI_OFFLOAD_XFER_RX_STREAM;
+ }
+
+ spi_message_init_with_transfers(&st->offload_msg, st->offload_xfer,
+ common_mode ? 2 : 1);
}
static int ad4030_offload_buffer_postenable(struct iio_dev *indio_dev)
@@ -1255,6 +1274,7 @@ static int ad4030_offload_buffer_predisable(struct iio_dev *indio_dev)
static const struct iio_buffer_setup_ops ad4030_offload_buffer_setup_ops = {
.postenable = &ad4030_offload_buffer_postenable,
.predisable = &ad4030_offload_buffer_predisable,
+ .validate_scan_mask = ad4030_validate_scan_mask,
};
static int ad4030_regulators_get(struct ad4030_state *st)
@@ -1506,7 +1526,7 @@ static int ad4030_probe(struct spi_device *spi)
* Offloaded SPI transfers can't support software timestamp so
* no additional timestamp channel is added.
*/
- indio_dev->num_channels = st->chip->num_voltage_inputs;
+ indio_dev->num_channels = 2 * st->chip->num_voltage_inputs;
indio_dev->channels = st->chip->offload_channels;
ret = ad4030_spi_offload_setup(indio_dev, st);
if (ret)
@@ -1627,6 +1647,7 @@ static const struct ad4030_chip_info ad4030_24_chip_info = {
},
.offload_channels = {
AD4030_OFFLOAD_CHAN_DIFF(0, ad4030_24_offload_scan_types),
+ AD4030_OFFLOAD_CHAN_CMO(1, 0),
},
.grade = AD4030_REG_CHIP_GRADE_AD4030_24_GRADE,
.precision_bits = 24,
@@ -1648,6 +1669,8 @@ static const struct ad4030_chip_info ad4630_16_chip_info = {
.offload_channels = {
AD4030_OFFLOAD_CHAN_DIFF(0, ad4030_16_offload_scan_types),
AD4030_OFFLOAD_CHAN_DIFF(1, ad4030_16_offload_scan_types),
+ AD4030_OFFLOAD_CHAN_CMO(2, 0),
+ AD4030_OFFLOAD_CHAN_CMO(3, 1),
},
.grade = AD4030_REG_CHIP_GRADE_AD4630_16_GRADE,
.precision_bits = 16,
@@ -1669,6 +1692,8 @@ static const struct ad4030_chip_info ad4630_24_chip_info = {
.offload_channels = {
AD4030_OFFLOAD_CHAN_DIFF(0, ad4030_24_offload_scan_types),
AD4030_OFFLOAD_CHAN_DIFF(1, ad4030_24_offload_scan_types),
+ AD4030_OFFLOAD_CHAN_CMO(2, 0),
+ AD4030_OFFLOAD_CHAN_CMO(3, 1),
},
.grade = AD4030_REG_CHIP_GRADE_AD4630_24_GRADE,
.precision_bits = 24,
@@ -1690,6 +1715,8 @@ static const struct ad4030_chip_info ad4632_16_chip_info = {
.offload_channels = {
AD4030_OFFLOAD_CHAN_DIFF(0, ad4030_16_offload_scan_types),
AD4030_OFFLOAD_CHAN_DIFF(1, ad4030_16_offload_scan_types),
+ AD4030_OFFLOAD_CHAN_CMO(2, 0),
+ AD4030_OFFLOAD_CHAN_CMO(3, 1),
},
.grade = AD4030_REG_CHIP_GRADE_AD4632_16_GRADE,
.precision_bits = 16,
@@ -1711,6 +1738,8 @@ static const struct ad4030_chip_info ad4632_24_chip_info = {
.offload_channels = {
AD4030_OFFLOAD_CHAN_DIFF(0, ad4030_24_offload_scan_types),
AD4030_OFFLOAD_CHAN_DIFF(1, ad4030_24_offload_scan_types),
+ AD4030_OFFLOAD_CHAN_CMO(2, 0),
+ AD4030_OFFLOAD_CHAN_CMO(3, 1),
},
.grade = AD4030_REG_CHIP_GRADE_AD4632_24_GRADE,
.precision_bits = 24,
@@ -1729,6 +1758,7 @@ static const struct ad4030_chip_info adaq4216_chip_info = {
},
.offload_channels = {
ADAQ4216_OFFLOAD_CHAN_DIFF(0, ad4030_16_offload_scan_types),
+ AD4030_OFFLOAD_CHAN_CMO(1, 0),
},
.grade = AD4030_REG_CHIP_GRADE_ADAQ4216_GRADE,
.precision_bits = 16,
@@ -1748,6 +1778,7 @@ static const struct ad4030_chip_info adaq4224_chip_info = {
},
.offload_channels = {
ADAQ4216_OFFLOAD_CHAN_DIFF(0, ad4030_24_offload_scan_types),
+ AD4030_OFFLOAD_CHAN_CMO(1, 0),
},
.grade = AD4030_REG_CHIP_GRADE_ADAQ4224_GRADE,
.precision_bits = 24,
--
2.39.2
Powered by blists - more mailing lists