Modifying uboot of Jetson TX2 to enable additional UART for serial interface

I want to modify the U-Boot code to enable UART2 (the one in J17 header) to do perform some serial interfacing with a peripheral device during the booting process. I found some discussion on the topic, but most of them are about enabling an alternate uart for debug console. I want it to behave like a normal serial port.

The discussions in the links [1] and [2] points to the steps for enabling an alternate debug port.

Can some body guide me with the steps needed to enable an additional uart during U-boot. I have been struggling with this over a week and would be eager to get any inputs.

Please answer the relevant questions below.

  1. I understand that I need to enable the UART2 on the device tree. But there is only one serial port mentioned in the device tree file after decompiling.
    /Linux_for_Tegra/sources/u-boot/arch/arm/dts/tegra186-p2771-0000-500.dtb
    Is this file right and what additional information should be added to this?
serial@3100000 {
		compatible = "nvidia,tegra186-uart", "nvidia,tegra20-uart";
		reg = <0x0 0x3100000 0x0 0x10000>;
		reg-shift = <0x2>;
		status = "disabled";
	};
  1. Are there any changes that I need to do in the file Linux_for_Tegra/p2771-0000.conf.common file? According to [2], I can see a line related to the serial console here.
    CMDLINE_ADD=“console=ttyS0,115200n8 console=tty0 fbcon=map:0 net.ifnames=0”

  2. According to [1] the below file needs to be modified. Does it apply to my case?
    Linux_for_Tegra/bootloader/tegra186-mb1-bct-misc-si-l4t.cfg

  3. Sending and receiving data through a serial port would need the getc, putc functions to be defined for the serial port. Where to define it for the additional serial port UART2 that is enabled? For example, if I have to use UART2 in u-boot/common/autoboot.c file, how should I access the port?

[1] https://devtalk.nvidia.com/default/topic/1025894/jetson-tx2/uart1-acts-as-default-debug-port-on-tx2-r28-1/post/5220368/#5220368

[2] https://devtalk.nvidia.com/default/topic/1031764/jetson-tx1/in-uboot-initing-stage-of-tx1-can-uartb-j17-be-enabled-and-rx-tx-data-while-uarta-j21-using-as-console-cmdline-/post/5249294/?offset=3#

hello vinmeen,

you should use UART-1 on J17 — pin 5 is Tx, pin 4 is Rx. please also refer to Topic 1058564 for reference.
thanks

The link you provided provides general guidance to use uart on J17 header. After booting up ubuntu, I have been able to successfully access the uart on J17. But my question is about using the uart on J17 during the booting process. I want to modify the u-boot code to accept booting options through this uart. Please guide me with steps to enable additional uart during booting process.

I couldn’t tell you the base address of the UART 1 serial controller, but basically you would need the same device tree you mentioned for address “serial@3100000”…only adjust the base address. Earlier boot stages will read the device tree and should make the UART available if this is in place. Sorry, I don’t know the address for the specific controller.

Hi linuxdev,

  1. In case I get the base address right, is that the only change I need to make? I mean, is this
    /Linux_for_Tegra/sources/u-boot/arch/arm/dts/tegra186-p2771-0000-500.dtb
    the only file I need to modify?

  2. How and where to define the getc and putc functions for accessing the additional uart? for example, currently the getc, putc, printf functions are printing into the uart0 (debug port).

could you please help me with the procedure to enable the additional serial interface in u-boot? That will help me research for more specific details like addresses to get it working.

Someone else may know specific addresses, I am just going through how to think about it below since I cannot say what specific addresses are used.

— Device Tree “Stuff” —

I do not have a saved copy of a flash to say for sure which file, but if you modify that (and preferably keep a pristine copy), then you’ll know right away after first boot simply by decompiling from the running Jetson and seeing if your changes are present. To decompile on the Jetson:

sudo apt-get install device-tree-compiler
dtc -I fs -O dts -o extracted.dts /proc/device-tree

In the original I see:

status = "<b>disabled</b>";

…which would need to be:

status = "<b>okay</b>";

If that base address is for the correct UART, then you’d just need to set it to “okay”. If the base address for your controller is different, then you would need to duplicate that entire block, edit to the new base address, and then set that to “okay”.

— General UART “Stuff” —

Sorry, I can’t answer the specific addresses for using the UART directly. What follows might help as a rule of thumb “theme”.

“getc” and “putc” are just aliases to “fgetc” and “fputc” to the stdio I/O file descriptors. File descriptors are in turn addresses. If this were a full operating system, then this would be a virtual address (given with fopen) when outside of the kernel, or a physical address on bare metal (kernel and bootloader qualify as bare metal). Serial console and other uses of UARTs do not really care if someone is monitoring that file descriptor (address) as a terminal, or as some third party hardware. Anything you find related to serial console applies to other uses as well so long as the address being written to or read from is to the correct controller address.

If you examine the device tree you will see the “compatible” line. This is a comma delimited set of drivers which the hardware can work with. Anything with “hs” in the name is the direct DMA access driver, and U-Boot does not support this; the other drivers can be found in U-Boot. Continuity of service when changing control via U-Boot to the Linux kernel occurs if the driver actually used does not change (changing the driver requires resetting the UART). A recursive grep for shows you might have some interest in these files:

drivers/serial/ns16550.c
doc/device-tree-bindings/serial/8250.txt

In some cases you might find the old “COM1” through “COM4” designations. An interesting search is from “drivers/serial/”:

egrep -R COM1 * | egrep -i '(8250|16550|nvidia|tegra)'

(like stdio, a COM# port is just a physical address in the end, and that address is labeled as something like “COM1”)

This points hints at:

drivers/serial/serial_ns16550.c

You’ll note some defines are being typecast, and although I have not looked at it, I suspect each of those typecast CONFIG_SYS_… are the addresses from the TRM for those specific chipsets. Somewhere in that mess is likely an “nvidia,tegra…-uart” combination of base address and offset…base address from the device tree, offset from the TRM. There are probably other #define abstractions in there, but in the end it is all just an address.