Last edited 10 months ago

OTG device tree configuration

Applicable for STM32MP13x lines, STM32MP15x lines

1. Article purpose[edit | edit source]

This article explains how to configure the OTG internal peripheral when it is assigned to the Linux® OS. In that case, it is controlled by the USB framework.

The configuration is performed using the device tree mechanism.

It is used by OTG Linux driver[1] which registers the relevant information in the USB framework.

2. DT bindings documentation[edit | edit source]

The Platform DesignWare HS OTG USB 2.0 controller device tree bindings[2] document represents the OTG (DRD) controller.

The generic USB device tree bindings represents generic USB properties, used by the USB framework:

  • usb.yaml[3] is the base DT schema for all USB controllers. It describes properties such as maximum-speed.
  • usb-drd.yaml[4] is specific to dual-role USB controllers. It describes properties such as dr_mode, usb-role-switch...
  • usb-hcd.yaml[5] is specific to USB Host controllers.
  • usb-connector.yaml[6] is specific to USB connectors.

3. DT configuration[edit | edit source]

This hardware description is a combination of the STM32 microprocessor device tree files (.dtsi extension) and board device tree files (.dts extension). See the Device tree for an explanation of the device tree file split.

STM32CubeMX can be used to generate the board device tree. Refer to How to configure the DT using STM32CubeMX for more details.

3.1. DT configuration (STM32 level)[edit | edit source]

The usbotg_hs DT node is declared in:

  • stm32mp131.dtsi[7] on STM32MP13x lines More info.png
  • stm32mp151.dtsi[8] on STM32MP15x lines More info.png

It is composed of a set of properties, used to describe the OTG controller: registers address, clocks, resets, interrupts, FIFOs...

usbotg_hs: usb-otg@49000000 {
 	compatible = "st,stm32mp15-hsotg", "snps,dwc2";
	reg = <0x49000000 0x10000>;
	clocks = <&rcc USBO_K>;
	clock-names = "otg";
	resets = <&rcc USBO_R>;
	reset-names = "dwc2";
	interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
	dr_mode = "otg"; 	 	 	 	/* dr_mode[4] can be overwritten at board level to set a particular mode */
	status = "disabled";
};
Warning white.png Warning
This device tree part is related to STM32 microprocessors. It must be kept as is, without being modified by the end-user.

3.2. DT configuration (board level)[edit | edit source]

Follow the sequences described in the below chapters to configure and enable the OTG on your board.

OTG supports two PHY interfaces that can be statically selected via DT:

  • full-speed PHY, embedded with the OTG controller
  • high-speed USBPHYC HS PHY that can be assigned to either the USBH or the OTG controller.

OTG FIFO may be tuned via DT, to better fit gadget profile.
When operating in "otg" or "host" mode, an external charge pump, e.g. 5V regulator must be specified.

Info white.png Information
Please refer to Regulator overview for additional information on regulators configuration.

3.2.1. DT configuration using full-speed USB PHY[edit | edit source]

  • Enable the OTG by setting status = "okay".
  • Use embedded full-speed PHY by setting compatible = "st,stm32mp15-fsotg", "snps,dwc2"
  • Configure full-speed PHY pins (OTG ID, DM, DP) as analog via pinctrl, through pinctrl-0 and pinctrl-names.
  • Optionally set dual-role mode through dr_mode = "peripheral", "host" or "otg" (default to "otg" in case it is not set)
  • Optionally set vbus voltage regulator for otg and host modes, through vbus-supply = <&your_regulator>

3.2.2. DT configuration using high-speed USB PHY[edit | edit source]

  • Enable the OTG by setting status = "okay".
  • Select USBPHYC port#2 by setting phys = <&usbphyc_port1 0>; and phy-names = "usb2-phy";
  • Optionally configure OTG ID pin as analog via pinctrl, through pinctrl-0 and pinctrl-names.
  • Optionally set dual-role mode through dr_mode = "peripheral", "host" or "otg" (default to "otg" in case it is not set)
  • Optionally set vbus voltage regulator for otg and host modes, through vbus-supply = <&your_regulator>
