The most of devicetree has the following USB node structure.
The controller node is placed as a child node of the glue node.
Current dwc3-generic driver works on this premise.

    glue {
        /* glue node */
        usb {
            /* controller node */
        };
    };

However, UniPhier original devicetree has the following USB node structure.
The controller node is separately placed from the glue node.

    usb {
        /* controller node */
    };
    glue {
        /* glue node */
    };

In dwc_glue_bind(), this patch provides .glue_get_ctrl_dev() callback to
get such a controller node and binds the driver related to the node.

If this callback isn't defined, dwc_glue_bind() looks for the controller
nodes from the child nodes, as before.

Suggested-by: Marek Vasut <ma...@denx.de>
Signed-off-by: Kunihiko Hayashi <hayashi.kunih...@socionext.com>
Reviewed-by: Marek Vasut <ma...@denx.de>
---
 drivers/usb/dwc3/dwc3-generic.c | 93 ++++++++++++++++++++-------------
 1 file changed, 57 insertions(+), 36 deletions(-)

diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c
index 42e92478f2..e32003d68e 100644
--- a/drivers/usb/dwc3/dwc3-generic.c
+++ b/drivers/usb/dwc3/dwc3-generic.c
@@ -276,6 +276,7 @@ U_BOOT_DRIVER(dwc3_generic_host) = {
 #endif
 
 struct dwc3_glue_ops {
+       int (*glue_get_ctrl_dev)(struct udevice *parent, ofnode *node);
        void (*glue_configure)(struct udevice *dev, int index,
                               enum usb_dr_mode mode);
 };
@@ -415,54 +416,74 @@ struct dwc3_glue_ops ti_ops = {
        .glue_configure = dwc3_ti_glue_configure,
 };
 
-static int dwc3_glue_bind(struct udevice *parent)
+static int dwc3_glue_bind_common(struct udevice *parent, ofnode node)
 {
-       ofnode node;
-       int ret;
+       const char *name = ofnode_get_name(node);
+       const char *driver = NULL;
        enum usb_dr_mode dr_mode;
+       struct udevice *dev;
+       int ret;
 
-       dr_mode = usb_get_dr_mode(dev_ofnode(parent));
-
-       ofnode_for_each_subnode(node, dev_ofnode(parent)) {
-               const char *name = ofnode_get_name(node);
-               struct udevice *dev;
-               const char *driver = NULL;
-
-               debug("%s: subnode name: %s\n", __func__, name);
+       debug("%s: subnode name: %s\n", __func__, name);
 
-               /* if the parent node doesn't have a mode check the leaf */
-               if (!dr_mode)
-                       dr_mode = usb_get_dr_mode(node);
+       /* if the parent node doesn't have a mode check the leaf */
+       dr_mode = usb_get_dr_mode(dev_ofnode(parent));
+       if (!dr_mode)
+               dr_mode = usb_get_dr_mode(node);
 
-               switch (dr_mode) {
-               case USB_DR_MODE_PERIPHERAL:
-               case USB_DR_MODE_OTG:
+       switch (dr_mode) {
+       case USB_DR_MODE_PERIPHERAL:
+       case USB_DR_MODE_OTG:
 #if CONFIG_IS_ENABLED(DM_USB_GADGET)
-                       debug("%s: dr_mode: OTG or Peripheral\n", __func__);
-                       driver = "dwc3-generic-peripheral";
+               debug("%s: dr_mode: OTG or Peripheral\n", __func__);
+               driver = "dwc3-generic-peripheral";
 #endif
-                       break;
+               break;
 #if defined(CONFIG_SPL_USB_HOST) || !defined(CONFIG_SPL_BUILD)
-               case USB_DR_MODE_HOST:
-                       debug("%s: dr_mode: HOST\n", __func__);
-                       driver = "dwc3-generic-host";
-                       break;
+       case USB_DR_MODE_HOST:
+               debug("%s: dr_mode: HOST\n", __func__);
+               driver = "dwc3-generic-host";
+               break;
 #endif
-               default:
-                       debug("%s: unsupported dr_mode\n", __func__);
-                       return -ENODEV;
-               };
+       default:
+               debug("%s: unsupported dr_mode\n", __func__);
+               return -ENODEV;
+       };
 
-               if (!driver)
-                       continue;
+       if (!driver)
+               return -ENXIO;
+
+       ret = device_bind_driver_to_node(parent, driver, name,
+                                        node, &dev);
+       if (ret) {
+               debug("%s: not able to bind usb device mode\n",
+                     __func__);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int dwc3_glue_bind(struct udevice *parent)
+{
+       struct dwc3_glue_ops *ops = (struct dwc3_glue_ops 
*)dev_get_driver_data(parent);
+       ofnode node;
+       int ret;
 
-               ret = device_bind_driver_to_node(parent, driver, name,
-                                                node, &dev);
-               if (ret) {
-                       debug("%s: not able to bind usb device mode\n",
-                             __func__);
+       if (ops && ops->glue_get_ctrl_dev) {
+               ret = ops->glue_get_ctrl_dev(parent, &node);
+               if (ret)
+                       return ret;
+
+               return dwc3_glue_bind_common(parent, node);
+       }
+
+       ofnode_for_each_subnode(node, dev_ofnode(parent)) {
+               ret = dwc3_glue_bind_common(parent, node);
+               if (ret == -ENXIO)
+                       continue;
+               if (ret)
                        return ret;
-               }
        }
 
        return 0;
-- 
2.25.1

Reply via email to