+// 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 <asm/arch/clock.h>
#include <asm/arch/imx-regs.h>
-#include <asm/imx-common/sys_proto.h>
+#include <asm/mach-imx/sys_proto.h>
DECLARE_GLOBAL_DATA_PTR;
static void fec_rbd_init(struct fec_priv *fec, int count, int dsize)
{
uint32_t size;
- uint8_t *data;
+ ulong data;
int i;
/*
*/
size = roundup(dsize, ARCH_DMA_MINALIGN);
for (i = 0; i < count; i++) {
- data = (uint8_t *)fec->rbd_base[i].data_pointer;
- memset(data, 0, dsize);
- flush_dcache_range((uint32_t)data, (uint32_t)data + size);
+ data = fec->rbd_base[i].data_pointer;
+ memset((void *)data, 0, dsize);
+ flush_dcache_range(data, data + size);
fec->rbd_base[i].status = FEC_RBD_EMPTY;
fec->rbd_base[i].data_length = 0;
fec->rbd_base[i - 1].status = FEC_RBD_WRAP | FEC_RBD_EMPTY;
fec->rbd_index = 0;
- flush_dcache_range((unsigned)fec->rbd_base,
- (unsigned)fec->rbd_base + size);
+ flush_dcache_range((ulong)fec->rbd_base,
+ (ulong)fec->rbd_base + size);
}
/**
*/
static void fec_tbd_init(struct fec_priv *fec)
{
- unsigned addr = (unsigned)fec->tbd_base;
+ ulong addr = (ulong)fec->tbd_base;
unsigned size = roundup(2 * sizeof(struct fec_bd),
ARCH_DMA_MINALIGN);
struct fec_priv *fec = (struct fec_priv *)edev->priv;
#endif
int speed;
- uint32_t addr, size;
+ ulong addr, size;
int i;
debug("fec_open: fec_open(dev)\n");
/* Flush the descriptors into RAM */
size = roundup(FEC_RBD_NUM * sizeof(struct fec_bd),
ARCH_DMA_MINALIGN);
- addr = (uint32_t)fec->rbd_base;
+ addr = (ulong)fec->rbd_base;
flush_dcache_range(addr, addr + size);
#ifdef FEC_QUIRK_ENET_MAC
#else
struct fec_priv *fec = (struct fec_priv *)dev->priv;
#endif
- uint32_t mib_ptr = (uint32_t)&fec->eth->rmon_t_drop;
- int i;
+ u8 *mib_ptr = (uint8_t *)&fec->eth->rmon_t_drop;
+ u8 *i;
+ ulong addr;
/* Initialize MAC address */
#ifdef CONFIG_DM_ETH
writel(0x00000000, &fec->eth->gaddr1);
writel(0x00000000, &fec->eth->gaddr2);
- /* Do not access reserved register for i.MX6UL */
- if (!is_mx6ul() && !is_mx6ull()) {
+ /* Do not access reserved register */
+ if (!is_mx6ul() && !is_mx6ull() && !is_mx8m()) {
/* clear MIB RAM */
for (i = mib_ptr; i <= mib_ptr + 0xfc; i += 4)
writel(0, i);
/* size and address of each buffer */
writel(FEC_MAX_PKT_SIZE, &fec->eth->emrbr);
- writel((uint32_t)fec->tbd_base, &fec->eth->etdsr);
- writel((uint32_t)fec->rbd_base, &fec->eth->erdsr);
+
+ addr = (ulong)fec->tbd_base;
+ writel((uint32_t)addr, &fec->eth->etdsr);
+
+ addr = (ulong)fec->rbd_base;
+ writel((uint32_t)addr, &fec->eth->erdsr);
#ifndef CONFIG_PHYLIB
if (fec->xcv_type != SEVENWIRE)
#endif
{
unsigned int status;
- uint32_t size, end;
- uint32_t addr;
+ u32 size;
+ ulong addr, end;
int timeout = FEC_XFER_TIMEOUT;
int ret = 0;
swap_packet((uint32_t *)packet, length);
#endif
- addr = (uint32_t)packet;
+ addr = (ulong)packet;
end = roundup(addr + length, ARCH_DMA_MINALIGN);
addr &= ~(ARCH_DMA_MINALIGN - 1);
flush_dcache_range(addr, end);
writew(length, &fec->tbd_base[fec->tbd_index].data_length);
- writel(addr, &fec->tbd_base[fec->tbd_index].data_pointer);
+ writel((uint32_t)addr, &fec->tbd_base[fec->tbd_index].data_pointer);
/*
* update BD's status now
* can start DMA.
*/
size = roundup(2 * sizeof(struct fec_bd), ARCH_DMA_MINALIGN);
- addr = (uint32_t)fec->tbd_base;
+ addr = (ulong)fec->tbd_base;
flush_dcache_range(addr, addr + size);
/*
unsigned long ievent;
int frame_length, len = 0;
uint16_t bd_status;
- uint32_t addr, size, end;
+ 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);
* the descriptor. The solution is to mark the whole cache line when all
* descriptors in the cache line are processed.
*/
- addr = (uint32_t)rbd;
+ addr = (ulong)rbd;
addr &= ~(ARCH_DMA_MINALIGN - 1);
size = roundup(sizeof(struct fec_bd), ARCH_DMA_MINALIGN);
invalidate_dcache_range(addr, addr + size);
#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)
- printf("error frame: 0x%08x 0x%08x\n",
- addr, bd_status);
+ debug("error frame: 0x%08lx 0x%08x\n",
+ addr, bd_status);
}
/*
size = RXDESC_PER_CACHELINE - 1;
if ((fec->rbd_index & size) == size) {
i = fec->rbd_index - size;
- addr = (uint32_t)&fec->rbd_base[i];
+ addr = (ulong)&fec->rbd_base[i];
for (; i <= fec->rbd_index ; i++) {
fec_rbd_clean(i == (FEC_RBD_NUM - 1),
&fec->rbd_base[i]);
unsigned int size;
int i;
uint8_t *data;
+ ulong addr;
/* Allocate TX descriptors. */
size = roundup(2 * sizeof(struct fec_bd), ARCH_DMA_MINALIGN);
memset(data, 0, size);
- fec->rbd_base[i].data_pointer = (uint32_t)data;
+ addr = (ulong)data;
+ fec->rbd_base[i].data_pointer = (uint32_t)addr;
fec->rbd_base[i].status = FEC_RBD_EMPTY;
fec->rbd_base[i].data_length = 0;
/* Flush the buffer to memory. */
- flush_dcache_range((uint32_t)data, (uint32_t)data + size);
+ flush_dcache_range(addr, addr + size);
}
/* Mark the last RBD to close the ring. */
return 0;
err_ring:
- for (; i >= 0; i--)
- free((void *)fec->rbd_base[i].data_pointer);
+ for (; i >= 0; i--) {
+ addr = fec->rbd_base[i].data_pointer;
+ free((void *)addr);
+ }
free(fec->rbd_base);
err_rx:
free(fec->tbd_base);
static void fec_free_descs(struct fec_priv *fec)
{
int i;
+ ulong addr;
- for (i = 0; i < FEC_RBD_NUM; i++)
- free((void *)fec->rbd_base[i].data_pointer);
+ for (i = 0; i < FEC_RBD_NUM; i++) {
+ addr = fec->rbd_base[i].data_pointer;
+ free((void *)addr);
+ }
free(fec->rbd_base);
free(fec->tbd_base);
}
-struct mii_dev *fec_get_miibus(uint32_t base_addr, int dev_id)
+struct mii_dev *fec_get_miibus(ulong base_addr, int dev_id)
{
struct ethernet_regs *eth = (struct ethernet_regs *)base_addr;
struct mii_dev *bus;
edev->halt = fec_halt;
edev->write_hwaddr = fec_set_hwaddr;
- fec->eth = (struct ethernet_regs *)base_addr;
+ fec->eth = (struct ethernet_regs *)(ulong)base_addr;
fec->bd = bd;
fec->xcv_type = CONFIG_FEC_XCV_TYPE;
sprintf(mac, "eth%daddr", fec->dev_id);
else
strcpy(mac, "ethaddr");
- if (!getenv(mac))
- eth_setenv_enetaddr(mac, ethaddr);
+ if (!env_get(mac))
+ eth_env_set_enetaddr(mac, ethaddr);
}
return ret;
err4:
#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
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;
- bus = fec_get_miibus((uint32_t)priv->eth, dev_id);
- if (!bus)
- goto err_mii;
-
- priv->bus = bus;
- priv->xcv_type = CONFIG_FEC_XCV_TYPE;
- priv->interface = pdata->phy_interface;
- ret = fec_phy_init(priv, dev);
- if (ret)
- goto err_phy;
-
/* 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;
+
+ 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;
+ }
+
+ priv->bus = bus;
+ priv->xcv_type = CONFIG_FEC_XCV_TYPE;
+ priv->interface = pdata->phy_interface;
+ ret = fec_phy_init(priv, dev);
+ if (ret)
+ goto err_phy;
return 0;
-err_timeout:
- free(priv->phydev);
err_phy:
mdio_unregister(bus);
free(bus);
err_mii:
+err_timeout:
fec_free_descs(priv);
return ret;
}
struct fec_priv *priv = dev_get_priv(dev);
const char *phy_mode;
- pdata->iobase = (phys_addr_t)dev_get_addr(dev);
+ pdata->iobase = (phys_addr_t)devfdt_get_addr(dev);
priv->eth = (struct ethernet_regs *)pdata->iobase;
pdata->phy_interface = -1;
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" },
{ }
};