spi: axi-spi-engine: add support for cs_off
authorDavid Lechner <dlechner@baylibre.com>
Fri, 17 Nov 2023 20:13:04 +0000 (14:13 -0600)
committerMark Brown <broonie@kernel.org>
Mon, 20 Nov 2023 13:29:14 +0000 (13:29 +0000)
This adds support for the spi_transfer::cs_off flag to the AXI SPI
Engine driver.

The logic is copied from the generic spi_transfer_one_message() in
spi.c.

Signed-off-by: David Lechner <dlechner@baylibre.com>
Link: https://lore.kernel.org/r/20231117-axi-spi-engine-series-1-v1-13-cc59db999b87@baylibre.com
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/spi/spi-axi-spi-engine.c

index c39f478f34a7112f7b1314f5f83827a0427c51c8..1c60e6486ee24e61d978d27aa3513e12ac4246cd 100644 (file)
@@ -216,7 +216,7 @@ static int spi_engine_compile_message(struct spi_engine *spi_engine,
        struct spi_device *spi = msg->spi;
        struct spi_transfer *xfer;
        int clk_div, new_clk_div;
-       bool cs_change = true;
+       bool keep_cs = false;
 
        clk_div = -1;
 
@@ -224,6 +224,9 @@ static int spi_engine_compile_message(struct spi_engine *spi_engine,
                SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_CONFIG,
                        spi_engine_get_config(spi)));
 
+       xfer = list_first_entry(&msg->transfers, struct spi_transfer, transfer_list);
+       spi_engine_gen_cs(p, dry, spi, !xfer->cs_off);
+
        list_for_each_entry(xfer, &msg->transfers, transfer_list) {
                new_clk_div = spi_engine_get_clk_div(spi_engine, spi, xfer);
                if (new_clk_div != clk_div) {
@@ -233,20 +236,28 @@ static int spi_engine_compile_message(struct spi_engine *spi_engine,
                                        clk_div));
                }
 
-               if (cs_change)
-                       spi_engine_gen_cs(p, dry, spi, true);
-
                spi_engine_gen_xfer(p, dry, xfer);
                spi_engine_gen_sleep(p, dry, spi_engine, clk_div, xfer);
 
-               cs_change = xfer->cs_change;
-               if (list_is_last(&xfer->transfer_list, &msg->transfers))
-                       cs_change = !cs_change;
-
-               if (cs_change)
-                       spi_engine_gen_cs(p, dry, spi, false);
+               if (xfer->cs_change) {
+                       if (list_is_last(&xfer->transfer_list, &msg->transfers)) {
+                               keep_cs = true;
+                       } else {
+                               if (!xfer->cs_off)
+                                       spi_engine_gen_cs(p, dry, spi, false);
+
+                               if (!list_next_entry(xfer, transfer_list)->cs_off)
+                                       spi_engine_gen_cs(p, dry, spi, true);
+                       }
+               } else if (!list_is_last(&xfer->transfer_list, &msg->transfers) &&
+                          xfer->cs_off != list_next_entry(xfer, transfer_list)->cs_off) {
+                       spi_engine_gen_cs(p, dry, spi, xfer->cs_off);
+               }
        }
 
+       if (!keep_cs)
+               spi_engine_gen_cs(p, dry, spi, false);
+
        return 0;
 }