Info white.png Information
Please refer to USBPHYC device tree configuration for additional information on USBPHYC port#2 configuration

3.2.3. DT configuration of gadget FIFO[edit | edit source]

OTG in gadget mode uses a dedicated memory buffer to hold the FIFOs of all the USB endpoints. Depending on the application, the amount of FIFO allocated for each endpoint can impact the USB transfer performance.

The amount of memory allocated for each FIFO can be set through the DT properties:

  • g-rx-fifo-size: size of common RX FIFO (in 32 bits words);
  • g-np-tx-fifo-size: size of non-periodic TX FIFO (in 32 bits words);
  • g-tx-fifo-size: size of periodic TX FIFO (in 32 bits words), one value for each endpoint ep1..ep7 (ep0 is excluded).
Info white.png Information
Interrupt and isochronous USB endpoints are named as "periodic".
Control and bulk USB endpoints are named as "non-periodic".

The total OTG memory size is 4096 bytes (1024 x 32 bits words). Part of this memory is used by the DMA engine: 32 bytes (8 words) per each of the 9 channels (1 RX plus 8 TX). This lefts 3808 bytes (952 words) available for the USB FIFOs. Such info is also printed at boot during driver probe:

dwc2 49000000.usb-otg: EPs: 9, dedicated fifos, 952 entries in SPRAM
Warning white.png Warning
The sum of all the values of FIFO size in the three DT properties must not exceed 952.

If the FIFO size configured in DT for an endpoint is lower that the amount required by the user driver, a run time error is logged by the kernel:

dwc2 49000000.usb-otg: dwc2_hsotg_ep_enable: No suitable fifo found
Info white.png Information
Each FIFO size should at least contain one USB packet. Recommendation: allocating space for two or more packets

is preferred as it would increase the overall performance by having DMA and OTG working in parallel.

The minimum value of each FIFO size is 16 words, even for unused endpoints.

3.3. DT configuration examples[edit | edit source]

3.3.1. DT configuration example as high speed OTG, with micro-B connector, Vbus and ID mapped on GPIOs[edit | edit source]

The example below shows how to configure high-speed OTG, with the Vbus and ID pins mapped on GPIOs[9] to detect the role (peripheral, host).

  • OTG ID pin: use id-gpios to configure PA10 as GPIO (refer to GPIO device tree configuration).
  • Vbus pin: use vbus-gpios to configure PA13 as GPIO.
  • Use vbus-supply to configure vbus voltage regulator.
  • Use port and endpoint child nodes to reference usbotg_hs_ep OTG controller as remote-endpoint
# part of board dt root node
/ {
	usb-b-connector {
		compatible = "gpio-usb-b-connector", "usb-b-connector";  /* see USB connector bindings [6] */
		label = "micro-USB";
		type = "micro";
		id-gpios = <&gpioa 10 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
		vbus-gpios = <&gpioa 13 GPIO_ACTIVE_HIGH>;
		vbus-supply = <&vbus_otg>;

		port {
			con_usbotg_hs_ep: endpoint {
				remote-endpoint = <&usbotg_hs_ep>;
			};
		};
	};
};
  • Use USB HS PHY port#2, with the UTMI switch that selects the OTG controller
  • Use usb-role-switch to indicate the device is capable of assigning the USB data role (host or device) through the connector
  • Dual-role mode (dr_mode) is "otg" (e.g. the default as unspecified)
  • Use port and endpoint child nodes labels to cross-link usbotg_hs together with usb-b-connector
  • Use port and endpoint child nodes to reference &con_usbotg_hs_ep usb-b-connector as remote-endpoint
&usbotg_hs {
	phys = <&usbphyc_port1 0>;                        /* 0: UTMI switch selects the OTG controller */
	phy-names = "usb2-phy";
	usb-role-switch;                                  /* see USB generic bindings [4] */
	status = "okay";

	port {
		usbotg_hs_ep: endpoint {
			remote-endpoint = <&con_usbotg_hs_ep>;
		};
	};
};
Warning white.png Warning
This example isn't currently supported in U-Boot. Please refer to Configure USB OTG node in U-Boot in case Vbus and ID pins sensing is performed by using GPIOs.
Info white.png Information
Linux kernel needs to be configured with CONFIG_USB_CONN_GPIO, with the Linux Menuconfig tool, refer to Menuconfig or how to configure kernel

