Application use of USB0 vs forced recovery


we have made a custom PCB for the TX2 where USB0 is supposed to be used as a general-purpose USB 2.0 Host. I see that the development board uses USB1 for a similar purpose. Our aim is to reduce the number of USB plugs exposed in the casing of the finished product. We will need both recovery and GP-USB.

Is it recommended to use USB0 for general purposes in our application, or should we leave it alone and only use it for forced recovery?

If we may use it as a general purpose USB 2.0 Host, which files should we edit to enable it? What is the best place to define the standard class drivers we want?

While in forced recovery, does the TX2 appear as a USB Device (which may be given an image file by a computer) or as a USB Host (which may fetch an image file from connected storage)?


I can’t answer regarding specific ports, but in recovery mode the Jetson is a custom USB device. The driver package used in flashing is the only software which understands a recovery mode Jetson (JetPack/SDK Manager downloads the driver package and sample rootfs, followed by acting as a front end to the driver package).

Note that unless a USB connector supports device mode use of a connector for flash will fail. The micro-OTG connector is actually capable of being used as a type-A connector (as a host) or a type-B connector (as a device) when the ID detect pin is used correctly. Other type-A connectors tend to not have the wiring to act as type-B.


My plan is to use USB0 as a fully functional USB2.0 OTG port in the application. I will use a micro-AB receptacle and connect the ID pin.

Judging from your advice I should be able then to have the TX2 system appear purely as a device during recovery mode, and as either host or device (depending on the ID pin) while running the application. In order to connect devices to it I guess I’ll need to use a micro-B OTG adapter.

With this machinery in place there shouldn’t be anything standing in the way for using USB2.0 OTG on the USB0 port in the application. Or should it? I just don’t want to risk bricking the TX2 module and make it non-programmable.

Do you know where I configure USB0 in my Linux build?

On a general note, how hard is it to have a bootloader work over the HID class drivers? It may be slower but field upgrades, particularly by unskilled users, is orders of magnitude easier.


This should work so far as the OTG connector and switching between device mode and host mode goes. If this is wired differently from the dev kit, then you’ll still need device tree edits, but this USB connector design and use is valid.

I couldn’t tell you about the specific USB0 wiring/device tree edits, someone else will need to provide those details.

The bootloader in more recent releases does not support simple boot on external drives (I’ll add later on why I mention this, but I am assuming you are updating the Jetson and drives the following comments). This is a somewhat complicated history, but the gist is that embedded systems do not have their own BIOS/UEFI. This means much boot support is added via extra partitions, and that those partitions are used during boot as something of a substitute. These must remain on the eMMC even though the rootfs partition can be migrated. Often the rootfs release is tied to the other partitions and likely mixing rootfs releases and other partition releases will fail.

HID class (Human Interface Device) is only for keyboard/mouse style input devices. If extlinux configuration were used, then this would be fine for interacting/picking U-Boot options, but now U-Boot may not do everything it used to do…much of what U-Boot uses as options or input starting data is from those extra partitions, and sometimes prior boot stages edit the data (U-Boot does not directly read those partitions…previous boot stages will instead pass this data on to U-Boot, e.g., device tree from an extlinux.conf specification is no longer used). I’ll assume that maybe you are interested in external boot over USB with USB mass storage as a method of doing flash or updates.

Another complication is that many of these partitions are now signed, and so unless you have the correct signing done, and unless the partitions still fit without becoming too large, then you can’t just do a “dd” style partition overwrite (which is probably what you wanted to do if booting from an external drive). You can use the flash software and create signed files which can then be installed via dd, but it would get more complicated if the partition size was too large (which would mean you’d have to shift partitions around).

The final issue is that any flash software does not run on arm64/aarch64 architecture…the executable behind requires a desktop PC architecture under Linux (such as for interacting with a device mode Jetson or for creating signed partitions). So in order to “self flash” one would have to give up on flash software and understand the process well enough to sign and overwrite partitions while the Jetson is running on your external hard drive (which I assume is why you asked…I could be wrong though and maybe you are not wanting to flash via boot from an external disk).

Keep in mind that if boot partitions are not installed correctly, then the unit will no longer boot and the only way to fix the issue is via flash software while the unit is in recovery mode and attached to a Linux PC. If power were lost, or if the update were interrupted, the unit would require actual flash.

By far the simplest way to do updates is via a Linux laptop while the unit is in recovery mode. Saving prior data once more complicates things.

Better answers can probably be provided if you give exact details of what you are working with and what you wish to accomplish.

My experience is from much simpler devices than the TX2, and from Linux on PC quite a while back.

The benefit of the USB HID class is that you can declare a very “strange” HID device which the USB class driver will accept and which can then be accessed by a user-mode program which is aware of the device’s “strangeness”. That way there is no need for a driver installation, only a user mode program. (I sell an AVR32 based device where the driver install is what prevents my users from upgrading the software.) So having HID as the protocol layer would be helpful.

But back on topic: I appreciate your comments! Where should I start searching in order to add USB0 to my device tree?


The documentation at the download URL will help:

This is specific to the TX2 (this is the above URL with search limited to TX2):$product,jetson_tx2

In particular, the PINMUX spreadsheet has macros which help to set up various pins. Device trees can be set up this way (search for “pinmux”). There are other ways to work with the device tree, but the PINMUX spreadsheet macros might provide a better overview (editing a device tree by hand is not an issue, but the spreadsheet might prevent some errors if you are building a completely new carrier board).

Here is a URL you will want to see, the “Adaptation and Bring-Up Guide”:

This latter URL is for the guide which will probably be the first thing you’ll want to read.


Now the thing which we keep smashing our heads into again and again are the I2C devices which are present on the dev-kit but not needed in our product.

While not strictly USB-centric, the U28 and U29 I2C IO expanders are on the dev kit and thereby deeply embedded in all device trees we have seen. Just not the pinmux document.

We will now halt our bring-up process and make a second board with dummy I2C IO expanders so that we can at least boot OS images that require them.

<This is for all of you googling U28, U29, I2C IO expander, TCA9539PWR, TCA9539 with Nvidia Tegra TX2 :>

The IO expanders add $3-ish to the manufacturing cost of the finished product, but until we sell tens of thousands, money is better spent just having them stick around in our product than spending the time it takes to design them out of device trees, drivers and source code. The Linux varieties you find for the TX2 are aren’t ports for the TX2 module, they are ports for the TX2 development kit INCLUDING AND NEVER OMITTING the I2C IO expanders.

<This is for all of you expecting Atmel-style documentation where board signal name, device IO pin, base address, .h style #define file and .c example code are on the same page of Nvidia’s documentation :>

Winter has come. You are alone.


I couldn’t tell you what the specific base address is for the i2c controller you are looking to disable, but in the device tree you will see a number of “i2c@some_hex_address” entries. For an enabled controller you will see an entry like this:

status = "okay";

If you change this to “disabled”, then the controller will be ignored:

status = "disabled";

The trick is that someone other than myself will need to tell you which i2c base address corresponds to those pins.