#undef DEBUG
-struct nbuf {
- uint8_t data[1500]; /**< actual data */
- int length; /**< actual length */
- int used; /**< buffer in use or not */
- uint8_t head[16]; /**< MAC header(6 + 6 + 2) + 2(aligned) */
-};
-
-static int rx_idx;
-
#ifdef CONFIG_FEC_MXC_SWAP_PACKET
static void swap_packet(uint32_t *packet, int length)
{
if (readl(ð->ievent) & FEC_IEVENT_MII)
break;
printf("Read MDIO failed...\n");
- return -1;
+ return -ETIMEDOUT;
}
}
if (readl(ð->ievent) & FEC_IEVENT_MII)
break;
printf("Write MDIO failed...\n");
- return -1;
+ return -ETIMEDOUT;
}
}
static int miiphy_wait_aneg(struct eth_device *dev)
{
- uint32_t start;
+ ulong start;
int status;
struct fec_priv *fec = (struct fec_priv *)dev->priv;
struct ethernet_regs *eth = fec->bus->priv;
do {
if (get_timer(start) > (CONFIG_SYS_HZ * 5)) {
printf("%s: Autonegotiation timeout\n", dev->name);
- return -1;
+ return -ETIMEDOUT;
}
status = fec_mdio_read(eth, fec->phy_id, MII_BMSR);
if (status < 0) {
printf("%s: Autonegotiation failed. status: %d\n",
dev->name, status);
- return -1;
+ return status;
}
} while (!(status & BMSR_LSTATUS));
static inline void fec_rx_task_enable(struct fec_priv *fec)
{
- writel(1 << 24, &fec->eth->r_des_active);
+ writel(FEC_X_DES_ACTIVE_TDAR, &fec->eth->r_des_active);
}
static inline void fec_rx_task_disable(struct fec_priv *fec)
static inline void fec_tx_task_enable(struct fec_priv *fec)
{
- writel(1 << 24, &fec->eth->x_des_active);
+ writel(FEC_X_DES_ACTIVE_TDAR, &fec->eth->x_des_active);
}
static inline void fec_tx_task_disable(struct fec_priv *fec)
*/
static void fec_rbd_init(struct fec_priv *fec, int count, int dsize)
{
- uint32_t size;
- uint8_t *data;
+ size_t rbd_size, pkt_size;
+ void *data;
int i;
/*
* Reload the RX descriptors with default values and wipe
* the RX buffers.
*/
- size = roundup(dsize, ARCH_DMA_MINALIGN);
+ pkt_size = roundup(dsize, ARCH_DMA_MINALIGN);
for (i = 0; i < count; i++) {
- data = (uint8_t *)fec->rbd_base[i].data_pointer;
+ data = (void *)fec->rbd_base[i].data_pointer;
memset(data, 0, dsize);
- flush_dcache_range((uint32_t)data, (uint32_t)data + size);
+ flush_dcache_range((unsigned long)data,
+ (unsigned long)data + pkt_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);
+ rbd_size = roundup(sizeof(struct fec_bd) * count, ARCH_DMA_MINALIGN);
+ flush_dcache_range((unsigned long)fec->rbd_base,
+ (unsigned long)fec->rbd_base + rbd_size);
}
/**
*/
static void fec_tbd_init(struct fec_priv *fec)
{
- unsigned addr = (unsigned)fec->tbd_base;
+ unsigned long addr = (unsigned long)fec->tbd_base;
unsigned size = roundup(2 * sizeof(struct fec_bd),
ARCH_DMA_MINALIGN);
static int fec_set_hwaddr(struct eth_device *dev)
{
uchar *mac = dev->enetaddr;
- struct fec_priv *fec = (struct fec_priv *)dev->priv;
+ struct fec_priv *fec = dev->priv;
writel(0, &fec->eth->iaddr1);
writel(0, &fec->eth->iaddr2);
static int fec_init(struct eth_device *dev, bd_t* bd)
{
struct fec_priv *fec = dev->priv;
- uint32_t *mib_ptr = (uint32_t *)&fec->eth->rmon_t_drop;
- int i;
/* Initialize MAC address */
fec_set_hwaddr(dev);
writel(0x00000000, &fec->eth->gaddr1);
writel(0x00000000, &fec->eth->gaddr2);
-
- /* clear MIB RAM */
- for (i = 0; i <= 0xfc >> 2; i++)
- writel(0, &mib_ptr[i]);
-
+ /* Do not access reserved register for i.MX6UL */
+#if !(defined(CONFIG_SOC_MX6UL) || defined(CONFIG_SOC_MX6ULL))
/* FIFO receive start register */
writel(0x520, &fec->eth->r_fstart);
-
+#endif
/* size and address of each buffer */
writel(FEC_MAX_PKT_SIZE, &fec->eth->emrbr);
writel((uint32_t)fec->tbd_base, &fec->eth->etdsr);
*/
static void fec_halt(struct eth_device *dev)
{
- struct fec_priv *fec = (struct fec_priv *)dev->priv;
+ struct fec_priv *fec = dev->priv;
int counter = 1000;
/*
*/
if ((length > 1500) || (length <= 0)) {
printf("Payload (%d) too large\n", length);
- return -1;
+ return -EINVAL;
}
/*
* engine. We also flush the packet to RAM here to avoid cache trouble.
*/
#ifdef CONFIG_FEC_MXC_SWAP_PACKET
- swap_packet((uint32_t *)packet, length);
+ swap_packet(packet, length);
#endif
addr = (uint32_t)packet;
while (--timeout) {
if (!(readl(&fec->eth->x_des_active) & FEC_X_DES_ACTIVE_TDAR))
break;
+ udelay(1);
}
if (!timeout) {
- ret = -EINVAL;
+ ret = -ETIMEDOUT;
goto out;
}
if (!(readw(&fec->tbd_base[fec->tbd_index].status) &
FEC_TBD_READY))
break;
+ udelay(1);
}
if (!timeout)
- ret = -EINVAL;
+ ret = -ETIMEDOUT;
out:
debug("fec_send: status 0x%x index %d ret %i\n",
*/
static int fec_recv(struct eth_device *dev)
{
- struct fec_priv *fec = (struct fec_priv *)dev->priv;
+ struct fec_priv *fec = dev->priv;
struct fec_bd *rbd = &fec->rbd_base[fec->rbd_index];
unsigned long ievent;
int frame_length, len = 0;
- struct nbuf *frame;
uint16_t bd_status;
uint32_t addr, size, end;
int i;
+ ALLOC_CACHE_ALIGN_BUFFER(uchar, buff, FEC_MAX_PKT_SIZE);
/*
* Check if any critical events have happened
/*
* Get buffer address and size
*/
- frame = (struct nbuf *)readl(&rbd->data_pointer);
+ addr = readl(&rbd->data_pointer);
frame_length = readw(&rbd->data_length) - 4;
/*
* Invalidate data cache over the buffer
*/
- addr = (uint32_t)frame;
end = roundup(addr + frame_length, ARCH_DMA_MINALIGN);
addr &= ~(ARCH_DMA_MINALIGN - 1);
invalidate_dcache_range(addr, end);
* Fill the buffer and pass it to upper layers
*/
#ifdef CONFIG_FEC_MXC_SWAP_PACKET
- swap_packet((uint32_t *)frame->data, frame_length);
+ swap_packet((uint32_t *)addr, frame_length);
#endif
- memcpy(buff, frame->data, frame_length);
+ memcpy(buff, (char *)addr, frame_length);
net_process_received_packet(buff, frame_length);
len = frame_length;
} else {
if (bd_status & FEC_RBD_ERR)
- printf("error frame: 0x%08lx 0x%08x\n",
- (ulong)rbd->data_pointer,
- bd_status);
+ printf("error frame: 0x%08x 0x%08x\n",
+ addr, bd_status);
}
/*
static int fec_alloc_descs(struct fec_priv *fec)
{
- unsigned int size;
+ size_t tbd_size, rbd_size, pkt_size;
int i;
- uint8_t *data;
+ void *data;
/* Allocate TX descriptors. */
- size = roundup(2 * sizeof(struct fec_bd), ARCH_DMA_MINALIGN);
- fec->tbd_base = memalign(ARCH_DMA_MINALIGN, size);
+ tbd_size = roundup(2 * sizeof(struct fec_bd), ARCH_DMA_MINALIGN);
+ fec->tbd_base = memalign(ARCH_DMA_MINALIGN, tbd_size);
if (!fec->tbd_base)
goto err_tx;
/* Allocate RX descriptors. */
- size = roundup(FEC_RBD_NUM * sizeof(struct fec_bd), ARCH_DMA_MINALIGN);
- fec->rbd_base = memalign(ARCH_DMA_MINALIGN, size);
+ rbd_size = roundup(FEC_RBD_NUM * sizeof(struct fec_bd), ARCH_DMA_MINALIGN);
+ fec->rbd_base = memalign(ARCH_DMA_MINALIGN, rbd_size);
if (!fec->rbd_base)
goto err_rx;
- memset(fec->rbd_base, 0, size);
+ memset(fec->rbd_base, 0, rbd_size);
/* Allocate RX buffers. */
/* Maximum RX buffer size. */
- size = roundup(FEC_MAX_PKT_SIZE, FEC_DMA_RX_MINALIGN);
+ pkt_size = roundup(FEC_MAX_PKT_SIZE, FEC_DMA_RX_MINALIGN);
for (i = 0; i < FEC_RBD_NUM; i++) {
- data = memalign(FEC_DMA_RX_MINALIGN, size);
+ data = memalign(FEC_DMA_RX_MINALIGN, pkt_size);
if (!data) {
printf("%s: error allocating rxbuf %d\n", __func__, i);
goto err_ring;
}
- memset(data, 0, size);
+ memset(data, 0, pkt_size);
fec->rbd_base[i].data_pointer = (uint32_t)data;
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((uint32_t)data, (uint32_t)data + pkt_size);
}
/* Mark the last RBD to close the ring. */
fec->rbd_base[i - 1].status = FEC_RBD_WRAP | FEC_RBD_EMPTY;
+ flush_dcache_range((unsigned long)fec->rbd_base, rbd_size);
fec->rbd_index = 0;
fec->tbd_index = 0;
#endif
int ret;
-#ifdef CONFIG_SOC_MX28
+#if defined(CONFIG_SOC_MX28)
/*
* 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;
+#elif defined(FEC_MDIO_BASE_ADDR)
+ base_mii = FEC_MDIO_BASE_ADDR;
#else
base_mii = addr;
#endif
if (!bus)
return -ENOMEM;
#ifdef CONFIG_PHYLIB
- phydev = phy_find_by_mask(bus, 1 << phy_id, PHY_INTERFACE_MODE_RGMII);
+ static u8 phy_mask = 0xff;
+ phydev = phy_find_by_mask(bus, phy_id < 0 ? phy_mask : (1 << phy_id),
+ PHY_INTERFACE_MODE_RGMII);
if (!phydev) {
free(bus);
return -ENOMEM;
}
+ phy_mask &= ~(1 << phydev->addr);
ret = fec_probe(bd, dev_id, addr, bus, phydev);
#else
ret = fec_probe(bd, dev_id, addr, bus, phy_id);
#ifndef CONFIG_PHYLIB
int fecmxc_register_mii_postcall(struct eth_device *dev, int (*cb)(int))
{
- struct fec_priv *fec = (struct fec_priv *)dev->priv;
+ struct fec_priv *fec = dev->priv;
fec->mii_postcall = cb;
return 0;
}