spi: tegra210-quad: Allocate DMA memory for DMA engine

When the SPI controllers are running in DMA mode, it is the DMA engine
that performs the memory accesses rather than the SPI controller. Pass
the DMA engine's struct device pointer to the DMA API to make sure the
correct DMA operations are used.

Suggested-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
Link: https://patch.msgid.link/20260525-tegra194-qspi-iommu-v2-1-a11c53f804b2@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Aaron Kling 2026-05-25 01:47:44 -05:00 committed by Mark Brown
parent 4503b2fe76
commit f469138a77
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0

View File

@ -226,11 +226,13 @@ struct tegra_qspi {
struct completion xfer_completion;
struct spi_transfer *curr_xfer;
struct device *rx_dma_dev;
struct dma_chan *rx_dma_chan;
u32 *rx_dma_buf;
dma_addr_t rx_dma_phys;
struct dma_async_tx_descriptor *rx_dma_desc;
struct device *tx_dma_dev;
struct dma_chan *tx_dma_chan;
u32 *tx_dma_buf;
dma_addr_t tx_dma_phys;
@ -574,15 +576,15 @@ static int tegra_qspi_dma_map_xfer(struct tegra_qspi *tqspi, struct spi_transfer
len = DIV_ROUND_UP(tqspi->curr_dma_words * tqspi->bytes_per_word, 4) * 4;
if (t->tx_buf) {
t->tx_dma = dma_map_single(tqspi->dev, (void *)tx_buf, len, DMA_TO_DEVICE);
if (dma_mapping_error(tqspi->dev, t->tx_dma))
t->tx_dma = dma_map_single(tqspi->tx_dma_dev, (void *)tx_buf, len, DMA_TO_DEVICE);
if (dma_mapping_error(tqspi->tx_dma_dev, t->tx_dma))
return -ENOMEM;
}
if (t->rx_buf) {
t->rx_dma = dma_map_single(tqspi->dev, (void *)rx_buf, len, DMA_FROM_DEVICE);
if (dma_mapping_error(tqspi->dev, t->rx_dma)) {
dma_unmap_single(tqspi->dev, t->tx_dma, len, DMA_TO_DEVICE);
t->rx_dma = dma_map_single(tqspi->rx_dma_dev, (void *)rx_buf, len, DMA_FROM_DEVICE);
if (dma_mapping_error(tqspi->rx_dma_dev, t->rx_dma)) {
dma_unmap_single(tqspi->tx_dma_dev, t->tx_dma, len, DMA_TO_DEVICE);
return -ENOMEM;
}
}
@ -597,9 +599,9 @@ static void tegra_qspi_dma_unmap_xfer(struct tegra_qspi *tqspi, struct spi_trans
len = DIV_ROUND_UP(tqspi->curr_dma_words * tqspi->bytes_per_word, 4) * 4;
if (t->tx_buf)
dma_unmap_single(tqspi->dev, t->tx_dma, len, DMA_TO_DEVICE);
dma_unmap_single(tqspi->tx_dma_dev, t->tx_dma, len, DMA_TO_DEVICE);
if (t->rx_buf)
dma_unmap_single(tqspi->dev, t->rx_dma, len, DMA_FROM_DEVICE);
dma_unmap_single(tqspi->rx_dma_dev, t->rx_dma, len, DMA_FROM_DEVICE);
}
static int tegra_qspi_start_dma_based_transfer(struct tegra_qspi *tqspi, struct spi_transfer *t)
@ -745,7 +747,7 @@ static int tegra_qspi_start_cpu_based_transfer(struct tegra_qspi *qspi, struct s
static void tegra_qspi_deinit_dma(struct tegra_qspi *tqspi)
{
if (tqspi->tx_dma_buf) {
dma_free_coherent(tqspi->dev, tqspi->dma_buf_size,
dma_free_coherent(tqspi->tx_dma_dev, tqspi->dma_buf_size,
tqspi->tx_dma_buf, tqspi->tx_dma_phys);
tqspi->tx_dma_buf = NULL;
}
@ -756,7 +758,7 @@ static void tegra_qspi_deinit_dma(struct tegra_qspi *tqspi)
}
if (tqspi->rx_dma_buf) {
dma_free_coherent(tqspi->dev, tqspi->dma_buf_size,
dma_free_coherent(tqspi->rx_dma_dev, tqspi->dma_buf_size,
tqspi->rx_dma_buf, tqspi->rx_dma_phys);
tqspi->rx_dma_buf = NULL;
}
@ -782,6 +784,7 @@ static int tegra_qspi_init_dma(struct tegra_qspi *tqspi)
}
tqspi->rx_dma_chan = dma_chan;
tqspi->rx_dma_dev = dmaengine_get_dma_device(tqspi->rx_dma_chan);
dma_chan = dma_request_chan(tqspi->dev, "tx");
if (IS_ERR(dma_chan)) {
@ -790,15 +793,19 @@ static int tegra_qspi_init_dma(struct tegra_qspi *tqspi)
}
tqspi->tx_dma_chan = dma_chan;
tqspi->tx_dma_dev = dmaengine_get_dma_device(tqspi->tx_dma_chan);
} else {
if (!device_iommu_mapped(tqspi->dev)) {
dev_warn(tqspi->dev,
"IOMMU not enabled in device-tree, falling back to PIO mode\n");
return 0;
}
tqspi->rx_dma_dev = tqspi->dev;
tqspi->tx_dma_dev = tqspi->dev;
}
dma_buf = dma_alloc_coherent(tqspi->dev, tqspi->dma_buf_size, &dma_phys, GFP_KERNEL);
dma_buf = dma_alloc_coherent(tqspi->rx_dma_dev, tqspi->dma_buf_size, &dma_phys, GFP_KERNEL);
if (!dma_buf) {
err = -ENOMEM;
goto err_out;
@ -807,7 +814,7 @@ static int tegra_qspi_init_dma(struct tegra_qspi *tqspi)
tqspi->rx_dma_buf = dma_buf;
tqspi->rx_dma_phys = dma_phys;
dma_buf = dma_alloc_coherent(tqspi->dev, tqspi->dma_buf_size, &dma_phys, GFP_KERNEL);
dma_buf = dma_alloc_coherent(tqspi->tx_dma_dev, tqspi->dma_buf_size, &dma_phys, GFP_KERNEL);
if (!dma_buf) {
err = -ENOMEM;
goto err_out;