(OSD3358) USB PHY pinmux conflict

Hi,
Custom board using Octavo Systems OSD3358-basic based upon Beaglebone Black. My design has two ethernet PHYs connected in RMII mode.
Referring to USB document https://octavosystems.com/app_notes/osd335x-design-tutorial/osd335x-lesson-2-minimal-linux-boot/osd335x-lesson-2-usb-circuitry/

The active low Over Current output of the Power Switch (pin 5 of the TPS2501 attached to the USB1_OCN signal in Figure 1) can be connected to any of the GPIOs of the OSD335x as shown in Figure 3 (GPMC_A10 pin is chosen in this case) to detect issues with USB Client devices trying to draw more power than allowed.

The BBB and the app note has USB1_OCn output pad T16 (mode 0, GPMC_A10, gpio1-26).
However in my design, PHY2 is connected to pad T16 (mode3, GPMC_A10.RMII2_RXD1, gpio1-26).

The app note states that ‘any’ GPIO can be attached to USB1_OCn. I have pad V5 (mode 3, LCD_PCLK.GPMC_A10, gpio2-24) available.

I have many questions.

USB subsystem questions,
Does the USB subsystem have to specificly use GPMC_A10?
Does it have to use GPMC_A10 or can it use any open GPMC?
Does it have to use a GPMC or can it use any open GPIO?
If any GPIO, Is the GPIO line an input or output?

Device tree questions,
snippets from am33xx.dtsi device tree file

	gpio1: gpio@4804c000 {
		compatible = "ti,omap4-gpio";
		ti,hwmods = "gpio2";
		gpio-controller;
		#gpio-cells = <2>;
		interrupt-controller;
		#interrupt-cells = <2>;
		reg = <0x4804c000 0x1000>;
		interrupts = <98>;
		gpio-line-names =
			"GPMC_A10",	// 26
	};
		usb1_phy: usb-phy@47401b00 {
			compatible = "ti,am335x-usb-phy";
			reg = <0x47401b00 0x100>;
			reg-names = "phy";
			status = "disabled";
			ti,ctrl_mod = <&usb_ctrl_mod>;
			#phy-cells = <0>;
		};

		usb1: usb@47401800 {
			compatible = "ti,musb-am33xx";
			status = "disabled";
			reg = <0x47401c00 0x400
				0x47401800 0x200>;
			reg-names = "mc", "control";
			interrupts = <19>;
			interrupt-names = "mc";
			dr_mode = "otg";
			mentor,multipoint = <1>;
			mentor,num-eps = <16>;
			mentor,ram-bits = <12>;
			mentor,power = <500>;
			phys = <&usb1_phy>;

			dmas = <&cppi41dma 15 0 &cppi41dma 16 0
				&cppi41dma 17 0 &cppi41dma 18 0
				&cppi41dma 19 0 &cppi41dma 20 0
				&cppi41dma 21 0 &cppi41dma 22 0
				&cppi41dma 23 0 &cppi41dma 24 0
				&cppi41dma 25 0 &cppi41dma 26 0
				&cppi41dma 27 0 &cppi41dma 28 0
				&cppi41dma 29 0 &cppi41dma 15 1
				&cppi41dma 16 1 &cppi41dma 17 1
				&cppi41dma 18 1 &cppi41dma 19 1
				&cppi41dma 20 1 &cppi41dma 21 1
				&cppi41dma 22 1 &cppi41dma 23 1
				&cppi41dma 24 1 &cppi41dma 25 1
				&cppi41dma 26 1 &cppi41dma 27 1
				&cppi41dma 28 1 &cppi41dma 29 1>;
			dma-names =
				"rx1", "rx2", "rx3", "rx4", "rx5", "rx6", "rx7",
				"rx8", "rx9", "rx10", "rx11", "rx12", "rx13",
				"rx14", "rx15",
				"tx1", "tx2", "tx3", "tx4", "tx5", "tx6", "tx7",
				"tx8", "tx9", "tx10", "tx11", "tx12", "tx13",
				"tx14", "tx15";
		};

Which setting in the am33xx.dtsi (or other) file configures the USB subsystem to use GPMC_A10 (gpio1-26) as the USB1_OCn signal?
If pad V5 (gpio2-24 or any other unused GPIO) is used instead of pad T16, what setting(s) in the device tree require changes to configure the USB subsystem to use the new instead of T16 gpio1-26?
Is the new line pinmux configured as input or output?
How and where is the pinmux defined?

Is there a way to temporary disable USB subsystem from checking for a Over Current event?

I apologize for the number of questions asked.
Thank you in advance for your answers/suggestions.

Which version of am33xx.dtsi, i’m looking at Linus’ tree, and it doesn’t seem to exist for the BeagleBone? We probably should submit something. :wink:

