test/py: fs: add fstest/unlink test
[oweals/u-boot.git] / drivers / net / fec_mxc.c
index ff7ad91116ce02aa813898616b303cca8581c227..dac07b6e34d24c26c8b39fcc13e631d5bd372f36 100644 (file)
@@ -1,21 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * (C) Copyright 2009 Ilya Yanok, Emcraft Systems Ltd <yanok@emcraft.com>
  * (C) Copyright 2008,2009 Eric Jarrige <eric.jarrige@armadeus.org>
  * (C) Copyright 2008 Armadeus Systems nc
  * (C) Copyright 2007 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
  * (C) Copyright 2007 Pengutronix, Juergen Beisert <j.beisert@pengutronix.de>
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <common.h>
 #include <dm.h>
+#include <environment.h>
 #include <malloc.h>
 #include <memalign.h>
 #include <miiphy.h>
 #include <net.h>
 #include <netdev.h>
-#include "fec_mxc.h"
 
 #include <asm/io.h>
 #include <linux/errno.h>
@@ -24,6 +23,9 @@
 #include <asm/arch/clock.h>
 #include <asm/arch/imx-regs.h>
 #include <asm/mach-imx/sys_proto.h>
+#include <asm-generic/gpio.h>
+
+#include "fec_mxc.h"
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -806,7 +808,16 @@ static int fec_recv(struct eth_device *dev)
        uint16_t bd_status;
        ulong addr, size, end;
        int i;
+
+#ifdef CONFIG_DM_ETH
+       *packetp = memalign(ARCH_DMA_MINALIGN, FEC_MAX_PKT_SIZE);
+       if (*packetp == 0) {
+               printf("%s: error allocating packetp\n", __func__);
+               return -ENOMEM;
+       }
+#else
        ALLOC_CACHE_ALIGN_BUFFER(uchar, buff, FEC_MAX_PKT_SIZE);
+#endif
 
        /* Check if any critical events have happened */
        ievent = readl(&fec->eth->ievent);
@@ -882,8 +893,13 @@ static int fec_recv(struct eth_device *dev)
 #ifdef CONFIG_FEC_MXC_SWAP_PACKET
                        swap_packet((uint32_t *)addr, frame_length);
 #endif
+
+#ifdef CONFIG_DM_ETH
+                       memcpy(*packetp, (char *)addr, frame_length);
+#else
                        memcpy(buff, (char *)addr, frame_length);
                        net_process_received_packet(buff, frame_length);
+#endif
                        len = frame_length;
                } else {
                        if (bd_status & FEC_RBD_ERR)
@@ -997,18 +1013,9 @@ static void fec_free_descs(struct fec_priv *fec)
        free(fec->tbd_base);
 }
 
-#ifdef CONFIG_DM_ETH
-struct mii_dev *fec_get_miibus(struct udevice *dev, int dev_id)
-#else
-struct mii_dev *fec_get_miibus(uint32_t base_addr, int dev_id)
-#endif
+struct mii_dev *fec_get_miibus(ulong base_addr, int dev_id)
 {
-#ifdef CONFIG_DM_ETH
-       struct fec_priv *priv = dev_get_priv(dev);
-       struct ethernet_regs *eth = priv->eth;
-#else
-       struct ethernet_regs *eth = (struct ethernet_regs *)(ulong)base_addr;
-#endif
+       struct ethernet_regs *eth = (struct ethernet_regs *)base_addr;
        struct mii_dev *bus;
        int ret;
 
@@ -1140,12 +1147,12 @@ int fecmxc_initialize_multi(bd_t *bd, int dev_id, int phy_id, uint32_t addr)
 #endif
        int ret;
 
-#ifdef CONFIG_MX28
+#ifdef CONFIG_FEC_MXC_MDIO_BASE
        /*
         * The i.MX28 has two ethernet interfaces, but they are not equal.
         * Only the first one can access the MDIO bus.
         */
-       base_mii = MXS_ENET0_BASE;
+       base_mii = CONFIG_FEC_MXC_MDIO_BASE;
 #else
        base_mii = addr;
 #endif
@@ -1201,10 +1208,19 @@ static int fecmxc_read_rom_hwaddr(struct udevice *dev)
        return fec_get_hwaddr(priv->dev_id, pdata->enetaddr);
 }
 
