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:

  => 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 <[email protected]>
---
 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 40393141ca95..d1d4fa7618b0 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 mode\n");
+               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.52.0

Reply via email to