For comparison, here is how the “pepper” board defines those pin’s. So feel free to move, just set is as PIN_INPUT, MUX_MODE7 aka generic gpio input…

/* USB */
&usb {
	pinctrl-names = "default";
	pinctrl-0 = <&usb_pins>;
};

&usb0 {
        dr_mode = "host";
};

&usb1 {
        dr_mode = "host";
};

&am33xx_pinmux {
	usb_pins: pinmux_usb {
		pinctrl-single,pins = <
			/* USB0 Over-Current (active low) */
			AM33XX_PADCONF(AM335X_PIN_GPMC_A9, PIN_INPUT, MUX_MODE7)	/* gpmc_a9.gpio1_25 */
			/* USB1 Over-Current (active low) */
			AM33XX_PADCONF(AM335X_PIN_GPMC_A10, PIN_INPUT, MUX_MODE7)	/* gpmc_a10.gpio1_26 */
		>;
	};
};

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm/boot/dts/am335x-pepper.dts#n554

So you can safely move it anywhere…

Regards,

Robert,
I am using version of am33xx.dtsi from BeagleBoard-DeviceTrees-4.19.x-ti folder.

I should note that on the BBB the USB0 is the ‘peripheral’ and USB1 is the ‘host’.
My custom board, USB0 is the ‘host’ and has the TPS2051 power switch connected. USB1 is my ‘peripheral’ port.


Note that pin-5 of the TPS2051 is not connected to any pad on the OSD3358. However pad T16 (GPMC_A10) is connected to rmii2_rxd1. (not shown) Pad T16 is part of the PHY2 pinmux. What I am concerned about is that USB0 subsystem is still looking at T16 which is being held low by rmii1_rxd1 signal. I think that is causing USB0 to trigger an over current event and deassert USB0_DRVVBUS.
I want to change the GPIO line USB0 subsystem is looking at.

I have made no changes to the am33xx.dtsi file. I am using my own ‘my_common.dtsi’ file and made usb changes in my file.

snippet from my ‘my_common.dtsi’ file.

&usb {
	status = "okay";
};

&usb_ctrl_mod {
	status = "okay";
};

&usb0_phy {
	status = "okay";
};

&usb1_phy {
	status = "okay";
};

&usb1 {
	status = "okay";
	dr_mode = "peripheral";
	interrupts-extended = <&intc 18 &tps 0>; // I am not sure what this does or if this is correct or belongs here or in &usb0
	interrupt-names = "mc", "vbus"; // I am not sure what this does or if this is correct or belongs here on in &usb0
};

&usb0 {
	status = "okay";
	dr_mode = "host";
};

I can’t find anywhere where the USB0 subsystem’s pinmux is defined. I see that the pepper has a pinmux and understand how to add to my_common.dtsi. I still don’t understand how the addition of the pinmux changes the over-current pin that the USB0 subsystem uses.

How does the USB0 subsystem know to use the defined pinmux?
Is there only one configurable pin for the subsystem?
Thank you,

No, you are correct “USB1_OCn” is “NOT” defined anywhere… You have found an actual bug with the BeagleBone family device tree. This should be defined! Today on Beagle this is an undefined condition.

I’m going to try and test this over the weekend with my collection of boards:

diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
index 2d51d4bba6d4..e6bda1bf05e8 100644
--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
+++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
@@ -182,6 +182,13 @@ AM33XX_PADCONF(AM335X_PIN_GPMC_AD6, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad6.mmc
 			AM33XX_PADCONF(AM335X_PIN_GPMC_AD7, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad7.mmc1_dat7 */
 		>;
 	};
+
+	usb_pins: pinmux_usb {
+		pinctrl-single,pins = <
+			/* USB1 Over-Current (active low) */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_A10, PIN_INPUT, MUX_MODE7)	/* gpmc_a10.gpio1_26 */
+		>;
+	};
 };
 
 &uart0 {
@@ -191,6 +198,11 @@ &uart0 {
 	status = "okay";
 };
 
+&usb {
+	pinctrl-names = "default";
+	pinctrl-0 = <&usb_pins>;
+};
+
 &usb0 {
 	dr_mode = "peripheral";
 	interrupts-extended = <&intc 18 &tps 0>;

Regards,

Robert,
I look forward to your test results.

I don’t have a pepper board, but I understand USB0 and USB1 are ‘host’ ports.
snippet from pepper,

&usb0 {
        dr_mode = "host";
};

&usb1 {
        dr_mode = "host";
};

&am33xx_pinmux {
	usb_pins: pinmux_usb {
		pinctrl-single,pins = <
			/* USB0 Over-Current (active low) */
			AM33XX_PADCONF(AM335X_PIN_GPMC_A9, PIN_INPUT, MUX_MODE7)	/* gpmc_a9.gpio1_25 */
			/* USB1 Over-Current (active low) */
			AM33XX_PADCONF(AM335X_PIN_GPMC_A10, PIN_INPUT, MUX_MODE7)	/* gpmc_a10.gpio1_26 */
		>;
	};
};

There are two padconf(), the first is commented as ‘USB0 over-current’, the second is commented ‘USB1 over-current’.
Are there two padconf() because USB0 and USB1 dr_mode(s) are ‘host’?
Is the order of the padconf() important?

In your patch, USB0 dr_mode = ‘peripheral’ and USB1 dr_mode = ‘host’ and there is single padconf().
Is the single padconf() mapped to USB1_OCn because USB1 is host and USB0 was skipped because it is peripheral?

On my board USB0 dr_mode = ‘host’ and USB1 dr_mode is ‘peripheral’.
Will I have a single padconf() and will that get mapped to USB0_OCn?

Maybe I am missing something. Maybe it is the actual gpiox_xx that is important.
AM33XX_PADCONF(AM335X_PIN_GPMC_A10, PIN_INPUT, MUX_MODE7)
mode7 configures the pad as gpio1_26.
Is gpio1_26 dedicated to be used as USB1_OCn?
If yes, then what gpio is dedicated as USB0_OCn?

What happens to the pinmux padconf() if the USB0 and/or USB1 dr_mode = ‘otg’?

Does the USB dt-binding describe what is supposed to be included in the device tree to connect/map the padconf() to the USBx_OCn?

Thank you,

Correct, on the pepper board, it has two host’s and two IC’s to detect the OverCurrent issue.

I believe so… Just haven’t found the matching reference in mainline…

gpio1_26 is not dedicated to USB1_OCn, it’s just a generic gpio ‘used’ in the design, feel free to use any normal gpio for your USB0_OCn situation.

otg bring’s other fun issues, it’s why we only list usb1 peripheral

It’s not documented, haven’t found it in the driver yet either.

Regards,

Robert,

Did you mean to say, “on the BBB, it’s why we only list usb1 as host”?

Thank you,

Yeah i messed that up…

This uses peripheral, as otg is a little painful to support. :wink: (When you have default usb gadget cdc/serial/flash auto load on startup for the out of box experience.)

&usb0 {
	dr_mode = "peripheral";
	interrupts-extended = <&intc 18 &tps 0>;
	interrupt-names = "mc", "vbus";
};

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm/boot/dts/am335x-bone-common.dtsi?h=v5.9-rc3#n194

Regards,

Robert,
Referring to USB section 16 of the am335x TRM
https://www.ti.com/lit/ug/spruh73q/spruh73q.pdf

I have been studying the USB subsystem. The subsystem checks for over-current condition by analog sample of the USBx_VBUS line. The event produced by TPS2051 pin-5 is similar but not the same. I don’t think the USB subsystem has a USBx_OCn input. I am guessing that code was added to the kernel to handle the event generated by pin-5 of the TPS2051. I don’t know which source .c file the event is handled. USBx_OCn still needs defined so that I can set the PADCONF() to an unused gpio input_pullup.

I think the USBx_OCn event handler may be in the kernel/drivers/usb/core/hub.c code.
Where is the source code for the USBx_OCn event handler?

Have you made any progress on the device tree patch?

Thank you,

Sorry, i haven’t found anything yet that actually uses that feature.

Regards,

Robert,
kernel 4.19.106-bone49.
It has been awhile since this subject was discussed. I found a gumstix_pepper.pdf file. https://pubs.gumstix.com/boards/PEPPER/R4021/B80000.pdf
I noticed that the pepper uses two TPS2051 Power Distribution Switch chips. U11 pin-5 (OC signal) is connected to GPMC_A9 (U16). U13 pin-5 is connected to GMPC_A10 (T16). I understand why the pepper.dtsi file includes &usb pinmux for _A9 and _A10.
On my board, TPS2051 pin-5 is not connected to the OSD3358. I will not be adding an ‘USBx over-current’ pinmux.

I am counting on the OSD3358 USB subsystem to monitor the USB0_VBUS analog input for a voltage <=4.4v to trigger a VBUS error interrupt. I understand musb_core.c has an interrupt handler that is responsible for handling the interrupt generated by the USB subsystem.
Do I understand correctly?

Here is a snippet from the am33xx.dtsi

usb0: usb@47401000 {
	interrupts = <18>;
	interrupt-names = "mc";
};
usb1: usb@47401800 {
	interrupts = <19>;
	interrupt-names = "mc";
};

Here is a snippet from am335x-bone-common.dtsi

&usb0 {
	status = "okay";
	dr_mode = "peripheral";
	interrupts-extended = <&intc 18 &tps 0>;
	interrupt-names = "mc", "vbus";
};

&usb1 {
	status = "okay";
	dr_mode = "host";
};

I understand that ‘interrupts-extended = <&intc 18 &tps 0>;’ and ‘interrupt-names = “mc”, vbus";’ override/replace the previously defined ‘interrupts’ and ‘interrupt-names’.

The ‘&intc 18’ and ‘mc’ part does nothing because ‘18’ and ‘mc’ are already defined. I am guessing the ‘&tps 0’ and ‘vbus’ is adding an interrupt ‘0’ named ‘vbus’.

Here is where I am confused. On the BBB the USB0 port is a peripheral.
Why does the BBB USB0 port have an’ interrupt’ entry for ‘vbus’?

On the BBB the USB1 port, TPS2051 pin-5 is connected to T18, but there is no ‘interrupt’ entry in the device tree.
How doe the kernel handle USB1 over-current condition? Is it handled based upon vbus error interrupt generated by the USB subsystem or from the TPS2051 pin-5?

Thank you,

This is to help trigger the TPS for DC → USB power change over or for TPS battery charging situations. Last i checked, that doesn’t seamlessly work on mainline yet…

The output of the TPS2051 is wired to the USB1_OCn, which isn’t currently handled by the BeagleBoard device tree.

I still think something like: (OSD3358) USB PHY pinmux conflict - #4 by RobertCNelson would make it work…

Regards,

My custom board is using USB0 as my host port. USB0_VBUS +5volts is created by the TPS2051 and is connected to OSD3358 P15 USB0_VBUS analog input. (See above drawing)
After the kernel boots, I can connect an oscilloscope to P15 and read +4.98 volts.
The over-current condition event occurs when I plug a USB stick into USB0. However the o-scope (P15) does not drop below 4.90volts.
I can try to reset the USB0 port using
echo 0 > /sys/bus/usb/devices/usb1/authorized
echo 1 > /sys/bus/usb/devices/usb1/authorized
Each time the USB controller reports
root@arm:~# echo 1 > /sys/bus/usb/devices/usb1/authorized
[ 913.118327] hub 1-0:1.0: USB hub found
[ 913.125498] hub 1-0:1.0: 1 port detected
[ 913.139626] usb usb1: authorized to connect
root@arm:~# [ 913.291841] musb-hdrc musb-hdrc.0: VBUS_ERROR in a_wait_vrise (89, <AValid), retry #1, port1 0008010c
[ 913.444259] musb-hdrc musb-hdrc.0: VBUS_ERROR in a_wait_vrise (89, <AValid), retry #2, port1 0000010c
[ 913.561378] usb usb1-port1: over-current condition
[ 917.276188] musb-hdrc musb-hdrc.0: VBUS_ERROR in a_wait_bcon (89, <AValid), retry #3, port1 0000010c
[ 917.428622] musb-hdrc musb-hdrc.0: VBUS_ERROR in a_wait_vrise (88, <AValid), retry #3, port1 0008010c

Unless I misunderstand, I think the controller is shutting down the VBUS because it thinks there is an over-current condition caused by USB0_VBUS (P15) dropping below 4.4v. However the o-scope shows the USB0_VBUS never dips below 4.90v. The USB0_DRVVBUS signal does toggle on/off(100ms)/on(100ms)/off… The USB0_VBUS voltage follows the pattern.

I have found in hub.c where the ‘over-current condition’ is printed to the console. I would like to know what the USB controller thinks the voltage is at P15.
There has to be someway that the kernel (editing hub.c, musb_core.c or other .c file) can report the analog voltage at P15.

Does the kernel have access to the P15 analog value?
Is there a register in the USB controller that stores the P15 analog value?
Using printk(), what is the syntax to print the analog value of P15 to the console?

More:
I have found this debug message at line 327 in the davinci.c.
davinci_musb_source_power(musb, drvvbus, 0);
dev_dbg(musb->controller, “VBUS %s (%s)%s, devctl %02x\n”,
drvvbus ? “on” : “off”,
usb_otg_state_string(musb->xceiv->otg->state),
err ? " ERROR" : “”,
devctl);

I was hoping that at least the message would tell me if VBUS is on or off. I have passed in the kernel bootargs loglevel=8 but the the dev_dbg() text is not being displayed on the console. Either the code is not being called when the over-current event occurs or loglevel=8 doesn’t cause dev_dbg() to run.

Is there a USB forum to post this and similar questions?
Who maintains the kernel’s USB code?

Thank you,

I posted a question about reading the USBx_VBUS raw analog value on E2E forum. Here is the reply.
Me:
Is there a register in the USBx controller that stores the raw voltage value of the USBx_VBUS analog input?

TI:
No.
Only Register DevCtl[bit4-3] records the VBUS voltage level:
00 - VBUS is below SessionEnd
01 - VBUS is above Session End and below AValid
10 - VBUS is above AValid and below VBusValid
11 - VBUS is above VBusValid

Me:
Does the kernel and/or user code have access to the raw voltage value of the USBx_VBUS analog input?

TI:
No.