* [PATCH v3 0/7] spi: add multi-lane support
@ 2025-12-02 2:20 David Lechner
2025-12-02 2:20 ` [PATCH v3 1/7] spi: dt-bindings: Add data-lanes property David Lechner
` (6 more replies)
0 siblings, 7 replies; 24+ messages in thread
From: David Lechner @ 2025-12-02 2:20 UTC (permalink / raw)
To: Mark Brown, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Marcelo Schmitt, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Andy Shevchenko
Cc: Sean Anderson, linux-spi, devicetree, linux-kernel, linux-iio,
David Lechner
This series is adding support for SPI controllers and peripherals that
have multiple SPI data lanes (data lanes being independent sets of
SDI/SDO lines, each with their own serializer/deserializer).
This series covers this specific use case:
+--------------+ +---------+
| SPI | | SPI |
| Controller | | ADC |
| | | |
| CS0 |--->| CS |
| SCLK |--->| SCLK |
| SDO |--->| SDI |
| SDI0 |<---| SDOA |
| SDI1 |<---| SDOB |
| SDI2 |<---| SDOC |
| SDI3 |<---| SDOD |
+--------------+ +--------+
The ADC is a simultaneous sampling ADC that can convert 4 samples at the
same time. It has 4 data output lines (SDOA-D) that each contain the
data of one of the 4 channels. So it requires a SPI controller with 4
separate deserializers in order to receive all of the information at the
same time.
This should also work for the use case in [1] as well. (Some of the
patches in this series were already submitted there). In that case the
SPI controller is used kind of like it is two separate SPI controllers,
each with its own chip select, clock, and data lines.
[1]: https://lore.kernel.org/linux-spi/20250616220054.3968946-1-sean.anderson@linux.dev/
The DT bindings are a fairly straight-forward mapping of which pins on
the peripheral are connected to which pins on the controller. The SPI
core code parses this and makes the information available to drivers.
When a peripheral driver sees that multiple data lanes are wired up, it
can chose to use them when sending messages.
The SPI message API is a bit higher-level than just specifying the
number of data lines for a SPI transfer though. I did some research on
other SPI controllers that have this feature. They tend to be the kind
meant for connecting to two flash memory chips at the same time but can
be used more generically as well. They generally have the option to
either use one lane at a time (Sean's use case), or can mirror the same
data on multiple lanes (no users of this yet) or can perform striping
of a single data FIFO/DMA stream to/from the two lanes (our use case).
For now, the API assumes that if you want to do mirror/striping, then
you want to use all available data lanes. Otherwise, it just uses the
first data lane for "normal" SPI transfers.
Signed-off-by: David Lechner <dlechner@baylibre.com>
---
Changes in v3:
- Use existing data-lanes devicetree property name instead of creating a
new one.
- Renamed "buses" to "lanes" everywhere to match the devicetree property
name.
- Clarified bindings description about how to specify data lanes.
- Link to v2: https://lore.kernel.org/r/20251107-spi-add-multi-bus-support-v2-0-8a92693314d9@baylibre.com
Changes in v2:
- Renamed devicetree property spi-buses to spi-data-buses. (Driver code
was already using spi->data_buses, so it matches).
- Fixed a small bug in the AXI ADC driver changes.
- Moved one line of code in the ADC driver changes.
- Link to v1: https://lore.kernel.org/r/20251014-spi-add-multi-bus-support-v1-0-2098c12d6f5f@baylibre.com
---
David Lechner (7):
spi: dt-bindings: Add data-lanes property
spi: Support controllers with multiple data lanes
spi: add multi_lane_mode field to struct spi_transfer
spi: axi-spi-engine: support SPI_MULTI_LANE_MODE_STRIPE
dt-bindings: iio: adc: adi,ad7380: add spi-lanes property
iio: adc: ad7380: Add support for multiple SPI lanes
dt-bindings: iio: adc: adi,ad4030: add data-lanes property
.../devicetree/bindings/iio/adc/adi,ad4030.yaml | 36 ++++++
.../devicetree/bindings/iio/adc/adi,ad7380.yaml | 22 ++++
.../bindings/spi/spi-peripheral-props.yaml | 14 +++
drivers/iio/adc/ad7380.c | 42 ++++---
drivers/spi/spi-axi-spi-engine.c | 128 ++++++++++++++++++++-
drivers/spi/spi.c | 28 ++++-
include/linux/spi/spi.h | 23 ++++
7 files changed, 275 insertions(+), 18 deletions(-)
---
base-commit: 1a26618e7466b8d825989201086c235e76aa999a
change-id: 20250815-spi-add-multi-bus-support-1b35d05c54f6
Best regards,
--
David Lechner <dlechner@baylibre.com>
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH v3 1/7] spi: dt-bindings: Add data-lanes property
2025-12-02 2:20 [PATCH v3 0/7] spi: add multi-lane support David Lechner
@ 2025-12-02 2:20 ` David Lechner
2025-12-04 21:29 ` Rob Herring (Arm)
2025-12-02 2:20 ` [PATCH v3 2/7] spi: Support controllers with multiple data lanes David Lechner
` (5 subsequent siblings)
6 siblings, 1 reply; 24+ messages in thread
From: David Lechner @ 2025-12-02 2:20 UTC (permalink / raw)
To: Mark Brown, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Marcelo Schmitt, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Andy Shevchenko
Cc: Sean Anderson, linux-spi, devicetree, linux-kernel, linux-iio,
David Lechner
Add a data-lanes property to the spi-peripheral-props binding to
allow specifying the SPI data lane or lanes that a peripheral is
connected to in cases where the SPI controller has more than one
physical SPI data lane.
Signed-off-by: David Lechner <dlechner@baylibre.com>
---
v3 changes:
* Renamed spi-buses to data-lanes to reuse existing common property name.
* Added to description to clarify index is peripheral and value is
controller.
v2 changes:
* Renamed property from spi-buses to spi-data-buses to make it clear
that we are only talking about the SDI/SDO lines and not the entire
SPI bus (SCK, CS, etc).
* Fixed prefix order in subject.
This patch has been seen before in a different series from Sean [1].
[1]: https://lore.kernel.org/linux-spi/20250616220054.3968946-2-sean.anderson@linux.dev/
Changes:
* Added maxItems. (8 is the most I've seen so far on an ADC)
* Tweaked the description a bit.
---
.../devicetree/bindings/spi/spi-peripheral-props.yaml | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml b/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml
index 8b6e8fc009dbdc80978f3afef84ddc688ade4348..a2d1b3d82799f6e93e274711eb57f3739eb8f405 100644
--- a/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml
+++ b/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml
@@ -89,6 +89,20 @@ properties:
description:
Delay, in microseconds, after a write transfer.
+ data-lanes:
+ description:
+ Array of data lane numbers that describes which SPI data lanes of the
+ controller are connected to the peripheral. The index in the array
+ corresponds to the lane on the peripheral and the value corresponds to
+ the lane on the controller. This only applies to peripherals connected to
+ specialized SPI controllers that have multiple SPI data lanes (a set of
+ independent SDI/SDO lines each with its own serializer) on a single
+ controller.
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ minItems: 1
+ maxItems: 8
+ default: [0]
+
stacked-memories:
description: Several SPI memories can be wired in stacked mode.
This basically means that either a device features several chip
--
2.43.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v3 2/7] spi: Support controllers with multiple data lanes
2025-12-02 2:20 [PATCH v3 0/7] spi: add multi-lane support David Lechner
2025-12-02 2:20 ` [PATCH v3 1/7] spi: dt-bindings: Add data-lanes property David Lechner
@ 2025-12-02 2:20 ` David Lechner
2025-12-02 14:44 ` Andy Shevchenko
2025-12-02 2:20 ` [PATCH v3 3/7] spi: add multi_lane_mode field to struct spi_transfer David Lechner
` (4 subsequent siblings)
6 siblings, 1 reply; 24+ messages in thread
From: David Lechner @ 2025-12-02 2:20 UTC (permalink / raw)
To: Mark Brown, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Marcelo Schmitt, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Andy Shevchenko
Cc: Sean Anderson, linux-spi, devicetree, linux-kernel, linux-iio,
David Lechner
Add support for SPI controllers with multiple physical SPI data lanes.
(A data lane in this context means lines connected to a serializer, so a
controller with two data lanes would have two serializers in a single
controller).
This is common in the type of controller that can be used with parallel
flash memories, but can be used for general purpose SPI as well.
To indicate support, a controller just needs to set ctlr->num_data_lanes
to something greater than 1. Peripherals indicate which lane they are
connected to via device tree (ACPI support can be added if needed).
Acked-by: Nuno Sá <nuno.sa@analog.com>
Acked-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
Signed-off-by: David Lechner <dlechner@baylibre.com>
---
v3 changes:
* Renamed "buses" to "lanes" to reflect devicetree property name change.
This patch has been seen in a different series [1] by Sean before:
[1]: https://lore.kernel.org/linux-spi/20250616220054.3968946-4-sean.anderson@linux.dev/
Changes:
* Use u8 array instead of bitfield so that the order of the mapping is
preserved. (Now looks very much like chip select mapping.)
* Added doc strings for added fields.
* Tweaked the comments.
---
drivers/spi/spi.c | 28 +++++++++++++++++++++++++++-
include/linux/spi/spi.h | 17 +++++++++++++++++
2 files changed, 44 insertions(+), 1 deletion(-)
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index e25df9990f82de37c5ee20b703abcefc6f80c082..6b0fcbb26f424fe9972276b183117bdac2ee8ad4 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -2354,7 +2354,7 @@ static void of_spi_parse_dt_cs_delay(struct device_node *nc,
static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi,
struct device_node *nc)
{
- u32 value, cs[SPI_DEVICE_CS_CNT_MAX];
+ u32 value, lanes[SPI_DEVICE_DATA_LANE_CNT_MAX], cs[SPI_DEVICE_CS_CNT_MAX];
int rc, idx;
/* Mode (clock phase/polarity/etc.) */
@@ -2446,6 +2446,31 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi,
for (idx = 0; idx < rc; idx++)
spi_set_chipselect(spi, idx, cs[idx]);
+ rc = of_property_read_variable_u32_array(nc, "data-lanes", lanes, 1,
+ ARRAY_SIZE(lanes));
+ if (rc < 0 && rc != -EINVAL) {
+ dev_err(&ctlr->dev, "%pOF has invalid 'data-lanes' property (%d)\n",
+ nc, rc);
+ return rc;
+ }
+
+ if (rc == -EINVAL) {
+ /* Default when property is omitted. */
+ spi->num_data_lanes = 1;
+ } else {
+ for (idx = 0; idx < rc; idx++) {
+ if (lanes[idx] >= ctlr->num_data_lanes) {
+ dev_err(&ctlr->dev,
+ "%pOF has out of range 'data-lanes' property (%d/%d)\n",
+ nc, lanes[idx], ctlr->num_data_lanes);
+ return -EINVAL;
+ }
+ spi->data_lanes[idx] = lanes[idx];
+ }
+
+ spi->num_data_lanes = rc;
+ }
+
/*
* By default spi->chip_select[0] will hold the physical CS number,
* so set bit 0 in spi->cs_index_mask.
@@ -3066,6 +3091,7 @@ struct spi_controller *__spi_alloc_controller(struct device *dev,
mutex_init(&ctlr->add_lock);
ctlr->bus_num = -1;
ctlr->num_chipselect = 1;
+ ctlr->num_data_lanes = 1;
ctlr->target = target;
if (IS_ENABLED(CONFIG_SPI_SLAVE) && target)
ctlr->dev.class = &spi_target_class;
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index cb2c2df3108999a73b67ef4a7b0d2cb07adfc669..607f1eac96364a73f95876ec27a9f86f14fa6112 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -23,6 +23,9 @@
/* Max no. of CS supported per spi device */
#define SPI_DEVICE_CS_CNT_MAX 4
+/* Max no. of data lanes supported per spi device */
+#define SPI_DEVICE_DATA_LANE_CNT_MAX 8
+
struct dma_chan;
struct software_node;
struct ptp_system_timestamp;
@@ -171,6 +174,9 @@ extern void spi_transfer_cs_change_delay_exec(struct spi_message *msg,
* @chip_select: Array of physical chipselect, spi->chipselect[i] gives
* the corresponding physical CS for logical CS i.
* @num_chipselect: Number of physical chipselects used.
+ * @data_lanes: Array of physical data lanes. This is only used with specialized
+ * controllers that support multiple data lanes.
+ * @num_data_lanes: Number of physical data lanes used.
* @cs_index_mask: Bit mask of the active chipselect(s) in the chipselect array
* @cs_gpiod: Array of GPIO descriptors of the corresponding chipselect lines
* (optional, NULL when not using a GPIO line)
@@ -231,6 +237,8 @@ struct spi_device {
u8 chip_select[SPI_DEVICE_CS_CNT_MAX];
u8 num_chipselect;
+ u8 data_lanes[SPI_DEVICE_DATA_LANE_CNT_MAX];
+ u8 num_data_lanes;
/*
* Bit mask of the chipselect(s) that the driver need to use from
@@ -401,6 +409,7 @@ extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 ch
* SPI targets, and are numbered from zero to num_chipselects.
* each target has a chipselect signal, but it's common that not
* every chipselect is connected to a target.
+ * @num_data_lanes: Number of data lanes supported by this controller. Default is 1.
* @dma_alignment: SPI controller constraint on DMA buffers alignment.
* @mode_bits: flags understood by this controller driver
* @buswidth_override_bits: flags to override for this controller driver
@@ -576,6 +585,14 @@ struct spi_controller {
*/
u16 num_chipselect;
+ /*
+ * Some specialized SPI controllers can have more than one physical
+ * data lane interface per controller (each having it's own serializer).
+ * This specifies the number of data lanes in that case. Other
+ * controllers do not need to set this (defaults to 1).
+ */
+ u16 num_data_lanes;
+
/* Some SPI controllers pose alignment requirements on DMAable
* buffers; let protocol drivers know about these requirements.
*/
--
2.43.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v3 3/7] spi: add multi_lane_mode field to struct spi_transfer
2025-12-02 2:20 [PATCH v3 0/7] spi: add multi-lane support David Lechner
2025-12-02 2:20 ` [PATCH v3 1/7] spi: dt-bindings: Add data-lanes property David Lechner
2025-12-02 2:20 ` [PATCH v3 2/7] spi: Support controllers with multiple data lanes David Lechner
@ 2025-12-02 2:20 ` David Lechner
2025-12-02 14:48 ` Andy Shevchenko
2025-12-02 2:20 ` [PATCH v3 4/7] spi: axi-spi-engine: support SPI_MULTI_LANE_MODE_STRIPE David Lechner
` (3 subsequent siblings)
6 siblings, 1 reply; 24+ messages in thread
From: David Lechner @ 2025-12-02 2:20 UTC (permalink / raw)
To: Mark Brown, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Marcelo Schmitt, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Andy Shevchenko
Cc: Sean Anderson, linux-spi, devicetree, linux-kernel, linux-iio,
David Lechner
Add a new multi_lane_mode field to struct spi_transfer to allow
peripherals that support multiple SPI lanes to be used with a single
SPI controller.
This requires both the peripheral and the controller to have multiple
serializers connected to separate data lanes. It could also be used with
a single controller and multiple peripherals that are functioning as a
single logical device (similar to parallel memories).
The possible values for this field have the following semantics:
- SPI_MULTI_BUS_MODE_SINGLE: Only use the first lane. This means that it
it is operating just like a conventional SPI lane. It is the default
value so that existing drivers do not need to be modified.
Example:
tx_buf[0] = 0x88;
struct spi_transfer xfer = {
.tx_buf = tx_buf,
.len = 1,
};
spi_sync_transfer(spi, &xfer, 1);
controller > data bits > peripheral
---------- ---------------- ----------
SDO 0 0-0-0-1-0-0-0-1 SDI 0
- SPI_MULTI_BUS_MODE_MIRROR: Send a single data word over all of the
lanes at the same time. This only makes sense for writes and not
for reads.
Example:
tx_buf[0] = 0x88;
struct spi_transfer xfer = {
.tx_buf = tx_buf,
.len = 1,
.multi_lane_mode = SPI_MULTI_BUS_MODE_MIRROR,
};
spi_sync_transfer(spi, &xfer, 1);
controller > data bits > peripheral
---------- ---------------- ----------
SDO 0 0-0-0-1-0-0-0-1 SDI 0
SDO 1 0-0-0-1-0-0-0-1 SDI 1
- SPI_MULTI_BUS_MODE_STRIPE: Send or receive two different data words at
the same time, one on each lane.
Example:
struct spi_transfer xfer = {
.rx_buf = rx_buf,
.len = 2, /* must be multiple of number of lanes */
.multi_lane_mode = SPI_MULTI_BUS_MODE_STRIPE,
};
spi_sync_transfer(spi, &xfer, 1);
controller < data bits < peripheral
---------- ---------------- ----------
SDI 0 0-0-0-1-0-0-0-1 SDO 0
SDI 1 1-0-0-0-1-0-0-0 SDO 1
After the transfer, rx_buf[0] == 0x11 (word from SDO 0) and
rx_buf[1] == 0x88 (word from SDO 1). If the transfer was longer,
the data would continue in an alternating fashion.
Acked-by: Nuno Sá <nuno.sa@analog.com>
Acked-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
Signed-off-by: David Lechner <dlechner@baylibre.com>
---
v3 changes:
* Renamed "buses" to "lanes" to reflect devicetree property name change.
---
include/linux/spi/spi.h | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 607f1eac96364a73f95876ec27a9f86f14fa6112..5fad82989853d69cc4bb3e6775e323e2ba8f1144 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -976,6 +976,8 @@ struct spi_res {
* (SPI_NBITS_SINGLE) is used.
* @rx_nbits: number of bits used for reading. If 0 the default
* (SPI_NBITS_SINGLE) is used.
+ * @multi_lane_mode: How to serialize data on multiple lanes. One of the
+ * SPI_MULTI_LANE_MODE_* values.
* @len: size of rx and tx buffers (in bytes)
* @speed_hz: Select a speed other than the device default for this
* transfer. If 0 the default (from @spi_device) is used.
@@ -1112,6 +1114,10 @@ struct spi_transfer {
unsigned cs_change:1;
unsigned tx_nbits:4;
unsigned rx_nbits:4;
+ unsigned multi_lane_mode: 2;
+#define SPI_MULTI_LANE_MODE_SINGLE 0 /* only use single lane */
+#define SPI_MULTI_LANE_MODE_STRIPE 1 /* one data word per lane */
+#define SPI_MULTI_LANE_MODE_MIRROR 2 /* same word sent on all lanes */
unsigned timestamped:1;
bool dtr_mode;
#define SPI_NBITS_SINGLE 0x01 /* 1-bit transfer */
--
2.43.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v3 4/7] spi: axi-spi-engine: support SPI_MULTI_LANE_MODE_STRIPE
2025-12-02 2:20 [PATCH v3 0/7] spi: add multi-lane support David Lechner
` (2 preceding siblings ...)
2025-12-02 2:20 ` [PATCH v3 3/7] spi: add multi_lane_mode field to struct spi_transfer David Lechner
@ 2025-12-02 2:20 ` David Lechner
2025-12-02 14:53 ` Andy Shevchenko
2025-12-02 2:20 ` [PATCH v3 5/7] dt-bindings: iio: adc: adi,ad7380: add spi-lanes property David Lechner
` (2 subsequent siblings)
6 siblings, 1 reply; 24+ messages in thread
From: David Lechner @ 2025-12-02 2:20 UTC (permalink / raw)
To: Mark Brown, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Marcelo Schmitt, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Andy Shevchenko
Cc: Sean Anderson, linux-spi, devicetree, linux-kernel, linux-iio,
David Lechner
Add support for SPI_MULTI_LANE_MODE_STRIPE to the AXI SPI engine driver.
The v2.0.0 version of the AXI SPI Engine IP core supports multiple
lanes. This can be used with SPI_MULTI_LANE_MODE_STRIPE to support
reading from simultaneous sampling ADCs that have a separate SDO line
for each analog channel. This allows reading all channels at the same
time to increase throughput.
Signed-off-by: David Lechner <dlechner@baylibre.com>
---
v3 changes:
* Renamed "buses" to "lanes" to reflect devicetree property name change.
v2 changes:
* Fixed off-by-one in SPI_ENGINE_REG_DATA_WIDTH_NUM_OF_SDIO_MASK GENMASK
---
drivers/spi/spi-axi-spi-engine.c | 128 +++++++++++++++++++++++++++++++++++++--
1 file changed, 124 insertions(+), 4 deletions(-)
diff --git a/drivers/spi/spi-axi-spi-engine.c b/drivers/spi/spi-axi-spi-engine.c
index e06f412190fd243161a0b3df992f26157531f6a1..4a514002d03789a62b29c68ea0f8f20789c830c8 100644
--- a/drivers/spi/spi-axi-spi-engine.c
+++ b/drivers/spi/spi-axi-spi-engine.c
@@ -23,6 +23,9 @@
#include <linux/spi/spi.h>
#include <trace/events/spi.h>
+#define SPI_ENGINE_REG_DATA_WIDTH 0x0C
+#define SPI_ENGINE_REG_DATA_WIDTH_NUM_OF_SDIO_MASK GENMASK(23, 16)
+#define SPI_ENGINE_REG_DATA_WIDTH_MASK GENMASK(15, 0)
#define SPI_ENGINE_REG_OFFLOAD_MEM_ADDR_WIDTH 0x10
#define SPI_ENGINE_REG_RESET 0x40
@@ -75,6 +78,8 @@
#define SPI_ENGINE_CMD_REG_CLK_DIV 0x0
#define SPI_ENGINE_CMD_REG_CONFIG 0x1
#define SPI_ENGINE_CMD_REG_XFER_BITS 0x2
+#define SPI_ENGINE_CMD_REG_SDI_MASK 0x3
+#define SPI_ENGINE_CMD_REG_SDO_MASK 0x4
#define SPI_ENGINE_MISC_SYNC 0x0
#define SPI_ENGINE_MISC_SLEEP 0x1
@@ -105,6 +110,10 @@
#define SPI_ENGINE_OFFLOAD_CMD_FIFO_SIZE 16
#define SPI_ENGINE_OFFLOAD_SDO_FIFO_SIZE 16
+/* Extending SPI_MULTI_LANE_MODE values for optimizing messages. */
+#define SPI_ENGINE_MULTI_BUS_MODE_UNKNOWN -1
+#define SPI_ENGINE_MULTI_BUS_MODE_CONFLICTING -2
+
struct spi_engine_program {
unsigned int length;
uint16_t instructions[] __counted_by(length);
@@ -142,6 +151,9 @@ struct spi_engine_offload {
unsigned long flags;
unsigned int offload_num;
unsigned int spi_mode_config;
+ unsigned int multi_lane_mode;
+ u8 primary_lane_mask;
+ u8 all_lane_mask;
u8 bits_per_word;
};
@@ -165,6 +177,22 @@ struct spi_engine {
bool offload_requires_sync;
};
+static u8 spi_engine_primary_lane_flag(struct spi_device *spi)
+{
+ return BIT(spi->data_lanes[0]);
+}
+
+static u8 spi_engine_all_lane_flags(struct spi_device *spi)
+{
+ u8 flags = 0;
+ int i;
+
+ for (i = 0; i < spi->num_data_lanes; i++)
+ flags |= BIT(spi->data_lanes[i]);
+
+ return flags;
+}
+
static void spi_engine_program_add_cmd(struct spi_engine_program *p,
bool dry, uint16_t cmd)
{
@@ -193,7 +221,7 @@ static unsigned int spi_engine_get_config(struct spi_device *spi)
}
static void spi_engine_gen_xfer(struct spi_engine_program *p, bool dry,
- struct spi_transfer *xfer)
+ struct spi_transfer *xfer, u32 num_lanes)
{
unsigned int len;
@@ -204,6 +232,9 @@ static void spi_engine_gen_xfer(struct spi_engine_program *p, bool dry,
else
len = xfer->len / 4;
+ if (xfer->multi_lane_mode == SPI_MULTI_LANE_MODE_STRIPE)
+ len /= num_lanes;
+
while (len) {
unsigned int n = min(len, 256U);
unsigned int flags = 0;
@@ -269,6 +300,7 @@ static int spi_engine_precompile_message(struct spi_message *msg)
{
unsigned int clk_div, max_hz = msg->spi->controller->max_speed_hz;
struct spi_transfer *xfer;
+ int multi_lane_mode = SPI_ENGINE_MULTI_BUS_MODE_UNKNOWN;
u8 min_bits_per_word = U8_MAX;
u8 max_bits_per_word = 0;
@@ -284,6 +316,24 @@ static int spi_engine_precompile_message(struct spi_message *msg)
min_bits_per_word = min(min_bits_per_word, xfer->bits_per_word);
max_bits_per_word = max(max_bits_per_word, xfer->bits_per_word);
}
+
+ if (xfer->rx_buf || xfer->offload_flags & SPI_OFFLOAD_XFER_RX_STREAM ||
+ xfer->tx_buf || xfer->offload_flags & SPI_OFFLOAD_XFER_TX_STREAM) {
+ switch (xfer->multi_lane_mode) {
+ case SPI_MULTI_LANE_MODE_SINGLE:
+ case SPI_MULTI_LANE_MODE_STRIPE:
+ break;
+ default:
+ /* Other modes, like mirror not supported */
+ return -EINVAL;
+ }
+
+ /* If all xfers have the same multi-lane mode, we can optimize. */
+ if (multi_lane_mode == SPI_ENGINE_MULTI_BUS_MODE_UNKNOWN)
+ multi_lane_mode = xfer->multi_lane_mode;
+ else if (multi_lane_mode != xfer->multi_lane_mode)
+ multi_lane_mode = SPI_ENGINE_MULTI_BUS_MODE_CONFLICTING;
+ }
}
/*
@@ -297,6 +347,10 @@ static int spi_engine_precompile_message(struct spi_message *msg)
priv->bits_per_word = min_bits_per_word;
else
priv->bits_per_word = 0;
+
+ priv->multi_lane_mode = multi_lane_mode;
+ priv->primary_lane_mask = spi_engine_primary_lane_flag(msg->spi);
+ priv->all_lane_mask = spi_engine_all_lane_flags(msg->spi);
}
return 0;
@@ -310,6 +364,7 @@ static void spi_engine_compile_message(struct spi_message *msg, bool dry,
struct spi_engine_offload *priv;
struct spi_transfer *xfer;
int clk_div, new_clk_div, inst_ns;
+ int prev_multi_lane_mode = SPI_MULTI_LANE_MODE_SINGLE;
bool keep_cs = false;
u8 bits_per_word = 0;
@@ -334,6 +389,7 @@ static void spi_engine_compile_message(struct spi_message *msg, bool dry,
* in the same way.
*/
bits_per_word = priv->bits_per_word;
+ prev_multi_lane_mode = priv->multi_lane_mode;
} else {
spi_engine_program_add_cmd(p, dry,
SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_CONFIG,
@@ -344,6 +400,24 @@ static void spi_engine_compile_message(struct spi_message *msg, bool dry,
spi_engine_gen_cs(p, dry, spi, !xfer->cs_off);
list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+ if (xfer->rx_buf || xfer->offload_flags & SPI_OFFLOAD_XFER_RX_STREAM ||
+ xfer->tx_buf || xfer->offload_flags & SPI_OFFLOAD_XFER_TX_STREAM) {
+ if (xfer->multi_lane_mode != prev_multi_lane_mode) {
+ u8 lane_flags = spi_engine_primary_lane_flag(spi);
+
+ if (xfer->multi_lane_mode == SPI_MULTI_LANE_MODE_STRIPE)
+ lane_flags = spi_engine_all_lane_flags(spi);
+
+ spi_engine_program_add_cmd(p, dry,
+ SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_SDI_MASK,
+ lane_flags));
+ spi_engine_program_add_cmd(p, dry,
+ SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_SDO_MASK,
+ lane_flags));
+ }
+ prev_multi_lane_mode = xfer->multi_lane_mode;
+ }
+
new_clk_div = host->max_speed_hz / xfer->effective_speed_hz;
if (new_clk_div != clk_div) {
clk_div = new_clk_div;
@@ -360,7 +434,7 @@ static void spi_engine_compile_message(struct spi_message *msg, bool dry,
bits_per_word));
}
- spi_engine_gen_xfer(p, dry, xfer);
+ spi_engine_gen_xfer(p, dry, xfer, spi->num_data_lanes);
spi_engine_gen_sleep(p, dry, spi_delay_to_ns(&xfer->delay, xfer),
inst_ns, xfer->effective_speed_hz);
@@ -394,6 +468,17 @@ static void spi_engine_compile_message(struct spi_message *msg, bool dry,
if (clk_div != 1)
spi_engine_program_add_cmd(p, dry,
SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_CLK_DIV, 0));
+
+ /* Restore single lane mode unless offload disable will restore it later. */
+ if (prev_multi_lane_mode == SPI_MULTI_LANE_MODE_STRIPE &&
+ (!msg->offload || priv->multi_lane_mode != SPI_MULTI_LANE_MODE_STRIPE)) {
+ u8 lane_flags = spi_engine_primary_lane_flag(spi);
+
+ spi_engine_program_add_cmd(p, dry,
+ SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_SDI_MASK, lane_flags));
+ spi_engine_program_add_cmd(p, dry,
+ SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_SDO_MASK, lane_flags));
+ }
}
static void spi_engine_xfer_next(struct spi_message *msg,
@@ -799,6 +884,17 @@ static int spi_engine_setup(struct spi_device *device)
writel_relaxed(SPI_ENGINE_CMD_CS_INV(spi_engine->cs_inv),
spi_engine->base + SPI_ENGINE_REG_CMD_FIFO);
+ if (host->num_data_lanes > 1) {
+ u8 lane_flags = spi_engine_primary_lane_flag(device);
+
+ writel_relaxed(SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_SDI_MASK,
+ lane_flags),
+ spi_engine->base + SPI_ENGINE_REG_CMD_FIFO);
+ writel_relaxed(SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_SDO_MASK,
+ lane_flags),
+ spi_engine->base + SPI_ENGINE_REG_CMD_FIFO);
+ }
+
/*
* In addition to setting the flags, we have to do a CS assert command
* to make the new setting actually take effect.
@@ -902,6 +998,15 @@ static int spi_engine_trigger_enable(struct spi_offload *offload)
priv->bits_per_word),
spi_engine->base + SPI_ENGINE_REG_CMD_FIFO);
+ if (priv->multi_lane_mode == SPI_MULTI_LANE_MODE_STRIPE) {
+ writel_relaxed(SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_SDI_MASK,
+ priv->all_lane_mask),
+ spi_engine->base + SPI_ENGINE_REG_CMD_FIFO);
+ writel_relaxed(SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_SDO_MASK,
+ priv->all_lane_mask),
+ spi_engine->base + SPI_ENGINE_REG_CMD_FIFO);
+ }
+
writel_relaxed(SPI_ENGINE_CMD_SYNC(1),
spi_engine->base + SPI_ENGINE_REG_CMD_FIFO);
@@ -929,6 +1034,16 @@ static void spi_engine_trigger_disable(struct spi_offload *offload)
reg &= ~SPI_ENGINE_OFFLOAD_CTRL_ENABLE;
writel_relaxed(reg, spi_engine->base +
SPI_ENGINE_REG_OFFLOAD_CTRL(priv->offload_num));
+
+ /* Restore single-lane mode. */
+ if (priv->multi_lane_mode == SPI_MULTI_LANE_MODE_STRIPE) {
+ writel_relaxed(SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_SDI_MASK,
+ priv->primary_lane_mask),
+ spi_engine->base + SPI_ENGINE_REG_CMD_FIFO);
+ writel_relaxed(SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_SDO_MASK,
+ priv->primary_lane_mask),
+ spi_engine->base + SPI_ENGINE_REG_CMD_FIFO);
+ }
}
static struct dma_chan
@@ -973,7 +1088,7 @@ static int spi_engine_probe(struct platform_device *pdev)
{
struct spi_engine *spi_engine;
struct spi_controller *host;
- unsigned int version;
+ unsigned int version, data_width_reg_val;
int irq, ret;
irq = platform_get_irq(pdev, 0);
@@ -1042,7 +1157,7 @@ static int spi_engine_probe(struct platform_device *pdev)
return PTR_ERR(spi_engine->base);
version = readl(spi_engine->base + ADI_AXI_REG_VERSION);
- if (ADI_AXI_PCORE_VER_MAJOR(version) != 1) {
+ if (ADI_AXI_PCORE_VER_MAJOR(version) > 2) {
dev_err(&pdev->dev, "Unsupported peripheral version %u.%u.%u\n",
ADI_AXI_PCORE_VER_MAJOR(version),
ADI_AXI_PCORE_VER_MINOR(version),
@@ -1050,6 +1165,8 @@ static int spi_engine_probe(struct platform_device *pdev)
return -ENODEV;
}
+ data_width_reg_val = readl(spi_engine->base + SPI_ENGINE_REG_DATA_WIDTH);
+
if (adi_axi_pcore_ver_gteq(version, 1, 1)) {
unsigned int sizes = readl(spi_engine->base +
SPI_ENGINE_REG_OFFLOAD_MEM_ADDR_WIDTH);
@@ -1097,6 +1214,9 @@ static int spi_engine_probe(struct platform_device *pdev)
}
if (adi_axi_pcore_ver_gteq(version, 1, 3))
host->mode_bits |= SPI_MOSI_IDLE_LOW | SPI_MOSI_IDLE_HIGH;
+ if (adi_axi_pcore_ver_gteq(version, 2, 0))
+ host->num_data_lanes = FIELD_GET(SPI_ENGINE_REG_DATA_WIDTH_NUM_OF_SDIO_MASK,
+ data_width_reg_val);
if (host->max_speed_hz == 0)
return dev_err_probe(&pdev->dev, -EINVAL, "spi_clk rate is 0");
--
2.43.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v3 5/7] dt-bindings: iio: adc: adi,ad7380: add spi-lanes property
2025-12-02 2:20 [PATCH v3 0/7] spi: add multi-lane support David Lechner
` (3 preceding siblings ...)
2025-12-02 2:20 ` [PATCH v3 4/7] spi: axi-spi-engine: support SPI_MULTI_LANE_MODE_STRIPE David Lechner
@ 2025-12-02 2:20 ` David Lechner
2025-12-04 21:29 ` Rob Herring (Arm)
2025-12-02 2:20 ` [PATCH v3 6/7] iio: adc: ad7380: Add support for multiple SPI lanes David Lechner
2025-12-02 2:20 ` [PATCH v3 7/7] dt-bindings: iio: adc: adi,ad4030: add data-lanes property David Lechner
6 siblings, 1 reply; 24+ messages in thread
From: David Lechner @ 2025-12-02 2:20 UTC (permalink / raw)
To: Mark Brown, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Marcelo Schmitt, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Andy Shevchenko
Cc: Sean Anderson, linux-spi, devicetree, linux-kernel, linux-iio,
David Lechner
Add spi-lanes property to describe how many SDO lines are wired up on
the ADC. These chips are simultaneous sampling ADCs and have one SDO
line per channel, either 2 or 4 total depending on the part number.
Signed-off-by: David Lechner <dlechner@baylibre.com>
---
v3 changes:
* Renamed "buses" to "lanes" to reflect devicetree property name change.
---
.../devicetree/bindings/iio/adc/adi,ad7380.yaml | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml
index b91bfb16ed6bc6c605880f81050250d1ed9c307a..3d2de67d3c27548020337bb2fbd54f977657b034 100644
--- a/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml
@@ -62,6 +62,10 @@ properties:
spi-cpol: true
spi-cpha: true
+ data-lanes:
+ minItems: 1
+ maxItems: 4
+
vcc-supply:
description: A 3V to 3.6V supply that powers the chip.
@@ -245,6 +249,22 @@ allOf:
patternProperties:
"^channel@[0-3]$": false
+ # 2-channel chip can only have up to 2 buses
+ - if:
+ properties:
+ compatible:
+ enum:
+ - adi,ad7380
+ - adi,ad7381
+ - adi,ad7386
+ - adi,ad7387
+ - adi,ad7388
+ - adi,ad7389
+ then:
+ properties:
+ data-lanes:
+ maxItems: 2
+
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
@@ -260,6 +280,7 @@ examples:
spi-cpol;
spi-cpha;
spi-max-frequency = <80000000>;
+ data-lanes = <0>, <1>;
interrupts = <27 IRQ_TYPE_EDGE_FALLING>;
interrupt-parent = <&gpio0>;
@@ -284,6 +305,7 @@ examples:
spi-cpol;
spi-cpha;
spi-max-frequency = <80000000>;
+ data-lanes = <0>, <1>, <2>, <3>;
interrupts = <27 IRQ_TYPE_EDGE_FALLING>;
interrupt-parent = <&gpio0>;
--
2.43.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v3 6/7] iio: adc: ad7380: Add support for multiple SPI lanes
2025-12-02 2:20 [PATCH v3 0/7] spi: add multi-lane support David Lechner
` (4 preceding siblings ...)
2025-12-02 2:20 ` [PATCH v3 5/7] dt-bindings: iio: adc: adi,ad7380: add spi-lanes property David Lechner
@ 2025-12-02 2:20 ` David Lechner
2025-12-02 2:20 ` [PATCH v3 7/7] dt-bindings: iio: adc: adi,ad4030: add data-lanes property David Lechner
6 siblings, 0 replies; 24+ messages in thread
From: David Lechner @ 2025-12-02 2:20 UTC (permalink / raw)
To: Mark Brown, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Marcelo Schmitt, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Andy Shevchenko
Cc: Sean Anderson, linux-spi, devicetree, linux-kernel, linux-iio,
David Lechner
Add support for multiple SPI lanes to increase throughput. The AD7380
family of ADCs have multiple SDO lines on the chip that can be used to
read each channel on a separate SPI lane. If wired up to a SPI
controller that supports it, the driver will now take advantage of this
feature. This allows reaching the maximum sample rate advertised in the
datasheet when combined with SPI offloading.
Reviewed-by: Nuno Sá <nuno.sa@analog.com>
Signed-off-by: David Lechner <dlechner@baylibre.com>
---
v3 changes:
* Renamed "buses" to "lanes" to reflect devicetree property name change.
v2 changes:
* Move st->seq_xfer[3].multi_lane_mode = SPI_MULTI_BUS_MODE_STRIPE;
to probe().
---
drivers/iio/adc/ad7380.c | 42 +++++++++++++++++++++++++++++-------------
1 file changed, 29 insertions(+), 13 deletions(-)
diff --git a/drivers/iio/adc/ad7380.c b/drivers/iio/adc/ad7380.c
index bfd908deefc0f40b42bd8a44bfce7a2510b2fdf1..5c4caf31cecc398e5475569b49e0c16c7dcf673c 100644
--- a/drivers/iio/adc/ad7380.c
+++ b/drivers/iio/adc/ad7380.c
@@ -77,8 +77,7 @@
#define AD7380_CONFIG1_REFSEL BIT(1)
#define AD7380_CONFIG1_PMODE BIT(0)
-#define AD7380_CONFIG2_SDO2 GENMASK(9, 8)
-#define AD7380_CONFIG2_SDO BIT(8)
+#define AD7380_CONFIG2_SDO GENMASK(9, 8)
#define AD7380_CONFIG2_RESET GENMASK(7, 0)
#define AD7380_CONFIG2_RESET_SOFT 0x3C
@@ -92,11 +91,6 @@
#define T_CONVERT_X_NS 500 /* xth conversion start time (oversampling) */
#define T_POWERUP_US 5000 /* Power up */
-/*
- * AD738x support several SDO lines to increase throughput, but driver currently
- * supports only 1 SDO line (standard SPI transaction)
- */
-#define AD7380_NUM_SDO_LINES 1
#define AD7380_DEFAULT_GAIN_MILLI 1000
/*
@@ -1084,7 +1078,7 @@ static int ad7380_set_ch(struct ad7380_state *st, unsigned int ch)
if (oversampling_ratio > 1)
xfer.delay.value = T_CONVERT_0_NS +
T_CONVERT_X_NS * (oversampling_ratio - 1) *
- st->chip_info->num_simult_channels / AD7380_NUM_SDO_LINES;
+ st->chip_info->num_simult_channels / st->spi->num_data_lanes;
return spi_sync_transfer(st->spi, &xfer, 1);
}
@@ -1113,7 +1107,7 @@ static int ad7380_update_xfers(struct ad7380_state *st,
if (oversampling_ratio > 1)
t_convert = T_CONVERT_0_NS + T_CONVERT_X_NS *
(oversampling_ratio - 1) *
- st->chip_info->num_simult_channels / AD7380_NUM_SDO_LINES;
+ st->chip_info->num_simult_channels / st->spi->num_data_lanes;
if (st->seq) {
xfer[0].delay.value = xfer[1].delay.value = t_convert;
@@ -1198,6 +1192,8 @@ static int ad7380_init_offload_msg(struct ad7380_state *st,
xfer->bits_per_word = scan_type->realbits;
xfer->offload_flags = SPI_OFFLOAD_XFER_RX_STREAM;
xfer->len = AD7380_SPI_BYTES(scan_type) * st->chip_info->num_simult_channels;
+ if (st->spi->num_data_lanes > 1)
+ xfer->multi_lane_mode = SPI_MULTI_LANE_MODE_STRIPE;
spi_message_init_with_transfers(&st->offload_msg, xfer, 1);
st->offload_msg.offload = st->offload;
@@ -1793,6 +1789,7 @@ static const struct iio_info ad7380_info = {
static int ad7380_init(struct ad7380_state *st, bool external_ref_en)
{
+ u32 sdo;
int ret;
/* perform hard reset */
@@ -1815,11 +1812,24 @@ static int ad7380_init(struct ad7380_state *st, bool external_ref_en)
st->ch = 0;
st->seq = false;
- /* SPI 1-wire mode */
+ /* SDO field has an irregular mapping. */
+ switch (st->spi->num_data_lanes) {
+ case 1:
+ sdo = 1;
+ break;
+ case 2:
+ sdo = 0;
+ break;
+ case 4:
+ sdo = 2;
+ break;
+ default:
+ return -EINVAL;
+ }
+
return regmap_update_bits(st->regmap, AD7380_REG_ADDR_CONFIG2,
AD7380_CONFIG2_SDO,
- FIELD_PREP(AD7380_CONFIG2_SDO,
- AD7380_NUM_SDO_LINES));
+ FIELD_PREP(AD7380_CONFIG2_SDO, sdo));
}
static int ad7380_probe_spi_offload(struct iio_dev *indio_dev,
@@ -1842,7 +1852,7 @@ static int ad7380_probe_spi_offload(struct iio_dev *indio_dev,
"failed to get offload trigger\n");
sample_rate = st->chip_info->max_conversion_rate_hz *
- AD7380_NUM_SDO_LINES / st->chip_info->num_simult_channels;
+ spi->num_data_lanes / st->chip_info->num_simult_channels;
st->sample_freq_range[0] = 1; /* min */
st->sample_freq_range[1] = 1; /* step */
@@ -2010,6 +2020,8 @@ static int ad7380_probe(struct spi_device *spi)
st->normal_xfer[0].cs_change_delay.value = st->chip_info->timing_specs->t_csh_ns;
st->normal_xfer[0].cs_change_delay.unit = SPI_DELAY_UNIT_NSECS;
st->normal_xfer[1].rx_buf = st->scan_data;
+ if (spi->num_data_lanes > 1)
+ st->normal_xfer[1].multi_lane_mode = SPI_MULTI_LANE_MODE_STRIPE;
spi_message_init_with_transfers(&st->normal_msg, st->normal_xfer,
ARRAY_SIZE(st->normal_xfer));
@@ -2031,6 +2043,10 @@ static int ad7380_probe(struct spi_device *spi)
st->seq_xfer[2].cs_change = 1;
st->seq_xfer[2].cs_change_delay.value = st->chip_info->timing_specs->t_csh_ns;
st->seq_xfer[2].cs_change_delay.unit = SPI_DELAY_UNIT_NSECS;
+ if (spi->num_data_lanes > 1) {
+ st->seq_xfer[2].multi_lane_mode = SPI_MULTI_LANE_MODE_STRIPE;
+ st->seq_xfer[3].multi_lane_mode = SPI_MULTI_LANE_MODE_STRIPE;
+ }
spi_message_init_with_transfers(&st->seq_msg, st->seq_xfer,
ARRAY_SIZE(st->seq_xfer));
--
2.43.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v3 7/7] dt-bindings: iio: adc: adi,ad4030: add data-lanes property
2025-12-02 2:20 [PATCH v3 0/7] spi: add multi-lane support David Lechner
` (5 preceding siblings ...)
2025-12-02 2:20 ` [PATCH v3 6/7] iio: adc: ad7380: Add support for multiple SPI lanes David Lechner
@ 2025-12-02 2:20 ` David Lechner
2025-12-04 21:33 ` Rob Herring
6 siblings, 1 reply; 24+ messages in thread
From: David Lechner @ 2025-12-02 2:20 UTC (permalink / raw)
To: Mark Brown, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Marcelo Schmitt, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Andy Shevchenko
Cc: Sean Anderson, linux-spi, devicetree, linux-kernel, linux-iio,
David Lechner
Add data-lanes property to specify the number of data lanes used on the
ad463x chips that support reading two samples at the same time using
two data lanes with a capable SPI controller.
Signed-off-by: David Lechner <dlechner@baylibre.com>
---
v3 changes: new patch
I added this one to give a real-world use case where spi-rx-bus-width
was not sufficient to fully describe the hardware configuration.
spi-rx-bus-width = <4>; alone could be be interpreted as either:
+--------------+ +----------+
| SPI | | AD4630 |
| Controller | | ADC |
| | | |
| SDIA0 |<---| SDOA0 |
| SDIA1 |<---| SDOA1 |
| SDIA2 |<---| SDOA2 |
| SDIA3 |<---| SDOA3 |
| | | |
| SDIB0 |x | SDOB0 |
| SDIB1 |x | SDOB1 |
| SDIB2 |x | SDOB2 |
| SDIB3 |x | SDOB3 |
| | | |
+--------------+ +---------+
or
+--------------+ +----------+
| SPI | | AD4630 |
| Controller | | ADC |
| | | |
| SDIA0 |<---| SDOA0 |
| SDIA1 |<---| SDOA1 |
| SDIA2 |x | SDOA2 |
| SDIA3 |x | SDOA3 |
| | | |
| SDIB0 |<---| SDOB0 |
| SDIB1 |<---| SDOB1 |
| SDIB2 |x | SDOB2 |
| SDIB3 |x | SDOB3 |
| | | |
+--------------+ +---------+
Now, with data-lanes having a default value of [0] (inherited from
spi-peripheral-props.yaml), specifying:
spi-rx-bus-width = <4>;
is unambiguously the first case and the example given in the binding
documentation is the second case:
spi-rx-bus-width = <2>;
data-lanes = <0>, <1>;
---
.../devicetree/bindings/iio/adc/adi,ad4030.yaml | 36 ++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad4030.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad4030.yaml
index 54e7349317b77f032ecafde0102bf3a09f140f03..315ebcfbfa28888a4518073c1b286f0993f83673 100644
--- a/Documentation/devicetree/bindings/iio/adc/adi,ad4030.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ad4030.yaml
@@ -39,6 +39,10 @@ properties:
spi-rx-bus-width:
enum: [1, 2, 4]
+ data-lanes:
+ minItems: 1
+ maxItems: 2
+
vdd-5v-supply: true
vdd-1v8-supply: true
vio-supply: true
@@ -88,6 +92,17 @@ oneOf:
unevaluatedProperties: false
+allOf:
+ - if:
+ properties:
+ compatible:
+ enum:
+ - adi,ad4030-24
+ - adi,ad4032-24
+ then:
+ properties:
+ data-lanes: false
+
examples:
- |
#include <dt-bindings/gpio/gpio.h>
@@ -108,3 +123,24 @@ examples:
reset-gpios = <&gpio0 1 GPIO_ACTIVE_LOW>;
};
};
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ adc@0 {
+ compatible = "adi,ad4630-24";
+ reg = <0>;
+ spi-max-frequency = <80000000>;
+ spi-rx-bus-width = <2>;
+ data-lanes = <0>, <1>;
+ vdd-5v-supply = <&supply_5V>;
+ vdd-1v8-supply = <&supply_1_8V>;
+ vio-supply = <&supply_1_8V>;
+ ref-supply = <&supply_5V>;
+ cnv-gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&gpio0 1 GPIO_ACTIVE_LOW>;
+ };
+ };
--
2.43.0
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH v3 2/7] spi: Support controllers with multiple data lanes
2025-12-02 2:20 ` [PATCH v3 2/7] spi: Support controllers with multiple data lanes David Lechner
@ 2025-12-02 14:44 ` Andy Shevchenko
2025-12-02 14:47 ` David Lechner
0 siblings, 1 reply; 24+ messages in thread
From: Andy Shevchenko @ 2025-12-02 14:44 UTC (permalink / raw)
To: David Lechner
Cc: Mark Brown, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Marcelo Schmitt, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Andy Shevchenko, Sean Anderson, linux-spi,
devicetree, linux-kernel, linux-iio
On Mon, Dec 01, 2025 at 08:20:40PM -0600, David Lechner wrote:
> Add support for SPI controllers with multiple physical SPI data lanes.
> (A data lane in this context means lines connected to a serializer, so a
> controller with two data lanes would have two serializers in a single
> controller).
I'm a bit confused. Does it mean the three data lanes require three
serializers?
> This is common in the type of controller that can be used with parallel
> flash memories, but can be used for general purpose SPI as well.
>
> To indicate support, a controller just needs to set ctlr->num_data_lanes
> to something greater than 1. Peripherals indicate which lane they are
> connected to via device tree (ACPI support can be added if needed).
...
> + rc = of_property_read_variable_u32_array(nc, "data-lanes", lanes, 1,
> + ARRAY_SIZE(lanes));
> + if (rc < 0 && rc != -EINVAL) {
It's a dup check for EINVAL, see below...
> + dev_err(&ctlr->dev, "%pOF has invalid 'data-lanes' property (%d)\n",
> + nc, rc);
> + return rc;
> + }
> +
> + if (rc == -EINVAL) {
> + /* Default when property is omitted. */
> + spi->num_data_lanes = 1;
...just move it here as
} else if (rc < 0) {
...
(and yes, I know that this is not so usual pattern, but it makes the code less
duplicative).
> + } else {
> + for (idx = 0; idx < rc; idx++) {
> + if (lanes[idx] >= ctlr->num_data_lanes) {
> + dev_err(&ctlr->dev,
> + "%pOF has out of range 'data-lanes' property (%d/%d)\n",
> + nc, lanes[idx], ctlr->num_data_lanes);
> + return -EINVAL;
> + }
> + spi->data_lanes[idx] = lanes[idx];
> + }
> +
> + spi->num_data_lanes = rc;
> + }
...
> * @chip_select: Array of physical chipselect, spi->chipselect[i] gives
> * the corresponding physical CS for logical CS i.
> * @num_chipselect: Number of physical chipselects used.
> + * @data_lanes: Array of physical data lanes. This is only used with specialized
> + * controllers that support multiple data lanes.
> + * @num_data_lanes: Number of physical data lanes used.
This split the group of cs related members. Can you move it out or explain how
does it relate?
> * @cs_index_mask: Bit mask of the active chipselect(s) in the chipselect array
> * @cs_gpiod: Array of GPIO descriptors of the corresponding chipselect lines
> * (optional, NULL when not using a GPIO line)
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v3 2/7] spi: Support controllers with multiple data lanes
2025-12-02 14:44 ` Andy Shevchenko
@ 2025-12-02 14:47 ` David Lechner
0 siblings, 0 replies; 24+ messages in thread
From: David Lechner @ 2025-12-02 14:47 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Mark Brown, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Marcelo Schmitt, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Andy Shevchenko, Sean Anderson, linux-spi,
devicetree, linux-kernel, linux-iio
On 12/2/25 8:44 AM, Andy Shevchenko wrote:
> On Mon, Dec 01, 2025 at 08:20:40PM -0600, David Lechner wrote:
>> Add support for SPI controllers with multiple physical SPI data lanes.
>> (A data lane in this context means lines connected to a serializer, so a
>> controller with two data lanes would have two serializers in a single
>> controller).
>
> I'm a bit confused. Does it mean the three data lanes require three
> serializers?
>
Correct.
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v3 3/7] spi: add multi_lane_mode field to struct spi_transfer
2025-12-02 2:20 ` [PATCH v3 3/7] spi: add multi_lane_mode field to struct spi_transfer David Lechner
@ 2025-12-02 14:48 ` Andy Shevchenko
0 siblings, 0 replies; 24+ messages in thread
From: Andy Shevchenko @ 2025-12-02 14:48 UTC (permalink / raw)
To: David Lechner
Cc: Mark Brown, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Marcelo Schmitt, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Andy Shevchenko, Sean Anderson, linux-spi,
devicetree, linux-kernel, linux-iio
On Mon, Dec 01, 2025 at 08:20:41PM -0600, David Lechner wrote:
> Add a new multi_lane_mode field to struct spi_transfer to allow
> peripherals that support multiple SPI lanes to be used with a single
> SPI controller.
>
> This requires both the peripheral and the controller to have multiple
> serializers connected to separate data lanes. It could also be used with
> a single controller and multiple peripherals that are functioning as a
> single logical device (similar to parallel memories).
>
> The possible values for this field have the following semantics:
I believe it's too much for a commit message and will be hidden deeply
for the (potential) user. Can we rather create or update the respective
documentation file?
> * @rx_nbits: number of bits used for reading. If 0 the default
> * (SPI_NBITS_SINGLE) is used.
> + * @multi_lane_mode: How to serialize data on multiple lanes. One of the
> + * SPI_MULTI_LANE_MODE_* values.
> * @len: size of rx and tx buffers (in bytes)
> * @speed_hz: Select a speed other than the device default for this
> * transfer. If 0 the default (from @spi_device) is used.
> @@ -1112,6 +1114,10 @@ struct spi_transfer {
> unsigned cs_change:1;
> unsigned tx_nbits:4;
> unsigned rx_nbits:4;
> + unsigned multi_lane_mode: 2;
> +#define SPI_MULTI_LANE_MODE_SINGLE 0 /* only use single lane */
> +#define SPI_MULTI_LANE_MODE_STRIPE 1 /* one data word per lane */
> +#define SPI_MULTI_LANE_MODE_MIRROR 2 /* same word sent on all lanes */
> unsigned timestamped:1;
> bool dtr_mode;
> #define SPI_NBITS_SINGLE 0x01 /* 1-bit transfer */
Seems to me that this also fell apart, as this define sounds like a part of
*x_bits above and your patch makes it even diverse further. Can we keep grouped
members to be in a group?
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v3 4/7] spi: axi-spi-engine: support SPI_MULTI_LANE_MODE_STRIPE
2025-12-02 2:20 ` [PATCH v3 4/7] spi: axi-spi-engine: support SPI_MULTI_LANE_MODE_STRIPE David Lechner
@ 2025-12-02 14:53 ` Andy Shevchenko
2025-12-02 16:36 ` Mark Brown
2025-12-10 0:02 ` David Lechner
0 siblings, 2 replies; 24+ messages in thread
From: Andy Shevchenko @ 2025-12-02 14:53 UTC (permalink / raw)
To: David Lechner
Cc: Mark Brown, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Marcelo Schmitt, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Andy Shevchenko, Sean Anderson, linux-spi,
devicetree, linux-kernel, linux-iio
On Mon, Dec 01, 2025 at 08:20:42PM -0600, David Lechner wrote:
> Add support for SPI_MULTI_LANE_MODE_STRIPE to the AXI SPI engine driver.
>
> The v2.0.0 version of the AXI SPI Engine IP core supports multiple
> lanes. This can be used with SPI_MULTI_LANE_MODE_STRIPE to support
> reading from simultaneous sampling ADCs that have a separate SDO line
> for each analog channel. This allows reading all channels at the same
> time to increase throughput.
...
> +static u8 spi_engine_all_lane_flags(struct spi_device *spi)
> +{
> + u8 flags = 0;
> + int i;
Why signed?
> + for (i = 0; i < spi->num_data_lanes; i++)
> + flags |= BIT(spi->data_lanes[i]);
> +
> + return flags;
> +}
...
> static void spi_engine_gen_xfer(struct spi_engine_program *p, bool dry,
> - struct spi_transfer *xfer)
> + struct spi_transfer *xfer, u32 num_lanes)
Side note: this bool parameter makes code harder to follow. And now we have
pointers and integers/booleans to be interleaved. Perhaps reconsider the order
of the parameters (and ideally get rid of boolean by making two distinct
functions?).
...
> version = readl(spi_engine->base + ADI_AXI_REG_VERSION);
> - if (ADI_AXI_PCORE_VER_MAJOR(version) != 1) {
> + if (ADI_AXI_PCORE_VER_MAJOR(version) > 2) {
But this includes v0 as well!
> }
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v3 4/7] spi: axi-spi-engine: support SPI_MULTI_LANE_MODE_STRIPE
2025-12-02 14:53 ` Andy Shevchenko
@ 2025-12-02 16:36 ` Mark Brown
2025-12-10 0:02 ` David Lechner
1 sibling, 0 replies; 24+ messages in thread
From: Mark Brown @ 2025-12-02 16:36 UTC (permalink / raw)
To: Andy Shevchenko
Cc: David Lechner, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Marcelo Schmitt, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Andy Shevchenko, Sean Anderson, linux-spi,
devicetree, linux-kernel, linux-iio
[-- Attachment #1: Type: text/plain, Size: 744 bytes --]
On Tue, Dec 02, 2025 at 04:53:47PM +0200, Andy Shevchenko wrote:
> On Mon, Dec 01, 2025 at 08:20:42PM -0600, David Lechner wrote:
> > Add support for SPI_MULTI_LANE_MODE_STRIPE to the AXI SPI engine driver.
> > +static u8 spi_engine_all_lane_flags(struct spi_device *spi)
> > +{
> > + u8 flags = 0;
> > + int i;
> Why signed?
>
> > + for (i = 0; i < spi->num_data_lanes; i++)
> > + flags |= BIT(spi->data_lanes[i]);
> > +
> > + return flags;
Variables called i used for iteration are typically declared signed even
if they never cover negative values; IIRC there used to be some
compiler interaction reasons to do so although I expect those aren't so
relevant any more. Using a signed type here is perfectly normal.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v3 1/7] spi: dt-bindings: Add data-lanes property
2025-12-02 2:20 ` [PATCH v3 1/7] spi: dt-bindings: Add data-lanes property David Lechner
@ 2025-12-04 21:29 ` Rob Herring (Arm)
0 siblings, 0 replies; 24+ messages in thread
From: Rob Herring (Arm) @ 2025-12-04 21:29 UTC (permalink / raw)
To: David Lechner
Cc: Conor Dooley, Marcelo Schmitt, Nuno Sá, Sean Anderson,
Jonathan Cameron, Mark Brown, Krzysztof Kozlowski,
Michael Hennerich, linux-spi, linux-kernel, linux-iio, devicetree,
Andy Shevchenko
On Mon, 01 Dec 2025 20:20:39 -0600, David Lechner wrote:
> Add a data-lanes property to the spi-peripheral-props binding to
> allow specifying the SPI data lane or lanes that a peripheral is
> connected to in cases where the SPI controller has more than one
> physical SPI data lane.
>
> Signed-off-by: David Lechner <dlechner@baylibre.com>
> ---
> v3 changes:
> * Renamed spi-buses to data-lanes to reuse existing common property name.
> * Added to description to clarify index is peripheral and value is
> controller.
> v2 changes:
> * Renamed property from spi-buses to spi-data-buses to make it clear
> that we are only talking about the SDI/SDO lines and not the entire
> SPI bus (SCK, CS, etc).
> * Fixed prefix order in subject.
>
> This patch has been seen before in a different series from Sean [1].
>
> [1]: https://lore.kernel.org/linux-spi/20250616220054.3968946-2-sean.anderson@linux.dev/
>
> Changes:
> * Added maxItems. (8 is the most I've seen so far on an ADC)
> * Tweaked the description a bit.
> ---
> .../devicetree/bindings/spi/spi-peripheral-props.yaml | 14 ++++++++++++++
> 1 file changed, 14 insertions(+)
>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v3 5/7] dt-bindings: iio: adc: adi,ad7380: add spi-lanes property
2025-12-02 2:20 ` [PATCH v3 5/7] dt-bindings: iio: adc: adi,ad7380: add spi-lanes property David Lechner
@ 2025-12-04 21:29 ` Rob Herring (Arm)
0 siblings, 0 replies; 24+ messages in thread
From: Rob Herring (Arm) @ 2025-12-04 21:29 UTC (permalink / raw)
To: David Lechner
Cc: linux-iio, devicetree, linux-kernel, Nuno Sá,
Andy Shevchenko, Michael Hennerich, Mark Brown,
Krzysztof Kozlowski, linux-spi, Sean Anderson, Marcelo Schmitt,
Conor Dooley, Jonathan Cameron
On Mon, 01 Dec 2025 20:20:43 -0600, David Lechner wrote:
> Add spi-lanes property to describe how many SDO lines are wired up on
> the ADC. These chips are simultaneous sampling ADCs and have one SDO
> line per channel, either 2 or 4 total depending on the part number.
>
> Signed-off-by: David Lechner <dlechner@baylibre.com>
> ---
> v3 changes:
> * Renamed "buses" to "lanes" to reflect devicetree property name change.
> ---
> .../devicetree/bindings/iio/adc/adi,ad7380.yaml | 22 ++++++++++++++++++++++
> 1 file changed, 22 insertions(+)
>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v3 7/7] dt-bindings: iio: adc: adi,ad4030: add data-lanes property
2025-12-02 2:20 ` [PATCH v3 7/7] dt-bindings: iio: adc: adi,ad4030: add data-lanes property David Lechner
@ 2025-12-04 21:33 ` Rob Herring
2025-12-05 21:12 ` Marcelo Schmitt
0 siblings, 1 reply; 24+ messages in thread
From: Rob Herring @ 2025-12-04 21:33 UTC (permalink / raw)
To: David Lechner
Cc: Mark Brown, Krzysztof Kozlowski, Conor Dooley, Marcelo Schmitt,
Michael Hennerich, Nuno Sá, Jonathan Cameron,
Andy Shevchenko, Sean Anderson, linux-spi, devicetree,
linux-kernel, linux-iio
On Mon, Dec 01, 2025 at 08:20:45PM -0600, David Lechner wrote:
> Add data-lanes property to specify the number of data lanes used on the
> ad463x chips that support reading two samples at the same time using
> two data lanes with a capable SPI controller.
>
> Signed-off-by: David Lechner <dlechner@baylibre.com>
> ---
> v3 changes: new patch
>
> I added this one to give a real-world use case where spi-rx-bus-width
> was not sufficient to fully describe the hardware configuration.
>
> spi-rx-bus-width = <4>; alone could be be interpreted as either:
>
> +--------------+ +----------+
> | SPI | | AD4630 |
> | Controller | | ADC |
> | | | |
> | SDIA0 |<---| SDOA0 |
> | SDIA1 |<---| SDOA1 |
> | SDIA2 |<---| SDOA2 |
> | SDIA3 |<---| SDOA3 |
> | | | |
> | SDIB0 |x | SDOB0 |
> | SDIB1 |x | SDOB1 |
> | SDIB2 |x | SDOB2 |
> | SDIB3 |x | SDOB3 |
> | | | |
> +--------------+ +---------+
>
> or
>
> +--------------+ +----------+
> | SPI | | AD4630 |
> | Controller | | ADC |
> | | | |
> | SDIA0 |<---| SDOA0 |
> | SDIA1 |<---| SDOA1 |
> | SDIA2 |x | SDOA2 |
> | SDIA3 |x | SDOA3 |
> | | | |
> | SDIB0 |<---| SDOB0 |
> | SDIB1 |<---| SDOB1 |
> | SDIB2 |x | SDOB2 |
> | SDIB3 |x | SDOB3 |
> | | | |
> +--------------+ +---------+
>
> Now, with data-lanes having a default value of [0] (inherited from
> spi-peripheral-props.yaml), specifying:
>
> spi-rx-bus-width = <4>;
>
> is unambiguously the first case and the example given in the binding
> documentation is the second case:
>
> spi-rx-bus-width = <2>;
> data-lanes = <0>, <1>;
I just reviewed this and all, but what if you just did:
spi-rx-bus-width = <2>, <2>;
So *-bus-width becomes equal to the number of serializers/channels.
Rob
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v3 7/7] dt-bindings: iio: adc: adi,ad4030: add data-lanes property
2025-12-04 21:33 ` Rob Herring
@ 2025-12-05 21:12 ` Marcelo Schmitt
2025-12-05 21:33 ` David Lechner
0 siblings, 1 reply; 24+ messages in thread
From: Marcelo Schmitt @ 2025-12-05 21:12 UTC (permalink / raw)
To: Rob Herring
Cc: David Lechner, Mark Brown, Krzysztof Kozlowski, Conor Dooley,
Marcelo Schmitt, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Andy Shevchenko, Sean Anderson, linux-spi,
devicetree, linux-kernel, linux-iio
On 12/04, Rob Herring wrote:
> On Mon, Dec 01, 2025 at 08:20:45PM -0600, David Lechner wrote:
> > Add data-lanes property to specify the number of data lanes used on the
> > ad463x chips that support reading two samples at the same time using
> > two data lanes with a capable SPI controller.
> >
> > Signed-off-by: David Lechner <dlechner@baylibre.com>
> > ---
> > v3 changes: new patch
> >
> > I added this one to give a real-world use case where spi-rx-bus-width
> > was not sufficient to fully describe the hardware configuration.
> >
> > spi-rx-bus-width = <4>; alone could be be interpreted as either:
> >
> > +--------------+ +----------+
> > | SPI | | AD4630 |
> > | Controller | | ADC |
> > | | | |
> > | SDIA0 |<---| SDOA0 |
> > | SDIA1 |<---| SDOA1 |
> > | SDIA2 |<---| SDOA2 |
> > | SDIA3 |<---| SDOA3 |
> > | | | |
> > | SDIB0 |x | SDOB0 |
> > | SDIB1 |x | SDOB1 |
> > | SDIB2 |x | SDOB2 |
> > | SDIB3 |x | SDOB3 |
> > | | | |
> > +--------------+ +---------+
> >
> > or
> >
> > +--------------+ +----------+
> > | SPI | | AD4630 |
> > | Controller | | ADC |
> > | | | |
> > | SDIA0 |<---| SDOA0 |
> > | SDIA1 |<---| SDOA1 |
> > | SDIA2 |x | SDOA2 |
> > | SDIA3 |x | SDOA3 |
> > | | | |
> > | SDIB0 |<---| SDOB0 |
> > | SDIB1 |<---| SDOB1 |
> > | SDIB2 |x | SDOB2 |
> > | SDIB3 |x | SDOB3 |
> > | | | |
> > +--------------+ +---------+
> >
> > Now, with data-lanes having a default value of [0] (inherited from
> > spi-peripheral-props.yaml), specifying:
> >
> > spi-rx-bus-width = <4>;
> >
> > is unambiguously the first case and the example given in the binding
> > documentation is the second case:
> >
> > spi-rx-bus-width = <2>;
> > data-lanes = <0>, <1>;
>
> I just reviewed this and all, but what if you just did:
>
> spi-rx-bus-width = <2>, <2>;
>
> So *-bus-width becomes equal to the number of serializers/channels.
Unless I'm missing something, I think that would also describe the currently
possible use cases as well. To me, it actually seems even more accurate than
data-lanes. The data-lanes property only describes the SPI controller input
lines/lanes, no info is given about the output lanes. Well yeah, that would only
be a problem for a device with multiple input serializers and multiple output
serializers. Still, the *-bus-width = <N>, <N>, ... <N>; notation looks clearer,
IMHO.
>
> Rob
>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v3 7/7] dt-bindings: iio: adc: adi,ad4030: add data-lanes property
2025-12-05 21:12 ` Marcelo Schmitt
@ 2025-12-05 21:33 ` David Lechner
2025-12-05 23:43 ` David Lechner
0 siblings, 1 reply; 24+ messages in thread
From: David Lechner @ 2025-12-05 21:33 UTC (permalink / raw)
To: Marcelo Schmitt, Rob Herring
Cc: Mark Brown, Krzysztof Kozlowski, Conor Dooley, Marcelo Schmitt,
Michael Hennerich, Nuno Sá, Jonathan Cameron,
Andy Shevchenko, Sean Anderson, linux-spi, devicetree,
linux-kernel, linux-iio
On 12/5/25 3:12 PM, Marcelo Schmitt wrote:
> On 12/04, Rob Herring wrote:
>> On Mon, Dec 01, 2025 at 08:20:45PM -0600, David Lechner wrote:
>>> Add data-lanes property to specify the number of data lanes used on the
>>> ad463x chips that support reading two samples at the same time using
>>> two data lanes with a capable SPI controller.
>>>
>>> Signed-off-by: David Lechner <dlechner@baylibre.com>
>>> ---
>>> v3 changes: new patch
>>>
>>> I added this one to give a real-world use case where spi-rx-bus-width
>>> was not sufficient to fully describe the hardware configuration.
>>>
>>> spi-rx-bus-width = <4>; alone could be be interpreted as either:
>>>
>>> +--------------+ +----------+
>>> | SPI | | AD4630 |
>>> | Controller | | ADC |
>>> | | | |
>>> | SDIA0 |<---| SDOA0 |
>>> | SDIA1 |<---| SDOA1 |
>>> | SDIA2 |<---| SDOA2 |
>>> | SDIA3 |<---| SDOA3 |
>>> | | | |
>>> | SDIB0 |x | SDOB0 |
>>> | SDIB1 |x | SDOB1 |
>>> | SDIB2 |x | SDOB2 |
>>> | SDIB3 |x | SDOB3 |
>>> | | | |
>>> +--------------+ +---------+
>>>
>>> or
>>>
>>> +--------------+ +----------+
>>> | SPI | | AD4630 |
>>> | Controller | | ADC |
>>> | | | |
>>> | SDIA0 |<---| SDOA0 |
>>> | SDIA1 |<---| SDOA1 |
>>> | SDIA2 |x | SDOA2 |
>>> | SDIA3 |x | SDOA3 |
>>> | | | |
>>> | SDIB0 |<---| SDOB0 |
>>> | SDIB1 |<---| SDOB1 |
>>> | SDIB2 |x | SDOB2 |
>>> | SDIB3 |x | SDOB3 |
>>> | | | |
>>> +--------------+ +---------+
>>>
>>> Now, with data-lanes having a default value of [0] (inherited from
>>> spi-peripheral-props.yaml), specifying:
>>>
>>> spi-rx-bus-width = <4>;
>>>
>>> is unambiguously the first case and the example given in the binding
>>> documentation is the second case:
>>>
>>> spi-rx-bus-width = <2>;
>>> data-lanes = <0>, <1>;
>>
>> I just reviewed this and all, but what if you just did:
>>
>> spi-rx-bus-width = <2>, <2>;
>>
>> So *-bus-width becomes equal to the number of serializers/channels.
>
> Unless I'm missing something, I think that would also describe the currently
> possible use cases as well. To me, it actually seems even more accurate than
> data-lanes. The data-lanes property only describes the SPI controller input
> lines/lanes, no info is given about the output lanes.
It describes both directions.
> Well yeah, that would only> be a problem for a device with multiple input serializers and multiple output
> serializers. Still, the *-bus-width = <N>, <N>, ... <N>; notation looks clearer,
> IMHO.
>
>>
>> Rob
>>
It think it complicates Sean's use case though where such
a controller is being used as basically two separate SPI
buses.
For that case, we want to be able to do:
spi {
...
thing@0 {
compatible = ...;
reg = <0>;
/* (implicit) data-lanes = <0>; */
};
thing@1 {
compatible = ...;
reg = <1>;
data-lanes = <1>;
};
};
Meaning:
+--------------+ +----------+
| SPI | | Thing 1 |
| Controller | | |
| | | |
| CS0 |--->| CS |
| SDI0 |<---| SDO |
| SDO0 |--->| SDI |
| SCLK0 |--->| SCLK |
| | | |
| | +----------+
| |
| | +----------+
| | | Thing 2 |
| | | |
| CS1 |--->| CS |
| SDI1 |<---| SDO |
| SDO1 |--->| SDI |
| SCLK1 |--->| SCLK |
| | | |
+--------------+ +----------+
(I don't remember if SCLKs are shared or separate, but I don't
think that is relevant anyway).
I guess we could write it like this?
spi {
...
thing@0 {
compatible = ...;
reg = <0>;
};
thing@1 {
compatible = ...;
reg = <1>;
spi-tx-bus-width = <0>, <1>;
spi-rx-bus-width = <0>, <1>;
};
};
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v3 7/7] dt-bindings: iio: adc: adi,ad4030: add data-lanes property
2025-12-05 21:33 ` David Lechner
@ 2025-12-05 23:43 ` David Lechner
2025-12-06 0:47 ` Rob Herring
0 siblings, 1 reply; 24+ messages in thread
From: David Lechner @ 2025-12-05 23:43 UTC (permalink / raw)
To: Marcelo Schmitt, Rob Herring
Cc: Mark Brown, Krzysztof Kozlowski, Conor Dooley, Marcelo Schmitt,
Michael Hennerich, Nuno Sá, Jonathan Cameron,
Andy Shevchenko, Sean Anderson, linux-spi, devicetree,
linux-kernel, linux-iio
On 12/5/25 3:33 PM, David Lechner wrote:
> On 12/5/25 3:12 PM, Marcelo Schmitt wrote:
>> On 12/04, Rob Herring wrote:
>>> On Mon, Dec 01, 2025 at 08:20:45PM -0600, David Lechner wrote:
>>>> Add data-lanes property to specify the number of data lanes used on the
>>>> ad463x chips that support reading two samples at the same time using
>>>> two data lanes with a capable SPI controller.
>>>>
>>>> Signed-off-by: David Lechner <dlechner@baylibre.com>
>>>> ---
>>>> v3 changes: new patch
>>>>
>>>> I added this one to give a real-world use case where spi-rx-bus-width
>>>> was not sufficient to fully describe the hardware configuration.
>>>>
>>>> spi-rx-bus-width = <4>; alone could be be interpreted as either:
>>>>
>>>> +--------------+ +----------+
>>>> | SPI | | AD4630 |
>>>> | Controller | | ADC |
>>>> | | | |
>>>> | SDIA0 |<---| SDOA0 |
>>>> | SDIA1 |<---| SDOA1 |
>>>> | SDIA2 |<---| SDOA2 |
>>>> | SDIA3 |<---| SDOA3 |
>>>> | | | |
>>>> | SDIB0 |x | SDOB0 |
>>>> | SDIB1 |x | SDOB1 |
>>>> | SDIB2 |x | SDOB2 |
>>>> | SDIB3 |x | SDOB3 |
>>>> | | | |
>>>> +--------------+ +---------+
>>>>
>>>> or
>>>>
>>>> +--------------+ +----------+
>>>> | SPI | | AD4630 |
>>>> | Controller | | ADC |
>>>> | | | |
>>>> | SDIA0 |<---| SDOA0 |
>>>> | SDIA1 |<---| SDOA1 |
>>>> | SDIA2 |x | SDOA2 |
>>>> | SDIA3 |x | SDOA3 |
>>>> | | | |
>>>> | SDIB0 |<---| SDOB0 |
>>>> | SDIB1 |<---| SDOB1 |
>>>> | SDIB2 |x | SDOB2 |
>>>> | SDIB3 |x | SDOB3 |
>>>> | | | |
>>>> +--------------+ +---------+
>>>>
>>>> Now, with data-lanes having a default value of [0] (inherited from
>>>> spi-peripheral-props.yaml), specifying:
>>>>
>>>> spi-rx-bus-width = <4>;
>>>>
>>>> is unambiguously the first case and the example given in the binding
>>>> documentation is the second case:
>>>>
>>>> spi-rx-bus-width = <2>;
>>>> data-lanes = <0>, <1>;
>>>
>>> I just reviewed this and all, but what if you just did:
>>>
>>> spi-rx-bus-width = <2>, <2>;
>>>
>>> So *-bus-width becomes equal to the number of serializers/channels.
>>
>> Unless I'm missing something, I think that would also describe the currently
>> possible use cases as well. To me, it actually seems even more accurate than
>> data-lanes. The data-lanes property only describes the SPI controller input
>> lines/lanes, no info is given about the output lanes.
>
> It describes both directions.
>
>> Well yeah, that would only> be a problem for a device with multiple input serializers and multiple output
>> serializers. Still, the *-bus-width = <N>, <N>, ... <N>; notation looks clearer,
>> IMHO.
>>
>>>
>>> Rob
>>>
>
> It think it complicates Sean's use case though where such
> a controller is being used as basically two separate SPI
> buses.
>
> For that case, we want to be able to do:
>
> spi {
> ...
>
> thing@0 {
> compatible = ...;
> reg = <0>;
> /* (implicit) data-lanes = <0>; */
> };
>
> thing@1 {
> compatible = ...;
> reg = <1>;
> data-lanes = <1>;
> };
> };
>
> Meaning:
>
> +--------------+ +----------+
> | SPI | | Thing 1 |
> | Controller | | |
> | | | |
> | CS0 |--->| CS |
> | SDI0 |<---| SDO |
> | SDO0 |--->| SDI |
> | SCLK0 |--->| SCLK |
> | | | |
> | | +----------+
> | |
> | | +----------+
> | | | Thing 2 |
> | | | |
> | CS1 |--->| CS |
> | SDI1 |<---| SDO |
> | SDO1 |--->| SDI |
> | SCLK1 |--->| SCLK |
> | | | |
> +--------------+ +----------+
>
> (I don't remember if SCLKs are shared or separate, but I don't
> think that is relevant anyway).
>
>
> I guess we could write it like this?
>
> spi {
> ...
>
> thing@0 {
> compatible = ...;
> reg = <0>;
> };
>
> thing@1 {
> compatible = ...;
> reg = <1>;
> spi-tx-bus-width = <0>, <1>;
> spi-rx-bus-width = <0>, <1>;
> };
> };
>
>
I started down this road. Before I do the working of changing the
whole series, this is what it will probably look like. Is this really
what we want?
There is one issue I see with this. If we allow <0> to mean that a lane
isn't wired up on the controller, then we can't constrain the length of
the array in peripheral bindings. For example, the ad403x chips can only
have one lane and the ad463x chips can have one or two lanes. But I
don't see a way to express that in the binding if <0> at any index
doesn't count towards the number of lanes that are actually wired up.
This is e.g. why the binding in sitronix,st7789v.yaml is
items:
enum: [0, 1]
rather than
items:
- enum: [0, 1]
---
commit 049b9508b1b0190f87a4b35fe3ed8a9f3d0d3c50
Author: David Lechner <dlechner@baylibre.com>
Date: Fri Dec 5 16:09:08 2025 -0600
spi: dt-bindings: change spi-{rx,tx}-bus-width to arrays
Change spi-rx-bus-width and spi-tx-bus-width properties from single
uint32 values to arrays of uint32 values. This allows describing SPI
peripherals connected to controllers that have multiple data lanes for
receiving or transmitting two or more words at the same time.
Bindings that make use of this property are updated in the same commit
to avoid validation errors. Bindings that used minimum/maximum are
changed to use enum instead to be consistent with the base property
definition.
The adi,ad4030 binding has an example added now that we can fully
describe the peripheral's capabilities.
Converting from single uint32 to array of uint32 does not break .dts/
.dtb files since there is no difference between specifying a single
uint32 value and an array with a single uint32 value in devicetree.
Signed-off-by: David Lechner <dlechner@baylibre.com>
---
diff --git a/Documentation/devicetree/bindings/display/panel/sitronix,st7789v.yaml b/Documentation/devicetree/bindings/display/panel/sitronix,st7789v.yaml
index 0ce2ea13583d..23b33dcd5ed4 100644
--- a/Documentation/devicetree/bindings/display/panel/sitronix,st7789v.yaml
+++ b/Documentation/devicetree/bindings/display/panel/sitronix,st7789v.yaml
@@ -34,8 +34,8 @@ properties:
spi-cpol: true
spi-rx-bus-width:
- minimum: 0
- maximum: 1
+ items:
+ enum: [0, 1]
dc-gpios:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad4030.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad4030.yaml
index 54e7349317b7..6052a44b04de 100644
--- a/Documentation/devicetree/bindings/iio/adc/adi,ad4030.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ad4030.yaml
@@ -37,7 +37,8 @@ properties:
maximum: 102040816
spi-rx-bus-width:
- enum: [1, 2, 4]
+ items:
+ enum: [1, 2, 4]
vdd-5v-supply: true
vdd-1v8-supply: true
@@ -108,3 +109,23 @@ examples:
reset-gpios = <&gpio0 1 GPIO_ACTIVE_LOW>;
};
};
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ adc@0 {
+ compatible = "adi,ad4630-24";
+ reg = <0>;
+ spi-max-frequency = <80000000>;
+ spi-rx-bus-width = <4>, <4>;
+ vdd-5v-supply = <&supply_5V>;
+ vdd-1v8-supply = <&supply_1_8V>;
+ vio-supply = <&supply_1_8V>;
+ ref-supply = <&supply_5V>;
+ cnv-gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&gpio0 1 GPIO_ACTIVE_LOW>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad4695.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad4695.yaml
index cbde7a0505d2..e15d985e8c59 100644
--- a/Documentation/devicetree/bindings/iio/adc/adi,ad4695.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ad4695.yaml
@@ -38,8 +38,8 @@ properties:
spi-cpha: true
spi-rx-bus-width:
- minimum: 1
- maximum: 4
+ items:
+ enum: [1, 2, 4]
avdd-supply:
description: Analog power supply.
diff --git a/Documentation/devicetree/bindings/spi/allwinner,sun4i-a10-spi.yaml b/Documentation/devicetree/bindings/spi/allwinner,sun4i-a10-spi.yaml
index e1ab3f523ad6..a34e6471dbe8 100644
--- a/Documentation/devicetree/bindings/spi/allwinner,sun4i-a10-spi.yaml
+++ b/Documentation/devicetree/bindings/spi/allwinner,sun4i-a10-spi.yaml
@@ -55,10 +55,12 @@ patternProperties:
maximum: 4
spi-rx-bus-width:
- const: 1
+ items:
+ - const: 1
spi-tx-bus-width:
- const: 1
+ items:
+ - const: 1
required:
- compatible
diff --git a/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml b/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml
index 3b47b68b92cb..414f5bc36304 100644
--- a/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml
+++ b/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml
@@ -77,10 +77,12 @@ patternProperties:
maximum: 4
spi-rx-bus-width:
- const: 1
+ items:
+ - const: 1
spi-tx-bus-width:
- const: 1
+ items:
+ - const: 1
required:
- compatible
diff --git a/Documentation/devicetree/bindings/spi/nvidia,tegra210-quad.yaml b/Documentation/devicetree/bindings/spi/nvidia,tegra210-quad.yaml
index 8b3640280559..909c204b8adf 100644
--- a/Documentation/devicetree/bindings/spi/nvidia,tegra210-quad.yaml
+++ b/Documentation/devicetree/bindings/spi/nvidia,tegra210-quad.yaml
@@ -54,10 +54,12 @@ patternProperties:
properties:
spi-rx-bus-width:
- enum: [1, 2, 4]
+ items:
+ - enum: [1, 2, 4]
spi-tx-bus-width:
- enum: [1, 2, 4]
+ items:
+ - enum: [1, 2, 4]
required:
- compatible
diff --git a/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml b/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml
index 8b6e8fc009db..6288740d8af3 100644
--- a/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml
+++ b/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml
@@ -64,9 +64,17 @@ properties:
description:
Bus width to the SPI bus used for read transfers.
If 0 is provided, then no RX will be possible on this device.
- $ref: /schemas/types.yaml#/definitions/uint32
- enum: [0, 1, 2, 4, 8]
- default: 1
+
+ Some SPI peripherals and controllers may have multiple data lanes for
+ receiving two or more words at the same time. If this is the case, each
+ index in the array represents the lane of the SPI controller. Lanes of
+ the peripheral are assumed to be connected in a logical order for each
+ non-zero entry in the array. Indexes where both spi-rx-bus-width and
+ spi-tx-bus-width are 0 are interpreted as not connected.
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ items:
+ enum: [0, 1, 2, 4, 8]
+ default: [1]
spi-rx-delay-us:
description:
@@ -81,9 +89,17 @@ properties:
description:
Bus width to the SPI bus used for write transfers.
If 0 is provided, then no TX will be possible on this device.
- $ref: /schemas/types.yaml#/definitions/uint32
- enum: [0, 1, 2, 4, 8]
- default: 1
+
+ Some SPI peripherals and controllers may have multiple data lanes for
+ transmitting two or more words at the same time. If this is the case, each
+ index in the array represents the lane of the SPI controller. Lanes of
+ the peripheral are assumed to be connected in a logical order for each
+ non-zero entry in the array. Indexes where both spi-rx-bus-width and
+ spi-tx-bus-width are 0 are interpreted as not connected.
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ items:
+ enum: [0, 1, 2, 4, 8]
+ default: [1]
spi-tx-delay-us:
description:
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH v3 7/7] dt-bindings: iio: adc: adi,ad4030: add data-lanes property
2025-12-05 23:43 ` David Lechner
@ 2025-12-06 0:47 ` Rob Herring
2025-12-08 16:14 ` David Lechner
0 siblings, 1 reply; 24+ messages in thread
From: Rob Herring @ 2025-12-06 0:47 UTC (permalink / raw)
To: David Lechner
Cc: Marcelo Schmitt, Mark Brown, Krzysztof Kozlowski, Conor Dooley,
Marcelo Schmitt, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Andy Shevchenko, Sean Anderson, linux-spi,
devicetree, linux-kernel, linux-iio
On Fri, Dec 05, 2025 at 05:43:31PM -0600, David Lechner wrote:
> On 12/5/25 3:33 PM, David Lechner wrote:
> > On 12/5/25 3:12 PM, Marcelo Schmitt wrote:
> >> On 12/04, Rob Herring wrote:
> >>> On Mon, Dec 01, 2025 at 08:20:45PM -0600, David Lechner wrote:
> >>>> Add data-lanes property to specify the number of data lanes used on the
> >>>> ad463x chips that support reading two samples at the same time using
> >>>> two data lanes with a capable SPI controller.
> >>>>
> >>>> Signed-off-by: David Lechner <dlechner@baylibre.com>
> >>>> ---
> >>>> v3 changes: new patch
> >>>>
> >>>> I added this one to give a real-world use case where spi-rx-bus-width
> >>>> was not sufficient to fully describe the hardware configuration.
> >>>>
> >>>> spi-rx-bus-width = <4>; alone could be be interpreted as either:
> >>>>
> >>>> +--------------+ +----------+
> >>>> | SPI | | AD4630 |
> >>>> | Controller | | ADC |
> >>>> | | | |
> >>>> | SDIA0 |<---| SDOA0 |
> >>>> | SDIA1 |<---| SDOA1 |
> >>>> | SDIA2 |<---| SDOA2 |
> >>>> | SDIA3 |<---| SDOA3 |
> >>>> | | | |
> >>>> | SDIB0 |x | SDOB0 |
> >>>> | SDIB1 |x | SDOB1 |
> >>>> | SDIB2 |x | SDOB2 |
> >>>> | SDIB3 |x | SDOB3 |
> >>>> | | | |
> >>>> +--------------+ +---------+
> >>>>
> >>>> or
> >>>>
> >>>> +--------------+ +----------+
> >>>> | SPI | | AD4630 |
> >>>> | Controller | | ADC |
> >>>> | | | |
> >>>> | SDIA0 |<---| SDOA0 |
> >>>> | SDIA1 |<---| SDOA1 |
> >>>> | SDIA2 |x | SDOA2 |
> >>>> | SDIA3 |x | SDOA3 |
> >>>> | | | |
> >>>> | SDIB0 |<---| SDOB0 |
> >>>> | SDIB1 |<---| SDOB1 |
> >>>> | SDIB2 |x | SDOB2 |
> >>>> | SDIB3 |x | SDOB3 |
> >>>> | | | |
> >>>> +--------------+ +---------+
> >>>>
> >>>> Now, with data-lanes having a default value of [0] (inherited from
> >>>> spi-peripheral-props.yaml), specifying:
> >>>>
> >>>> spi-rx-bus-width = <4>;
> >>>>
> >>>> is unambiguously the first case and the example given in the binding
> >>>> documentation is the second case:
> >>>>
> >>>> spi-rx-bus-width = <2>;
> >>>> data-lanes = <0>, <1>;
> >>>
> >>> I just reviewed this and all, but what if you just did:
> >>>
> >>> spi-rx-bus-width = <2>, <2>;
> >>>
> >>> So *-bus-width becomes equal to the number of serializers/channels.
> >>
> >> Unless I'm missing something, I think that would also describe the currently
> >> possible use cases as well. To me, it actually seems even more accurate than
> >> data-lanes. The data-lanes property only describes the SPI controller input
> >> lines/lanes, no info is given about the output lanes.
> >
> > It describes both directions.
> >
> >> Well yeah, that would only> be a problem for a device with multiple input serializers and multiple output
> >> serializers. Still, the *-bus-width = <N>, <N>, ... <N>; notation looks clearer,
> >> IMHO.
> >>
> >>>
> >>> Rob
> >>>
> >
> > It think it complicates Sean's use case though where such
> > a controller is being used as basically two separate SPI
> > buses.
> >
> > For that case, we want to be able to do:
> >
> > spi {
> > ...
> >
> > thing@0 {
> > compatible = ...;
> > reg = <0>;
> > /* (implicit) data-lanes = <0>; */
> > };
> >
> > thing@1 {
> > compatible = ...;
> > reg = <1>;
> > data-lanes = <1>;
> > };
> > };
> >
> > Meaning:
> >
> > +--------------+ +----------+
> > | SPI | | Thing 1 |
> > | Controller | | |
> > | | | |
> > | CS0 |--->| CS |
> > | SDI0 |<---| SDO |
> > | SDO0 |--->| SDI |
> > | SCLK0 |--->| SCLK |
> > | | | |
> > | | +----------+
> > | |
> > | | +----------+
> > | | | Thing 2 |
> > | | | |
> > | CS1 |--->| CS |
> > | SDI1 |<---| SDO |
> > | SDO1 |--->| SDI |
> > | SCLK1 |--->| SCLK |
> > | | | |
> > +--------------+ +----------+
> >
> > (I don't remember if SCLKs are shared or separate, but I don't
> > think that is relevant anyway).
> >
> >
> > I guess we could write it like this?
> >
> > spi {
> > ...
> >
> > thing@0 {
> > compatible = ...;
> > reg = <0>;
> > };
> >
> > thing@1 {
> > compatible = ...;
> > reg = <1>;
> > spi-tx-bus-width = <0>, <1>;
> > spi-rx-bus-width = <0>, <1>;
> > };
> > };
I forget the details on that, but just looking at the above I think
something like that should have 2 SPI bus nodes under the controller.
Unless CS0 and CS1 can't be asserted at the same time and they aren't
really independent.
But would be good to wait for Sean's comments here.
>
> I started down this road. Before I do the working of changing the
> whole series, this is what it will probably look like. Is this really
> what we want?
>
> There is one issue I see with this. If we allow <0> to mean that a lane
> isn't wired up on the controller, then we can't constrain the length of
> the array in peripheral bindings. For example, the ad403x chips can only
> have one lane and the ad463x chips can have one or two lanes. But I
> don't see a way to express that in the binding if <0> at any index
> doesn't count towards the number of lanes that are actually wired up.
That's fine I think. How many entries is primarily a controller
property. We set the length in the controller binding. The device just
sets the maximum width per channel.
>
> This is e.g. why the binding in sitronix,st7789v.yaml is
>
> items:
> enum: [0, 1]
>
> rather than
>
> items:
> - enum: [0, 1]
>
> ---
> commit 049b9508b1b0190f87a4b35fe3ed8a9f3d0d3c50
> Author: David Lechner <dlechner@baylibre.com>
> Date: Fri Dec 5 16:09:08 2025 -0600
>
> spi: dt-bindings: change spi-{rx,tx}-bus-width to arrays
>
> Change spi-rx-bus-width and spi-tx-bus-width properties from single
> uint32 values to arrays of uint32 values. This allows describing SPI
> peripherals connected to controllers that have multiple data lanes for
> receiving or transmitting two or more words at the same time.
>
> Bindings that make use of this property are updated in the same commit
> to avoid validation errors. Bindings that used minimum/maximum are
> changed to use enum instead to be consistent with the base property
> definition.
>
> The adi,ad4030 binding has an example added now that we can fully
> describe the peripheral's capabilities.
>
> Converting from single uint32 to array of uint32 does not break .dts/
> .dtb files since there is no difference between specifying a single
> uint32 value and an array with a single uint32 value in devicetree.
>
> Signed-off-by: David Lechner <dlechner@baylibre.com>
> ---
>
> diff --git a/Documentation/devicetree/bindings/display/panel/sitronix,st7789v.yaml b/Documentation/devicetree/bindings/display/panel/sitronix,st7789v.yaml
> index 0ce2ea13583d..23b33dcd5ed4 100644
> --- a/Documentation/devicetree/bindings/display/panel/sitronix,st7789v.yaml
> +++ b/Documentation/devicetree/bindings/display/panel/sitronix,st7789v.yaml
> @@ -34,8 +34,8 @@ properties:
> spi-cpol: true
>
> spi-rx-bus-width:
> - minimum: 0
> - maximum: 1
> + items:
> + enum: [0, 1]
>
> dc-gpios:
> maxItems: 1
> diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad4030.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad4030.yaml
> index 54e7349317b7..6052a44b04de 100644
> --- a/Documentation/devicetree/bindings/iio/adc/adi,ad4030.yaml
> +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad4030.yaml
> @@ -37,7 +37,8 @@ properties:
> maximum: 102040816
>
> spi-rx-bus-width:
> - enum: [1, 2, 4]
> + items:
> + enum: [1, 2, 4]
We'd need to allow 0 here, right?
What we really want to say is there is exactly 1 entry of 1, 2, or 4. I
can't think of a concise way to say that. The closest is something like
this:
uniqueItems: true
items:
enum: [0, 1, 2, 4]
contains:
enum: [1, 2, 4]
That implicitly limits the length to 4, but does allow [0, 1, 2, 4] and
other ordering. More generally, if the device supports fewer channels
than the host, then we can't constrain that. Oh well, we can't check
everything (we hardly check values within reg, interrupts, clocks, and
on and on). But most controllers are going to limit the length to 1
entry, so it should end up with the same constraints most of the time.
Are these updates all of them or just a sampling. If the latter and
there's a lot more, then we may want to split spi-controller.yaml into
2 (3 really with a common part). Make spi-controller.yaml define single
channel SPI controllers which keeps the length of spi-[rt]x-bus-width at
1 entry and then define a spi-multi-chan-controller.yaml which doesn't
constrain it.
Rob
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v3 7/7] dt-bindings: iio: adc: adi,ad4030: add data-lanes property
2025-12-06 0:47 ` Rob Herring
@ 2025-12-08 16:14 ` David Lechner
2025-12-08 18:32 ` Rob Herring
0 siblings, 1 reply; 24+ messages in thread
From: David Lechner @ 2025-12-08 16:14 UTC (permalink / raw)
To: Rob Herring
Cc: Marcelo Schmitt, Mark Brown, Krzysztof Kozlowski, Conor Dooley,
Marcelo Schmitt, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Andy Shevchenko, Sean Anderson, linux-spi,
devicetree, linux-kernel, linux-iio
On 12/5/25 6:47 PM, Rob Herring wrote:
> On Fri, Dec 05, 2025 at 05:43:31PM -0600, David Lechner wrote:
>> On 12/5/25 3:33 PM, David Lechner wrote:
>>> On 12/5/25 3:12 PM, Marcelo Schmitt wrote:
>>>> On 12/04, Rob Herring wrote:
>>>>> On Mon, Dec 01, 2025 at 08:20:45PM -0600, David Lechner wrote:
>>>>>> Add data-lanes property to specify the number of data lanes used on the
>>>>>> ad463x chips that support reading two samples at the same time using
>>>>>> two data lanes with a capable SPI controller.
>>>>>>
>>>>>> Signed-off-by: David Lechner <dlechner@baylibre.com>
>>>>>> ---
>>>>>> v3 changes: new patch
>>>>>>
>>>>>> I added this one to give a real-world use case where spi-rx-bus-width
>>>>>> was not sufficient to fully describe the hardware configuration.
>>>>>>
>>>>>> spi-rx-bus-width = <4>; alone could be be interpreted as either:
>>>>>>
>>>>>> +--------------+ +----------+
>>>>>> | SPI | | AD4630 |
>>>>>> | Controller | | ADC |
>>>>>> | | | |
>>>>>> | SDIA0 |<---| SDOA0 |
>>>>>> | SDIA1 |<---| SDOA1 |
>>>>>> | SDIA2 |<---| SDOA2 |
>>>>>> | SDIA3 |<---| SDOA3 |
>>>>>> | | | |
>>>>>> | SDIB0 |x | SDOB0 |
>>>>>> | SDIB1 |x | SDOB1 |
>>>>>> | SDIB2 |x | SDOB2 |
>>>>>> | SDIB3 |x | SDOB3 |
>>>>>> | | | |
>>>>>> +--------------+ +---------+
>>>>>>
>>>>>> or
>>>>>>
>>>>>> +--------------+ +----------+
>>>>>> | SPI | | AD4630 |
>>>>>> | Controller | | ADC |
>>>>>> | | | |
>>>>>> | SDIA0 |<---| SDOA0 |
>>>>>> | SDIA1 |<---| SDOA1 |
>>>>>> | SDIA2 |x | SDOA2 |
>>>>>> | SDIA3 |x | SDOA3 |
>>>>>> | | | |
>>>>>> | SDIB0 |<---| SDOB0 |
>>>>>> | SDIB1 |<---| SDOB1 |
>>>>>> | SDIB2 |x | SDOB2 |
>>>>>> | SDIB3 |x | SDOB3 |
>>>>>> | | | |
>>>>>> +--------------+ +---------+
>>>>>>
>>>>>> Now, with data-lanes having a default value of [0] (inherited from
>>>>>> spi-peripheral-props.yaml), specifying:
>>>>>>
>>>>>> spi-rx-bus-width = <4>;
>>>>>>
>>>>>> is unambiguously the first case and the example given in the binding
>>>>>> documentation is the second case:
>>>>>>
>>>>>> spi-rx-bus-width = <2>;
>>>>>> data-lanes = <0>, <1>;
>>>>>
>>>>> I just reviewed this and all, but what if you just did:
>>>>>
>>>>> spi-rx-bus-width = <2>, <2>;
>>>>>
>>>>> So *-bus-width becomes equal to the number of serializers/channels.
>>>>
>>>> Unless I'm missing something, I think that would also describe the currently
>>>> possible use cases as well. To me, it actually seems even more accurate than
>>>> data-lanes. The data-lanes property only describes the SPI controller input
>>>> lines/lanes, no info is given about the output lanes.
>>>
>>> It describes both directions.
>>>
>>>> Well yeah, that would only> be a problem for a device with multiple input serializers and multiple output
>>>> serializers. Still, the *-bus-width = <N>, <N>, ... <N>; notation looks clearer,
>>>> IMHO.
>>>>
>>>>>
>>>>> Rob
>>>>>
>>>
>>> It think it complicates Sean's use case though where such
>>> a controller is being used as basically two separate SPI
>>> buses.
>>>
>>> For that case, we want to be able to do:
>>>
>>> spi {
>>> ...
>>>
>>> thing@0 {
>>> compatible = ...;
>>> reg = <0>;
>>> /* (implicit) data-lanes = <0>; */
>>> };
>>>
>>> thing@1 {
>>> compatible = ...;
>>> reg = <1>;
>>> data-lanes = <1>;
>>> };
>>> };
>>>
>>> Meaning:
>>>
>>> +--------------+ +----------+
>>> | SPI | | Thing 1 |
>>> | Controller | | |
>>> | | | |
>>> | CS0 |--->| CS |
>>> | SDI0 |<---| SDO |
>>> | SDO0 |--->| SDI |
>>> | SCLK0 |--->| SCLK |
>>> | | | |
>>> | | +----------+
>>> | |
>>> | | +----------+
>>> | | | Thing 2 |
>>> | | | |
>>> | CS1 |--->| CS |
>>> | SDI1 |<---| SDO |
>>> | SDO1 |--->| SDI |
>>> | SCLK1 |--->| SCLK |
>>> | | | |
>>> +--------------+ +----------+
>>>
>>> (I don't remember if SCLKs are shared or separate, but I don't
>>> think that is relevant anyway).
>>>
>>>
>>> I guess we could write it like this?
>>>
>>> spi {
>>> ...
>>>
>>> thing@0 {
>>> compatible = ...;
>>> reg = <0>;
>>> };
>>>
>>> thing@1 {
>>> compatible = ...;
>>> reg = <1>;
>>> spi-tx-bus-width = <0>, <1>;
>>> spi-rx-bus-width = <0>, <1>;
>>> };
>>> };
>
> I forget the details on that, but just looking at the above I think
> something like that should have 2 SPI bus nodes under the controller.
> Unless CS0 and CS1 can't be asserted at the same time and they aren't
> really independent.
It is the case that they aren't really independent. Only one "bus"
can operate at a time.
>
> But would be good to wait for Sean's comments here.
>
>>
>> I started down this road. Before I do the working of changing the
>> whole series, this is what it will probably look like. Is this really
>> what we want?
>>
>> There is one issue I see with this. If we allow <0> to mean that a lane
>> isn't wired up on the controller, then we can't constrain the length of
>> the array in peripheral bindings. For example, the ad403x chips can only
>> have one lane and the ad463x chips can have one or two lanes. But I
>> don't see a way to express that in the binding if <0> at any index
>> doesn't count towards the number of lanes that are actually wired up.
>
> That's fine I think. How many entries is primarily a controller
> property. We set the length in the controller binding. The device just
> sets the maximum width per channel.
>
>>
>> This is e.g. why the binding in sitronix,st7789v.yaml is
>>
>> items:
>> enum: [0, 1]
>>
>> rather than
>>
>> items:
>> - enum: [0, 1]
>>
>> ---
>> commit 049b9508b1b0190f87a4b35fe3ed8a9f3d0d3c50
>> Author: David Lechner <dlechner@baylibre.com>
>> Date: Fri Dec 5 16:09:08 2025 -0600
>>
>> spi: dt-bindings: change spi-{rx,tx}-bus-width to arrays
>>
>> Change spi-rx-bus-width and spi-tx-bus-width properties from single
>> uint32 values to arrays of uint32 values. This allows describing SPI
>> peripherals connected to controllers that have multiple data lanes for
>> receiving or transmitting two or more words at the same time.
>>
>> Bindings that make use of this property are updated in the same commit
>> to avoid validation errors. Bindings that used minimum/maximum are
>> changed to use enum instead to be consistent with the base property
>> definition.
>>
>> The adi,ad4030 binding has an example added now that we can fully
>> describe the peripheral's capabilities.
>>
>> Converting from single uint32 to array of uint32 does not break .dts/
>> .dtb files since there is no difference between specifying a single
>> uint32 value and an array with a single uint32 value in devicetree.
>>
>> Signed-off-by: David Lechner <dlechner@baylibre.com>
>> ---
>>
>> diff --git a/Documentation/devicetree/bindings/display/panel/sitronix,st7789v.yaml b/Documentation/devicetree/bindings/display/panel/sitronix,st7789v.yaml
>> index 0ce2ea13583d..23b33dcd5ed4 100644
>> --- a/Documentation/devicetree/bindings/display/panel/sitronix,st7789v.yaml
>> +++ b/Documentation/devicetree/bindings/display/panel/sitronix,st7789v.yaml
>> @@ -34,8 +34,8 @@ properties:
>> spi-cpol: true
>>
>> spi-rx-bus-width:
>> - minimum: 0
>> - maximum: 1
>> + items:
>> + enum: [0, 1]
>>
>> dc-gpios:
>> maxItems: 1
>> diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad4030.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad4030.yaml
>> index 54e7349317b7..6052a44b04de 100644
>> --- a/Documentation/devicetree/bindings/iio/adc/adi,ad4030.yaml
>> +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad4030.yaml
>> @@ -37,7 +37,8 @@ properties:
>> maximum: 102040816
>>
>> spi-rx-bus-width:
>> - enum: [1, 2, 4]
>> + items:
>> + enum: [1, 2, 4]
>
> We'd need to allow 0 here, right?
To avoid binding check failures, yes, I suppose so. All of the
`const: 1` would need to be changed to `enum: [0, 1]` as well.
Although since the controller also could have limitations maybe
we should have the controller use `enum` and have the peripheral
use `maximum`?
Then, if we have a controller with:
patternProperties:
"@[0-9a-f]+$":
# controller has 2 lanes with 2 lines per lane
spi-rx-bus-width:
maxItems: 2
items:
enum: [0, 1, 2]
And a peripheral with:
properties:
spi-rx-bus-width:
items:
maximum: 4
The controller limit would be in effect and cause a binding check error
if attempting to use bus width of 4.
But if the controller was enum: [0, 1, 2, 4, 8], then the peripheral
maximum would be the limiting factor if attempting to use bus width of 8.
>
> What we really want to say is there is exactly 1 entry of 1, 2, or 4. I
Not sure this is what we want. For the ADC cases, we want 2 or 4 items
in the array to be the same value.
> can't think of a concise way to say that. The closest is something like
> this:
>
> uniqueItems: true
> items:
> enum: [0, 1, 2, 4]
> contains:
> enum: [1, 2, 4]
>
> That implicitly limits the length to 4, but does allow [0, 1, 2, 4] and
> other ordering. More generally, if the device supports fewer channels
> than the host, then we can't constrain that. Oh well, we can't check
> everything (we hardly check values within reg, interrupts, clocks, and
> on and on). But most controllers are going to limit the length to 1
> entry, so it should end up with the same constraints most of the time.
>
> Are these updates all of them or just a sampling.
This is everything currently in linux-next.
> If the latter and
> there's a lot more, then we may want to split spi-controller.yaml into
> 2 (3 really with a common part). Make spi-controller.yaml define single
> channel SPI controllers which keeps the length of spi-[rt]x-bus-width at
> 1 entry and then define a spi-multi-chan-controller.yaml which doesn't
> constrain it.
>
> Rob
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v3 7/7] dt-bindings: iio: adc: adi,ad4030: add data-lanes property
2025-12-08 16:14 ` David Lechner
@ 2025-12-08 18:32 ` Rob Herring
0 siblings, 0 replies; 24+ messages in thread
From: Rob Herring @ 2025-12-08 18:32 UTC (permalink / raw)
To: David Lechner
Cc: Marcelo Schmitt, Mark Brown, Krzysztof Kozlowski, Conor Dooley,
Marcelo Schmitt, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Andy Shevchenko, Sean Anderson, linux-spi,
devicetree, linux-kernel, linux-iio
On Mon, Dec 08, 2025 at 10:14:36AM -0600, David Lechner wrote:
> On 12/5/25 6:47 PM, Rob Herring wrote:
> > On Fri, Dec 05, 2025 at 05:43:31PM -0600, David Lechner wrote:
> >> On 12/5/25 3:33 PM, David Lechner wrote:
> >>> On 12/5/25 3:12 PM, Marcelo Schmitt wrote:
> >>>> On 12/04, Rob Herring wrote:
> >>>>> On Mon, Dec 01, 2025 at 08:20:45PM -0600, David Lechner wrote:
> >>>>>> Add data-lanes property to specify the number of data lanes used on the
> >>>>>> ad463x chips that support reading two samples at the same time using
> >>>>>> two data lanes with a capable SPI controller.
> >>>>>>
> >>>>>> Signed-off-by: David Lechner <dlechner@baylibre.com>
> >>>>>> ---
> >>>>>> v3 changes: new patch
> >>>>>>
> >>>>>> I added this one to give a real-world use case where spi-rx-bus-width
> >>>>>> was not sufficient to fully describe the hardware configuration.
> >>>>>>
> >>>>>> spi-rx-bus-width = <4>; alone could be be interpreted as either:
> >>>>>>
> >>>>>> +--------------+ +----------+
> >>>>>> | SPI | | AD4630 |
> >>>>>> | Controller | | ADC |
> >>>>>> | | | |
> >>>>>> | SDIA0 |<---| SDOA0 |
> >>>>>> | SDIA1 |<---| SDOA1 |
> >>>>>> | SDIA2 |<---| SDOA2 |
> >>>>>> | SDIA3 |<---| SDOA3 |
> >>>>>> | | | |
> >>>>>> | SDIB0 |x | SDOB0 |
> >>>>>> | SDIB1 |x | SDOB1 |
> >>>>>> | SDIB2 |x | SDOB2 |
> >>>>>> | SDIB3 |x | SDOB3 |
> >>>>>> | | | |
> >>>>>> +--------------+ +---------+
> >>>>>>
> >>>>>> or
> >>>>>>
> >>>>>> +--------------+ +----------+
> >>>>>> | SPI | | AD4630 |
> >>>>>> | Controller | | ADC |
> >>>>>> | | | |
> >>>>>> | SDIA0 |<---| SDOA0 |
> >>>>>> | SDIA1 |<---| SDOA1 |
> >>>>>> | SDIA2 |x | SDOA2 |
> >>>>>> | SDIA3 |x | SDOA3 |
> >>>>>> | | | |
> >>>>>> | SDIB0 |<---| SDOB0 |
> >>>>>> | SDIB1 |<---| SDOB1 |
> >>>>>> | SDIB2 |x | SDOB2 |
> >>>>>> | SDIB3 |x | SDOB3 |
> >>>>>> | | | |
> >>>>>> +--------------+ +---------+
> >>>>>>
> >>>>>> Now, with data-lanes having a default value of [0] (inherited from
> >>>>>> spi-peripheral-props.yaml), specifying:
> >>>>>>
> >>>>>> spi-rx-bus-width = <4>;
> >>>>>>
> >>>>>> is unambiguously the first case and the example given in the binding
> >>>>>> documentation is the second case:
> >>>>>>
> >>>>>> spi-rx-bus-width = <2>;
> >>>>>> data-lanes = <0>, <1>;
> >>>>>
> >>>>> I just reviewed this and all, but what if you just did:
> >>>>>
> >>>>> spi-rx-bus-width = <2>, <2>;
> >>>>>
> >>>>> So *-bus-width becomes equal to the number of serializers/channels.
> >>>>
> >>>> Unless I'm missing something, I think that would also describe the currently
> >>>> possible use cases as well. To me, it actually seems even more accurate than
> >>>> data-lanes. The data-lanes property only describes the SPI controller input
> >>>> lines/lanes, no info is given about the output lanes.
> >>>
> >>> It describes both directions.
> >>>
> >>>> Well yeah, that would only> be a problem for a device with multiple input serializers and multiple output
> >>>> serializers. Still, the *-bus-width = <N>, <N>, ... <N>; notation looks clearer,
> >>>> IMHO.
> >>>>
> >>>>>
> >>>>> Rob
> >>>>>
> >>>
> >>> It think it complicates Sean's use case though where such
> >>> a controller is being used as basically two separate SPI
> >>> buses.
> >>>
> >>> For that case, we want to be able to do:
> >>>
> >>> spi {
> >>> ...
> >>>
> >>> thing@0 {
> >>> compatible = ...;
> >>> reg = <0>;
> >>> /* (implicit) data-lanes = <0>; */
> >>> };
> >>>
> >>> thing@1 {
> >>> compatible = ...;
> >>> reg = <1>;
> >>> data-lanes = <1>;
> >>> };
> >>> };
> >>>
> >>> Meaning:
> >>>
> >>> +--------------+ +----------+
> >>> | SPI | | Thing 1 |
> >>> | Controller | | |
> >>> | | | |
> >>> | CS0 |--->| CS |
> >>> | SDI0 |<---| SDO |
> >>> | SDO0 |--->| SDI |
> >>> | SCLK0 |--->| SCLK |
> >>> | | | |
> >>> | | +----------+
> >>> | |
> >>> | | +----------+
> >>> | | | Thing 2 |
> >>> | | | |
> >>> | CS1 |--->| CS |
> >>> | SDI1 |<---| SDO |
> >>> | SDO1 |--->| SDI |
> >>> | SCLK1 |--->| SCLK |
> >>> | | | |
> >>> +--------------+ +----------+
> >>>
> >>> (I don't remember if SCLKs are shared or separate, but I don't
> >>> think that is relevant anyway).
> >>>
> >>>
> >>> I guess we could write it like this?
> >>>
> >>> spi {
> >>> ...
> >>>
> >>> thing@0 {
> >>> compatible = ...;
> >>> reg = <0>;
> >>> };
> >>>
> >>> thing@1 {
> >>> compatible = ...;
> >>> reg = <1>;
> >>> spi-tx-bus-width = <0>, <1>;
> >>> spi-rx-bus-width = <0>, <1>;
> >>> };
> >>> };
> >
> > I forget the details on that, but just looking at the above I think
> > something like that should have 2 SPI bus nodes under the controller.
> > Unless CS0 and CS1 can't be asserted at the same time and they aren't
> > really independent.
>
> It is the case that they aren't really independent. Only one "bus"
> can operate at a time.
>
> >
> > But would be good to wait for Sean's comments here.
> >
> >>
> >> I started down this road. Before I do the working of changing the
> >> whole series, this is what it will probably look like. Is this really
> >> what we want?
> >>
> >> There is one issue I see with this. If we allow <0> to mean that a lane
> >> isn't wired up on the controller, then we can't constrain the length of
> >> the array in peripheral bindings. For example, the ad403x chips can only
> >> have one lane and the ad463x chips can have one or two lanes. But I
> >> don't see a way to express that in the binding if <0> at any index
> >> doesn't count towards the number of lanes that are actually wired up.
> >
> > That's fine I think. How many entries is primarily a controller
> > property. We set the length in the controller binding. The device just
> > sets the maximum width per channel.
> >
> >>
> >> This is e.g. why the binding in sitronix,st7789v.yaml is
> >>
> >> items:
> >> enum: [0, 1]
> >>
> >> rather than
> >>
> >> items:
> >> - enum: [0, 1]
> >>
> >> ---
> >> commit 049b9508b1b0190f87a4b35fe3ed8a9f3d0d3c50
> >> Author: David Lechner <dlechner@baylibre.com>
> >> Date: Fri Dec 5 16:09:08 2025 -0600
> >>
> >> spi: dt-bindings: change spi-{rx,tx}-bus-width to arrays
> >>
> >> Change spi-rx-bus-width and spi-tx-bus-width properties from single
> >> uint32 values to arrays of uint32 values. This allows describing SPI
> >> peripherals connected to controllers that have multiple data lanes for
> >> receiving or transmitting two or more words at the same time.
> >>
> >> Bindings that make use of this property are updated in the same commit
> >> to avoid validation errors. Bindings that used minimum/maximum are
> >> changed to use enum instead to be consistent with the base property
> >> definition.
> >>
> >> The adi,ad4030 binding has an example added now that we can fully
> >> describe the peripheral's capabilities.
> >>
> >> Converting from single uint32 to array of uint32 does not break .dts/
> >> .dtb files since there is no difference between specifying a single
> >> uint32 value and an array with a single uint32 value in devicetree.
> >>
> >> Signed-off-by: David Lechner <dlechner@baylibre.com>
> >> ---
> >>
> >> diff --git a/Documentation/devicetree/bindings/display/panel/sitronix,st7789v.yaml b/Documentation/devicetree/bindings/display/panel/sitronix,st7789v.yaml
> >> index 0ce2ea13583d..23b33dcd5ed4 100644
> >> --- a/Documentation/devicetree/bindings/display/panel/sitronix,st7789v.yaml
> >> +++ b/Documentation/devicetree/bindings/display/panel/sitronix,st7789v.yaml
> >> @@ -34,8 +34,8 @@ properties:
> >> spi-cpol: true
> >>
> >> spi-rx-bus-width:
> >> - minimum: 0
> >> - maximum: 1
> >> + items:
> >> + enum: [0, 1]
> >>
> >> dc-gpios:
> >> maxItems: 1
> >> diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad4030.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad4030.yaml
> >> index 54e7349317b7..6052a44b04de 100644
> >> --- a/Documentation/devicetree/bindings/iio/adc/adi,ad4030.yaml
> >> +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad4030.yaml
> >> @@ -37,7 +37,8 @@ properties:
> >> maximum: 102040816
> >>
> >> spi-rx-bus-width:
> >> - enum: [1, 2, 4]
> >> + items:
> >> + enum: [1, 2, 4]
> >
> > We'd need to allow 0 here, right?
>
> To avoid binding check failures, yes, I suppose so. All of the
> `const: 1` would need to be changed to `enum: [0, 1]` as well.
>
> Although since the controller also could have limitations maybe
> we should have the controller use `enum` and have the peripheral
> use `maximum`?
Yeah, that's probably better.
> Then, if we have a controller with:
>
> patternProperties:
> "@[0-9a-f]+$":
> # controller has 2 lanes with 2 lines per lane
> spi-rx-bus-width:
> maxItems: 2
> items:
> enum: [0, 1, 2]
>
> And a peripheral with:
>
> properties:
> spi-rx-bus-width:
> items:
> maximum: 4
>
> The controller limit would be in effect and cause a binding check error
> if attempting to use bus width of 4.
>
> But if the controller was enum: [0, 1, 2, 4, 8], then the peripheral
> maximum would be the limiting factor if attempting to use bus width of 8.
>
> >
> > What we really want to say is there is exactly 1 entry of 1, 2, or 4. I
>
> Not sure this is what we want. For the ADC cases, we want 2 or 4 items
> in the array to be the same value.
I meant for devices with only 1 possible channel attached to a
controller with multiple channels.
On an ADC with multiple channels, you'd want 'minItems: 2' (or more)
unless it can work with a single channel.
>
> > can't think of a concise way to say that. The closest is something like
> > this:
> >
> > uniqueItems: true
> > items:
> > enum: [0, 1, 2, 4]
> > contains:
> > enum: [1, 2, 4]
Actually, uniqueItems doesn't work here. It would prevent multiple
unused channels (e.g. [0, 4, 0, 0] ).
So there's not really any sane way to constrain this case. That's fine I
guess.
Rob
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v3 4/7] spi: axi-spi-engine: support SPI_MULTI_LANE_MODE_STRIPE
2025-12-02 14:53 ` Andy Shevchenko
2025-12-02 16:36 ` Mark Brown
@ 2025-12-10 0:02 ` David Lechner
2025-12-10 10:59 ` Andy Shevchenko
1 sibling, 1 reply; 24+ messages in thread
From: David Lechner @ 2025-12-10 0:02 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Mark Brown, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Marcelo Schmitt, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Andy Shevchenko, Sean Anderson, linux-spi,
devicetree, linux-kernel, linux-iio
On 12/2/25 8:53 AM, Andy Shevchenko wrote:
> On Mon, Dec 01, 2025 at 08:20:42PM -0600, David Lechner wrote:
>> Add support for SPI_MULTI_LANE_MODE_STRIPE to the AXI SPI engine driver.
>>
>> The v2.0.0 version of the AXI SPI Engine IP core supports multiple
>> lanes. This can be used with SPI_MULTI_LANE_MODE_STRIPE to support
>> reading from simultaneous sampling ADCs that have a separate SDO line
>> for each analog channel. This allows reading all channels at the same
>> time to increase throughput.
>
> ...
>
>> +static u8 spi_engine_all_lane_flags(struct spi_device *spi)
>> +{
>> + u8 flags = 0;
>
>> + int i;
>
> Why signed?
Because it is conventional.
>
>> + for (i = 0; i < spi->num_data_lanes; i++)
>> + flags |= BIT(spi->data_lanes[i]);
>> +
>> + return flags;
>> +}
>
> ...
>
>> static void spi_engine_gen_xfer(struct spi_engine_program *p, bool dry,
>> - struct spi_transfer *xfer)
>> + struct spi_transfer *xfer, u32 num_lanes)
>
> Side note: this bool parameter makes code harder to follow. And now we have
> pointers and integers/booleans to be interleaved. Perhaps reconsider the order
> of the parameters (and ideally get rid of boolean by making two distinct
> functions?).
There would be significant code duplication if we split this
which would make it error prone.
Perhaps a bit unusual parameter ordering according to data type,
but they are grouped logically, so I think it is OK. `dry` affects
what is written to `p` and `num_lanes` supplements `xfer`.
>
> ...
>
>> version = readl(spi_engine->base + ADI_AXI_REG_VERSION);
>> - if (ADI_AXI_PCORE_VER_MAJOR(version) != 1) {
>> + if (ADI_AXI_PCORE_VER_MAJOR(version) > 2) {
>
> But this includes v0 as well!
I think it is OK. There was never a version 0 released, nor
is one expected.
>
>> }
>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v3 4/7] spi: axi-spi-engine: support SPI_MULTI_LANE_MODE_STRIPE
2025-12-10 0:02 ` David Lechner
@ 2025-12-10 10:59 ` Andy Shevchenko
0 siblings, 0 replies; 24+ messages in thread
From: Andy Shevchenko @ 2025-12-10 10:59 UTC (permalink / raw)
To: David Lechner
Cc: Andy Shevchenko, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Marcelo Schmitt, Michael Hennerich, Nuno Sá,
Jonathan Cameron, Andy Shevchenko, Sean Anderson, linux-spi,
devicetree, linux-kernel, linux-iio
On Wed, Dec 10, 2025 at 2:02 AM David Lechner <dlechner@baylibre.com> wrote:
> On 12/2/25 8:53 AM, Andy Shevchenko wrote:
> > On Mon, Dec 01, 2025 at 08:20:42PM -0600, David Lechner wrote:
...
> >> +static u8 spi_engine_all_lane_flags(struct spi_device *spi)
> >> +{
> >> + u8 flags = 0;
> >
> >> + int i;
> >
> > Why signed?
>
> Because it is conventional.
I would expect the variable to be the same or close enough to the one
that defines the limit.
> >> + for (i = 0; i < spi->num_data_lanes; i++)
> >> + flags |= BIT(spi->data_lanes[i]);
> >> +
> >> + return flags;
> >> +}
...
> >> version = readl(spi_engine->base + ADI_AXI_REG_VERSION);
> >> - if (ADI_AXI_PCORE_VER_MAJOR(version) != 1) {
> >> + if (ADI_AXI_PCORE_VER_MAJOR(version) > 2) {
> >
> > But this includes v0 as well!
>
> I think it is OK. There was never a version 0 released, nor
> is one expected.
Perhaps a note in the commit message?
> >> }
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 24+ messages in thread
end of thread, other threads:[~2025-12-10 11:00 UTC | newest]
Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-02 2:20 [PATCH v3 0/7] spi: add multi-lane support David Lechner
2025-12-02 2:20 ` [PATCH v3 1/7] spi: dt-bindings: Add data-lanes property David Lechner
2025-12-04 21:29 ` Rob Herring (Arm)
2025-12-02 2:20 ` [PATCH v3 2/7] spi: Support controllers with multiple data lanes David Lechner
2025-12-02 14:44 ` Andy Shevchenko
2025-12-02 14:47 ` David Lechner
2025-12-02 2:20 ` [PATCH v3 3/7] spi: add multi_lane_mode field to struct spi_transfer David Lechner
2025-12-02 14:48 ` Andy Shevchenko
2025-12-02 2:20 ` [PATCH v3 4/7] spi: axi-spi-engine: support SPI_MULTI_LANE_MODE_STRIPE David Lechner
2025-12-02 14:53 ` Andy Shevchenko
2025-12-02 16:36 ` Mark Brown
2025-12-10 0:02 ` David Lechner
2025-12-10 10:59 ` Andy Shevchenko
2025-12-02 2:20 ` [PATCH v3 5/7] dt-bindings: iio: adc: adi,ad7380: add spi-lanes property David Lechner
2025-12-04 21:29 ` Rob Herring (Arm)
2025-12-02 2:20 ` [PATCH v3 6/7] iio: adc: ad7380: Add support for multiple SPI lanes David Lechner
2025-12-02 2:20 ` [PATCH v3 7/7] dt-bindings: iio: adc: adi,ad4030: add data-lanes property David Lechner
2025-12-04 21:33 ` Rob Herring
2025-12-05 21:12 ` Marcelo Schmitt
2025-12-05 21:33 ` David Lechner
2025-12-05 23:43 ` David Lechner
2025-12-06 0:47 ` Rob Herring
2025-12-08 16:14 ` David Lechner
2025-12-08 18:32 ` Rob Herring
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).