Enabling USB client mode on iMX8MP on Mallow board in Yocto

I’m trying to enable a USB connection between PC and iMX8MP plus Mallow carrier, that will let me either access a serial port for a terminal session, or achieve a network connection for SSH.

I’ve tried following the instructions in this article: USB Device Mode (Linux) | Toradex Developer Center but when I get to step 10, “# ls /sys/class/udc/”, there’s nothing in /sys/class/udc.

I notice when booting that there’s a message that says “dwc3 38100000.usb: Configuration mismatch. dr_mode forced to host“ (so presumably /sys/class/udc should contain controller 38100000.usb…?) but host mode doesn’t seem to be working either (I inserted a USB-C flash drive and it doesn’t appear to be seen, no kernel messages like there are when I insert a USB-A drive).

The image I’m building is Yocto-based, not Torizon, from the Scarthgap branch, using Toradex BSP layers. The device tree fdtfile variable in U-Boot is set to imx8mp-verdin-wifi-mallow.dtb, but I don’t know whether that should enable the USB-C, or whether I need an overlay.

I’m a relative newcomer to Yocto (or any form of embedded OS), and having spent hours trying to understand how to make the USB-C port work (and even consulting ChatGPT in desperation), I’m not getting anywhere, so I’m hoping that someone more knowledgeable than I am (which is likely everyone here) can point me in the right direction.

Thanks, Peter.

Hi, I’m the Toradex AI Assistant.

I might make mistakes or occasionally get you wrong. Our support team will step in if needed.


USB Configuration on Verdin iMX8M Plus with Mallow Carrier

Based on the Verdin iMX8M Plus datasheet, the USB configuration issue you’re experiencing is related to the specific USB port design and device tree configuration (1).

USB Port Configuration

The Verdin iMX8M Plus has two USB ports with different capabilities (1):

  • USB_1: OTG capable (can function as both host and device)
  • USB_2: Host-only port with USB 3.1 Gen 1 SuperSpeed support

The datasheet specifically states that “it is recommended to use only the USB_1 as an OTG port” and “for compatibility purposes, it is recommended to use the USB_1 only with the USB 2.0 signals” (1).

Device Tree Overlay Solution

To enable USB device mode functionality, you’ll need to create a device tree overlay that properly configures the USB_1 port for OTG operation (2). The overlay development process involves three main steps (2):

  1. Write a Device Tree Overlay (.dts) file
  2. Compile the .dts file to generate a .dtbo file
  3. Enable the overlay (using the .dtbo file)

Deployment Process

For your Yocto-based build, you can deploy the overlay by (2):

  1. Copy the .dtbo file to the overlays/ directory in the boot partition
  2. Add the overlay binary .dtbo to the overlays.txt file

The overlays.txt file should contain a space-separated list of overlays (2):

$ cat /boot/overlays.txt   
fdt_overlays=verdin-imx8mm_lt8912_overlay.dtbo verdin-imx8mm_ov5640_overlay.dtbo  

USB Pin Configuration

According to the Verdin iMX8M Plus V1.1 datasheet, the USB_1 interface pins include the OTG ID detection pin, which is critical for OTG functionality (1). The USB_1_ID pin (X1 Pin 161) is mapped to GPIO2_IO10 and is used “to detect the ID pin if you use the port in OTG mode” (1).

Next Steps

To resolve your issue, you’ll need to create a device tree overlay that:

  • Configures the USB_1 port for OTG operation instead of forced host mode
  • Properly sets up the USB controller for device mode functionality
  • Ensures the OTG ID detection is working correctly

The message you’re seeing about “dr_mode forced to host” indicates the current device tree configuration is explicitly setting the USB controller to host-only mode, which prevents device mode operation.

Best regards, Toradex AI Assistant.


Did you like my answer? :+1: :-1:

If I answered your question, please tick the “Solution” checkbox.

For follow-up questions to me, please use @ToradexAI in your post.

Thanks @ToradexAI, that’s useful.

I have tried writing a device tree overlay, but I still couldn’t get the USB-C port to work, so either the content of the dts was wrong, or I wasn’t enabling the overlay properly.

