[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <a9b64ad7-41ff-4428-b47a-e3b3e50670a3@baylibre.com>
Date: Sat, 30 Aug 2025 12:19:04 -0500
From: David Lechner <dlechner@...libre.com>
To: Marcelo Schmitt <marcelo.schmitt@...log.com>, linux-iio@...r.kernel.org,
linux-kernel@...r.kernel.org, linux-doc@...r.kernel.org,
devicetree@...r.kernel.org, linux-spi@...r.kernel.org
Cc: jic23@...nel.org, Michael.Hennerich@...log.com, nuno.sa@...log.com,
eblanc@...libre.com, andy@...nel.org, corbet@....net, robh@...nel.org,
krzk+dt@...nel.org, conor+dt@...nel.org, broonie@...nel.org,
Jonathan.Cameron@...wei.com, andriy.shevchenko@...ux.intel.com,
ahaslam@...libre.com, sergiu.cuciurean@...log.com, marcelo.schmitt1@...il.com
Subject: Re: [PATCH 09/15] iio: adc: ad4030: Support multiple data lanes per
channel
On 8/29/25 7:43 PM, Marcelo Schmitt wrote:
> AD4030 and similar chips can output ADC sample data through 1, 2, or 4
> lines per channel. The number of SPI lines the device uses to output data
> is specified in firmware. Parse SPI read bus width setting from firmware
> and configure the device to use that amount of lines to output data.
>
> Co-developed-by: Sergiu Cuciurean <sergiu.cuciurean@...log.com>
> Signed-off-by: Sergiu Cuciurean <sergiu.cuciurean@...log.com>
> Signed-off-by: Marcelo Schmitt <marcelo.schmitt@...log.com>
> ---
> drivers/iio/adc/ad4030.c | 33 ++++++++++++++++++++++++++++++---
> 1 file changed, 30 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/iio/adc/ad4030.c b/drivers/iio/adc/ad4030.c
> index 68f76432dbfd..e6c1c9be1632 100644
> --- a/drivers/iio/adc/ad4030.c
> +++ b/drivers/iio/adc/ad4030.c
> @@ -20,6 +20,7 @@
> #include <linux/iio/iio.h>
> #include <linux/iio/trigger_consumer.h>
> #include <linux/iio/triggered_buffer.h>
> +#include <linux/log2.h>
> #include <linux/pwm.h>
> #include <linux/regmap.h>
> #include <linux/regulator/consumer.h>
> @@ -258,6 +259,10 @@ struct ad4030_state {
> #define AD4030_OFFLOAD_CHAN_DIFF(_idx, _scan_type) \
> __AD4030_CHAN_DIFF(_idx, _scan_type, 1)
>
> +static const int ad4030_rx_bus_width[] = {
> + 1, 2, 4, 8,
> +};
> +
> static const int ad4030_average_modes[] = {
> 1, 2, 4, 8, 16, 32, 64, 128,
> 256, 512, 1024, 2048, 4096, 8192, 16384, 32768,
> @@ -1197,7 +1202,7 @@ static void ad4030_prepare_offload_msg(struct ad4030_state *st)
> */
> offload_bpw = data_width * st->chip->num_voltage_inputs;
> else
> - offload_bpw = data_width;
> + offload_bpw = data_width / (1 << st->lane_mode);
To make proper use of 2 or 4 lines for a single channel, we should be
using the SPI APIs correctly and set rx_nbits in struct spi_transfer
instead of providing an inaccurate bits per word.
>
> st->offload_xfer.speed_hz = AD4030_SPI_MAX_REG_XFER_SPEED;
> st->offload_xfer.bits_per_word = offload_bpw;
> @@ -1208,6 +1213,10 @@ static void ad4030_prepare_offload_msg(struct ad4030_state *st)
>
> static int ad4030_config(struct ad4030_state *st)
> {
> + struct device *dev = &st->spi->dev;
> + const char *propname;
> + u32 rx_bus_width;
> + unsigned int i;
> int ret;
> u8 reg_modes;
>
> @@ -1215,10 +1224,28 @@ static int ad4030_config(struct ad4030_state *st)
> st->offset_avail[1] = 1;
> st->offset_avail[2] = BIT(st->chip->precision_bits - 1) - 1;
>
> - if (st->chip->num_voltage_inputs > 1)
> + /* Optional property specifying the number of lanes to read ADC data */
> + propname = "spi-rx-bus-width";
This property is already handled by the core SPI code and will set
spi->mode flags SPI_RX_DUAL, SPI_RX_QUAD or SPI_RX_OCTAL. So we don't
need to read the property again.
> + rx_bus_width = ad4030_rx_bus_width[0]; /* Default to 1 rx lane. */
> + device_property_read_u32(dev, propname, &rx_bus_width);
> + /* Check the rx bus width is valid */
> + for (i = 0; i < ARRAY_SIZE(ad4030_rx_bus_width); i++)
> + if (ad4030_rx_bus_width[i] == rx_bus_width)
> + break;
> +
> + if (i >= ARRAY_SIZE(ad4030_rx_bus_width))
> + return dev_err_probe(dev, -EINVAL, "Invalid %s: %u\n",
> + propname, rx_bus_width);
> +
> + rx_bus_width = ad4030_rx_bus_width[i];
> +
> + if (rx_bus_width == 8 && st->chip->num_voltage_inputs == 1)
> + return dev_err_probe(dev, -EINVAL, "1 channel with 8 lanes?\n");
As mentioned in the dt-bindings patch review, we really should consider
the 2 channel case separate as 2 SPI buses rather than 8 lines on a
single bus.
Only using "spi-rx-bus-width" also has the shortcoming that if we specify
4, we don't know if is it 4 lines on 1 channel or is it 2 lines each on 2
channels? There is no way to tell from just that information.
> +
> + if (rx_bus_width == 1 && st->chip->num_voltage_inputs > 1)
> st->lane_mode = AD4030_LANE_MD_INTERLEAVED;
> else
> - st->lane_mode = AD4030_LANE_MD_1_PER_CH;
> + st->lane_mode = ilog2(rx_bus_width / st->chip->num_voltage_inputs);
>
> reg_modes = FIELD_PREP(AD4030_REG_MODES_MASK_LANE_MODE, st->lane_mode);
>
Powered by blists - more mailing lists