cancel
Showing results for 
Search instead for 
Did you mean: 

STM32MP1 - OTG does not switch to host for data mode

KChar.1
Senior

Hey there,

I am trying to troubleshoot the following issue for quite some time now. I am working on an stm32mp157f based board attempting to enable a combination of stusb16xx and USB OTG . The behavior I am expecting to see is that when a usb device is connected to usbphyc_port1 (usb-c) it will get recognized in the same way as if it was on ehci but when a host device is connected to the same port I can trigger a gadget script in udev.rules. My current configuration works as expected for all gadget modes:

 

typec: stusb1600@28 {
		compatible = "st,stusb1600";
		reg = <0x28>;
		interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
		interrupt-parent = <&gpioi>;
		
        vsys-supply = <&vdd_usb>;

		pinctrl-names = "default";
		pinctrl-0 = <&stusb1600_pins_a>;
		status = "okay";
		vdd-supply = <&vin>;

		typec_con: connector {
			compatible = "usb-c-connector";
			label = "USB-C";
			power-role = "dual";
			data-role = "dual";
			typec-power-opmode = "default";
				
			port {
				con_usbotg_hs_ep: endpoint {
					remote-endpoint = <&usbotg_hs_ep>;
				};
			};
		};
	};

&usbotg_hs {
	compatible = "st,stm32mp15-hsotg", "snps,dwc2";
	phys = <&usbphyc_port1 0>;                                                /* 0: UTMI switch selects the OTG controller */
	phy-names = "usb2-phy";
	dr_mode = "otg";
	g-rx-fifo-size = <256>;
    g-np-tx-fifo-size = <32>;
    g-tx-fifo-size = <128 128 128 128 64 32 16 16>;
	usb-role-switch;
	role-switch-default-mode = "peripheral";                                                          /* see USB generic bindings [4] */
	status = "okay";                                                          /* enable OTG */
	
	port {
		usbotg_hs_ep: endpoint {
			remote-endpoint = <&con_usbotg_hs_ep>;            	  /* point the Type-C controller endpoint node */
		};
	};
};

 

To my understanding phys = <&usbphyc_port1 0>; will set the UTMI to OTG and dr_mode="otg" will set the mode in the same way.  In this configuration I can get the board recognized as a USB peripheral from other devices successfully. If I connect a peripheral device to the usb-c when the gadget is running the usb-c port will not provide any power as expected. If I stop the gadget and connect a peripheral the usb-c port will send the right power. Although this behavior looks correct according to the dts, no peripherals will get recognized in stlinux when the gadget is not running and a peripheral usb device is connected to the usb-c port. 

If I use the same phys to ehci and ohci then I will get the usb running only on host mode and all peripherals will get successfully detected in lsusb.

 

&usbh_ehci {
    phys = <&usbphyc_port0>, <&usbphyc_port1 1>;
    phy-names = "usb", "usb2-phy";
    status = "okay";
};

&usbh_ohci {
    status = "okay";
    phy-names = "usb", "usb2-phy";
    phys = <&usbphyc_port0>, <&usbphyc_port1 1>;
};

 

If I understand this correctly for recognizing USB 1.1 I need the OHCI host controller and for USB2.0 I need the EHCI controller. If this is the case in order for the OTG to work as expected I need to share <&usbphyc_port1> between usbotg_hs, usbh_ehci and usbh_ohci so when OTG performs a role switch the host part is managed by the USBH controllers. When attempting to share the same usbphyc between otg_hs and USBH I do not get OTG mode since the phy is already occupied before otg gets intialized:

 

[    4.069548] stusb160x 2-0028: Failed to get port caps: -6
[    4.108387] stm32-usbphyc 5a006000.usbphyc: phy port1 already used
[    4.113359] dwc2 49000000.usb-otg: error -EBUSY: error getting phy

 

If I share the node with 0 UTMI flag as below:

 

&usbotg_hs {
	compatible = "st,stm32mp15-hsotg", "snps,dwc2";
	phys = <&usbphyc_port1 0>;                                                /* 0: UTMI switch selects the OTG controller */
	phy-names = "usb2-phy";
	dr_mode = "otg";
	g-rx-fifo-size = <256>;
    g-np-tx-fifo-size = <32>;
    g-tx-fifo-size = <128 128 128 128 64 32 16 16>;
	usb-role-switch;
	role-switch-default-mode = "peripheral";                                                          /* see USB generic bindings [4] */
	status = "okay";                                                          /* enable OTG */
	
	port {
		usbotg_hs_ep: endpoint {
			remote-endpoint = <&con_usbotg_hs_ep>;            	  /* point the Type-C controller endpoint node */
		};
	};
};

&usbh_ehci {
    phys = <&usbphyc_port0>, <&usbphyc_port1 0>;
    phy-names = "usb", "usb2-phy";
    status = "okay";
};

&usbh_ohci {
    status = "okay";
    phy-names = "usb", "usb2-phy";
    phys = <&usbphyc_port0>, <&usbphyc_port1 0>;
};

 

I get all 3 entries recongized in lsusb but no peripherals recongised when connected.

Any ideas or pointers on how to debug this further are really appreciated.



1 ACCEPTED SOLUTION

Accepted Solutions
KChar.1
Senior

After some time I found out that the SDA and SCL I2C lines of the stusb1600x were inverted. By correcting this in HW I was able to change data roles from the stusb160x driver or from user space with

/sys/devices/platform/soc/49000000.usb-otg/usb_role/49000000.usb-otg-role-switch/role


This has been part of a more complex solution described in this post.

View solution in original post

1 REPLY 1
KChar.1
Senior

After some time I found out that the SDA and SCL I2C lines of the stusb1600x were inverted. By correcting this in HW I was able to change data roles from the stusb160x driver or from user space with

/sys/devices/platform/soc/49000000.usb-otg/usb_role/49000000.usb-otg-role-switch/role


This has been part of a more complex solution described in this post.