SPDX: Convert all of our single license tags to Linux Kernel style
[platform/kernel/u-boot.git] / drivers / net / designware.c
index f242fc6..cf12521 100644 (file)
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * (C) Copyright 2010
  * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
 /*
@@ -10,6 +9,7 @@
  */
 
 #include <common.h>
+#include <clk.h>
 #include <dm.h>
 #include <errno.h>
 #include <miiphy.h>
 #include <pci.h>
 #include <linux/compiler.h>
 #include <linux/err.h>
+#include <linux/kernel.h>
 #include <asm/io.h>
+#include <power/regulator.h>
 #include "designware.h"
 
-DECLARE_GLOBAL_DATA_PTR;
-
 static int dw_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
 {
 #ifdef CONFIG_DM_ETH
@@ -342,6 +342,8 @@ int designware_eth_enable(struct dw_eth_dev *priv)
        return 0;
 }
 
+#define ETH_ZLEN       60
+
 static int _dw_eth_send(struct dw_eth_dev *priv, void *packet, int length)
 {
        struct eth_dma_regs *dma_p = priv->dma_regs_p;
@@ -368,6 +370,8 @@ static int _dw_eth_send(struct dw_eth_dev *priv, void *packet, int length)
                return -EPERM;
        }
 
+       length = max(length, ETH_ZLEN);
+
        memcpy((void *)data_start, packet, length);
 
        /* Flush data to be sent */
@@ -660,6 +664,51 @@ 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 && err != -ENOSYS && err != -ENOTSUPP) {
+                               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;
+
+       ret = device_get_supply_regulator(dev, "phy-supply",
+                                         &phy_supply);
+       if (ret) {
+               debug("%s: No phy supply\n", dev->name);
+       } else {
+               ret = regulator_set_enable(phy_supply, true);
+               if (ret) {
+                       puts("Error enabling phy supply\n");
+                       return ret;
+               }
+       }
+#endif
 
 #ifdef CONFIG_DM_PCI
        /*
@@ -690,6 +739,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)
@@ -700,7 +758,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 = {
@@ -720,15 +782,14 @@ int designware_eth_ofdata_to_platdata(struct udevice *dev)
 #endif
        struct eth_pdata *pdata = &dw_pdata->eth_pdata;
        const char *phy_mode;
-       const fdt32_t *cell;
 #ifdef CONFIG_DM_GPIO
        int reset_flags = GPIOD_IS_OUT;
 #endif
        int ret = 0;
 
-       pdata->iobase = dev_get_addr(dev);
+       pdata->iobase = dev_read_addr(dev);
        pdata->phy_interface = -1;
-       phy_mode = fdt_getprop(gd->fdt_blob, dev->of_offset, "phy-mode", NULL);
+       phy_mode = dev_read_string(dev, "phy-mode");
        if (phy_mode)
                pdata->phy_interface = phy_get_interface_by_name(phy_mode);
        if (pdata->phy_interface == -1) {
@@ -736,21 +797,17 @@ int designware_eth_ofdata_to_platdata(struct udevice *dev)
                return -EINVAL;
        }
 
-       pdata->max_speed = 0;
-       cell = fdt_getprop(gd->fdt_blob, dev->of_offset, "max-speed", NULL);
-       if (cell)
-               pdata->max_speed = fdt32_to_cpu(*cell);
+       pdata->max_speed = dev_read_u32_default(dev, "max-speed", 0);
 
 #ifdef CONFIG_DM_GPIO
-       if (fdtdec_get_bool(gd->fdt_blob, dev->of_offset,
-                           "snps,reset-active-low"))
+       if (dev_read_bool(dev, "snps,reset-active-low"))
                reset_flags |= GPIOD_ACTIVE_LOW;
 
        ret = gpio_request_by_name(dev, "snps,reset-gpio", 0,
                &priv->reset_gpio, reset_flags);
        if (ret == 0) {
-               ret = fdtdec_get_int_array(gd->fdt_blob, dev->of_offset,
-                       "snps,reset-delays-us", dw_pdata->reset_delays, 3);
+               ret = dev_read_u32_array(dev, "snps,reset-delays-us",
+                                        dw_pdata->reset_delays, 3);
        } else if (ret == -ENOENT) {
                ret = 0;
        }
@@ -763,6 +820,8 @@ static const struct udevice_id designware_eth_ids[] = {
        { .compatible = "allwinner,sun7i-a20-gmac" },
        { .compatible = "altr,socfpga-stmmac" },
        { .compatible = "amlogic,meson6-dwmac" },
+       { .compatible = "amlogic,meson-gx-dwmac" },
+       { .compatible = "st,stm32-dwmac" },
        { }
 };