* [PATCH v2 0/2] arm64: tegra: Enable DMA Support on Tegra194 QSPI
@ 2026-05-25 6:47 Aaron Kling via B4 Relay
2026-05-25 6:47 ` [PATCH v2 1/2] spi: tegra210-quad: Allocate DMA memory for DMA engine Aaron Kling via B4 Relay
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Aaron Kling via B4 Relay @ 2026-05-25 6:47 UTC (permalink / raw)
To: Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Laxman Dewangan, Mark Brown, Sumit Semwal, Christian König,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-tegra, linux-spi, linux-kernel, linux-media, dri-devel,
linaro-mm-sig, devicetree, Thierry Reding, Aaron Kling
The reason for this is to properly support the spi nor chip on the
Jetson Xavier NX module. Prior to this, it would time out on all
transfers and sometimes even trigger a cbb fault, locking up the entire
unit. With this, reading and writing to the flash memory works as
expected.
This also fixes the tegra210-quad spi driver to properly use the dma
memory space instead of the spi controllers. Without this, enabling dma
on the controllers results in mmu faults.
The driver change has only been tested on tegra210 / p3450 and tegra194
/ p3518 as that is the only available test platforms. Tegra234 and
Tegra241 should also be verified. I have p3766 for tegra234, but the
qspi flash memory is firewalled by mb1 on all publicly available
bootloaders, and no other spi devices are part of the devkit.
---
Changes in v2:
- Drop bindings patches
- Add patch to use dma memory space instead of the spi controllers when
dma is enabled.
- Drop iommu properties from final patch
- Link to v1: https://lore.kernel.org/r/20260515-tegra194-qspi-iommu-v1-0-57dfb63cd3d6@gmail.com
---
Aaron Kling (2):
spi: tegra210-quad: Allocate DMA memory for DMA engine
arm64: tegra: Enable DMA Support on Tegra194 QSPI
arch/arm64/boot/dts/nvidia/tegra194.dtsi | 4 ++++
drivers/spi/spi-tegra210-quad.c | 29 ++++++++++++++++++-----------
2 files changed, 22 insertions(+), 11 deletions(-)
---
base-commit: c1ecb239fa3456529a32255359fc78b69eb9d847
change-id: 20260515-tegra194-qspi-iommu-e4e4644d5fdf
Best regards,
--
Aaron Kling <webgeek1234@gmail.com>
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH v2 1/2] spi: tegra210-quad: Allocate DMA memory for DMA engine 2026-05-25 6:47 [PATCH v2 0/2] arm64: tegra: Enable DMA Support on Tegra194 QSPI Aaron Kling via B4 Relay @ 2026-05-25 6:47 ` Aaron Kling via B4 Relay 2026-05-25 21:40 ` Claude review: " Claude Code Review Bot 2026-05-25 6:47 ` [PATCH v2 2/2] arm64: tegra: Enable DMA Support on Tegra194 QSPI Aaron Kling via B4 Relay 2026-05-25 21:40 ` Claude Code Review Bot 2 siblings, 1 reply; 6+ messages in thread From: Aaron Kling via B4 Relay @ 2026-05-25 6:47 UTC (permalink / raw) To: Thierry Reding, Jonathan Hunter, Sowjanya Komatineni, Laxman Dewangan, Mark Brown, Sumit Semwal, Christian König, Rob Herring, Krzysztof Kozlowski, Conor Dooley Cc: linux-tegra, linux-spi, linux-kernel, linux-media, dri-devel, linaro-mm-sig, devicetree, Thierry Reding, Aaron Kling From: Aaron Kling <webgeek1234@gmail.com> 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> --- drivers/spi/spi-tegra210-quad.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c index db28dd556484b2..588a929a97850a 100644 --- a/drivers/spi/spi-tegra210-quad.c +++ b/drivers/spi/spi-tegra210-quad.c @@ -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; -- 2.53.0 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Claude review: spi: tegra210-quad: Allocate DMA memory for DMA engine 2026-05-25 6:47 ` [PATCH v2 1/2] spi: tegra210-quad: Allocate DMA memory for DMA engine Aaron Kling via B4 Relay @ 2026-05-25 21:40 ` Claude Code Review Bot 0 siblings, 0 replies; 6+ messages in thread From: Claude Code Review Bot @ 2026-05-25 21:40 UTC (permalink / raw) To: dri-devel-reviews Patch Review This is the substantive driver change. It adds `rx_dma_dev` and `tx_dma_dev` fields to `struct tegra_qspi` and uses them consistently throughout all DMA API calls. **Structure additions look correct:** ```c + struct device *rx_dma_dev; struct dma_chan *rx_dma_chan; ... + struct device *tx_dma_dev; struct dma_chan *tx_dma_chan; ``` Placed logically next to their associated DMA channel pointers. **DMA device initialization is correct for the `has_ext_dma` path:** ```c tqspi->rx_dma_chan = dma_chan; + tqspi->rx_dma_dev = dmaengine_get_dma_device(tqspi->rx_dma_chan); ... tqspi->tx_dma_chan = dma_chan; + tqspi->tx_dma_dev = dmaengine_get_dma_device(tqspi->tx_dma_chan); ``` `dmaengine_get_dma_device()` returns either the channel-specific DMA device or the DMA controller's device, which is exactly what should be passed to `dma_map_single()` / `dma_alloc_coherent()`. **Fallback path (non-ext-dma) is correct:** ```c + tqspi->rx_dma_dev = tqspi->dev; + tqspi->tx_dma_dev = tqspi->dev; ``` When there's no external DMA engine (e.g. tegra234 with internal DMA), the SPI controller device itself is appropriate. **Minor observation on the error path in `tegra_qspi_dma_map_xfer`:** ```c 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); ``` The error path correctly unmaps `t->tx_dma` using `tqspi->tx_dma_dev`. This is a pre-existing pattern where the unmap happens unconditionally on the error path even if `t->tx_buf` was NULL (so tx_dma was never mapped). That's a pre-existing issue, not introduced by this patch, but worth noting. **All `dma_alloc_coherent`, `dma_free_coherent`, `dma_map_single`, `dma_unmap_single` call sites have been updated consistently.** I verified each callsite against the upstream code and they all match. **One question:** The commit message says "Pass the DMA engine's struct device pointer to the DMA API to make sure the correct DMA operations are used." This is good, but it might be worth adding a `Fixes:` tag if there is a specific commit that introduced the broken behavior, since this fixes real DMA/IOMMU faults. The cover letter mentions this fixes transfers on p3668/p3518 modules. A `Fixes:` tag would help stable backporters. --- Generated by Claude Code Patch Reviewer ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 2/2] arm64: tegra: Enable DMA Support on Tegra194 QSPI 2026-05-25 6:47 [PATCH v2 0/2] arm64: tegra: Enable DMA Support on Tegra194 QSPI Aaron Kling via B4 Relay 2026-05-25 6:47 ` [PATCH v2 1/2] spi: tegra210-quad: Allocate DMA memory for DMA engine Aaron Kling via B4 Relay @ 2026-05-25 6:47 ` Aaron Kling via B4 Relay 2026-05-25 21:40 ` Claude review: " Claude Code Review Bot 2026-05-25 21:40 ` Claude Code Review Bot 2 siblings, 1 reply; 6+ messages in thread From: Aaron Kling via B4 Relay @ 2026-05-25 6:47 UTC (permalink / raw) To: Thierry Reding, Jonathan Hunter, Sowjanya Komatineni, Laxman Dewangan, Mark Brown, Sumit Semwal, Christian König, Rob Herring, Krzysztof Kozlowski, Conor Dooley Cc: linux-tegra, linux-spi, linux-kernel, linux-media, dri-devel, linaro-mm-sig, devicetree, Aaron Kling From: Aaron Kling <webgeek1234@gmail.com> Without dma enabled pio mode is used and flash storage such as the one on the p3668 module times out and cannot complete any transfers. In some cases, these timeouts cause hangs and cbb faults. Signed-off-by: Aaron Kling <webgeek1234@gmail.com> --- arch/arm64/boot/dts/nvidia/tegra194.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/nvidia/tegra194.dtsi b/arch/arm64/boot/dts/nvidia/tegra194.dtsi index 1d659454a6f9fe..e2ddbc6715d5e8 100644 --- a/arch/arm64/boot/dts/nvidia/tegra194.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra194.dtsi @@ -923,6 +923,8 @@ spi@3270000 { <&bpmp TEGRA194_CLK_QSPI0_PM>; clock-names = "qspi", "qspi_out"; resets = <&bpmp TEGRA194_RESET_QSPI0>; + dmas = <&gpcdma 5>, <&gpcdma 5>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -1013,6 +1015,8 @@ spi@3300000 { <&bpmp TEGRA194_CLK_QSPI1_PM>; clock-names = "qspi", "qspi_out"; resets = <&bpmp TEGRA194_RESET_QSPI1>; + dmas = <&gpcdma 6>, <&gpcdma 6>; + dma-names = "rx", "tx"; status = "disabled"; }; -- 2.53.0 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Claude review: arm64: tegra: Enable DMA Support on Tegra194 QSPI 2026-05-25 6:47 ` [PATCH v2 2/2] arm64: tegra: Enable DMA Support on Tegra194 QSPI Aaron Kling via B4 Relay @ 2026-05-25 21:40 ` Claude Code Review Bot 0 siblings, 0 replies; 6+ messages in thread From: Claude Code Review Bot @ 2026-05-25 21:40 UTC (permalink / raw) To: dri-devel-reviews Patch Review This is a straightforward DT change adding `dmas` and `dma-names` properties to both QSPI controller nodes in tegra194.dtsi. **QSPI0 (spi@3270000):** ```c + dmas = <&gpcdma 5>, <&gpcdma 5>; + dma-names = "rx", "tx"; ``` **QSPI1 (spi@3300000):** ```c + dmas = <&gpcdma 6>, <&gpcdma 6>; + dma-names = "rx", "tx"; ``` The format matches exactly the pattern used by all other peripherals in the same file (I2C, UART nodes all use the same `<&gpcdma N>, <&gpcdma N>` with `"rx", "tx"` pattern). The DMA channel numbers (5 for QSPI0, 6 for QSPI1) use the same channel for both RX and TX, which is consistent with how other Tegra peripherals reference their gpcdma channels (e.g., UARTs, I2C controllers all share the same channel number for rx/tx). The commit message could be slightly improved - it mentions "Without dma enabled pio mode is used" which should probably be "Without DMA enabled, PIO mode is used" (capitalization and comma), but that's purely cosmetic. **No issues with this patch.** --- Generated by Claude Code Patch Reviewer ^ permalink raw reply [flat|nested] 6+ messages in thread
* Claude review: arm64: tegra: Enable DMA Support on Tegra194 QSPI 2026-05-25 6:47 [PATCH v2 0/2] arm64: tegra: Enable DMA Support on Tegra194 QSPI Aaron Kling via B4 Relay 2026-05-25 6:47 ` [PATCH v2 1/2] spi: tegra210-quad: Allocate DMA memory for DMA engine Aaron Kling via B4 Relay 2026-05-25 6:47 ` [PATCH v2 2/2] arm64: tegra: Enable DMA Support on Tegra194 QSPI Aaron Kling via B4 Relay @ 2026-05-25 21:40 ` Claude Code Review Bot 2 siblings, 0 replies; 6+ messages in thread From: Claude Code Review Bot @ 2026-05-25 21:40 UTC (permalink / raw) To: dri-devel-reviews Overall Series Review Subject: arm64: tegra: Enable DMA Support on Tegra194 QSPI Author: Aaron Kling via B4 Relay <devnull+webgeek1234.gmail.com@kernel.org> Patches: 3 Reviewed: 2026-05-26T07:40:38.386949 --- This is a 2-patch series that enables DMA support for the QSPI controllers on Tegra194 (Jetson Xavier NX). The first patch fixes the SPI driver to pass the DMA engine's `struct device` to DMA API calls instead of the SPI controller's device, ensuring the correct IOMMU mappings are used. The second patch adds the `dmas`/`dma-names` properties to the Tegra194 QSPI device tree nodes. The approach is correct and follows established patterns. `dmaengine_get_dma_device()` is the standard API for obtaining the right device pointer for DMA API calls when a DMA engine is involved, and several other drivers in the tree use it similarly. The series addresses a real functional problem (PIO timeouts, CBB faults) and the v2 changes address previous review feedback cleanly. The DT change follows existing conventions in the same file. I have a couple of minor observations but nothing blocking. **Verdict: Series looks good overall.** --- Generated by Claude Code Patch Reviewer ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-05-25 21:40 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-05-25 6:47 [PATCH v2 0/2] arm64: tegra: Enable DMA Support on Tegra194 QSPI Aaron Kling via B4 Relay 2026-05-25 6:47 ` [PATCH v2 1/2] spi: tegra210-quad: Allocate DMA memory for DMA engine Aaron Kling via B4 Relay 2026-05-25 21:40 ` Claude review: " Claude Code Review Bot 2026-05-25 6:47 ` [PATCH v2 2/2] arm64: tegra: Enable DMA Support on Tegra194 QSPI Aaron Kling via B4 Relay 2026-05-25 21:40 ` Claude review: " Claude Code Review Bot 2026-05-25 21:40 ` Claude Code Review Bot
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox