How to use USB0 as OTG in Device and Host Mode without changing device tree after flashing?

I would like to make a device tree where USB0 will function as a Device when the micro USB is plugged in, then as a host when the cable is not plugged in. I have a device on the board that I would like connected to the Jetson when the micro USB is not connected.

I know this question has been asked before but there hasn’t been an answer for dynamic device/host.

I see there exists some device tree logic with “vbus_excon” in other Jetson device trees.

Here is the USB device tree I currently have. USB0 only functions as a device. If I change OTG to HOST it works as a host but I am unable to flash the SSD. If I leave it as OTG, I can flash the SSD but not connect to my downstream device.

	xusb_padctl: xusb_padctl@3520000 {
		status = "okay";
		pads {
			usb2 {
				lanes {
					usb2-0 {
						nvidia,function = "xusb";
						status = "okay";
					};
					usb2-1 {
						nvidia,function = "xusb";
						status = "okay";
					};
					usb2-2 {
						nvidia,function = "xusb";
						status = "okay";
					};
				};
			};
			usb3 {
				lanes {
					usb3-0 {
						nvidia,function = "xusb";
						status = "okay";
					};
					usb3-1 {
						nvidia,function = "xusb";
						status = "okay";
					};
					usb3-2 {
						nvidia,function = "xusb";
						status = "okay";
					};					
				};
			};
		};

		ports {
			usb2-0 {/* Goes to recovery port when micro usb connected, otherwise goes to Pixhawk */
				mode = "otg";
				status = "okay";
				vbus-supply = <&p3768_vdd_5v_sys>;
				usb-role-switch;
				connector {
					compatible = "usb-b-connector", "gpio-usb-b-connector";
 					label = "micro-USB";
 					type = "micro";
 					vbus-gpio = <&tegra_main_gpio TEGRA234_MAIN_GPIO(Z, 1) GPIO_ACTIVE_LOW>;
 				};
				// port {
				// 	typec_p0: endpoint {
				// 		remote-endpoint = <&fusb_p0>;
				// 	};
				// };
			};
			usb2-1 {/* Goes to hub */
				mode = "host";
				vbus-supply = <&p3768_vdd_av10_hub>;
				status = "okay";
			};
			usb2-2 {/* Goes to Single USB A Port */
				mode = "host";
				vbus-supply = <&p3768_vdd_5v_sys>;
				status = "okay";
			};
			usb3-0 {/* Goes to Single USB A Port */
				nvidia,usb2-companion = <2>;
				status = "okay";
			};
			usb3-1 {/* Goes to Dual USB A Port (USB 2 comes from Hub)*/
				nvidia,usb2-companion = <1>;
				status = "okay";
			};
			usb3-2 {/* Goes to Dual USB A Port (USB 2 comes from Hub)*/
				nvidia,usb2-companion = <1>;
				status = "okay";
			};
		};
	};

	tegra_xudc: xudc@3550000 {
		status = "okay";
		phys = <&{/xusb_padctl@3520000/pads/usb2/lanes/usb2-0}>;
		phy-names = "usb2-0";
		nvidia,xusb-padctl = <&xusb_padctl>;
	};

	tegra_xhci: xhci@3610000 {
		status = "okay";
		phys = <&{/xusb_padctl@3520000/pads/usb2/lanes/usb2-0}>,
			<&{/xusb_padctl@3520000/pads/usb2/lanes/usb2-1}>,
			<&{/xusb_padctl@3520000/pads/usb2/lanes/usb2-2}>,
			<&{/xusb_padctl@3520000/pads/usb3/lanes/usb3-0}>,
			<&{/xusb_padctl@3520000/pads/usb3/lanes/usb3-1}>,
			<&{/xusb_padctl@3520000/pads/usb3/lanes/usb3-2}>;
		phy-names = "usb2-0", "usb2-1", "usb2-2", "usb3-0", "usb3-1", "usb3-2";
		nvidia,xusb-padctl = <&xusb_padctl>;
	};

Here is the schematic. I don’t have the USB C controller, just the VBUS DET GPIO.



image

Hi,

Actually this is kind of question that got asked almost every week.

You need to change device tree if your hardware is different from the NV devkit.

The concern here is I am not sure about that usb mux. And your usb2-0 vbus-supply may need update. For example, you should give a regulator which has your GPIO0 as EN on/off.

Another error is I saw you have 2 usb3 port setting companion with same usb2. It is wrong.
The usb2 should be the one from jetson side. Not the downport from the hub.

I see this question has been asked for the Orin NX/Nano but the only answers have been to manually change the device tree binary after flashing to fix USB0 as a host. No answer with dynamic switching.

Yes I have changed the device tree and posted it here.

The device that is on the same carrier doesn’t need VBUS switched. It is self powered.

My USB architecture is working overall with the Hub and USB3. No issues there.

All I want to do is change the state of USB0 from a Device to Host based on the state of GPIO0.

Hi,

I don’t know what kind of answers you searched.

The document is over here. The method to configure as OTG port is also here.
https://docs.nvidia.com/jetson/archives/r35.3.1/DeveloperGuide/text/HR/JetsonModuleAdaptationAndBringUp/JetsonAgxOrinSeries.html?highlight=universal#porting-the-universal-serial-bus

BTW, if you are happy with those USB A design, then be it. This is totally your choice.

But just a reminder that our usb driver cannot support your design on that Dual usb A well. It may hit issue one day. Most of such kind of cases could be downgrade to usb2 speed only.

Our driver only controls each USB2 ports separately but your case will have USB1 to control multiple ports all at once.

