From f7b7c721332c2e262035d306296d53c2511763a0 Mon Sep 17 00:00:00 2001 From: Kunihiko Hayashi Date: Mon, 20 Feb 2023 14:50:26 +0900 Subject: [PATCH] usb: dwc3-generic: Allow different controller DT node pattern 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 Signed-off-by: Kunihiko Hayashi Reviewed-by: Marek Vasut --- 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.39.5