+// 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 <miiphy.h>
#include <net.h>
#include <netdev.h>
-#include "fec_mxc.h"
#include <asm/io.h>
#include <linux/errno.h>
#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;
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);
#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)
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;
#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
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,
struct phy_device *phydev;
int mask = 0xffffffff;
-#ifdef CONFIG_PHYLIB
+#ifdef CONFIG_FEC_MXC_PHYADDR
mask = 1 << CONFIG_FEC_MXC_PHYADDR;
#endif
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;
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);
}
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;
return 0;
-err_timeout:
- free(priv->phydev);
err_phy:
mdio_unregister(bus);
free(bus);
err_mii:
+err_timeout:
fec_free_descs(priv);
return ret;
}
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;
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" },
{ }
};