Would you be able to direct me to instructions for writing the correct dts to enable OTG on USB_1, or even just provide the .dts contents to configure USB-1 for OTG operation, for an iMX8MP on a Mallow carrier?

Thanks, Peter.

I can guide you through creating a device tree overlay for USB OTG on the Verdin iMX8M Plus with Mallow carrier.

Device Tree Overlay Structure

Based on the Toradex documentation, writing a device tree overlay involves four main steps (1):

  1. Define a target hardware: Specify the hardware your overlay will be compatible with (1)
  2. Create a pin group: Configure pins for specific functions (1)
  3. Enable your group: Tell the kernel which peripheral should control the pin group (1)
  4. Avoid Pinmux conflicts: Ensure no other peripheral is using your pin (1)

Basic Overlay Template

Here’s the basic structure for your USB OTG overlay, following the standard template (2):

/dts-v1/;
/plugin/; //Indicates a Device Tree Overlay

// Header file with pin definitions
#include <soc-pinfunc.h>

/ {
	compatible = "toradex,verdin-imx8mp"; // Set hardware compatibility
};
	
&iomuxc {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl-originally-in-device-tree>, <&pinctrl_my_pins>;  // Pin group available in userspace i.e. as GPIO

	name-of-som {
		pinctrl_my_pins: my_muxgrp {
			fsl,pins = <
				PIN_NAME_PIN_MUX   PAD_CTRL // PINS
			>;
		};
	};
};

&node {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_my_pins>;  // Pin group used in genericPeripheral
	status = "okay";
};

(2)

Key Considerations for USB OTG

For your specific USB OTG configuration, you’ll need to:

  1. Identify the USB controller node in the base device tree that corresponds to USB_1
  2. Modify the dr_mode property from “host” to “otg” to enable OTG functionality
  3. Configure the OTG ID pin properly for detection

Finding Existing Overlays

The most recommended approach is to start with existing overlays and adapt them to your needs (3). You can find Toradex’s device tree overlays in the device-tree-overlays repository (3).

Compilation and Deployment

To build your overlay (2):

  1. Manual Build: Use the Device Tree Compiler (DTC) tool as described in Build Device Tree Overlays from Source Code (2)

  2. Yocto Project: Use the recipes that handle device tree overlays for your build (2)

Deployment Process

For your Yocto-based system (3):

  1. Copy the .dtbo file to the overlays/ directory in the boot partition (3)
  2. Add the file name to the overlays.txt file (3):
$ cat /boot/overlays.txt   
fdt_overlays=verdin-imx8mm_lt8912_overlay.dtbo verdin-imx8mm_ov5640_overlay.dtbo custom-overlay.dtbo

(3)

  1. Run sync and reboot (3):
$ sync   
$ reboot

(3)

Troubleshooting

If your device doesn’t boot or the functionality doesn’t work (1):

  • Check if you disabled the previously used function of your pin (1)
  • Connect via serial to view boot log information (1)
  • Use dmesg to read kernel messages for debug information (1)
  • Verify your overlay is applied correctly (1)

For the specific USB controller nodes and pin configurations for the Verdin iMX8M Plus, you’ll need to examine the base device tree files in your kernel source to identify the exact node names and properties to modify.

Best regards, Toradex AI Assistant.


Did you like my answer? :+1: :-1:

If I answered your question, please tick the “Solution” checkbox.

For follow-up questions to me, please use @ToradexAI in your post.

Thanks @ToradexAI.

I’m not sure why your example is about pin groups and pinmux conflicts, is that just a standard template? It doesn’t seem related to USB OTG configuration.

None of the existing overlays in the repository are related to USB, so they’re of limited use.

From inspecting the device tree dtsi files, I believe that the USB controller node is usb_dwc3_0, but this already has dr_mode set to “otg” in imx8mp-verdin.dtsi. This doesn’t seem to be overridden anywhere else, so I think this is already correct.

The only other thing you’ve mentioned is configuring the OTG ID pin, which I can find no obvious reference to in the device tree files, could you expand on how this should be done please?

Thanks, Peter.

I notice you need help with the specific USB OTG configuration. I don’t have specific information about the OTG ID pin configuration for the Verdin iMX8M Plus in the available sources.

