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 */ }; }; };
View more

 

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.