diff options
Diffstat (limited to 'drivers/net/designware.c')
-rw-r--r-- | drivers/net/designware.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/drivers/net/designware.c b/drivers/net/designware.c index 036d231071..6d5307128d 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -10,6 +10,7 @@ */ #include <common.h> +#include <clk.h> #include <dm.h> #include <errno.h> #include <miiphy.h> @@ -17,6 +18,7 @@ #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" @@ -343,6 +345,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; @@ -369,6 +373,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 */ @@ -661,6 +667,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 +742,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 +761,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 = { |