* [PATCH v2 0/6] spi: add multi-bus support
@ 2025-11-07 20:52 David Lechner
2025-11-07 20:52 ` [PATCH v2 1/6] spi: dt-bindings: Add spi-data-buses property David Lechner
` (6 more replies)
0 siblings, 7 replies; 8+ messages in thread
From: David Lechner @ 2025-11-07 20:52 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 buses (data buses 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 buses 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 bus at a time (Sean's use case), or can mirror the same
data on multiple buses (no users of this yet) or can perform striping
of a single data FIFO/DMA stream to/from the two buses (our use case).
For now, the API assumes that if you want to do mirror/striping, then
you want to use all available data buses. Otherwise, it just uses the
first data bus for "normal" SPI transfers.
Signed-off-by: David Lechner <dlechner@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 (6):
spi: dt-bindings: Add spi-data-buses property
spi: Support multi-bus controllers
spi: add multi_bus_mode field to struct spi_transfer
spi: axi-spi-engine: support SPI_MULTI_BUS_MODE_STRIPE
dt-bindings: iio: adc: adi,ad7380: add spi-buses property
iio: adc: ad7380: Add support for multiple SPI buses
.../devicetree/bindings/iio/adc/adi,ad7380.yaml | 22 ++++
.../bindings/spi/spi-peripheral-props.yaml | 12 ++
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 ++++
6 files changed, 237 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] 8+ messages in thread
* [PATCH v2 1/6] spi: dt-bindings: Add spi-data-buses property
2025-11-07 20:52 [PATCH v2 0/6] spi: add multi-bus support David Lechner
@ 2025-11-07 20:52 ` David Lechner
2025-11-07 20:52 ` [PATCH v2 2/6] spi: Support multi-bus controllers David Lechner
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: David Lechner @ 2025-11-07 20:52 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 spi-data-buses property to the spi-peripheral-props binding to
allow specifying the SPI data bus or buses that a peripheral is
connected to in cases where the SPI controller has more than one
physical SPI data bus.
Signed-off-by: David Lechner <dlechner@baylibre.com>
---
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 | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml b/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml
index 8b6e8fc009dbdc80978f3afef84ddc688ade4348..6fe739eaf09876b9c5d8902f792ca02181d7266f 100644
--- a/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml
+++ b/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml
@@ -89,6 +89,18 @@ properties:
description:
Delay, in microseconds, after a write transfer.
+ spi-data-buses:
+ description:
+ Array of data bus numbers that describes which SPI data buses of the
+ controller are connected to the peripheral. This only applies to
+ peripherals connected to specialized SPI controllers that have multiple
+ SPI data buses (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] 8+ messages in thread
* [PATCH v2 2/6] spi: Support multi-bus controllers
2025-11-07 20:52 [PATCH v2 0/6] spi: add multi-bus support David Lechner
2025-11-07 20:52 ` [PATCH v2 1/6] spi: dt-bindings: Add spi-data-buses property David Lechner
@ 2025-11-07 20:52 ` David Lechner
2025-11-07 20:52 ` [PATCH v2 3/6] spi: add multi_bus_mode field to struct spi_transfer David Lechner
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: David Lechner @ 2025-11-07 20:52 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 buses.
(A data bus in this context means lines connected to a serializer, so a
controller with two data buses 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_bus
to something greater than 1. Peripherals indicate which bus 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>
---
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 8588e8562220ff5f77977a91b869e220b400c0b2..1cc193ee81120180264047039ef035a958481ede 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, buses[SPI_DEVICE_DATA_BUS_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, "spi-data-buses", buses, 1,
+ ARRAY_SIZE(buses));
+ if (rc < 0 && rc != -EINVAL) {
+ dev_err(&ctlr->dev, "%pOF has invalid 'spi-data-buses' property (%d)\n",
+ nc, rc);
+ return rc;
+ }
+
+ if (rc == -EINVAL) {
+ /* Default when property is omitted. */
+ spi->num_data_bus = 1;
+ } else {
+ for (idx = 0; idx < rc; idx++) {
+ if (buses[idx] >= ctlr->num_data_bus) {
+ dev_err(&ctlr->dev,
+ "%pOF has out of range 'spi-data-buses' property (%d/%d)\n",
+ nc, buses[idx], ctlr->num_data_bus);
+ return -EINVAL;
+ }
+ spi->data_bus[idx] = buses[idx];
+ }
+
+ spi->num_data_bus = rc;
+ }
+
/*
* By default spi->chip_select[0] will hold the physical CS number,
* so set bit 0 in spi->cs_index_mask.
@@ -3064,6 +3089,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_bus = 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..c314194d4e7e2b396795ece10e142118ca05f4eb 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 buses supported per spi device */
+#define SPI_DEVICE_DATA_BUS_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_bus: Array of physical data buses. This is only used with specialized
+ * controllers that support multiple data buses.
+ * @num_data_bus: Number of physical data buses 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_bus[SPI_DEVICE_DATA_BUS_CNT_MAX];
+ u8 num_data_bus;
/*
* 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_bus: Number of data buses 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
+ * bus interface per controller (each having it's own serializer). This
+ * specifies the number of buses in that case. Other controllers do not
+ * need to set this (defaults to 1).
+ */
+ u16 num_data_bus;
+
/* 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] 8+ messages in thread
* [PATCH v2 3/6] spi: add multi_bus_mode field to struct spi_transfer
2025-11-07 20:52 [PATCH v2 0/6] spi: add multi-bus support David Lechner
2025-11-07 20:52 ` [PATCH v2 1/6] spi: dt-bindings: Add spi-data-buses property David Lechner
2025-11-07 20:52 ` [PATCH v2 2/6] spi: Support multi-bus controllers David Lechner
@ 2025-11-07 20:52 ` David Lechner
2025-11-07 20:52 ` [PATCH v2 4/6] spi: axi-spi-engine: support SPI_MULTI_BUS_MODE_STRIPE David Lechner
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: David Lechner @ 2025-11-07 20:52 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_bus_mode field to struct spi_transfer to allow
peripherals that support multiple SPI buses to be used with a single
SPI controller.
This requires both the peripheral and the controller to have multiple
serializers connected to separate data buses. 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 bus. This means that it
it is operating just like a conventional SPI bus. 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
buses 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_bus_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 bus.
Example:
struct spi_transfer xfer = {
.rx_buf = rx_buf,
.len = 2, /* must be multiple of number of buses */
.multi_bus_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>
---
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 c314194d4e7e2b396795ece10e142118ca05f4eb..7d22ef5077d1229cac2574831f80092c591b972f 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_bus_mode: How to serialize data on multiple buses. One of the
+ * SPI_MULTI_BUS_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_bus_mode: 2;
+#define SPI_MULTI_BUS_MODE_SINGLE 0 /* only use single bus */
+#define SPI_MULTI_BUS_MODE_STRIPE 1 /* one data word per bus */
+#define SPI_MULTI_BUS_MODE_MIRROR 2 /* same word sent on all buses */
unsigned timestamped:1;
bool dtr_mode;
#define SPI_NBITS_SINGLE 0x01 /* 1-bit transfer */
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 4/6] spi: axi-spi-engine: support SPI_MULTI_BUS_MODE_STRIPE
2025-11-07 20:52 [PATCH v2 0/6] spi: add multi-bus support David Lechner
` (2 preceding siblings ...)
2025-11-07 20:52 ` [PATCH v2 3/6] spi: add multi_bus_mode field to struct spi_transfer David Lechner
@ 2025-11-07 20:52 ` David Lechner
2025-11-07 20:52 ` [PATCH v2 5/6] dt-bindings: iio: adc: adi,ad7380: add spi-buses property David Lechner
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: David Lechner @ 2025-11-07 20:52 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_BUS_MODE_STRIPE to the AXI SPI engine driver.
The v2.0.0 version of the AXI SPI Engine IP core supports multiple
buses. This can be used with SPI_MULTI_BUS_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>
---
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..c9d146e978b89abb8273900722ae2cfafdd6325f 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_BUS_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_bus_mode;
+ u8 primary_bus_mask;
+ u8 all_bus_mask;
u8 bits_per_word;
};
@@ -165,6 +177,22 @@ struct spi_engine {
bool offload_requires_sync;
};
+static u8 spi_engine_primary_bus_flag(struct spi_device *spi)
+{
+ return BIT(spi->data_bus[0]);
+}
+
+static u8 spi_engine_all_bus_flags(struct spi_device *spi)
+{
+ u8 flags = 0;
+ int i;
+
+ for (i = 0; i < spi->num_data_bus; i++)
+ flags |= BIT(spi->data_bus[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_bus_mode == SPI_MULTI_BUS_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_bus_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_bus_mode) {
+ case SPI_MULTI_BUS_MODE_SINGLE:
+ case SPI_MULTI_BUS_MODE_STRIPE:
+ break;
+ default:
+ /* Other modes, like mirror not supported */
+ return -EINVAL;
+ }
+
+ /* If all xfers have the same multi-bus mode, we can optimize. */
+ if (multi_bus_mode == SPI_ENGINE_MULTI_BUS_MODE_UNKNOWN)
+ multi_bus_mode = xfer->multi_bus_mode;
+ else if (multi_bus_mode != xfer->multi_bus_mode)
+ multi_bus_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_bus_mode = multi_bus_mode;
+ priv->primary_bus_mask = spi_engine_primary_bus_flag(msg->spi);
+ priv->all_bus_mask = spi_engine_all_bus_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_bus_mode = SPI_MULTI_BUS_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_bus_mode = priv->multi_bus_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_bus_mode != prev_multi_bus_mode) {
+ u8 bus_flags = spi_engine_primary_bus_flag(spi);
+
+ if (xfer->multi_bus_mode == SPI_MULTI_BUS_MODE_STRIPE)
+ bus_flags = spi_engine_all_bus_flags(spi);
+
+ spi_engine_program_add_cmd(p, dry,
+ SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_SDI_MASK,
+ bus_flags));
+ spi_engine_program_add_cmd(p, dry,
+ SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_SDO_MASK,
+ bus_flags));
+ }
+ prev_multi_bus_mode = xfer->multi_bus_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_bus);
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 bus mode unless offload disable will restore it later. */
+ if (prev_multi_bus_mode == SPI_MULTI_BUS_MODE_STRIPE &&
+ (!msg->offload || priv->multi_bus_mode != SPI_MULTI_BUS_MODE_STRIPE)) {
+ u8 bus_flags = spi_engine_primary_bus_flag(spi);
+
+ spi_engine_program_add_cmd(p, dry,
+ SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_SDI_MASK, bus_flags));
+ spi_engine_program_add_cmd(p, dry,
+ SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_SDO_MASK, bus_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_bus > 1) {
+ u8 bus_flags = spi_engine_primary_bus_flag(device);
+
+ writel_relaxed(SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_SDI_MASK,
+ bus_flags),
+ spi_engine->base + SPI_ENGINE_REG_CMD_FIFO);
+ writel_relaxed(SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_SDO_MASK,
+ bus_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_bus_mode == SPI_MULTI_BUS_MODE_STRIPE) {
+ writel_relaxed(SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_SDI_MASK,
+ priv->all_bus_mask),
+ spi_engine->base + SPI_ENGINE_REG_CMD_FIFO);
+ writel_relaxed(SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_SDO_MASK,
+ priv->all_bus_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-bus mode. */
+ if (priv->multi_bus_mode == SPI_MULTI_BUS_MODE_STRIPE) {
+ writel_relaxed(SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_SDI_MASK,
+ priv->primary_bus_mask),
+ spi_engine->base + SPI_ENGINE_REG_CMD_FIFO);
+ writel_relaxed(SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_SDO_MASK,
+ priv->primary_bus_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_bus = 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] 8+ messages in thread
* [PATCH v2 5/6] dt-bindings: iio: adc: adi,ad7380: add spi-buses property
2025-11-07 20:52 [PATCH v2 0/6] spi: add multi-bus support David Lechner
` (3 preceding siblings ...)
2025-11-07 20:52 ` [PATCH v2 4/6] spi: axi-spi-engine: support SPI_MULTI_BUS_MODE_STRIPE David Lechner
@ 2025-11-07 20:52 ` David Lechner
2025-11-07 20:52 ` [PATCH v2 6/6] iio: adc: ad7380: Add support for multiple SPI buses David Lechner
2025-11-09 17:05 ` [PATCH v2 0/6] spi: add multi-bus support Jonathan Cameron
6 siblings, 0 replies; 8+ messages in thread
From: David Lechner @ 2025-11-07 20:52 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-buses 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>
---
.../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..9ef46cdb047d45d088e0fbc345f58c5b09083385 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
+ spi-data-buses:
+ 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:
+ spi-data-buses:
+ maxItems: 2
+
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
@@ -260,6 +280,7 @@ examples:
spi-cpol;
spi-cpha;
spi-max-frequency = <80000000>;
+ spi-data-buses = <0>, <1>;
interrupts = <27 IRQ_TYPE_EDGE_FALLING>;
interrupt-parent = <&gpio0>;
@@ -284,6 +305,7 @@ examples:
spi-cpol;
spi-cpha;
spi-max-frequency = <80000000>;
+ spi-data-buses = <0>, <1>, <2>, <3>;
interrupts = <27 IRQ_TYPE_EDGE_FALLING>;
interrupt-parent = <&gpio0>;
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 6/6] iio: adc: ad7380: Add support for multiple SPI buses
2025-11-07 20:52 [PATCH v2 0/6] spi: add multi-bus support David Lechner
` (4 preceding siblings ...)
2025-11-07 20:52 ` [PATCH v2 5/6] dt-bindings: iio: adc: adi,ad7380: add spi-buses property David Lechner
@ 2025-11-07 20:52 ` David Lechner
2025-11-09 17:05 ` [PATCH v2 0/6] spi: add multi-bus support Jonathan Cameron
6 siblings, 0 replies; 8+ messages in thread
From: David Lechner @ 2025-11-07 20:52 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 buses 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 bus. 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>
---
v2 changes:
* Move st->seq_xfer[3].multi_bus_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..8891c31e61714b00fb01571f7ddd163cc948a8fb 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_bus;
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_bus;
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_bus > 1)
+ xfer->multi_bus_mode = SPI_MULTI_BUS_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_bus) {
+ 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_bus / 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_bus > 1)
+ st->normal_xfer[1].multi_bus_mode = SPI_MULTI_BUS_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_bus > 1) {
+ st->seq_xfer[2].multi_bus_mode = SPI_MULTI_BUS_MODE_STRIPE;
+ st->seq_xfer[3].multi_bus_mode = SPI_MULTI_BUS_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] 8+ messages in thread
* Re: [PATCH v2 0/6] spi: add multi-bus support
2025-11-07 20:52 [PATCH v2 0/6] spi: add multi-bus support David Lechner
` (5 preceding siblings ...)
2025-11-07 20:52 ` [PATCH v2 6/6] iio: adc: ad7380: Add support for multiple SPI buses David Lechner
@ 2025-11-09 17:05 ` Jonathan Cameron
6 siblings, 0 replies; 8+ messages in thread
From: Jonathan Cameron @ 2025-11-09 17:05 UTC (permalink / raw)
To: David Lechner
Cc: Mark Brown, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Marcelo Schmitt, Michael Hennerich, Nuno Sá, Andy Shevchenko,
Sean Anderson, linux-spi, devicetree, linux-kernel, linux-iio
On Fri, 07 Nov 2025 14:52:46 -0600
David Lechner <dlechner@baylibre.com> wrote:
> This series is adding support for SPI controllers and peripherals that
> have multiple SPI data buses (data buses 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 buses 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 bus at a time (Sean's use case), or can mirror the same
> data on multiple buses (no users of this yet) or can perform striping
> of a single data FIFO/DMA stream to/from the two buses (our use case).
>
> For now, the API assumes that if you want to do mirror/striping, then
> you want to use all available data buses. Otherwise, it just uses the
> first data bus for "normal" SPI transfers.
>
> Signed-off-by: David Lechner <dlechner@baylibre.com>
Series looks good to me. If the SPI and DT folk are fine with it, then
I guess time to ask Mark for another immutable branch so the SPI stuff
can be in the SPI tree and IIO tree.
J
> ---
> 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 (6):
> spi: dt-bindings: Add spi-data-buses property
> spi: Support multi-bus controllers
> spi: add multi_bus_mode field to struct spi_transfer
> spi: axi-spi-engine: support SPI_MULTI_BUS_MODE_STRIPE
> dt-bindings: iio: adc: adi,ad7380: add spi-buses property
> iio: adc: ad7380: Add support for multiple SPI buses
>
> .../devicetree/bindings/iio/adc/adi,ad7380.yaml | 22 ++++
> .../bindings/spi/spi-peripheral-props.yaml | 12 ++
> 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 ++++
> 6 files changed, 237 insertions(+), 18 deletions(-)
> ---
> base-commit: 1a26618e7466b8d825989201086c235e76aa999a
> change-id: 20250815-spi-add-multi-bus-support-1b35d05c54f6
>
> Best regards,
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2025-11-09 17:05 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-07 20:52 [PATCH v2 0/6] spi: add multi-bus support David Lechner
2025-11-07 20:52 ` [PATCH v2 1/6] spi: dt-bindings: Add spi-data-buses property David Lechner
2025-11-07 20:52 ` [PATCH v2 2/6] spi: Support multi-bus controllers David Lechner
2025-11-07 20:52 ` [PATCH v2 3/6] spi: add multi_bus_mode field to struct spi_transfer David Lechner
2025-11-07 20:52 ` [PATCH v2 4/6] spi: axi-spi-engine: support SPI_MULTI_BUS_MODE_STRIPE David Lechner
2025-11-07 20:52 ` [PATCH v2 5/6] dt-bindings: iio: adc: adi,ad7380: add spi-buses property David Lechner
2025-11-07 20:52 ` [PATCH v2 6/6] iio: adc: ad7380: Add support for multiple SPI buses David Lechner
2025-11-09 17:05 ` [PATCH v2 0/6] spi: add multi-bus support Jonathan Cameron
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).