3.3.2. DT configuration example as full-speed OTG, with micro-B connector[edit | edit source]

The example below shows how to configure full-speed OTG, with the ID pin to detect role (peripheral, host):

  • OTG ID and data (DM, DP) pins: use Pinctrl device tree configuration to configure PA10, PA11 and PA12 as analog input.
  • Use integrated full-speed USB PHY by setting compatible
  • Dual-role (dr_mode) is "otg" (e.g. the default as unspecified)
  • Use vbus voltage regulator
# part of pin-controller dt node
usbotg_hs_pins_a: usbotg_hs-0 {
	pins {
		pinmux = <STM32_PINMUX('A', 10, ANALOG)>; /* OTG_ID */            /* configure 'PA10' as ANALOG */

	};
};

usbotg_fs_dp_dm_pins_a: usbotg-fs-dp-dm-0 {
	pins {
		pinmux = <STM32_PINMUX('A', 11, ANALOG)>, /* OTG_FS_DM */
			 <STM32_PINMUX('A', 12, ANALOG)>; /* OTG_FS_DP */
	};
};
&usbotg_hs {
	compatible = "st,stm32mp15-fsotg", "snps,dwc2";                            /* Use full-speed integrated PHY */
	pinctrl-names = "default";
	pinctrl-0 = <&usbotg_hs_pins_a &usbotg_fs_dp_dm_pins_a>;                  /* configure OTG ID and full-speed data pins */
	vbus-supply = <&vbus_otg>;                                                /* voltage regulator to supply Vbus */
	status = "okay";
};

3.3.3. DT configuration example as high speed OTG, with micro-B connector[edit | edit source]

The example below shows how to configure high-speed OTG, with the ID pin to detect role (peripheral, host):

  • OTG ID pin: use Pinctrl device tree configuration to configure PA10 as analog input.
  • Use USB HS PHY port#2, with the UTMI switch that selects the OTG controller
  • Dual-role mode (dr_mode) is "otg" (e.g. the default as unspecified)
  • Use vbus voltage regulator
# part of pin-controller dt node
usbotg_hs_pins_a: usbotg_hs-0 {
	pins {
		pinmux = <STM32_PINMUX('A', 10, ANALOG)>; /* OTG_ID */            /* configure 'PA10' as ANALOG */

	};
};
&usbotg_hs {
	compatible = "st,stm32mp15-hsotg", "snps,dwc2";
	pinctrl-names = "default";
	pinctrl-0 = <&usbotg_hs_pins_a>;                                          /* configure OTG_ID pin */
	phys = <&usbphyc_port1 0>;                                                /* 0: UTMI switch selects the OTG controller */
	phy-names = "usb2-phy";
	vbus-supply = <&vbus_otg>;                                                /* voltage regulator to supply Vbus */
	status = "okay";                                                          /* enable OTG */
};

3.3.4. DT configuration example as high speed OTG, with Type-C connector[edit | edit source]

The example below shows how to configure high-speed OTG with a Type-C connector. Type-C is managed by an external controller which detects connection and data role (peripheral, host) and implements Linux USB role switch class:

  • Use USB HS PHY port#2, with the UTMI switch that selects the OTG controller
  • Dual-role mode (dr_mode) is "otg" (e.g. the default as unspecified)
  • Add usb-role-switch property to OTG controller node: it indicates that the device is capable of assigning the USB data role (USB host or USB device) for a given USB connector.
  • Add a connector subnode to the Type-C controller node, with a port child node pointing to the OTG controller endpoint and add a port child node to the OTG controller node, pointing to the Type-C controller endpoint: Type-C controller driver will be able to get the USB role switch to inform it of a role change.
