USB Load Switches

The command copied from the terminal history:

$ sudo ./flash.sh -r -d ~/jetson_dev/dtb/compiled.dtb jetson-tx1 mmcblk0p1

What device tree was the original source from before modifying/compiling? Is this R28.2 (“head -n 1 /etc/nv_tegra_release”). R28.2 is what JetPack3.2 flashes.

R28.2 it is, yes.

Before modification which device tree source was used originally? E.g., one from the “Linux_for_Tegra/kernel/dtb/” directory? I’m looking to reproduce what you did (though without modifications).

As near as I can tell that should be it. The file at “/boot/dtb/tegra210-jetson-tx1-p2597-2180-a01-devit.dtb” was copied from the Jetson, decompiled, modified, and recompiled.

My experiment is failing. I want to document this now, but have not looked closely yet.

I wanted to be sneaky in case rootfs did get flashed and reduce work. What I did was clone the rootfs. Then I put a file in “/” of the clone via loopback mount to distinctly identify the clone. I put a similar file in “/” of the running TX1 to distinctly identify this file system.

Next I put a copy of my clone in “Linux_for_Tegra/” as file “system.img”, while removing “system.img.raw” from the original flash. If it turns out I reuse the image here, then the flashed image will be a match for the one I already run…except for that marker file I added to distinctly identify source as from the backup clone versus the original.

I verified my original flash (a log from installing R28.2) used the dtb file “kernel/dtb/tegra210-jetson-tx1-p2597-2180-a01-devkit.dtb”. So I ran this command to flash just dtb (and to log it):

<s>sudo ./flash.sh -r -d ./kernel/dtb/tegra210-jetson-tx1-p2597-2180-a01-devkit.dtb jetson-tx1 mmcblk0p1 2>&1 | tee log_dtb-flash_TX1_R28-2.txt</s>
# Corrected:
sudo ./flash.sh -r <b>-k DTB</b> -d ./kernel/dtb/tegra210-jetson-tx1-p2597-2180-a01-devkit.dtb jetson-tx1 mmcblk0p1 2>&1 | tee log_dtb-flash_TX1_R28-2.txt

I received this failure:

[   5.8635 ] 00000004: Filesize is bigger than partition size

Investigation shows this original file is size 449415 bytes. A log from a previous “gdisk -l” shows this for the DTB partition:

Number  Start (sector)    End (sector)  Size       Code  Name
...
  14        30482466        30490657   4.0 MiB     0700  DTB
...

This is a sector count of 8191. At 512 bytes per sector this is 4193792 bytes (about 4MiB). If the command was just filling in the DTB partition there should have been plenty of room (a signature though would increase requirements).

I can verify that the DTB flash command will fail and you won’t be able to boot.
(see corrected command above which has “-k DTB”)

Apparently this does not work with all release versions. I’m reflashing now before I can add anything.

[s]Can someone at NVIDIA confirm if this command is valid for flashing the DTB using the original “kernel/dtb/tegra210-jetson-tx1-p2597-2180-a01-devkit.dtb” file?

sudo ./flash.sh -r -d ./kernel/dtb/tegra210-jetson-tx1-p2597-2180-a01-devkit.dtb jetson-tx1 mmcblk0p1

[/s]

It looks like this is needed:

sudo ./flash.sh -r <b>-k DTB</b> -d ~/jetson_dev/dtb/compiled.dtb jetson-tx1 mmcblk0p1

…even with “-r” the “-k DTB” is still required or it doesn’t know you want to flash only that particular partition.

So I’m testing with:

sudo ./flash.sh -r <b>-k DTB</b> -d ./kernel/dtb/tegra210-jetson-tx1-p2597-2180-a01-devkit.dtb jetson-tx1 mmcblk0p1

I can verify this flashed and booted correctly on my TX1.