However, there is a known hardware issue that might be relevant to your situation. According to the Verdin iMX8M Plus Errata, there’s a documented problem with the USB 2.0 OTG interface (1):

Known Hardware Issue

Errata #2: HAR-6503 - Automatic role switching doesn’t work on the USB 2.0 OTG interface (1).

Affected Version: Verdin iMX8M Plus V1.0
Fixed in: Verdin iMX8M Plus V1.1 (1)

Customer Impact

The USB OTG port cannot dynamically switch between host and client function, depending on the OTG cable that is plugged in (1). The Toradex BSP sets the USB_1 port permanently to the client mode (1). It is also possible to set the USB_1 port permanently to host mode (1).

Troubleshooting Steps

Given this hardware limitation on V1.0 modules, you may need to:

  1. Check your module version - If you have a V1.0 module, the automatic OTG role switching won’t work due to this hardware errata
  2. Force device mode - You might need to explicitly configure the USB controller for device mode rather than relying on OTG detection

Next Steps

Since the specific OTG ID pin configuration details aren’t available in my current sources, I’d recommend checking these potentially helpful resources:

Would you like me to provide a general answer based on my knowledge of USB OTG configuration, or do you have access to the module version information to determine if this hardware errata applies to your setup?

Best regards, Toradex AI Assistant.


Did you like my answer? :+1: :-1:

If I answered your question, please tick the “Solution” checkbox.

For follow-up questions to me, please use @ToradexAI in your post.

I’m using a V1.1B module, so the errata doesn’t apply. Anyway, the problem I have isn’t role switching (I think), the USB-C port doesn’t work as either host or peripheral as far as I can tell.

If you don’t have OTG ID pin details, then it seems unlikely that I’m going to find anything (assuming that you’re trained on all of Toradex’s information sources).

Maybe the reason the AI doesn’t have OTG ID pin details is because there is no pin? The Mallow carrier board datasheet states that “the USB Type-C receptacle lacks the ID pin.”

Has anyone with non-artificial intelligence had any experience of using the USB-C port on the Mallow carrier?

My original issue was that I’ve tried following the instructions in this article: USB Device Mode (Linux) | Toradex Developer Center but when I get to step 10, “# ls /sys/class/udc/”, there’s nothing in /sys/class/udc.

Hi @PeterRT,

The USB C port (connector X8) which is linked to the USB_1 port on Mallow board should be enabled by default on the device tree for Verdin iMX8MP (enabled in imx8mp-verdin-mallow.dtsi file):

/* Verdin USB_1 */
&usb3_0 {
        status = "okay";
};

And you can see in imx8mp-verdin.dtsi:

/* Verdin USB_1 */
&usb3_0 {
        fsl,disable-port-power-control;
        fsl,over-current-active-low;
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_usb_1_oc_n>;
};

And in imx8mp.dtsi:

usb3_0: usb@32f10100 {
                        compatible = "fsl,imx8mp-dwc3";
                        reg = <0x32f10100 0x8>,
                              <0x381f0000 0x20>;
                        clocks = <&clk IMX8MP_CLK_HSIO_ROOT>,
                                 <&clk IMX8MP_CLK_USB_SUSP>;
                        clock-names = "hsio", "suspend";
                        interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
                        power-domains = <&hsio_blk_ctrl IMX8MP_HSIOBLK_PD_USB>;
                        #address-cells = <1>;
                        #size-cells = <1>;
                        dma-ranges = <0x40000000 0x40000000 0xc0000000>;
                        ranges;
                        status = "disabled";

                        usb_dwc3_0: usb@38100000 {
                                compatible = "snps,dwc3";
                                reg = <0x38100000 0x10000>;
                                clocks = <&clk IMX8MP_CLK_USB_ROOT>,
                                         <&clk IMX8MP_CLK_USB_CORE_REF>,
                                         <&clk IMX8MP_CLK_USB_SUSP>;
                                clock-names = "bus_early", "ref", "suspend";
                                interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
                                phys = <&usb3_phy0>, <&usb3_phy0>;
                                phy-names = "usb2-phy", "usb3-phy";
                                snps,gfladj-refclk-lpm-sel-quirk;
                                snps,parkmode-disable-ss-quirk;
                        };

                };

