[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-Id: <20250902-james-nxp-spi-dma-v6-5-f7aa2c5e56e2@linaro.org>
Date: Tue, 02 Sep 2025 13:44:57 +0100
From: James Clark <james.clark@...aro.org>
To: Vladimir Oltean <olteanv@...il.com>, Mark Brown <broonie@...nel.org>,
Vladimir Oltean <vladimir.oltean@....com>, Arnd Bergmann <arnd@...db.de>,
Larisa Grigore <larisa.grigore@....com>, Frank Li <Frank.li@....com>,
Christoph Hellwig <hch@....de>
Cc: linux-spi@...r.kernel.org, imx@...ts.linux.dev,
linux-kernel@...r.kernel.org, James Clark <james.clark@...aro.org>
Subject: [PATCH v6 5/7] spi: spi-fsl-dspi: Use whole page for DMA buffers
dma_alloc_noncoherent() allocations are backed by a full page anyway, so
use it all.
VF610 devices used to use the full page before commit a957499bd437
("spi: spi-fsl-dspi: Fix bits-per-word acceleration in DMA mode"), but
others still used the FIFO size. After that commit, all devices used the
FIFO size. Now all devices use the full page.
Signed-off-by: James Clark <james.clark@...aro.org>
---
drivers/spi/spi-fsl-dspi.c | 41 ++++++++++++++++++++++++++++++-----------
1 file changed, 30 insertions(+), 11 deletions(-)
diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
index 81d1e4470f94..6bf87ef01c13 100644
--- a/drivers/spi/spi-fsl-dspi.c
+++ b/drivers/spi/spi-fsl-dspi.c
@@ -331,6 +331,8 @@ struct fsl_dspi_dma {
dma_addr_t rx_dma_phys;
struct completion cmd_rx_complete;
struct dma_async_tx_descriptor *rx_desc;
+
+ size_t bufsize;
};
struct fsl_dspi {
@@ -493,6 +495,24 @@ static u32 dspi_pop_tx_pushr(struct fsl_dspi *dspi)
return cmd << 16 | data;
}
+static size_t dspi_dma_max_datawords(struct fsl_dspi *dspi)
+{
+ /*
+ * Transfers look like one of these, so we always use a full DMA word
+ * regardless of SPI word size:
+ *
+ * 31 16 15 0
+ * -----------------------------------------
+ * | CONTROL WORD | 16-bit DATA |
+ * -----------------------------------------
+ * or
+ * -----------------------------------------
+ * | CONTROL WORD | UNUSED | 8-bit DATA |
+ * -----------------------------------------
+ */
+ return dspi->dma->bufsize / DMA_SLAVE_BUSWIDTH_4_BYTES;
+}
+
static size_t dspi_dma_transfer_size(struct fsl_dspi *dspi)
{
return dspi->words_in_flight * DMA_SLAVE_BUSWIDTH_4_BYTES;
@@ -620,9 +640,8 @@ static void dspi_dma_xfer(struct fsl_dspi *dspi)
/* Figure out operational bits-per-word for this chunk */
dspi_setup_accel(dspi);
- dspi->words_in_flight = dspi->len / dspi->oper_word_size;
- if (dspi->words_in_flight > dspi->devtype_data->fifo_size)
- dspi->words_in_flight = dspi->devtype_data->fifo_size;
+ dspi->words_in_flight = min(dspi->len / dspi->oper_word_size,
+ dspi_dma_max_datawords(dspi));
message->actual_length += dspi->words_in_flight *
dspi->oper_word_size;
@@ -637,7 +656,6 @@ static void dspi_dma_xfer(struct fsl_dspi *dspi)
static int dspi_request_dma(struct fsl_dspi *dspi, phys_addr_t phy_addr)
{
- int dma_bufsize = dspi->devtype_data->fifo_size * 2;
struct device *dev = &dspi->pdev->dev;
struct dma_slave_config cfg;
struct fsl_dspi_dma *dma;
@@ -657,8 +675,10 @@ static int dspi_request_dma(struct fsl_dspi *dspi, phys_addr_t phy_addr)
goto err_tx_channel;
}
+ dma->bufsize = PAGE_SIZE;
+
dma->tx_dma_buf = dma_alloc_noncoherent(dma->chan_tx->device->dev,
- dma_bufsize, &dma->tx_dma_phys,
+ dma->bufsize, &dma->tx_dma_phys,
DMA_TO_DEVICE, GFP_KERNEL);
if (!dma->tx_dma_buf) {
ret = -ENOMEM;
@@ -666,7 +686,7 @@ static int dspi_request_dma(struct fsl_dspi *dspi, phys_addr_t phy_addr)
}
dma->rx_dma_buf = dma_alloc_noncoherent(dma->chan_rx->device->dev,
- dma_bufsize, &dma->rx_dma_phys,
+ dma->bufsize, &dma->rx_dma_phys,
DMA_FROM_DEVICE, GFP_KERNEL);
if (!dma->rx_dma_buf) {
ret = -ENOMEM;
@@ -702,11 +722,11 @@ static int dspi_request_dma(struct fsl_dspi *dspi, phys_addr_t phy_addr)
return 0;
err_slave_config:
- dma_free_noncoherent(dma->chan_rx->device->dev, dma_bufsize,
+ dma_free_noncoherent(dma->chan_rx->device->dev, dma->bufsize,
dma->rx_dma_buf, dma->rx_dma_phys,
DMA_FROM_DEVICE);
err_rx_dma_buf:
- dma_free_noncoherent(dma->chan_tx->device->dev, dma_bufsize,
+ dma_free_noncoherent(dma->chan_tx->device->dev, dma->bufsize,
dma->tx_dma_buf, dma->tx_dma_phys, DMA_TO_DEVICE);
err_tx_dma_buf:
dma_release_channel(dma->chan_tx);
@@ -721,21 +741,20 @@ static int dspi_request_dma(struct fsl_dspi *dspi, phys_addr_t phy_addr)
static void dspi_release_dma(struct fsl_dspi *dspi)
{
- int dma_bufsize = dspi->devtype_data->fifo_size * 2;
struct fsl_dspi_dma *dma = dspi->dma;
if (!dma)
return;
if (dma->chan_tx) {
- dma_free_noncoherent(dma->chan_tx->device->dev, dma_bufsize,
+ dma_free_noncoherent(dma->chan_tx->device->dev, dma->bufsize,
dma->tx_dma_buf, dma->tx_dma_phys,
DMA_TO_DEVICE);
dma_release_channel(dma->chan_tx);
}
if (dma->chan_rx) {
- dma_free_noncoherent(dma->chan_rx->device->dev, dma_bufsize,
+ dma_free_noncoherent(dma->chan_rx->device->dev, dma->bufsize,
dma->rx_dma_buf, dma->rx_dma_phys,
DMA_FROM_DEVICE);
dma_release_channel(dma->chan_rx);
--
2.34.1
Powered by blists - more mailing lists