Here’s an additional note on this. In the past the GPT partition labels differed between the TX1 and TX2…“DTB” was only for TX2, the TX1 had used “kernel-dtb” instead. At R28.2 they both seem to have unified partition labels and “DTB” is valid for both the TX1 and TX2.

Also, I had got the “-r” command from another post and had not verified by actual flashing…sorry, I should have. I had assumed (and should not have) that naming the device tree file would tell flash.sh to flash device tree…but it does not. You will still need to use “-k DTB”. If partition labels change in the future it will be a good idea to verify you have “DTB” with “sudo gdisk -l /dev/mmcblk0”.

Thanks for the awesome help. I couldn’t find any info about the -k option (sudo find / -iname flash.cfg => no result), but I see how it is used now.

I am still struggling to find a way to control that load switch. It looks like the GPIO should be owned by the xhci-tegra driver. In an #ifdef CONFIG_PM block there are some useful looking static functions, but I can’t find any way to interface with them either directly or indirectly without hacking the kernel driver. It appears that the PMIC supports shutting down USB in suspend mode which is almost exactly what I want, but I seem to be overlooking some critical piece of information. Can anybody give me some pointers on turning off USB power? I want to completely disable the USB port before I put the device to sleep and leave it off until the device is awakened.

I can’t help on the specifics, just advise to check that “/proc/device-tree/” reflects changes you made to know if dtb edits actually participated.

In general it sounds like you need to find out how to have USB manually enter or leave suspend mode (versus auto-suspend). I know how to disable auto-suspend, but I don’t know how to manually force one mode or the other outside of normal system function.

Sorry, I should have been more clear, but the suspend mode I am referring to isn’t the USB suspend, it’s the LP0 sleep mode of the device, I think - power manager suspend.

I think that when the Jetson is sleeping (LP0), USB devices are told to suspend but it will still wake on a change via the PMC sleepwalker monitoring it. While the bus devices are told to suspend, it doesn’t make a difference to me because the USB camera I’m using doesn’t support the USB suspend mode.

This is where I need the PMIC to actually switch off the 5V power bus feeding the USB port to disable the IR LEDs from drawing the battery down and engaging the lower safety limit of the solar charge controller. The xhci-tegra driver seems to enable powergating and it’s defined in the device tree. Is there a way to check which options the default 28.2 kernel was compiled with? If this option was disabled than it makes perfect sense why it behaves the way it does. If it was enabled for the compilation, then my problem is likely in the device tree…

xhci-tegra.c: 244-256

#if IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)
static struct of_device_id tegra_xusba_pd[] = {
	{ .compatible = "nvidia,tegra186-xusba-pd", },
	{ .compatible = "nvidia,tegra210-xusba-pd", },
	{},
};

static struct of_device_id tegra_xusbc_pd[] = {
	{ .compatible = "nvidia,tegra186-xusbc-pd", },
	{ .compatible = "nvidia,tegra210-xusbc-pd", },
	{},
};
#endif

Typically USB ties its modes to the system’s modes. Are you trying to force USB to change differently than the system? Or perhaps trying force the system to a given state in order to get USB to follow? What would you like to see occur and what would you like to trigger that occurrence?

The result I am looking for is the 5V USB power to be off and disabled completely, either under my control or during sleep. If it was under my control, I would immediately put the system to sleep after disabling it anyway. From what follows, I’m fairly certain the xhci-tegra driver is capable of disabling USB completely entering the LP0 sleep via writing “mem” to /sys/power/state.

Here USB and the system mode are different and can be controlled to do different things. And to be clear, the USB suspend mode if I remember correctly is not a hard suspend - some devices may follow the command and others may not suspend. I think mice and keyboards and maybe other human interface devices are the only ones that implement USB suspension. By LP0, I am referring to the system’s low power mode where it disables as much hardware as possible to conserve power via power-gating.

