UARTA DMA - Not enabled by default and doesn't work in JP6

Trying to use the Jetson Orin Nano, with JP6, in a devkit with uarta serial@3100000

I’ve seen the other topics that claim ttyTHS means the uart is running in DMA mode, but I checked the drivers, and they will revert to PIO mode when the dma settings are not included in the dtsi.

The /var/log/dmesg shows the output RX and TX in PIO by default after flashing.

[    3.583791] kernel: gpio-394 (camera-control-output-low): hogged as output/low
[    3.588464] kernel: tegra-gpcdma 2600000.dma-controller: Adding to iommu group 1
[    3.590027] kernel: tegra-gpcdma 2600000.dma-controller: GPC DMA driver register 31 channels
[    3.591731] kernel: serial-tegra 3100000.serial: RX in PIO mode
[    3.591736] kernel: serial-tegra 3100000.serial: TX in PIO mode
[    3.591805] kernel: 3100000.serial: ttyTHS1 at MMIO 0x3100000 (irq = 112, base_baud = 0) is a TEGRA_UART
[    3.592917] kernel: serial-tegra 3140000.serial: RX in PIO mode
[    3.592921] kernel: serial-tegra 3140000.serial: TX in PIO mode
[    3.592965] kernel: 3140000.serial: ttyTHS2 at MMIO 0x3140000 (irq = 113, base_baud = 0) is a TEGRA_UART

In fact, none of the serials have the dma names or dma values in the ./source/hardware/nvidia/t23x/nv-public/tegra234.dtsi (or any other overlay I can find):

uarta: serial@3100000 {
                        compatible = "nvidia,tegra234-uart", "nvidia,tegra20-uart";
                        reg = <0x0 0x03100000 0x0 0x10000>;
                        interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&bpmp TEGRA234_CLK_UARTA>;
                        resets = <&bpmp TEGRA234_RESET_UARTA>;
                };

I have tried to look at the TRM, and see uarta should be requestor 8, so I made an overlay and applied it:

/dts-v1/;
/plugin/;

/ {
  fragment@0 {
    target-path="/bus@0/serial@3100000";
    __overlay__ {
            dmas = <&gpcdma 8>;
            dma-names= "rx";
            status = "okay";
    };
  };
};

After the overlay, the log correctly shows that only the TX is in PIO mode:

[    1.749629] kernel: tegra-gpcdma 2600000.dma-controller: GPC DMA driver register 31 channels
[    1.752081] kernel: serial-tegra 3100000.serial: TX in PIO mode
[    1.752223] kernel: 3100000.serial: ttyTHS1 at MMIO 0x3100000 (irq = 112, base_baud = 0) is a TEGRA_UART

However, trying to read anything fails at any speeds with VPR and context violations:

[  280.749235] arm-smmu 12000000.iommu: Unhandled context fault: fsr=0x402, iova=0x80240000, fsynr=0xf0011, cbfrsynra=0xc04, cb=0
[  280.749389] arm-smmu 12000000.iommu: Unhandled context fault: fsr=0x402, iova=0x80240000, fsynr=0xf0011, cbfrsynra=0xc04, cb=0
[  280.749531] arm-smmu 12000000.iommu: Unhandled context fault: fsr=0x402, iova=0x80240000, fsynr=0xf0011, cbfrsynra=0xc04, cb=0
[  280.749671] arm-smmu 12000000.iommu: Unhandled context fault: fsr=0x402, iova=0x80240000, fsynr=0xf0011, cbfrsynra=0xc04, cb=0
[  280.749811] arm-smmu 12000000.iommu: Unhandled context fault: fsr=0x402, iova=0x80240000, fsynr=0xf0011, cbfrsynra=0xc04, cb=0
[  280.749951] arm-smmu 12000000.iommu: Unhandled context fault: fsr=0x402, iova=0x80240000, fsynr=0xf0011, cbfrsynra=0xc04, cb=0
[  280.750091] arm-smmu 12000000.iommu: Unhandled context fault: fsr=0x402, iova=0x80240040, fsynr=0xf0011, cbfrsynra=0xc04, cb=0
[  280.750231] arm-smmu 12000000.iommu: Unhandled context fault: fsr=0x402, iova=0x80240040, fsynr=0xf0011, cbfrsynra=0xc04, cb=0
[  280.750370] arm-smmu 12000000.iommu: Unhandled context fault: fsr=0x402, iova=0x80240040, fsynr=0xf0011, cbfrsynra=0xc04, cb=0
[  280.750506] arm-smmu 12000000.iommu: Unhandled context fault: fsr=0x402, iova=0x80240040, fsynr=0xf0011, cbfrsynra=0xc04, cb=0
[  280.751564] tegra-mc 2c00000.memory-controller: unknown: secure write @0x00000003ffffff00: VPR violation ((null))
[  281.894265] tegra-mc 2c00000.memory-controller: unknown: secure write @0x00000003ffffff00: VPR violation ((null))
[  282.425979] tegra-mc 2c00000.memory-controller: unknown: secure write @0x00000003ffffff00: VPR violation ((null))
[  282.577129] tegra-mc 2c00000.memory-controller: unknown: secure write @0x00000003ffffff00: VPR violation ((null))
[  283.404896] tegra-mc 2c00000.memory-controller: unknown: secure write @0x00000003ffffff00: VPR violation ((null))
[  283.407241] tegra-mc 2c00000.memory-controller: unknown: secure write @0x00000003ffffff00: VPR violation ((null))
[  283.411772] tegra-mc 2c00000.memory-controller: unknown: secure write @0x00000003ffffff00: VPR violation ((null))
[  283.414054] tegra-mc 2c00000.memory-controller: unknown: secure write @0x00000003ffffff00: VPR violation ((null))
[  283.416328] tegra-mc 2c00000.memory-controller: unknown: secure write @0x00000003ffffff00: VPR violation ((null))
[  283.420859] tegra-mc 2c00000.memory-controller: unknown: secure write @0x00000003ffffff00: VPR violation ((null))

