[PATCH] rockchip: rk3576: Properly handle USB controller takeover from BootROM

Quentin Schulz quentin.schulz at cherry.de
Mon Apr 27 16:43:36 CEST 2026


Hi Alexey,

On 4/27/26 2:53 PM, Alexey Charkov wrote:
> From: Anton Burticica <mouse at ya.ru>
> 
> When booting via USB download mode (Maskrom), the BootROM leaves the
> USB3OTG0 controller in an active state. U-Boot must properly reset
> the controller before reinitializing it for fastboot or other USB
> gadget functions.
> 
> Without this change, USB gadget mode commands such as fastboot and ums
> fail when U-Boot is loaded via Maskrom USB download because the
> controller state is inconsistent.
> 
> Signed-off-by: Anton Burticica <mouse at ya.ru>
> [Removed unrelated changes, adjusted the commit description]
> Signed-off-by: Alexey Charkov <alchark at flipper.net>
> ---
>   arch/arm/mach-rockchip/rk3576/rk3576.c | 18 ++++++++++++++++++
>   1 file changed, 18 insertions(+)
> 
> diff --git a/arch/arm/mach-rockchip/rk3576/rk3576.c b/arch/arm/mach-rockchip/rk3576/rk3576.c
> index c17ba418ced5..84618ad5acb7 100644
> --- a/arch/arm/mach-rockchip/rk3576/rk3576.c
> +++ b/arch/arm/mach-rockchip/rk3576/rk3576.c
> @@ -7,6 +7,8 @@
>   
>   #include <dm.h>
>   #include <misc.h>
> +#include <linux/bitops.h>
> +#include <linux/delay.h>
>   #include <asm/armv8/mmu.h>
>   #include <asm/arch-rockchip/bootrom.h>
>   #include <asm/arch-rockchip/hardware.h>
> @@ -39,6 +41,10 @@
>   #define USB_GRF_BASE		0x2601E000
>   #define USB3OTG0_CON1		0x0030
>   
> +#define TOP_CRU_BASE		0x27200000
> +#define TOP_CRU_SOFTRST_CON47	0x0abc
> +#define SOFTRST47_ARESETN_USB3OTG0	BIT(5)
> +
>   enum {
>   	BROM_BOOTSOURCE_FSPI0 = 3,
>   	BROM_BOOTSOURCE_FSPI1_M1 = 6,
> @@ -189,6 +195,18 @@ int arch_cpu_init(void)
>   	 */
>   	writel(0xffffff00, SYS_SGRF_BASE + SYS_SGRF_SOC_CON20);
>   
> +	/* If the controller was left running by the boot ROM, reset it */
> +	if (read_brom_bootsource_id() == BROM_BOOTSOURCE_USB) {
> +		/* Assert USB3OTG0 reset */
> +		writel(RK_SETBITS(SOFTRST47_ARESETN_USB3OTG0),
> +		       TOP_CRU_BASE + TOP_CRU_SOFTRST_CON47);
> +		udelay(1000);
> +		/* De-assert USB3OTG0 reset */
> +		writel(RK_CLRBITS(SOFTRST47_ARESETN_USB3OTG0),
> +		       TOP_CRU_BASE + TOP_CRU_SOFTRST_CON47);
> +		udelay(1000);
> +	}
> +

Uh... Wouldn't the issue rather be that the U-Boot driver doesn't 
actually reset the device?

Can you try with

diff --git a/drivers/usb/dwc3/dwc3-generic.c 
b/drivers/usb/dwc3/dwc3-generic.c
index 22b9ef0b24e..1b7d845bc75 100644
--- a/drivers/usb/dwc3/dwc3-generic.c
+++ b/drivers/usb/dwc3/dwc3-generic.c
@@ -604,6 +604,9 @@ static int dwc3_glue_reset_init(struct udevice *dev,
  		 * have slower sleep clocks so we'll play it safe.
  		 */
  		udelay(500);
+	} else if (device_is_compatible(dev, "rockchip,rk3576-dwc3")) {
+		reset_assert_bulk(&glue->resets);
+		udelay(1000);
  	}
  	ret = reset_deassert_bulk(&glue->resets);
  	if (ret) {

maybe? Hunch is that every variant of this driver actually needs to do 
this to avoid to rely on the device being out of reset already, but the 
delay is likely silicon-implementation-specific? The driver in the Linux 
kernel doesn't actually assert it either before deasserting it, so who 
knows. Adding Marek in Cc.

Otherwise, for sure we do not want to de-assert the signal in the rk3576 
SoC C file, we don't know if the driver is even built and we should let 
it do it if need be.

Cheers,
Quentin


More information about the U-Boot mailing list