From e69841fa71d67c560d767b786f956bb6f2873130 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Thu, 29 Jan 2026 19:52:05 +0000 Subject: [PATCH] usb: gadget: dwc2: Move dr_mode check from of_to_plat() to bind() Rockchip RK3288 and RK3506 contain two DWC2 USB controllers, typically one controller use dr_mode=otg and the other one use dr_mode=host. With USB_GADGET_DWC2_OTG, DM_USB_GADGET and USB_DWC2 enabled this result in the dwc2-udc-otg driver binding to both controllers, however only one will probe due to use of dr_mode=host on the other one. After the commit 6668b8e7cc68 ("dm: core: Support multiple drivers with same compatibles") it is possible to bind one controller to the dwc2-udc-otg driver and the other one to the dwc2_usb driver. Move the dr_mode check from of_to_plat() to bind() to allow dm core to bind the dwc2 host driver to dr_mode=host controllers. Before this: => dm tree ... usb_gadget 0 [ ] dwc2-udc-otg | |-- usb@ff740000 usb_gadget 1 [ ] dwc2-udc-otg | |-- usb@ff780000 => usb start starting USB... No USB controllers found After this: dwc2-udc-otg usb@ff780000: Invalid dr_mode 1 => dm tree ... usb_gadget 0 [ ] dwc2-udc-otg | |-- usb@ff740000 usb 0 [ ] dwc2_usb | |-- usb@ff780000 => usb start starting USB... USB DWC2 Bus usb@ff780000: 1 USB Device(s) found Signed-off-by: Jonas Karlman Reviewed-by: Mattijs Korpershoek Reviewed-by: Marek Vasut Link: https://lore.kernel.org/r/20260129195207.2260264-1-jonas@kwiboo.se Signed-off-by: Mattijs Korpershoek --- drivers/usb/gadget/dwc2_udc_otg.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c index 40393141ca9..e475b14b9ac 100644 --- a/drivers/usb/gadget/dwc2_udc_otg.c +++ b/drivers/usb/gadget/dwc2_udc_otg.c @@ -975,12 +975,6 @@ static int dwc2_udc_otg_of_to_plat(struct udevice *dev) void (*set_params)(struct dwc2_plat_otg_data *data); int ret; - if (usb_get_dr_mode(dev_ofnode(dev)) != USB_DR_MODE_PERIPHERAL && - usb_get_dr_mode(dev_ofnode(dev)) != USB_DR_MODE_OTG) { - dev_dbg(dev, "Invalid mode\n"); - return -ENODEV; - } - plat->regs_otg = dev_read_addr(dev); plat->rx_fifo_sz = dev_read_u32_default(dev, "g-rx-fifo-size", 0); @@ -1163,6 +1157,18 @@ static int dwc2_udc_otg_remove(struct udevice *dev) return dm_scan_fdt_dev(dev); } +static int dwc2_udc_otg_bind(struct udevice *dev) +{ + enum usb_dr_mode dr_mode = usb_get_dr_mode(dev_ofnode(dev)); + + if (dr_mode != USB_DR_MODE_PERIPHERAL && dr_mode != USB_DR_MODE_OTG) { + dev_dbg(dev, "Invalid dr_mode %d\n", dr_mode); + return -ENODEV; + } + + return 0; +} + static int dwc2_gadget_handle_interrupts(struct udevice *dev) { return dwc2_udc_handle_interrupt(); @@ -1186,6 +1192,7 @@ U_BOOT_DRIVER(dwc2_udc_otg) = { .of_match = dwc2_udc_otg_ids, .ops = &dwc2_gadget_ops, .of_to_plat = dwc2_udc_otg_of_to_plat, + .bind = dwc2_udc_otg_bind, .probe = dwc2_udc_otg_probe, .remove = dwc2_udc_otg_remove, .plat_auto = sizeof(struct dwc2_plat_otg_data), -- 2.47.3