Merge branch 'master' of git://git.denx.de/u-boot-usb
authorTom Rini <trini@konsulko.com>
Tue, 28 Apr 2020 14:08:47 +0000 (10:08 -0400)
committerTom Rini <trini@konsulko.com>
Tue, 28 Apr 2020 14:08:47 +0000 (10:08 -0400)
- DWC2/DWC3 improvements
- Assorted bugfixes

drivers/usb/gadget/ether.c
drivers/usb/host/dwc2.c
drivers/usb/host/dwc3-sti-glue.c
drivers/usb/host/ehci-hcd.c
include/clk.h

index a118283984c2d2e58226a93a2d26c11f58f71b8d..8533abfd9301835caa591727ae6395f2d8e67460 100644 (file)
@@ -2472,8 +2472,7 @@ static int _usb_eth_send(struct ether_priv *priv, void *packet, int length)
                }
                usb_gadget_handle_interrupts(0);
        }
-       if (rndis_pkt)
-               free(rndis_pkt);
+       free(rndis_pkt);
 
        return 0;
 drop:
index e4efaf1e5939eaebfb8a3556e74c9be96dfd53f0..f25ed2dab06800cf954d86752ac0dbf33fa14956 100644 (file)
@@ -5,13 +5,15 @@
  */
 
 #include <common.h>
+#include <clk.h>
 #include <cpu_func.h>
 #include <dm.h>
 #include <errno.h>
-#include <usb.h>
+#include <generic-phy.h>
 #include <malloc.h>
 #include <memalign.h>
 #include <phys2bus.h>
+#include <usb.h>
 #include <usbroothubdes.h>
 #include <wait_bit.h>
 #include <asm/io.h>
@@ -37,6 +39,8 @@ struct dwc2_priv {
 #ifdef CONFIG_DM_REGULATOR
        struct udevice *vbus_supply;
 #endif
+       struct phy phy;
+       struct clk_bulk clks;
 #else
        uint8_t *aligned_buffer;
        uint8_t *status_buffer;
@@ -1147,6 +1151,8 @@ static int dwc2_reset(struct udevice *dev)
                        return ret;
        }
 
+       /* force reset to clear all IP register */
+       reset_assert_bulk(&priv->resets);
        ret = reset_deassert_bulk(&priv->resets);
        if (ret) {
                reset_release_bulk(&priv->resets);
@@ -1213,6 +1219,8 @@ static int dwc2_init_common(struct udevice *dev, struct dwc2_priv *priv)
        if (readl(&regs->gintsts) & DWC2_GINTSTS_CURMODE_HOST)
                mdelay(1000);
 
+       printf("USB DWC2\n");
+
        return 0;
 }
 
@@ -1322,13 +1330,95 @@ static int dwc2_usb_ofdata_to_platdata(struct udevice *dev)
        return 0;
 }
 
