Merge tag 'ti-v2020.07-rc3' of https://gitlab.denx.de/u-boot/custodians/u-boot-ti
[oweals/u-boot.git] / drivers / usb / dwc3 / dwc3-generic.c
index d5c71d024f37844cf3db2c99a101cc567380a690..484e7a7b8c8bf6be176fd4d4d86923aabee73774 100644 (file)
@@ -8,11 +8,14 @@
  */
 
 #include <common.h>
+#include <cpu_func.h>
+#include <log.h>
 #include <asm-generic/io.h>
 #include <dm.h>
 #include <dm/device-internal.h>
 #include <dm/lists.h>
 #include <dwc3-uboot.h>
+#include <linux/bitops.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 #include <malloc.h>
@@ -21,6 +24,7 @@
 #include "gadget.h"
 #include <reset.h>
 #include <clk.h>
+#include <usb/xhci.h>
 
 struct dwc3_generic_plat {
        fdt_addr_t base;
@@ -31,8 +35,12 @@ struct dwc3_generic_plat {
 struct dwc3_generic_priv {
        void *base;
        struct dwc3 dwc3;
-       struct phy *phys;
-       int num_phys;
+       struct phy_bulk phys;
+};
+
+struct dwc3_generic_host_priv {
+       struct xhci_ctrl xhci_ctrl;
+       struct dwc3_generic_priv gen_priv;
 };
 
 static int dwc3_generic_probe(struct udevice *dev,
@@ -42,16 +50,20 @@ static int dwc3_generic_probe(struct udevice *dev,
        struct dwc3_generic_plat *plat = dev_get_platdata(dev);
        struct dwc3 *dwc3 = &priv->dwc3;
 
+       dwc3->dev = dev;
        dwc3->maximum_speed = plat->maximum_speed;
        dwc3->dr_mode = plat->dr_mode;
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+       dwc3_of_parse(dwc3);
+#endif
 
-       rc = dwc3_setup_phy(dev, &priv->phys, &priv->num_phys);
+       rc = dwc3_setup_phy(dev, &priv->phys);
        if (rc)
                return rc;
 
        priv->base = map_physmem(plat->base, DWC3_OTG_REGS_END, MAP_NOCACHE);
        dwc3->regs = priv->base + DWC3_GLOBALS_REGS_START;
-       dwc3->dev = dev;
+
 
        rc =  dwc3_init(dwc3);
        if (rc) {
@@ -68,7 +80,7 @@ static int dwc3_generic_remove(struct udevice *dev,
        struct dwc3 *dwc3 = &priv->dwc3;
 
        dwc3_remove(dwc3);
-       dwc3_shutdown_phy(dev, priv->phys, priv->num_phys);
+       dwc3_shutdown_phy(dev, &priv->phys);
        unmap_physmem(dwc3->regs, MAP_NOCACHE);
 
        return 0;
@@ -77,14 +89,14 @@ static int dwc3_generic_remove(struct udevice *dev,
 static int dwc3_generic_ofdata_to_platdata(struct udevice *dev)
 {
        struct dwc3_generic_plat *plat = dev_get_platdata(dev);
-       int node = dev_of_offset(dev);
+       ofnode node = dev->node;
 
-       plat->base = devfdt_get_addr(dev);
+       plat->base = dev_read_addr(dev);
 
        plat->maximum_speed = usb_get_maximum_speed(node);
        if (plat->maximum_speed == USB_SPEED_UNKNOWN) {
-               pr_err("Invalid usb maximum speed\n");
-               return -ENODEV;
+               pr_info("No USB maximum speed specified. Using super speed\n");
+               plat->maximum_speed = USB_SPEED_SUPER;
        }
 
        plat->dr_mode = usb_get_dr_mode(node);
@@ -132,6 +144,50 @@ U_BOOT_DRIVER(dwc3_generic_peripheral) = {
 };
 #endif
 
+#if defined(CONFIG_SPL_USB_HOST_SUPPORT) || !defined(CONFIG_SPL_BUILD)
+static int dwc3_generic_host_probe(struct udevice *dev)
+{
+       struct xhci_hcor *hcor;
+       struct xhci_hccr *hccr;
+       struct dwc3_generic_host_priv *priv = dev_get_priv(dev);
+       int rc;
+
+       rc = dwc3_generic_probe(dev, &priv->gen_priv);
+       if (rc)
+               return rc;
+
+       hccr = (struct xhci_hccr *)priv->gen_priv.base;
+       hcor = (struct xhci_hcor *)(priv->gen_priv.base +
+                       HC_LENGTH(xhci_readl(&(hccr)->cr_capbase)));
+
+       return xhci_register(dev, hccr, hcor);
+}
+
+static int dwc3_generic_host_remove(struct udevice *dev)
+{
+       struct dwc3_generic_host_priv *priv = dev_get_priv(dev);
+       int rc;
+
+       rc = xhci_deregister(dev);
+       if (rc)
+               return rc;
+
+       return dwc3_generic_remove(dev, &priv->gen_priv);
+}
+
+U_BOOT_DRIVER(dwc3_generic_host) = {
+       .name   = "dwc3-generic-host",
+       .id     = UCLASS_USB,
+       .ofdata_to_platdata = dwc3_generic_ofdata_to_platdata,
+       .probe = dwc3_generic_host_probe,
+       .remove = dwc3_generic_host_remove,
+       .priv_auto_alloc_size = sizeof(struct dwc3_generic_host_priv),
+       .platdata_auto_alloc_size = sizeof(struct dwc3_generic_plat),
+       .ops = &xhci_usb_ops,
+       .flags = DM_FLAG_ALLOC_PRIV_DMA,
+};
+#endif
+
 struct dwc3_glue_data {
        struct clk_bulk         clks;
        struct reset_ctl_bulk   resets;
@@ -229,13 +285,11 @@ struct dwc3_glue_ops ti_ops = {
 
 static int dwc3_glue_bind(struct udevice *parent)
 {
-       const void *fdt = gd->fdt_blob;
-       int node;
+       ofnode node;
        int ret;
 
-       for (node = fdt_first_subnode(fdt, dev_of_offset(parent)); node > 0;
-            node = fdt_next_subnode(fdt, node)) {
-               const char *name = fdt_get_name(fdt, node, NULL);
+       ofnode_for_each_subnode(node, parent->node) {
+               const char *name = ofnode_get_name(node);
                enum usb_dr_mode dr_mode;
                struct udevice *dev;
                const char *driver = NULL;
@@ -252,10 +306,12 @@ static int dwc3_glue_bind(struct udevice *parent)
                        driver = "dwc3-generic-peripheral";
 #endif
                        break;
+#if defined(CONFIG_SPL_USB_HOST_SUPPORT) || !defined(CONFIG_SPL_BUILD)
                case USB_DR_MODE_HOST:
                        debug("%s: dr_mode: HOST\n", __func__);
-                       driver = "xhci-dwc3";
+                       driver = "dwc3-generic-host";
                        break;
+#endif
                default:
                        debug("%s: unsupported dr_mode\n", __func__);
                        return -ENODEV;
@@ -265,7 +321,7 @@ static int dwc3_glue_bind(struct udevice *parent)
                        continue;
 
                ret = device_bind_driver_to_node(parent, driver, name,
-                                                offset_to_ofnode(node), &dev);
+                                                node, &dev);
                if (ret) {
                        debug("%s: not able to bind usb device mode\n",
                              __func__);
@@ -282,7 +338,7 @@ static int dwc3_glue_reset_init(struct udevice *dev,
        int ret;
 
        ret = reset_get_bulk(dev, &glue->resets);
-       if (ret == -ENOTSUPP)
+       if (ret == -ENOTSUPP || ret == -ENOENT)
                return 0;
        else if (ret)
                return ret;
@@ -302,7 +358,7 @@ static int dwc3_glue_clk_init(struct udevice *dev,
        int ret;
 
        ret = clk_get_bulk(dev, &glue->clks);
-       if (ret == -ENOSYS)
+       if (ret == -ENOSYS || ret == -ENOENT)
                return 0;
        if (ret)
                return ret;
@@ -343,7 +399,7 @@ static int dwc3_glue_probe(struct udevice *dev)
        while (child) {
                enum usb_dr_mode dr_mode;
 
-               dr_mode = usb_get_dr_mode(dev_of_offset(child));
+               dr_mode = usb_get_dr_mode(child->node);
                device_find_next_child(&child);
                if (ops && ops->select_dr_mode)
                        ops->select_dr_mode(dev, index, dr_mode);
@@ -366,9 +422,11 @@ static int dwc3_glue_remove(struct udevice *dev)
 
 static const struct udevice_id dwc3_glue_ids[] = {
        { .compatible = "xlnx,zynqmp-dwc3" },
+       { .compatible = "xlnx,versal-dwc3" },
        { .compatible = "ti,keystone-dwc3"},
        { .compatible = "ti,dwc3", .data = (ulong)&ti_ops },
        { .compatible = "ti,am437x-dwc3", .data = (ulong)&ti_ops },
+       { .compatible = "ti,am654-dwc3" },
        { }
 };