Merge tag 'u-boot-atmel-fixes-2021.01-b' of https://gitlab.denx.de/u-boot/custodians...
[platform/kernel/u-boot.git] / drivers / usb / dwc3 / dwc3-generic.c
index 023e953..a936f71 100644 (file)
@@ -8,11 +8,14 @@
  */
 
 #include <common.h>
-#include <asm-generic/io.h>
+#include <cpu_func.h>
+#include <log.h>
 #include <dm.h>
 #include <dm/device-internal.h>
 #include <dm/lists.h>
 #include <dwc3-uboot.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 #include <malloc.h>
 #include <clk.h>
 #include <usb/xhci.h>
 
+struct dwc3_glue_data {
+       struct clk_bulk         clks;
+       struct reset_ctl_bulk   resets;
+       fdt_addr_t regs;
+};
+
 struct dwc3_generic_plat {
        fdt_addr_t base;
        u32 maximum_speed;
@@ -32,8 +41,7 @@ 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 {
@@ -47,6 +55,7 @@ static int dwc3_generic_probe(struct udevice *dev,
        int rc;
        struct dwc3_generic_plat *plat = dev_get_platdata(dev);
        struct dwc3 *dwc3 = &priv->dwc3;
+       struct dwc3_glue_data *glue = dev_get_platdata(dev->parent);
 
        dwc3->dev = dev;
        dwc3->maximum_speed = plat->maximum_speed;
@@ -55,10 +64,22 @@ static int dwc3_generic_probe(struct udevice *dev,
        dwc3_of_parse(dwc3);
 #endif
 
-       rc = dwc3_setup_phy(dev, &priv->phys, &priv->num_phys);
-       if (rc)
+       /*
+        * It must hold whole USB3.0 OTG controller in resetting to hold pipe
+        * power state in P2 before initializing TypeC PHY on RK3399 platform.
+        */
+       if (device_is_compatible(dev->parent, "rockchip,rk3399-dwc3")) {
+               reset_assert_bulk(&glue->resets);
+               udelay(1);
+       }
+
+       rc = dwc3_setup_phy(dev, &priv->phys);
+       if (rc && rc != -ENOTSUPP)
                return rc;
 
+       if (device_is_compatible(dev->parent, "rockchip,rk3399-dwc3"))
+               reset_deassert_bulk(&glue->resets);
+
        priv->base = map_physmem(plat->base, DWC3_OTG_REGS_END, MAP_NOCACHE);
        dwc3->regs = priv->base + DWC3_GLOBALS_REGS_START;
 
@@ -78,7 +99,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;
@@ -87,9 +108,9 @@ 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) {
@@ -186,12 +207,6 @@ U_BOOT_DRIVER(dwc3_generic_host) = {
 };
 #endif
 
-struct dwc3_glue_data {
-       struct clk_bulk         clks;
-       struct reset_ctl_bulk   resets;
-       fdt_addr_t regs;
-};
-
 struct dwc3_glue_ops {
        void (*select_dr_mode)(struct udevice *dev, int index,
                               enum usb_dr_mode mode);
@@ -283,13 +298,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;
@@ -321,7 +334,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__);
@@ -338,7 +351,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;
@@ -358,7 +371,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;
@@ -396,10 +409,16 @@ static int dwc3_glue_probe(struct udevice *dev)
        if (ret)
                return ret;
 
+       if (glue->resets.count == 0) {
+               ret = dwc3_glue_reset_init(child, glue);
+               if (ret)
+                       return ret;
+       }
+
        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);
@@ -422,9 +441,14 @@ 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" },
+       { .compatible = "rockchip,rk3328-dwc3" },
+       { .compatible = "rockchip,rk3399-dwc3" },
+       { .compatible = "qcom,dwc3" },
        { }
 };