The node usb_dwc3_0 is what provides the dual role functionality, as it is redefined in imx8mp-verdin.dtsi:

&usb_dwc3_0 {
        /* dual role only, not full featured OTG */
        adp-disable;
        dr_mode = "otg";
        hnp-disable;
        maximum-speed = "high-speed";
        role-switch-default-mode = "peripheral";
        srp-disable;
        usb-role-switch;

        connector {
                compatible = "gpio-usb-b-connector", "usb-b-connector";
                id-gpios = <&gpio2 10 GPIO_ACTIVE_HIGH>;
                label = "Type-C";
                pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_usb_1_id>;
                self-powered;
                type = "micro";
                vbus-supply = <&reg_usb1_vbus>;
        };
};

I see in the comment that it is not fully featured for OTG operation. Regardless, I checked the schematics of Mallow board to see the connections to this USB C port and from the hardware point of view, I can see OTG functionality should work for this USB port.

I am not sure why you don’t see the name of the controller in /sys/class/UDC. I have a Verdin iMX8MP module on a Mallow carrier board here, running Tordaex BSP 7.4.0, with the device tree imx8mp-verdin-wifi-mallow.dtb enabled. I followed the article that you linked above to configure USB device mode on it. I can see:

root@verdin-imx8mp-15247177:/sys/kernel/config/usb_gadget# ls /sys/class/udc/
38100000.usb

Could you first check on the Toradex BSP 7.4.0?

My recommendation would be to first fix this part and then test the OTG functionality of the port.

Hi @rudhi.tx

Thanks for your reply, and for taking the time to look into this, it’s appreciated. And it’s good to know that this can work, I was starting to wonder!

I’m using BSP 7.2.0 at the moment, I’ll try 7.4.0 and see if that works for me. If not, there must be something else I’ve done that’s breaking it.

Thanks again, Peter.

Hi @rudhi.tx ,

I did the following steps to upgrade BSP to 7.4.0:

repo init -u git://git.toradex.com/toradex-manifest.git -b refs/tags/7.4.0 -m tdxref/default.xml
repo sync
bitbake core-image-minimal

Is that enough? Because it fails to build with:

ERROR: Cannot find specified cross file: build/tmp/work/armv8a-mx8mp-tdx-linux/cairo/1.18.0/meson.cross

I tried the same with 7.3.0 (as that’s listed as the latest released BSP version) with the same failure. Going back to 7.2.0 gives me a working core-image-minimal bitbake build.

There’s clearly a lot I don’t understand about Yocto and bitbake, and I’m almost certainly doing something wrong. Any pointers you can give to help would be gratefully received.

Thanks, Peter.

Hello @PeterRT,

Your yocto setup commands look right to me. You just need to make sure that you also change the machine name in the local.conf file to verdin-imx8mp.

Can you try building the image again after deleting build/tmp, build/cache directories ?

If these don’t fix the issue and you really need to build an image to test this, I would start a new project and try again.

Just in case you don’t know, for a simple test with the Toradex BSP, you don’t need to build one. You can download and install our reference images in different versions from our feed servers. You need to put the module in recovery mode, load Toradex Easy Installer and access it’s GUI to install an image.

Hi @rudhi.tx

A quick update to let you know that I have the USB-C port working now. The issue was with kernel config, it seems.

To get the port working in host mode (I haven’t tried gadget mode yet, but /sys/class/udc now has an entry in it, so I think gadget will be OK) I patched the kernel config as follows:

CONFIG_USB_DWC3_HOST unset  (previously ‘y')
CONFIG_USB_DWC3_DUAL_ROLE=y (previously unset)
CONFIG_PCI_HOST_COMMON=y    (previously ‘m')
CONFIG_PCI_HOST_GENERIC=y   (previously ‘m')

Thanks for your help, knowing that the USB-C worked with the 7.4 tdx reference image was enough to give me something to compare against to find where the problem was.

Best regards, Peter.

Thanks a lot for your update and for sharing your solution.