From 087591c9e4fde86fe2971c34a2745c208103248e Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 28 Apr 2025 15:58:58 -0500 Subject: [PATCH] spi: axi-spi-engine: optimize bits_per_word for offload Add an optimization to avoid repeating bits_per_word instructions in each message when using SPI offload. This only applies when all data xfers in a message have the same bits_per_word. In this case, we can execute the instruction that sets bits_per_word when the offload trigger is enabled. This is useful e.g. for obtaining higher sample rates on ADCs since each message takes less time to execute. Signed-off-by: David Lechner Link: https://patch.msgid.link/20250428-adi-main-v1-3-4b8a1b88a212@baylibre.com Signed-off-by: Mark Brown --- drivers/spi/spi-axi-spi-engine.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/spi/spi-axi-spi-engine.c b/drivers/spi/spi-axi-spi-engine.c index 05ef2589f8dc..b54d2e1437c9 100644 --- a/drivers/spi/spi-axi-spi-engine.c +++ b/drivers/spi/spi-axi-spi-engine.c @@ -142,6 +142,7 @@ struct spi_engine_offload { unsigned long flags; unsigned int offload_num; unsigned int spi_mode_config; + u8 bits_per_word; }; struct spi_engine { @@ -267,6 +268,8 @@ 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; + u8 min_bits_per_word = U8_MAX; + u8 max_bits_per_word = 0; list_for_each_entry(xfer, &msg->transfers, transfer_list) { /* If we have an offload transfer, we can't rx to buffer */ @@ -275,6 +278,24 @@ static int spi_engine_precompile_message(struct spi_message *msg) clk_div = DIV_ROUND_UP(max_hz, xfer->speed_hz); xfer->effective_speed_hz = max_hz / min(clk_div, 256U); + + if (xfer->len) { + 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 all xfers in the message use the same bits_per_word, we can + * provide some optimization when using SPI offload. + */ + if (msg->offload) { + struct spi_engine_offload *priv = msg->offload->priv; + + if (min_bits_per_word == max_bits_per_word) + priv->bits_per_word = min_bits_per_word; + else + priv->bits_per_word = 0; } return 0; @@ -306,6 +327,12 @@ static void spi_engine_compile_message(struct spi_message *msg, bool dry, if (msg->offload) { priv = msg->offload->priv; priv->spi_mode_config = spi_engine_get_config(spi); + + /* + * If all xfers use the same bits_per_word, it can be optimized + * in the same way. + */ + bits_per_word = priv->bits_per_word; } else { spi_engine_program_add_cmd(p, dry, SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_CONFIG, @@ -862,6 +889,11 @@ static int spi_engine_trigger_enable(struct spi_offload *offload) priv->spi_mode_config), spi_engine->base + SPI_ENGINE_REG_CMD_FIFO); + if (priv->bits_per_word) + writel_relaxed(SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_XFER_BITS, + priv->bits_per_word), + spi_engine->base + SPI_ENGINE_REG_CMD_FIFO); + writel_relaxed(SPI_ENGINE_CMD_SYNC(1), spi_engine->base + SPI_ENGINE_REG_CMD_FIFO); -- 2.50.1