]> git.sur5r.net Git - u-boot/commitdiff
net: designware: add clock support
authorPatrice Chotard <patrice.chotard@st.com>
Wed, 29 Nov 2017 08:06:11 +0000 (09:06 +0100)
committerJoe Hershberger <joe.hershberger@ni.com>
Mon, 15 Jan 2018 18:05:20 +0000 (12:05 -0600)
This implementation manages several clocks, disable and
free all of them in case of error during probe and in remove
callback.

Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Acked-by: Joe Hershberger <joe.hershberger@ni.com>
drivers/net/designware.c
drivers/net/designware.h

index 036d231071caefb75d304e8b77c8c85ac3a475bf..9207324731e5c2c38d6ac5d14e5498511c0833dd 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #include <common.h>
+#include <clk.h>
 #include <dm.h>
 #include <errno.h>
 #include <miiphy.h>
@@ -661,6 +662,35 @@ int designware_eth_probe(struct udevice *dev)
        u32 iobase = pdata->iobase;
        ulong ioaddr;
        int ret;
+#ifdef CONFIG_CLK
+       int i, err, clock_nb;
+
+       priv->clock_count = 0;
+       clock_nb = dev_count_phandle_with_args(dev, "clocks", "#clock-cells");
+       if (clock_nb > 0) {
+               priv->clocks = devm_kcalloc(dev, clock_nb, sizeof(struct clk),
+                                           GFP_KERNEL);
+               if (!priv->clocks)
+                       return -ENOMEM;
+
+               for (i = 0; i < clock_nb; i++) {
+                       err = clk_get_by_index(dev, i, &priv->clocks[i]);
+                       if (err < 0)
+                               break;
+
+                       err = clk_enable(&priv->clocks[i]);
+                       if (err) {
+                               pr_err("failed to enable clock %d\n", i);
+                               clk_free(&priv->clocks[i]);
+                               goto clk_err;
+                       }
+                       priv->clock_count++;
+               }
+       } else if (clock_nb != -ENOENT) {
+               pr_err("failed to get clock phandle(%d)\n", clock_nb);
+               return clock_nb;
+       }
+#endif
 
 #if defined(CONFIG_DM_REGULATOR)
        struct udevice *phy_supply;
@@ -707,6 +737,15 @@ int designware_eth_probe(struct udevice *dev)
        debug("%s, ret=%d\n", __func__, ret);
 
        return ret;
+
+#ifdef CONFIG_CLK
+clk_err:
+       ret = clk_release_all(priv->clocks, priv->clock_count);
+       if (ret)
+               pr_err("failed to disable all clocks\n");
+
+       return err;
+#endif
 }
 
 static int designware_eth_remove(struct udevice *dev)
@@ -717,7 +756,11 @@ static int designware_eth_remove(struct udevice *dev)
        mdio_unregister(priv->bus);
        mdio_free(priv->bus);
 
+#ifdef CONFIG_CLK
+       return clk_release_all(priv->clocks, priv->clock_count);
+#else
        return 0;
+#endif
 }
 
 const struct eth_ops designware_eth_ops = {
index 7992d0ebeebf8ffb0fb86c3bdced2f856e76d67e..252cd24f1aafbc46b0d030fc3e6a4a37e9736869 100644 (file)
@@ -239,6 +239,10 @@ struct dw_eth_dev {
 #ifdef CONFIG_DM_GPIO
        struct gpio_desc reset_gpio;
 #endif
+#ifdef CONFIG_CLK
+       struct clk *clocks;     /* clock list */
+       int clock_count;        /* number of clock in clock list */
+#endif
 
        struct phy_device *phydev;
        struct mii_dev *bus;