[PATCH v3 5/6] spi: spi-engine-ex: Add support for multi-CS devices
From: Jonathan Santos
Date: Mon Aug 17 2026 - 19:38:19 EST
The SPI Engine controller only handled the first chip select when
asserting CS lines and configuring CS polarity inversion, ignoring
additional CS indices present in cs_index_mask.
Update spi_engine_gen_cs() to iterate over all set bits in
cs_index_mask and toggle each corresponding CS line in the assert mask.
Update spi_engine_setup() likewise so that SPI_CS_HIGH polarity is
applied to every active CS index rather than only index 0.
Set SPI_CONTROLLER_MULTI_CS in the controller flags to reflect the
capability to the SPI core.
Acked-by: Nuno Sá <nuno.sa@xxxxxxxxxx>
Signed-off-by: Jonathan Santos <Jonathan.Santos@xxxxxxxxxx>
---
Changes in v3:
* None.
Changes in v2:
* Adaptation of the patch
"spi: spi-engine-ex: Add support for multi-CS devices" from v1,
discarding the per transfer CS mask and keeping the Multi-CS support
only.
---
drivers/spi/spi-axi-spi-engine.c | 22 ++++++++++++++++------
1 file changed, 16 insertions(+), 6 deletions(-)
diff --git a/drivers/spi/spi-axi-spi-engine.c b/drivers/spi/spi-axi-spi-engine.c
index 02bbc5d0cfc5..8a2cae81aea6 100644
--- a/drivers/spi/spi-axi-spi-engine.c
+++ b/drivers/spi/spi-axi-spi-engine.c
@@ -46,6 +46,7 @@
#define SPI_ENGINE_REG_SDI_DATA_FIFO_PEEK 0xec
#define SPI_ENGINE_MAX_NUM_OFFLOADS 32
+#define SPI_ENGINE_MAX_CS 8
#define SPI_ENGINE_REG_OFFLOAD_CTRL(x) (0x100 + SPI_ENGINE_MAX_NUM_OFFLOADS * (x))
#define SPI_ENGINE_REG_OFFLOAD_STATUS(x) (0x104 + SPI_ENGINE_MAX_NUM_OFFLOADS * (x))
@@ -281,10 +282,14 @@ static void spi_engine_gen_sleep(struct spi_engine_program *p, bool dry,
static void spi_engine_gen_cs(struct spi_engine_program *p, bool dry,
struct spi_device *spi, bool assert)
{
+ unsigned long cs_index_mask = spi->cs_index_mask;
unsigned int mask = 0xff;
+ unsigned int cs_bit;
- if (assert)
- mask ^= BIT(spi_get_chipselect(spi, 0));
+ if (assert) {
+ for_each_set_bit(cs_bit, &cs_index_mask, SPI_ENGINE_MAX_CS)
+ mask ^= BIT(spi_get_chipselect(spi, cs_bit));
+ }
spi_engine_program_add_cmd(p, dry, SPI_ENGINE_CMD_ASSERT(0, mask));
}
@@ -886,12 +891,16 @@ static int spi_engine_setup(struct spi_device *device)
{
struct spi_controller *host = device->controller;
struct spi_engine *spi_engine = spi_controller_get_devdata(host);
+ unsigned long cs_index_mask = device->cs_index_mask;
unsigned int reg;
+ u32 cs_bit;
- if (device->mode & SPI_CS_HIGH)
- spi_engine->cs_inv |= BIT(spi_get_chipselect(device, 0));
- else
- spi_engine->cs_inv &= ~BIT(spi_get_chipselect(device, 0));
+ for_each_set_bit(cs_bit, &cs_index_mask, SPI_ENGINE_MAX_CS) {
+ if (device->mode & SPI_CS_HIGH)
+ spi_engine->cs_inv |= BIT(spi_get_chipselect(device, cs_bit));
+ else
+ spi_engine->cs_inv &= ~BIT(spi_get_chipselect(device, cs_bit));
+ }
writel_relaxed(SPI_ENGINE_CMD_SYNC(0),
spi_engine->base + SPI_ENGINE_REG_CMD_FIFO);
@@ -1222,6 +1231,7 @@ static int spi_engine_probe(struct platform_device *pdev)
host->unoptimize_message = spi_engine_unoptimize_message;
host->get_offload = spi_engine_get_offload;
host->put_offload = spi_engine_put_offload;
+ host->flags |= SPI_CONTROLLER_MULTI_CS;
host->num_chipselect = 8;
if (adi_axi_pcore_ver_gteq(version, 1, 2)) {
--
2.34.1