The concept schematic on page 3 gives a diagram of the power tree showing the load switches I want control over, specifically the one feeding the USB 3.0 Type A Connector. On page 6 you will find a pin labeles USB_VBUS_EN1. On page 8 this feeds the enable pin of a USB switch (APL3511CBI-TRG - a power switch designed for USB application). This output is the 5V output of the USB connector. The alternate control point would be the VDD_5V0_IO_SYS but that appears to come straight off a buck converter beyond control of software. So the premise I am working from is that USB_VBUS_EN1, being a GPIO is controllable somewhere.

The TRM defines power-gating as powering-off a partition. 12.6.13 APBDEV_PMC_PWRGATE_TOGGLE_0 is a programmable register that provides three bits to control XUSB A, B, and C, followed by the related clamping register. This is where things start getting fuzzy. For one, my extracted DTS is pointing to the wrong PWRGATE_TOGGLE register (0x14 - 0x16). The kernel source accurately defines it per the TRM (TEGRA210_POWER_DOMAIN_XUSB macros: 0x20 - 0x22 in /dt-bindings/soc/tegra210-powergate.h:37-39).

xhci-tegra.c:2311-2315

#if IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)
	partition_id_xusba = tegra_pd_get_powergate_id(tegra_xusba_pd);
#else
	partition_id_xusba = TEGRA_POWERGATE_XUSBA;
#endif

My kernel has CONFIG_PM_GENERIC_DOMAINS enabled (per /proc/config.gz), so I expect it will be using the incorrect PWRGATE_TOGGLE register bit. The pmc.c file defines a set of TEGRA_POWERGATE_XUSB macros which are accurately labeled per the TRM; however, as noted the kernel is compiled to ignore them and read the configuration from the dtb.

tegra210-soc-power-domain.dsti:124-140; from the kernel source

xusba_pd: xusba-pd {
			compatible = "nvidia,tegra210-xusba-pd";
			#power-domain-cells = <0>;
			partition-id = <TEGRA210_POWER_DOMAIN_XUSBA>; // defined as <s>0x20</s> 20 in src
		};

		xusbb_pd: xusbb-pd {
			compatible = "nvidia,tegra210-xusbb-pd";
			#power-domain-cells = <0>;
			partition-id = <TEGRA210_POWER_DOMAIN_XUSBB>; // defined as <s>0x21</s> 21 in src
		};

		xusbc_pd: xusbc-pd {
			compatible = "nvidia,tegra210-xusbc-pd";
			#power-domain-cells = <0>;
			partition-id = <TEGRA210_POWER_DOMAIN_XUSBC>; // defined as <s>0x22</s> 22 in src
		};

extracted.dts:968-984; the actual values that made it to the .dtb

xusba-pd {
			compatible = "nvidia,tegra210-xusba-pd";
			#power-domain-cells = <0x0>;
			partition-id = <0x14>;
		};

		xusbb-pd {
			compatible = "nvidia,tegra210-xusbb-pd";
			#power-domain-cells = <0x0>;
			partition-id = <0x15>;
		};

		xusbc-pd {
			compatible = "nvidia,tegra210-xusbc-pd";
			#power-domain-cells = <0x0>;
			partition-id = <0x16>;
		};

Looking at the options and what I expect is the driver source, I should be able to modify the .dtb file again with the correct power management registers to achieve the result I want. I suspect that the power gating registers were configured to the CE0, C0NC, and an undefined address to enable the USB wake function to continue working even in LP0…

I’ll be working on this soon and update when I have a chance and confirm what happens when I change the dtb.

Something else that should be mentioned: in flash.sh, there are several “readlink -f ${val}” commands. These will fail if the path passed to them contains spaces. When choosing a path, use underscores instead of spaces.

You are correct that suspend mode does provide a very tiny power to USB…this is part of the standard for USB. It was added for activities such as “wake up” from pressing a keyboard key or moving a mouse.

Someone else will have to suggest how to force USB standby power to actually be power completely off. Realize that this would likely result in re-enumerating devices each time you come back from what would have been a simple suspend. This may not be a problem for your case.

