diff options
author | Joy Chakraborty <joychakr@google.com> | 2023-05-12 10:47:44 +0000 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2023-05-15 10:46:17 +0900 |
commit | 020a3947e7f18e790cc72785281755f8c49e11d4 (patch) | |
tree | 820a48a67b87bc4fa8b434b531568f958ee39d8b /drivers/spi | |
parent | d1ca1c5297ba9260942c0b3f1171a98a432bdfec (diff) |
spi: dw: Add DMA address widths capability check
Store address width capabilities of DMA controller during init and check
the same per transfer to make sure the bits/word requirement can be met.
Current DW DMA driver requires both tx and rx channel to be configured
and functional hence a subset of both tx and rx channel address width
capability is checked with the width requirement(n_bytes) for a
transfer.
* tested on Baikal-T1 based system with DW SPI-looped back interface
transferring a chunk of data with DFS:8,12,16.
Signed-off-by: Joy Chakraborty <joychakr@google.com
Reviewed-by: Serge Semin <fancer.lancer@gmail.com
Tested-by: Serge Semin <fancer.lancer@gmail.com
Link: https://lore.kernel.org/r/20230512104746.1797865-3-joychakr@google.com
Signed-off-by: Mark Brown <broonie@kernel.org
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/spi-dw-dma.c | 15 | ||||
-rw-r--r-- | drivers/spi/spi-dw.h | 1 |
2 files changed, 15 insertions, 1 deletions
diff --git a/drivers/spi/spi-dw-dma.c b/drivers/spi/spi-dw-dma.c index 2363317a0dca..df819652901a 100644 --- a/drivers/spi/spi-dw-dma.c +++ b/drivers/spi/spi-dw-dma.c @@ -98,6 +98,13 @@ static int dw_spi_dma_caps_init(struct dw_spi *dws) else dws->dma_sg_burst = 0; + /* + * Assuming both channels belong to the same DMA controller hence the + * peripheral side address width capabilities most likely would be + * the same. + */ + dws->dma_addr_widths = tx.dst_addr_widths & rx.src_addr_widths; + return 0; } @@ -239,8 +246,14 @@ static bool dw_spi_can_dma(struct spi_controller *master, struct spi_device *spi, struct spi_transfer *xfer) { struct dw_spi *dws = spi_controller_get_devdata(master); + enum dma_slave_buswidth dma_bus_width; + + if (xfer->len <= dws->fifo_len) + return false; + + dma_bus_width = dw_spi_dma_convert_width(dws->n_bytes); - return xfer->len > dws->fifo_len; + return dws->dma_addr_widths & BIT(dma_bus_width); } static int dw_spi_dma_wait(struct dw_spi *dws, unsigned int len, u32 speed) diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h index 9e8eb2b52d5c..3962e6dcf880 100644 --- a/drivers/spi/spi-dw.h +++ b/drivers/spi/spi-dw.h @@ -190,6 +190,7 @@ struct dw_spi { struct dma_chan *rxchan; u32 rxburst; u32 dma_sg_burst; + u32 dma_addr_widths; unsigned long dma_chan_busy; dma_addr_t dma_addr; /* phy address of the Data register */ const struct dw_spi_dma_ops *dma_ops; |