[PATCH v2] spi: qcom-geni: Use GSI mode if DMA channels are available

From: Pengyu Luo

Date: Tue Jun 16 2026 - 08:28:25 EST


Some devices (such as gaokun3) do not disable FIFO mode, causing the
driver to fallback to FIFO mode by default. However, these platforms
also support GSI mode, which is highly preferred for certain
peripherals like SPI touchscreens to improve performance.

So try GSI mode by getting DMA channels first, fallback to fifo mode
if it fails.

Suggested-by: Dmitry Baryshkov <dmitry.baryshkov@xxxxxxxxxxxxxxxx>
Signed-off-by: Pengyu Luo <mitltlatltl@xxxxxxxxx>
---
Changes in v2:
- Determine mode by checking DMA channels. (Dmitry)
- Link to v1: https://lore.kernel.org/linux-arm-msm/20260614083424.464132-1-mitltlatltl@xxxxxxxxx
---
drivers/spi/spi-geni-qcom.c | 34 ++++++++++++++--------------------
1 file changed, 14 insertions(+), 20 deletions(-)

diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c
index 26e723cfea61..d2fcd0bb0732 100644
--- a/drivers/spi/spi-geni-qcom.c
+++ b/drivers/spi/spi-geni-qcom.c
@@ -654,26 +654,21 @@ static int spi_geni_init(struct spi_geni_master *mas)
else
mas->oversampling = 1;

- fifo_disable = readl(se->base + GENI_IF_DISABLE_RO) & FIFO_IF_DISABLE;
- switch (fifo_disable) {
- case 1:
- ret = spi_geni_grab_gpi_chan(mas);
- if (!ret) { /* success case */
- mas->cur_xfer_mode = GENI_GPI_DMA;
- geni_se_select_mode(se, GENI_GPI_DMA);
- dev_dbg(mas->dev, "Using GPI DMA mode for SPI\n");
- break;
- } else if (ret == -EPROBE_DEFER) {
- goto out_pm;
- }
- /*
- * in case of failure to get gpi dma channel, we can still do the
- * FIFO mode, so fallthrough
- */
- dev_warn(mas->dev, "FIFO mode disabled, but couldn't get DMA, fall back to FIFO mode\n");
- fallthrough;
+ /* Try GPI DMA mode first, fallback to fifo mode if it fails. */
+ ret = spi_geni_grab_gpi_chan(mas);
+ if (!ret) { /* success case */
+ mas->cur_xfer_mode = GENI_GPI_DMA;
+ geni_se_select_mode(se, GENI_GPI_DMA);
+ dev_dbg(mas->dev, "Using GPI DMA mode for SPI\n");
+ } else if (ret == -EPROBE_DEFER) {
+ goto out_pm;
+ } else {
+ fifo_disable = readl(se->base + GENI_IF_DISABLE_RO) & FIFO_IF_DISABLE;
+ if (fifo_disable)
+ dev_warn(mas->dev, "FIFO mode disabled, but couldn't get GPI DMA, fall back to FIFO mode\n");
+ else
+ dev_dbg(mas->dev, "Using FIFO mode for SPI\n");

- case 0:
mas->cur_xfer_mode = GENI_SE_FIFO;
geni_se_select_mode(se, GENI_SE_FIFO);
/* setup_fifo_params assumes that these registers start with a zero value */
@@ -683,7 +678,6 @@ static int spi_geni_init(struct spi_geni_master *mas)
writel(0, se->base + SE_SPI_CPOL);
writel(0, se->base + SE_SPI_DEMUX_OUTPUT_INV);
ret = 0;
- break;
}

/* We never control CS manually */
--
2.54.0