Feedback on Experimental UEFI Firmware

@jonathanh Just a follow-up to serial/uart usage. After much investigation I’ve realized that there are no UARTs other than serial@3100000 that can be mapped to pins on the 40-pin header. Since we can’t use that one or the TCU port for general use, we’re kinda stuck with no serial ports.

For my GPS case, I’ve had to connect it via I2C, write a userspace program to interface to the I2C bus and pipe the result to socat to create a pty. Not exactly a good way going forward.

So, any thoughts on being able to free up that serial port and using the TCU for UEFI/boot?

Hello!

If you are using device-tree and not ACPI then you should be able to use the TCU. You just need to add ‘console=ttyTCU0,115200n8’ to the kernel command line. I believe that should work.

Regards,
Jon

No because before the kernel is even loaded, both the TCU and uart are being used by UEFI. The GPS not only gets confused by the output to the TCU, it’s error responses confuse UEFI.

Ah I see. Yes there is no simple way to get around that at the moment. It could be possible to disable the output enable for the serial port so that UEFI does not drive it, but then we would need a means to re-enable it again later on. Is there no way to keep the GPS in reset until you are ready to use it?

Sure there are ways to get around it. One of my options was to keep the GPS reset until a GPIO goes high but then the GPS would have to re-establish a lock every time. Another option was to use a buffer on the TX/RX lines and enable/disable that with a GPIO. Maybe I could also use 2 GPIOs to pull the TX and RX lines low and change them to high-z after the kernel boots. :) None of them are long-term solutions though and certainly not for the general public who need a uart.

So I have workarounds for now but a solution would need to be found before the UEFI firmware goes GA.

Noted. I can see that this is definitely a use case that was overlooked initially.

Cool! Thanks @jonathanh !

Hey @jonathanh

Where does pinctrl-tegra194 stand on your list of 5.x porting to-dos? I been trying to get gpio-aon pins DD00 and CC07 (pins 27 and 28 on the 40pin header) to work for something other than GEN2_I2C without luck. Then I realized that pinctrl-tegra194.c is only a stub in the 5.x kernels. :)

I’ve got workarounds so I’m really just curious.

thx.

Hello!

To follow up on the above, I believe that there is a simple fix for this. The UEFI bootloader for Jetson AGX Xavier uses the device-tree file in the directory Linux_for_Tegra/kernel/dtb/tegra194-p2972-0000-uefi.dtb. By default this device-tree has the serial port on the 40-pin header enabled …

$ fdtget -t s ./Linux_for_Tegra/kernel/dtb/tegra194-p2972-0000-uefi.dtb /bus@0/serial@3110000 status
okay

However, we can disable this so that UEFI will not use it …

$ fdtput -t s ./Linux_for_Tegra/kernel/dtb/tegra194-p2972-0000-uefi.dtb /bus@0/serial@3110000 status disabled

Now if you re-flash, UEFI will not output on the serial port on the 40-pin. Then to use the serial port on the 40-pin header, when you boot Linux you just need to pass a DTB with the serial-port enabled. For Fedora you can do this via GRUB by setting the ‘devicetree’ keyword in the GRUB config.

Jon

For the NX substitute the correct dtb name or does the firmware for the NX also read the AGX dtb?

Hello!

Unfortunately, I am not aware of any plans to upstream support for any additional pinmux support on Tegra194. Note that today there is only some support for some Tegra194 PCIe pins. So currently the only way to handle this is at flash time by updating the appropriate MB1 files.

Jon

Gotcha, thanks.

For NX, it would be ./Linux_for_Tegra/kernel/dtb/tegra194-p3509-0000+p3668-0000-uefi.dtb. There serial port is also different and so would be …

$ fdtput -t s ./Linux_for_Tegra/kernel/dtb/tegra194-p3509-0000+p3668-0000-uefi.dtb /bus@0/serial@3100000 status disabled

Jon

Yep, just making sure. :)
Will be testing this afternoon.

Unfortunately, while setting status to disabled and flashing bootloader-dtb does disable the port as far as UEFI is concerned, setting it to okay in the dtb grub loads for the kernel doesn’t enable it to actually pass data.

The device does show “okay” in /sys/firmware/devicetree/base/bus@0/serial@3100000 and it is claimed by 8250, no data will flow at all.

One thing I noticed was the different in the serial settings…
When enabled in the bootloader-dtb…

[root@nx1 ~]# setserial -a /dev/ttyS0
/dev/ttyS0, Line 0, UART: undefined, Port: 0x0000, IRQ: 22
	Baud_base: 115124, close_delay: 50, divisor: 0
	closing_wait: 3000
	Flags: spd_normal

[root@nx1 ~]# catsys /sys/class/tty/ttyS0
                     close_delay: 50
                    closing_wait: 3000
                         console: N
                  custom_divisor: 0
                             dev: 4:64
                           flags: 0x39000000
                      iomem_base: 0x3100000
                 iomem_reg_shift: 2
                         io_type: 3
                             irq: 22
                            line: 0
                            port: 0x0
                   rx_trig_bytes: 4
                            type: 20
                         uartclk: 1841984
                          uevent: MAJOR=4
MINOR=64
DEVNAME=ttyS0
                  xmit_fifo_size: 32

Notice the baud_base and uartclk.

Now with it disabled in the bootloader-dtb and re-enabled in the kernel dtb…

[root@nx1 ~]# setserial -a /dev/ttyS0
/dev/ttyS0, Line 0, UART: undefined, Port: 0x0000, IRQ: 22
	Baud_base: 12750000, close_delay: 50, divisor: 0
	closing_wait: 3000
	Flags: spd_normal

