RK3328 has a USB 3.0 dual role device controller (USB 3.0 Gadget mode on PINE64 Rock64, and maybe your RK3328 board too)

2026/08/27

This article assumes that you are already rather familiar with the Linux USB gadget subsystem. If you’re not, this is my preferred introduction.

I have an old PINE64 Rock64 board that I got a long while ago, it’s been sitting kind of on the backburner because it’s on the weaker end of devices I own. Recently, I noticed something a little bit unusual about the RK3328’s USB 3.0 port device tree node - it is laid out exactly like the RK3399’s dual role USB 3.0 device tree node. It is seemingly exactly the same Designware dwc3 USB 3.0 dual-role controller IP block as is used in many, many other SoCs, which can operate as a dual role controller. The technical reference manual seemed to imply that switching from host to device mode is possible, because a lot of the registers for role-switching the dwc3 controller were indeed noted, though not commented on at all in any other RK3328 documentation other than just being listed. In the end, I was able to get it working. It is very fussy though, here is my experience:

Device tree overlay/changes:

&usbdrd3 {
        dr_mode = "peripheral";
};

is enough for basic device operations. USB devices will no longer work on the port after this change is made, and you’ll most likely have to use an ‘illegal’ USB A-A 3.0 cable. Fortunately, those are pretty abundant due to the PCI-E risers that use them as interconnects, so I have many of them. I have not been able to get role-switching to operate properly, you’re gonna have to figure that out on your own, or just deal with it not being dynamically configurable.

You must have the USB cable plugged in at boot-time in order for the device to initialize properly on the host. Otherwise it just acts like nothing at all is connected on the USB host end. After everything is booted, you can then plug and unplug the device freely between computers as long as you un-register and re-register the USB gadget with the UDC on plug (echo "" > UDC; echo "usb.ff600000" > UDC) Not pursuing the root cause, it isn’t a concern with what I am considering using this for.

You must disable USB Link Power Management, or else the device will continually connect and disconnect with power management “U1/U2 enable/disable” type errors in dmesg on the host side: either use a kernel boot parameter, usbcore.quirks=$GADGET_VID:$GADGET_PID:k, or add it dynamically, echo "$GADGET_VID:$GADGET_PID:k" > /sys/module/usbcore/parameters/quirks.

Have fun, make something cool. Since this looked to me to not be an officially advertised feature by Rockchip, I would like to know of any other quirks people run into while using this functionality. I have tested on a basic level that both of these work simultaneously, but I am guessing that this only works by the grace of no one specifically trying to stop it, so there may be dragons here :)

>> Home