mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 01:32:21 +02:00
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:
parent
4503b2fe76
commit
f469138a77
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user