[root@nx1 ~]# catsys /sys/class/tty/ttyS0
                     close_delay: 50
                    closing_wait: 3000
                         console: N
                  custom_divisor: 0
                             dev: 4:64
                           flags: 0x39000000
                      iomem_base: 0x3100000
                 iomem_reg_shift: 2
                         io_type: 3
                             irq: 22
                            line: 0
                            port: 0x0
                   rx_trig_bytes: 4
                            type: 20
                         uartclk: 204000000
                          uevent: MAJOR=4
MINOR=64
DEVNAME=ttyS0
                  xmit_fifo_size: 32

Notice how the baud_base and uartclk are different.

I tried setting current-speed = <115200>; in the dtb and while it shows in the of node it seems to be ignored by the driver (8250_tegra maybe).

Ah well. Any other ideas?

I got it working.

In the bootloader-dtb, I’m using the stock tegra194-p3509-0000+p3668-0000-uefi.dtb with just serial@3100000 disabled. For the kernel dtb though, I had to switch serial@3100000 to use the serial-tegra driver (compatible = "nvidia,tegra194-hsuart") and set its alias serial0 = &uarta; instead of the tcu.

[    1.805243] serial-tegra 3100000.serial: RX in PIO mode
[    1.805273] serial-tegra 3100000.serial: TX in PIO mode
[    1.805333] serial-tegra 3100000.serial: Couldn't get the clock
[    4.242637] serial-tegra 3100000.serial: RX in PIO mode
[    4.242789] serial-tegra 3100000.serial: TX in PIO mode
[    4.242974] 3100000.serial: ttyTHS0 at MMIO 0x3100000 (irq = 22, base_baud = 0) is a TEGRA_UART

I do get…

[   81.876862] serial-tegra 3100000.serial: FIFO mode not enable

whenever the port is opened which is odd in that xmit_fifo_size = 32 and the device structure for tegra194 has .fifo_mode_enable_status = true, but maybe that has to do with being in PIO mode instead of DMA mode. Anyway it seems to be working fine for low rate stuff like GPS.

FInal steps…

$ cd <l4t_dir>/kernel/dtb
# Make copies of the stock dtb.
$ cp tegra194-p3509-0000+p3668-0000-uefi.dtb tegra194-p3509-0000+p3668-0000-uefi-stock.dtb
$ cp tegra194-p3509-0000+p3668-0000-uefi.dtb tegra194-p3509-0000+p3668-0000-uefi-kernel.dtb
# Fix up the default dtb for being bootloader-dtb.
$ fdtput -t s  tegra194-p3509-0000+p3668-0000-uefi.dtb /bus@0/serial@3100000 status disabled
# Fix up the kernel-dtb to re-enable it and change the driver.
$ fdtput -t s tegra194-p3509-0000+p3668-0000-uefi-kernel.dtb /bus@0/serial@3100000 status okay
$ fdtput -t s tegra194-p3509-0000+p3668-0000-uefi-kernel.dtb /bus@0/serial@3100000 compatible  "nvidia,tegra194-hsuart"
# Reset the serial0 alias to point to the serial port and not the tcu.
$ fdtput -t s tegra194-p3509-0000+p3668-0000-uefi-kernel.dtb /aliases serial0 /bus@0/serial@3100000

Now copy tegra194-p3509-0000+p3668-0000-uefi-kernel.dtb to the NX and add a devicetree entry in your /boot/loader/entries/ file. While you’re there, change the console entry that currently points to ttyS0 to console=ttyTCU0,115200.

You also need to disable the getty instance for ttyS0 and add one for ttyTCU0…

$ sudo systemctl disable serial-getty@ttyS0
$ sudo systemctl enable serial-getty@ttyTCU0

Now flash the bootloader-dtb.

$ sudo flash.sh --no-systemimg -k bootloader-dtb jetson-xavier-nx-uefi external

When the NX comes back up, ttyTHS0 should be available and free.

Hello!

This appears to be a bug in the kernel that is always printing this message regardless of whether enabling the FIFO was successful or not. If you are building the kernel it would be interesting to see if this message goes away after making the following change …

index 222032792d6c..cd481f7ba8eb 100644
--- a/drivers/tty/serial/serial-tegra.c
+++ b/drivers/tty/serial/serial-tegra.c
@@ -1045,9 +1045,10 @@ static int tegra_uart_hw_init(struct tegra_uart_port *tup)
 
        if (tup->cdata->fifo_mode_enable_status) {
                ret = tegra_uart_wait_fifo_mode_enabled(tup);
-               dev_err(tup->uport.dev, "FIFO mode not enabled\n");
-               if (ret < 0)
+               if (ret < 0) {
+                       dev_err(tup->uport.dev, "FIFO mode not enabled\n");
                        return ret;
+               }

I may post this as a fix for the upstream kernel anyway as it appears to be an obvious issue.

Great work on getting this going, it was on my list to look at a bit closer, so thanks for the update.

Jon

1 Like

I have checked and it appears that we have already fixed this error message internally and so I have posted a patch to fix this in the mainline kernel as well …

https://patchwork.ozlabs.org/project/linux-tegra/patch/20210630094601.136280-1-jonathanh@nvidia.com/

Jon

1 Like

Ha! I was scratching my head over that message because I couldn’t find where fifo_mode_enable_status was being reset to false. I guess that’s because it wasn’t. You’d think my real job wasn’t writing C code. :)

Do you plan to support GPU acceleration in a future experimental release?