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 pin | SoC pin | Connected to |
---|---|---|---|
uarta: serial@3100000 | UART1 | UART1 | 40 pin header 3v3 |
uartb: serial@3110000 | UART2 | UART5 | M.2 key E (WiFi card) |
uartc: serial@c280000 | UART3 | UART3 | USB Debug ttyACM0 |
uartd: serial@3130000 | UART4 | UART4 | Camera connector |
uarte: serial@3140000 | Not mapped | ||
uartf: serial@3150000 | Not mapped | ||
uartg: not on dtb | UART7 | UART7 | Optional, USB Debug ttyACM1 |
uarth: serial@3170000 | Not mapped | ||
uarti: serial@31d0000 | UART5 | UART2 | USB Debug ttyACM1 |
uartj: serial@c270000 | Not mapped |
In this table:
- 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.
note
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:
-
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"; };
-
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 the reg address to the one that was obtained from the QEMU monitor command: info mtree -f.
Starting Guest VM
To start the guest VM:
-
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.
-
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
-
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.
kernel_src/hardware/nvidia/soc/t23x/kernel-dts/tegra234-soc/tegra234-soc-uart.dtsi
bootloader/t186ref/BCT/tegra234-mb1-bct-pinmux-p3701-0000.dtsi available in the BSP sources on: https://developer.nvidia.com/embedded/jetson-linux-r3521
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