#example of Type-C controller node
stusb1600@28 {
	compatible = "st,stusb1600";
	reg = <0x28>;
	interrupts = <11 IRQ_TYPE_EDGE_FALLING>;
	interrupt-parent = <&gpioi>;
	pinctrl-names = "default";
	pinctrl-0 = <&stusb1600_pins_a>;
	status = "okay";
	vdd-supply = <&vin>;
	
	connector {
		compatible = "usb-c-connector";
		label = "USB-C";
		power-role = "dual";
		power-opmode = "default";
		
		port {
			con_usbotg_hs_ep: endpoint {
				remote-endpoint = <&usbotg_hs_ep>;          	  /* point the OTG controller endpoint node */
			};
		};
	};
};
&usbotg_hs {
	compatible = "st,stm32mp15-hsotg", "snps,dwc2";
	phys = <&usbphyc_port1 0>;                                                /* 0: UTMI switch selects the OTG controller */
	phy-names = "usb2-phy";
	usb-role-switch;                                                          /* 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 */
		};
	};
};

3.3.5. DT configuration example as high-speed OTG in Host or Peripheral mode, with micro-B or Type-C connector, and with VBUS and ID left unconnected[edit | edit source]

The example below shows how to configure high-speed OTG, with the ID and VBUS pins left unconnected:

  • Use USB HS PHY port#2, with the UTMI switch that selects the OTG controller
  • Force dr_mode to either "host" or "peripheral": it forces the controller in Host only or Device only mode.
  • Add usb-role-switch property to OTG controller node: it indicates that the device is capable of assigning the USB data role (USB host or USB device).
  • Add role-switch-default-mode = "host" or "peripheral" according to dr_mode: it forces corresponding valid session in OTG driver.
&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 = "peripheral";                                                   /* could be "host", see USB generic bindings [4] */
	usb-role-switch;                                                          /* see USB generic bindings [4] */
	role-switch-default-mode = "peripheral";                                  /* could be "host", see USB generic bindings [4] */
	status = "okay";                                                          /* enable OTG */
};

3.3.6. DT configuration example to tune FIFO for RDNIS gadget[edit | edit source]

The default OSTL configuration is tuned for RNDIS gadget. It requires one bulk IN/OUT endpoint and one control endpoint:

&usbotg_hs {
    g-rx-fifo-size = <512>;
    g-np-tx-fifo-size = <32>;
    g-tx-fifo-size = <256 16 16 16 16 16 16 16>;
};

4. How to configure the DT using STM32CubeMX[edit | edit source]

The STM32CubeMX tool can be used to configure the STM32MPU device and get the corresponding platform configuration device tree files.
The STM32CubeMX may not support all the properties described in the above DT bindings documentation paragraph. If so, the tool inserts user sections in the generated device tree. These sections can then be edited to add some properties and they are preserved from one generation to another. Refer to STM32CubeMX user manual for further information.

5. References[edit | edit source]

Please refer to the following links for additional information:

  1. drivers/usb/dwc2/ , DesignWare HS OTG Controller driver
  2. Documentation/devicetree/bindings/usb/dwc2.yaml , Platform DesignWare HS OTG USB 2.0 controller device tree bindings
  3. Documentation/devicetree/bindings/usb/usb.yaml , Generic USB Controller Device Tree Bindings
  4. 4.0 4.1 4.2 4.3 4.4 4.5 4.6 Documentation/devicetree/bindings/usb/usb-drd.yaml , Generic USB OTG Controller Device Tree Bindings
  5. Documentation/devicetree/bindings/usb/usb-hcd.yaml , Generic USB Host Controller Device Tree Bindings
  6. 6.0 6.1 Documentation/devicetree/bindings/connector/usb-connector.yaml , Generic USB Connector Device Tree Bindings
  7. arch/arm/boot/dts/stm32mp131.dtsi , STM32MP131 device tree file
  8. arch/arm/boot/dts/stm32mp151.dtsi , STM32MP151 device tree file
  9. AN4879, USB hardware and PCB guidelines using STM32 MCUs, by STMicroelectronics