+static int fecmxc_free_pkt(struct udevice *dev, uchar *packet, int length)
+{
+       if (packet)
+               free(packet);
+
+       return 0;
+}
+
 static const struct eth_ops fecmxc_ops = {
        .start                  = fecmxc_init,
        .send                   = fecmxc_send,
        .recv                   = fecmxc_recv,
+       .free_pkt               = fecmxc_free_pkt,
        .stop                   = fecmxc_halt,
        .write_hwaddr           = fecmxc_set_hwaddr,
        .read_rom_hwaddr        = fecmxc_read_rom_hwaddr,
@@ -1215,7 +1231,7 @@ static int fec_phy_init(struct fec_priv *priv, struct udevice *dev)
        struct phy_device *phydev;
        int mask = 0xffffffff;
 
-#ifdef CONFIG_PHYLIB
+#ifdef CONFIG_FEC_MXC_PHYADDR
        mask = 1 << CONFIG_FEC_MXC_PHYADDR;
 #endif
 
@@ -1231,12 +1247,24 @@ static int fec_phy_init(struct fec_priv *priv, struct udevice *dev)
        return 0;
 }
 
+#ifdef CONFIG_DM_GPIO
+/* FEC GPIO reset */
+static void fec_gpio_reset(struct fec_priv *priv)
+{
+       debug("fec_gpio_reset: fec_gpio_reset(dev)\n");
+       if (dm_gpio_is_valid(&priv->phy_reset_gpio)) {
+               dm_gpio_set_value(&priv->phy_reset_gpio, 1);
+               udelay(priv->reset_delay);
+               dm_gpio_set_value(&priv->phy_reset_gpio, 0);
+       }
+}
+#endif
+
 static int fecmxc_probe(struct udevice *dev)
 {
        struct eth_pdata *pdata = dev_get_platdata(dev);
        struct fec_priv *priv = dev_get_priv(dev);
        struct mii_dev *bus = NULL;
-       int dev_id = -1;
        uint32_t start;
        int ret;
 
@@ -1244,6 +1272,9 @@ static int fecmxc_probe(struct udevice *dev)
        if (ret)
                return ret;
 
+#ifdef CONFIG_DM_GPIO
+       fec_gpio_reset(priv);
+#endif
        /* Reset chip. */
        writel(readl(&priv->eth->ecntrl) | FEC_ECNTRL_RESET,
               &priv->eth->ecntrl);
@@ -1257,9 +1288,13 @@ static int fecmxc_probe(struct udevice *dev)
        }
 
        fec_reg_setup(priv);
-       priv->dev_id = (dev_id == -1) ? 0 : dev_id;
 
-       bus = fec_get_miibus(dev, dev_id);
+       priv->dev_id = dev->seq;
+#ifdef CONFIG_FEC_MXC_MDIO_BASE
+       bus = fec_get_miibus((ulong)CONFIG_FEC_MXC_MDIO_BASE, dev->seq);
+#else
+       bus = fec_get_miibus((ulong)priv->eth, dev->seq);
+#endif
        if (!bus) {
                ret = -ENOMEM;
                goto err_mii;
@@ -1274,12 +1309,11 @@ static int fecmxc_probe(struct udevice *dev)
 
        return 0;
 
-err_timeout:
-       free(priv->phydev);
 err_phy:
        mdio_unregister(bus);
        free(bus);
 err_mii:
+err_timeout:
        fec_free_descs(priv);
        return ret;
 }
@@ -1298,6 +1332,7 @@ static int fecmxc_remove(struct udevice *dev)
 
 static int fecmxc_ofdata_to_platdata(struct udevice *dev)
 {
+       int ret = 0;
        struct eth_pdata *pdata = dev_get_platdata(dev);
        struct fec_priv *priv = dev_get_priv(dev);
        const char *phy_mode;
@@ -1315,16 +1350,32 @@ static int fecmxc_ofdata_to_platdata(struct udevice *dev)
                return -EINVAL;
        }
 
-       /* TODO
-        * Need to get the reset-gpio and related properties from DT
-        * and implemet the enet reset code on .probe call
-        */
+#ifdef CONFIG_DM_GPIO
+       ret = gpio_request_by_name(dev, "phy-reset-gpios", 0,
+                            &priv->phy_reset_gpio, GPIOD_IS_OUT);
+       if (ret == 0) {
+               ret = dev_read_u32_array(dev, "phy-reset-duration",
+                                        &priv->reset_delay, 1);
+       } else if (ret == -ENOENT) {
+               priv->reset_delay = 1000;
+               ret = 0;
+       }
 
-       return 0;
+       if (priv->reset_delay > 1000) {
+               printf("FEX MXC: gpio reset timeout should be less the 1000\n");
+               priv->reset_delay = 1000;
+       }
+#endif
+
+       return ret;
 }
 
 static const struct udevice_id fecmxc_ids[] = {
        { .compatible = "fsl,imx6q-fec" },
+       { .compatible = "fsl,imx6sl-fec" },
+       { .compatible = "fsl,imx6sx-fec" },
+       { .compatible = "fsl,imx6ul-fec" },
+       { .compatible = "fsl,imx53-fec" },
        { }
 };