Can someone please help provide the proper way to configure UARTA for DMA? Only RX is fine, but I can’t seem to get it to work reliably.

Hi ryan65,

It is the expected result that it will run in PIO mode if the dma settings removed from device tree.

In JP6, it seems uarta(serial@3100000) is running in PIO mode by default.
You can try to modify the following lines in device tree to configure it as DMA mode.

                serial@3100000 {
                        compatible = "nvidia,tegra194-hsuart";
                        reg = <0x00 0x3100000 0x00 0x10000>;
                        interrupts = <0x00 0x70 0x04>;
                        clocks = <0x03 0x9b>;
                        resets = <0x03 0x64>;
+                       dmas = <0xed 0x8 0xed 0x8>;
+                       dma-names = "rx\0tx";
                        status = "okay";
                        reset-names = "serial";
                        phandle = <0x21f>;
                };

The phandle in your block for the dmas points to the usb lane 2 in the padctl controller, which throws errors when I try to use the DMA pointing to there.

The DMA controller is at :

dma-controller@2600000 {
                        phandle = <0xdf>;
                };

In any case, when pointing to the GPCDMA controller, the channel is allocated successfully, but throws the errors shown in my original post with memory access failures.

The effective DTB I’m using already matches what you provided except the dmas points to the gpcdma controller:

  serial@3100000 {
                        dma-names = "rx\0tx";
                        dmas = <0xdf 0x08 0xdf 0x08>;
                        compatible = "nvidia,tegra194-hsuart";
                        reg = <0x00 0x3100000 0x00 0x10000>;
                        interrupts = <0x00 0x70 0x04>;
                        clocks = <0x03 0x9b>;
                        resets = <0x03 0x64>;
                        status = "okay";
                        reset-names = "serial";
                        phandle = <0x1fc>;
                };

Is the reason the default doesn’t come with DMA anymore because with JP6 it broke the serial DMA transfer?

You can ignore the value of phandle in my case.

I’ve confirmed the patch working on my local Orin Nano devkit to run UART with DMA enabled.

Hey Kevin,

Did you confirm you’re able to transmit data once the DMA is enabled?

Yes, it should work as expected after enabling DMA for UART.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.

Please also add iommus attribute in this node as following to get UART DMA work.

                serial@3100000 {
                        compatible = "nvidia,tegra194-hsuart";
                        reg = <0x00 0x3100000 0x00 0x10000>;
                        interrupts = <0x00 0x70 0x04>;
                        clocks = <0x03 0x9b>;
                        resets = <0x03 0x64>;
+                       dmas = <0xed 0x8 0xed 0x8>;
+                       dma-names = "rx\0tx";
+                       iommus = <&smmu_niso0 TEGRA234_SID_GPCDMA>;
                        status = "okay";
                        reset-names = "serial";
                        phandle = <0x21f>;
                };