+static int dwc2_setup_phy(struct udevice *dev)
+{
+       struct dwc2_priv *priv = dev_get_priv(dev);
+       int ret;
+
+       ret = generic_phy_get_by_index(dev, 0, &priv->phy);
+       if (ret) {
+               if (ret == -ENOENT)
+                       return 0; /* no PHY, nothing to do */
+               dev_err(dev, "Failed to get USB PHY: %d.\n", ret);
+               return ret;
+       }
+
+       ret = generic_phy_init(&priv->phy);
+       if (ret) {
+               dev_dbg(dev, "Failed to init USB PHY: %d.\n", ret);
+               return ret;
+       }
+
+       ret = generic_phy_power_on(&priv->phy);
+       if (ret) {
+               dev_dbg(dev, "Failed to power on USB PHY: %d.\n", ret);
+               generic_phy_exit(&priv->phy);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int dwc2_shutdown_phy(struct udevice *dev)
+{
+       struct dwc2_priv *priv = dev_get_priv(dev);
+       int ret;
+
+       /* PHY is not valid when generic_phy_get_by_index() = -ENOENT */
+       if (!generic_phy_valid(&priv->phy))
+               return 0; /* no PHY, nothing to do */
+
+       ret = generic_phy_power_off(&priv->phy);
+       if (ret) {
+               dev_dbg(dev, "Failed to power off USB PHY: %d.\n", ret);
+               return ret;
+       }
+
+       ret = generic_phy_exit(&priv->phy);
+       if (ret) {
+               dev_dbg(dev, "Failed to power off USB PHY: %d.\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int dwc2_clk_init(struct udevice *dev)
+{
+       struct dwc2_priv *priv = dev_get_priv(dev);
+       int ret;
+
+       ret = clk_get_bulk(dev, &priv->clks);
+       if (ret == -ENOSYS || ret == -ENOENT)
+               return 0;
+       if (ret)
+               return ret;
+
+       ret = clk_enable_bulk(&priv->clks);
+       if (ret) {
+               clk_release_bulk(&priv->clks);
+               return ret;
+       }
+
+       return 0;
+}
+
 static int dwc2_usb_probe(struct udevice *dev)
 {
        struct dwc2_priv *priv = dev_get_priv(dev);
        struct usb_bus_priv *bus_priv = dev_get_uclass_priv(dev);
+       int ret;
 
        bus_priv->desc_before_addr = true;
 
+       ret = dwc2_clk_init(dev);
+       if (ret)
+               return ret;
+
+       ret = dwc2_setup_phy(dev);
+       if (ret)
+               return ret;
+
        return dwc2_init_common(dev, priv);
 }
 
@@ -1341,9 +1431,17 @@ static int dwc2_usb_remove(struct udevice *dev)
        if (ret)
                return ret;
 
+       ret = dwc2_shutdown_phy(dev);
+       if (ret) {
+               dev_dbg(dev, "Failed to shutdown USB PHY: %d.\n", ret);
+               return ret;
+       }
+
        dwc2_uninit_common(priv->regs);
 
        reset_release_bulk(&priv->resets);
+       clk_disable_bulk(&priv->clks);
+       clk_release_bulk(&priv->clks);
 
        return 0;
 }
index c99a1985cca56dd49036ff3c36dae239aa165e91..99d4e29414aa43f3c0d24cf9e7b2612db9a69cfc 100644 (file)
@@ -239,7 +239,7 @@ static const struct udevice_id sti_dwc3_glue_ids[] = {
 
 U_BOOT_DRIVER(dwc3_sti_glue) = {
        .name = "dwc3_sti_glue",
-       .id = UCLASS_MISC,
+       .id = UCLASS_NOP,
        .of_match = sti_dwc3_glue_ids,
        .ofdata_to_platdata = sti_dwc3_glue_ofdata_to_platdata,
        .probe = sti_dwc3_glue_probe,
index 1edb344d0fb22cfb97ee4c05d87a068ac772ce5c..a2a85db1e7b6b6e5de026e747de983b552e8c3e0 100644 (file)
@@ -1413,13 +1413,10 @@ static struct int_queue *_ehci_create_int_queue(struct usb_device *dev,
        debug("Exit create_int_queue\n");
        return result;
 fail3:
-       if (result->tds)
-               free(result->tds);
+       free(result->tds);
 fail2:
-       if (result->first)
-               free(result->first);
-       if (result)
-               free(result);
+       free(result->first);
+       free(result);
 fail1:
        return NULL;
 }
index 3336301815ff63a1513c09d20578631fbcf41399..60c4b7d075fe8674037ab731b8f6d16cc609ba1c 100644 (file)
@@ -9,6 +9,7 @@
 #define _CLK_H_
 
 #include <dm/ofnode.h>
+#include <linux/err.h>
 #include <linux/errno.h>
 #include <linux/types.h>
 
@@ -312,6 +313,7 @@ static inline int clk_release_bulk(struct clk_bulk *bulk)
        return clk_release_all(bulk->clks, bulk->count);
 }
 
+#if CONFIG_IS_ENABLED(CLK)
 /**
  * clk_request - Request a clock by provider-specific ID.
  *
@@ -433,19 +435,6 @@ int clk_disable_bulk(struct clk_bulk *bulk);
  */
 bool clk_is_match(const struct clk *p, const struct clk *q);
 
-int soc_clk_dump(void);
-
-/**
- * clk_valid() - check if clk is valid
- *
- * @clk:       the clock to check
- * @return true if valid, or false
- */
-static inline bool clk_valid(struct clk *clk)
-{
-       return clk && !!clk->dev;
-}
-
 /**
  * clk_get_by_id() - Get the clock by its ID
  *
@@ -465,6 +454,93 @@ int clk_get_by_id(ulong id, struct clk **clkp);
  * @return true on binded, or false on no
  */
 bool clk_dev_binded(struct clk *clk);
+
+#else /* CONFIG_IS_ENABLED(CLK) */
+
+static inline int clk_request(struct udevice *dev, struct clk *clk)
+{
+       return -ENOSYS;
+}
+
+static inline int clk_free(struct clk *clk)
+{
+       return 0;
+}
+
+static inline ulong clk_get_rate(struct clk *clk)
+{
+       return -ENOSYS;
+}
+
+static inline struct clk *clk_get_parent(struct clk *clk)
+{
+       return ERR_PTR(-ENOSYS);
+}
+
+static inline long long clk_get_parent_rate(struct clk *clk)
+{
+       return -ENOSYS;
+}
+
+static inline ulong clk_set_rate(struct clk *clk, ulong rate)
+{
+       return -ENOSYS;
+}
+
+static inline int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+       return -ENOSYS;
+}
+
+static inline int clk_enable(struct clk *clk)
+{
+       return 0;
+}
+
+static inline int clk_enable_bulk(struct clk_bulk *bulk)
+{
+       return 0;
+}
+
+static inline int clk_disable(struct clk *clk)
+{
+       return 0;
+}
+
+static inline int clk_disable_bulk(struct clk_bulk *bulk)
+{
+       return 0;
+}
+
+static inline bool clk_is_match(const struct clk *p, const struct clk *q)
+{
+       return false;
+}
+
+static inline int clk_get_by_id(ulong id, struct clk **clkp)
+{
+       return -ENOSYS;
+}
+
+static inline bool clk_dev_binded(struct clk *clk)
+{
+       return false;
+}
+#endif /* CONFIG_IS_ENABLED(CLK) */
+
+/**
+ * clk_valid() - check if clk is valid
+ *
+ * @clk:       the clock to check
+ * @return true if valid, or false
+ */
+static inline bool clk_valid(struct clk *clk)
+{
+       return clk && !!clk->dev;
+}
+
+int soc_clk_dump(void);
+
 #endif
 
 #define clk_prepare_enable(clk) clk_enable(clk)