[PATCH v2 4/5] spi: spi-engine-ex: Add support for multi-CS devices

Jonathan Santos <[email protected]> Mon, 3 Aug 2026 00:02:29 -0300
Newsgroups org.kernel.vger.linux-spi,org.kernel.vger.linux-kernel
Message-ID <a595944fda10f801dd3d11640f3a3726401c40d9.1785725359.git.Jonathan.Santos@analog.com>
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.

Signed-off-by: Jonathan Santos <[email protected]>
---
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