Reading through that document its not clear how to configure OTG for dual mode using a GPIO in TEGRA_XUSB_DT_VERSION >= DT_VERSION_3. All the examples are for earlier than DT_VERSION_3.

Okay this is mostly working how I want. On boot without micro USB connected, the port is a Host. When I plug in the cable, it switches to a Device. However, when I unplug the cable, it doesn’t go back to Host mode, just stays disabled. “l4tbr0: port 2(usb0) entered disabled state”

[   18.021897] l4tbr0: port 2(usb0) entered blocking state
[   18.021919] l4tbr0: port 2(usb0) entered disabled state
[   18.022117] device usb0 entered promiscuous mode
[   26.944466] usb 1-1: new full-speed USB device number 4 using tegra-xusb
[   27.098237] usb 1-1: New USB device found, idVendor=3185, idProduct=0039, bcdDevice= 1.01
[   27.098248] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[   27.098250] usb 1-1: Product: ARK FMU v6X.x
[   27.098252] usb 1-1: Manufacturer: ARK
[   27.098253] usb 1-1: SerialNumber: 0
[   27.298732] usbcore: registered new interface driver cdc_acm
[  116.433467] usb 1-1: USB disconnect, device number 4
[  116.434574] tegra-xusb 3610000.xhci: WARN Set TR Deq Ptr cmd failed due to incorrect slot or ep state.
[  116.444393] tegra-xusb 3610000.xhci: WARN Set TR Deq Ptr cmd failed due to incorrect slot or ep state.
[  116.454204] tegra-xusb 3610000.xhci: WARN Set TR Deq Ptr cmd failed due to incorrect slot or ep state.
[  116.464284] tegra-xusb 3610000.xhci: WARN Set TR Deq Ptr cmd failed due to incorrect slot or ep state.
[  117.609825] IPv6: ADDRCONF(NETDEV_CHANGE): usb0: link becomes ready
[  117.962686] l4tbr0: port 2(usb0) entered blocking state
[  117.962703] l4tbr0: port 2(usb0) entered forwarding state
[  135.613092] l4tbr0: port 2(usb0) entered disabled state

The device tree.

		ports {
			usb2-0 {/* Goes to recovery port when micro usb connected, otherwise goes to Pixhawk */
				mode = "otg";
				status = "okay";
				vbus-supply = <&p3768_vdd_5v_sys>;
				usb-role-switch;
				connector {
					compatible = "usb-b-connector", "gpio-usb-b-connector";
 					label = "micro-USB";
 					type = "micro";
 					//vbus-gpio = <&tegra_main_gpio TEGRA234_MAIN_GPIO(Z, 1) GPIO_ACTIVE_LOW>;
					id-gpio = <&tegra_main_gpio TEGRA234_MAIN_GPIO(Z, 1) GPIO_ACTIVE_LOW>;
					//cable-connected-on-boot = <USB_ROLE_DEVICE>;
 				};
				// port {
				// 	typec_p0: endpoint {
				// 		remote-endpoint = <&fusb_p0>;
				// 	};
				// };
			};
			usb2-1 {/* Goes to hub */
				mode = "host";
				vbus-supply = <&p3768_vdd_av10_hub>;
				status = "okay";
			};
			usb2-2 {/* Goes to Single USB A Port */
				mode = "host";
				vbus-supply = <&p3768_vdd_5v_sys>;
				status = "okay";
			};
			usb3-0 {/* Goes to Single USB A Port */
				nvidia,usb2-companion = <2>;
				status = "okay";
			};
			usb3-1 {/* Goes to Dual USB A Port (USB 2 comes from Hub)*/
				nvidia,usb2-companion = <1>;
				status = "okay";
			};
			usb3-2 {/* Goes to Dual USB A Port (USB 2 comes from Hub)*/
				nvidia,usb2-companion = <1>;
				status = "okay";
			};
		};
	};

	tegra_xudc: xudc@3550000 {
		status = "okay";
		phys = <&{/xusb_padctl@3520000/pads/usb2/lanes/usb2-0}>;
		phy-names = "usb2-0";
		nvidia,xusb-padctl = <&xusb_padctl>;
	};

	tegra_xhci: xhci@3610000 {
		status = "okay";
		phys = <&{/xusb_padctl@3520000/pads/usb2/lanes/usb2-0}>,
			<&{/xusb_padctl@3520000/pads/usb2/lanes/usb2-1}>,
			<&{/xusb_padctl@3520000/pads/usb2/lanes/usb2-2}>,
			<&{/xusb_padctl@3520000/pads/usb3/lanes/usb3-0}>,
			<&{/xusb_padctl@3520000/pads/usb3/lanes/usb3-1}>,
			<&{/xusb_padctl@3520000/pads/usb3/lanes/usb3-2}>;
		phy-names = "usb2-0", "usb2-1", "usb2-2", "usb3-0", "usb3-1", "usb3-2";
		nvidia,xusb-padctl = <&xusb_padctl>;
	};

Hi,

However, when I unplug the cable, it doesn’t go back to Host mode, just stays disabled. “l4tbr0: port 2(usb0) entered disabled state”

You need to plug another usb device so that it will go into host mode…

There are actually device, none and host modes there. 3 states but not only 2.

The other device is plugged in already when the cable is disconnected. Shouldn’t the usb port enter promiscuous state?

Does your hardware design only have id pin but does not have vbus det?

Just the one gpio that goes low when the micro USB is connected.

As the document mentioned. OTG can only work fine when both GPIOs are present in the design.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.