I don’t see a way to limit current on this board. If that is part of the standard, the Jetson module doesn’t seem to have a way to implement that sort of power control over its devices. The power supply can be either switched on or off, and the devices will draw what they will draw. If a device supports suspending itself, it can enter a low power state, otherwise there is no change. I verified this using a usb power meter. The wireless mouse dongle draws ~40 mA. On sleep it draws <10 mA. The USB camera draws ~290 mA, and on sleep it still draws ~290 mA.

I did make a mistake - I read the macro definitions of the POWER_DOMAIN registers as hexadecimal but they were decimal, so the hex representation in the .dsti source is accurate. Changing them to 0x20 etc., leads to disabled USB ports, but it does somewhat prove that it does what I want - those control the USB load switches.

Can anybody with Nvidia chime in and offer some guidance here?

I figured I’d chime in with another semi-related update… After doing a backup and flashing with the suggested command the .dtb hadn’t changed.

<b>Suggested</b> $ sudo ./flash.sh -r -k DTB -d /path/to/new/dtb jetson-tx1 mmcblk0p1

What I did that worked is renamed system.img and system.img.raw and renamed backup.img and backup.img.raw to take their place. Then running the flash script as:

<b>Works</b>
$ sudo ./flash.sh -r -k APP -G backup.img jetson-tx1 mmcblk0p1
$ mv bootloader/system.img bootloader/system.img.bak && mv system.img.raw system.img.raw.bak
$ mv backup.img bootloader/system.img && mv backup.img.raw bootloader system.img.raw
$ sudo ./flash.sh -r -d /path/to/new/dtb jetson-tx1 mmcblk0p1

The output is:

[   1.4027 ] Sending bootloader and pre-requisite binaries
[   1.4050 ] tegrarcm --download ebt cboot.bin 0 0 --download rp1 compiled.dtb 0
[   1.4071 ] Applet version 00.01.0000
[   1.4237 ] Sending ebt
[   1.4242 ] [................................................] 100%
[   1.5127 ] Sending rp1
[   1.5189 ] [................................................] 100%
[   1.6209 ] 
[   1.6210 ] Retrieving storage infomation
[   1.6235 ] tegrarcm --oem platformdetails storage storage_info.bin
[   1.6259 ] Applet version 00.01.0000
[   1.6440 ] Saved platform info in storage_info.bin
[   1.6910 ] 
[   1.6934 ] tegrarcm --boot recovery
[   1.6955 ] Applet version 00.01.0000
[   1.7124 ] 
[   1.7126 ] Flashing the device
[   1.7314 ] tegradevflash --pt flash.xml.bin --storageinfo storage_info.bin --create
[   1.7337 ] Cboot version 00.01.0000
[   2.4504 ] Writing partition GPT with gpt.bin
[   2.4510 ] [................................................] 100%
[   2.4552 ] Writing partition NVC with nvtboot.bin.encrypt
[   5.3189 ] [................................................] 100%
[   5.3340 ] Writing partition APP with system.img
[   5.3671 ] [................................................] 100%
[ 406.4826 ] Writing partition TBC with nvtboot_cpu.bin.encrypt
[ 408.4072 ] [................................................] 100%
[ 408.4646 ] Writing partition EBT with cboot.bin.encrypt
[ 408.4799 ] [................................................] 100%
[ 408.5152 ] Writing partition BPF with bpmp.bin
[ 408.5497 ] [................................................] 100%
[ 408.5679 ] Writing partition WB0 with warmboot.bin.encrypt
[ 408.5797 ] [................................................] 100%
[ 408.5869 ] Writing partition RP1 with compiled.dtb.encrypt
[ 408.5984 ] [................................................] 100%
[ 408.6400 ] Writing partition TOS with tos.img.encrypt
[ 408.6631 ] [................................................] 100%
[ 408.6713 ] Writing partition EKS with eks.img
[ 408.6829 ] [................................................] 100%
[ 408.6898 ] Writing partition BMP with bmp.blob
[ 408.7011 ] [................................................] 100%
[ 409.0542 ] Writing partition LNX with boot.img.encrypt
[ 409.4117 ] [................................................] 100%
[ 409.4537 ] Writing partition DTB with compiled.dtb.encrypt
[ 409.5062 ] [................................................] 100%
[ 409.5815 ] 
[ 409.5968 ] tegradevflash --write BCT P2180_A00_LP4_DSC_204Mhz.bct
[ 409.5990 ] Cboot version 00.01.0000
[ 409.6018 ] Writing partition BCT with P2180_A00_LP4_DSC_204Mhz.bct
[ 409.6027 ] [................................................] 100%
[ 409.7063 ] 
[ 409.7064 ] Flashing completed

