NVIDIA Jetson AGX Orin: UART Passthrough

This document describes the UART passthrough implementations on the NVIDIA Jetson AGX Orin board. The goal of this document is to guide more complex devices passthrough implementations.

UART Connections

There are eight UART units in the System on Chip (SoC) and two Server Base System Architecture (SBSA) UART units:

  • The SoC UART units are named with an alphabetical suffix:
    • UARTA, UARTB, UARTC, UARTD, UARTE, UARTF, UARTG, UARTH (which may be referred to as UART1, UART2, UART3, UART4, UART5, UART6, UART7, and UART8).
  • The SBRA UART units are named UARTI and UARTJ. These units are pin-muxed with the UARTE and UARTC respectively.

The following table describes the UART units mapping and connections:

Device tree def.CPU pinSoC pinConnected to
uarta: serial@3100000UART1UART140 pin header 3v3
uartb: serial@3110000UART2UART5M.2 key E (WiFi card)
uartc: serial@c280000UART3UART3USB Debug ttyACM0
uartd: serial@3130000UART4UART4Camera connector
uarte: serial@3140000Not mapped
uartf: serial@3150000Not mapped
uartg: not on dtbUART7UART7Optional, USB Debug ttyACM1
uarth: serial@3170000Not mapped
uarti: serial@31d0000UART5UART2USB Debug ttyACM1
uartj: serial@c270000Not mapped

Notes:

  • The first column shows how the UART units are defined in the UART device tree file tegra234-soc-uart.dtsi 1.
  • The second and third columns show the CPU and SoC pin connections. Note that for UART2 and UART5 these are swapped. The pin mapping configuration is described in the file tegra234-mb1-bct-pinmux-p3701-0000.dtsi 2. This device tree file is automatically generated by the macro Excel file Jetson_AGX_Orin_Series_Pinmux_Config_Template_1.5.xlsm which is available at the official Jetson Download Center as the Jetson AGX Orin Series Pinmux.
  • The last column describes where the UART units are connected to the exterior.

Only two UART units are connected to the micro USB debug interface. The UART7 is not connected by default but it can be connected to the debug interface ttyACM1 by swapping the fuse resistors (see Debug MCU page 7 on P3737_A04_Concept_schematics.pdf 3).

UARTI Selected for Passthrough

The UARTI unit was selected to do the first "Hello world" passthrough implementation as it does not show any dependencies on its device tree:

	uarti: serial@31d0000 {
		compatible = "arm,sbsa-uart";
		reg = <0x0 0x31d0000 0x0 0x10000>;
		interrupts = <0x0 TEGRA234_IRQ_UARTI 0x04>;
		current-speed = <115200>;
		status = "disabled";
	};

Host Device Tree

To prepare the UARTI on the host for the passthrough:

  1. Modify the UARTI node in the tegra234-soc-uart.dtsi device tree file 1:

    • compatible: put a dummy driver associated to this node so that the kernel will not bind any driver to this UART unit.
    • iommus: add the iommus field with the test stream ID TEGRA_SID_NISO1_SMMU_TEST which by default is not used by any other device.
    	uarti: serial@31d0000 {
    		compatible = "arm,dummy";
    		iommus = <&smmu_niso0 TEGRA_SID_NISO1_SMMU_TEST>;
    		reg = <0x0 0x31d0000 0x0 0x10000>;
    		interrupts = <0x0 TEGRA234_IRQ_UARTI 0x04>;
    		current-speed = <115200>;
    		status = "disabled";
    	};
    
  2. Include the modifications, compile the kernel to update the output DTB, and then flash it to the internal eMMC device tree A and B partitions with the following command:

    dd if=./arch/arm64/boot/dts/nvidia/tegra234-p3701-0000-p3737-0000.dtb of=/dev/mmcblk0p3
    dd if=./arch/arm64/boot/dts/nvidia/tegra234-p3701-0000-p3737-0000.dtb of=/dev/mmcblk0p6
    

Guest Device Tree

The guest device tree is based on the device tree extracted from QEMU VM.

To get the base QEMU device tree, run the following command:

qemu-system-aarch64 -machine virt,accel=kvm,dumpdtb=virt.dtb -cpu host

Add the passthrough devices inside the platform node to this device tree:

	platform@c000000 {
		interrupt-parent = <0x8001>;
		ranges = <0xc000000 0x00 0xc000000 0x2000000>;
		#address-cells = <0x01>;
		#size-cells = <0x01>;
		compatible = "qemu,platform\0simple-bus";

		uarti: serial@c000000 {
		    compatible = "arm,sbsa-uart";
		    current-speed = <0x1c200>;
		    interrupts = <0x00 0x70 0x04>;
		    reg = <0x0c000000 0x10000>;
		    status = "okay";
        	};
	};

In this example, the uarti node was added to the platform node. For this node the interrupt number was replaced to 0x70 and reg address to the one that was obtained from the QEMU monitor command: info mtree -f.

Starting Guest VM

To start the guest VM:

  1. Bind the UARTI to the VFIO driver:

    echo vfio-platform > /sys/bus/platform/devices/31d0000.serial/driver_override
    echo 31d0000.serial > /sys/bus/platform/drivers/vfio-platform/bind
    

    The VFIO gives the user-level an access to the devices, in this case, QEMU.

  2. Connect the NVIDIA Jetson AGX Orin Debug USB to your PC and open the serial port ttyACM1 at 115200 bps. You can use picocom with the next command:

    picocom -b 115200 /dev/ttyACM1
    
  3. Run the guest VM with the following QEMU command:

    qemu-system-aarch64 \
        -nographic \
        -machine virt,accel=kvm \
        -cpu host \
        -m 1024 \
        -no-reboot \
        -kernel Image \
        -drive file=focal-server-cloudimg-arm64.raw,if=virtio,format=raw \
        -device vfio-platform,host=31d0000.serial\
        -dtb uart.dtb \
        -append "rootwait root=/dev/vda1 console=ttyAMA0"
    

When the guest VM is launched you can see the VM Linux command line in the opened ttyACM1 terminal.

1

kernel_src/hardware/nvidia/soc/t23x/kernel-dts/tegra234-soc/tegra234-soc-uart.dtsi

2

bootloader/t186ref/BCT/tegra234-mb1-bct-pinmux-p3701-0000.dtsi available in the BSP sources on: https://developer.nvidia.com/embedded/jetson-linux-r3521

3

Jetson_AGX_Orin_DevKit_Carrier_Board_Design_Files_A04_20221003/P3737_A04_Concept_schematics.pdf available in https://developer.nvidia.com/jetson-agx-orin-developer-kit-carrier-board-design-files-a04