[ 409.7066 ] Coldbooting the device
[ 409.7091 ] tegradevflash --reboot coldboot
[ 409.7114 ] Cboot version 00.01.0000
[ 409.7145 ] 
*** The target t210ref has been flashed successfully. ***
Reset the board to boot from internal eMMC.

Lines 18 and 28 both show the .dtb file (or some encrypted derivative?) were flashed to two partitions: DTB and RP1. Compared to the suggested command’s output, where DTB doesn’t appear to be written to:

[   1.5383 ] Sending bootloader and pre-requisite binaries
[   1.5407 ] tegrarcm --download ebt cboot.bin 0 0 --download rp1 compiled.dtb 0
[   1.5429 ] Applet version 00.01.0000
[   1.5650 ] Sending ebt
[   1.5654 ] [................................................] 100%
[   1.6553 ] Sending rp1
[   1.6560 ] [................................................] 100%
[   1.7534 ] 
[   1.7560 ] tegrarcm --boot recovery
[   1.7582 ] Applet version 00.01.0000
[   1.7780 ] 
[   1.7781 ] Writing partition
[   1.7804 ] tegradevflash --write DTB /home/fred/Jetpack/64_TX1/Linux_for_Tegra/bootloader/signed/compiled_sigheader.dtb.encrypt
[   1.7824 ] Cboot version 00.01.0000
[   2.4026 ] Nothing to write
[   2.4026 ] 
[   2.4027 ] Coldbooting the device
[   2.4045 ] tegradevflash --reboot coldboot
[   2.4061 ] Cboot version 00.01.0000
[   2.4087 ] 
*** The [DTB] has been updated successfully. ***

The backup and restore method is time consuming, but it works… I did a quick search in the flash.sh file and it isn’t apparent where the tegradevflash command comes from, so I’m not sure why it isn’t finding the appropriate file to write or what works up to generating that file. As you can see, it completes without informing the user that an error occurred.

Hi Fred_Z,
Please check if it helps by disabling/enabling the regulator:

$ echo disabled >  /sys/class/regulator/regulator.35/state
$ echo enabled >  /sys/class/regulator/regulator.35/state

USB_VBUS_EN1 should be

en_usb_vbus2: regulator@208 {
			compatible = "regulator-fixed-sync";
			reg = <208>;
			regulator-name = "en-usb-vbus2";
			regulator-min-microvolt = <5000000>;
			regulator-max-microvolt = <5000000>;
			gpio = <&gpio TEGRA_GPIO(CC, 5) 0>;
			gpio-open-drain;
			enable-active-high;
		};

It maps to regulator.35:

$ ls -l /sys/class/regulator/
(skip...)
lrwxrwxrwx 1 root root 0 May  3 09:17 regulator.35 -> ../../devices/regulators/regulators:regulator@208/regulator/regulator.35
(...skip)

It is not the function supported by default. Hopefully it helps your case.

Hi Dane,

That works well, it lets me control the USB power without any external hardware. Thanks!

Hi Fred,

Could you please elaborate a bit more on your solution? I am having the same problem with my TX2

https://devtalk.nvidia.com/default/topic/1042460/jetson-tx2/usb-power-control/