#include <common.h>
#include <malloc.h>
+#include <memalign.h>
#include <net.h>
+#include <netdev.h>
#include <miiphy.h>
#include "fec_mxc.h"
#include <asm/arch/clock.h>
#include <asm/arch/imx-regs.h>
+#include <asm/imx-common/sys_proto.h>
#include <asm/io.h>
#include <asm/errno.h>
#include <linux/compiler.h>
#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) */
-};
-
#ifdef CONFIG_FEC_MXC_SWAP_PACKET
static void swap_packet(uint32_t *packet, int length)
{
return 0;
}
-int fec_phy_read(struct mii_dev *bus, int phyAddr, int dev_addr, int regAddr)
+static int fec_phy_read(struct mii_dev *bus, int phyAddr, int dev_addr,
+ int regAddr)
{
return fec_mdio_read(bus->priv, phyAddr, regAddr);
}
-int fec_phy_write(struct mii_dev *bus, int phyAddr, int dev_addr, int regAddr,
- u16 data)
+static int fec_phy_write(struct mii_dev *bus, int phyAddr, int dev_addr,
+ int regAddr, u16 data)
{
return fec_mdio_write(bus->priv, phyAddr, regAddr, data);
}
unsigned char *mac)
{
imx_get_mac_from_fuse(dev_id, mac);
- return !is_valid_ether_addr(mac);
+ return !is_valid_ethaddr(mac);
}
static int fec_set_hwaddr(struct eth_device *dev)
writel(0x00000000, &fec->eth->gaddr2);
- /* clear MIB RAM */
- for (i = mib_ptr; i <= mib_ptr + 0xfc; i += 4)
- writel(0, i);
+ /* Do not access reserved register for i.MX6UL */
+ if (!is_cpu_type(MXC_CPU_MX6UL)) {
+ /* clear MIB RAM */
+ for (i = mib_ptr; i <= mib_ptr + 0xfc; i += 4)
+ writel(0, i);
- /* FIFO receive start register */
- writel(0x520, &fec->eth->r_fstart);
+ /* FIFO receive start register */
+ writel(0x520, &fec->eth->r_fstart);
+ }
/* size and address of each buffer */
writel(FEC_MAX_PKT_SIZE, &fec->eth->emrbr);
break;
}
- if (!timeout)
+ if (!timeout) {
ret = -EINVAL;
+ goto out;
+ }
- invalidate_dcache_range(addr, addr + size);
- if (readw(&fec->tbd_base[fec->tbd_index].status) & FEC_TBD_READY)
+ /*
+ * The TDAR bit is cleared when the descriptors are all out from TX
+ * but on mx6solox we noticed that the READY bit is still not cleared
+ * right after TDAR.
+ * These are two distinct signals, and in IC simulation, we found that
+ * TDAR always gets cleared prior than the READY bit of last BD becomes
+ * cleared.
+ * In mx6solox, we use a later version of FEC IP. It looks like that
+ * this intrinsic behaviour of TDAR bit has changed in this newer FEC
+ * version.
+ *
+ * Fix this by polling the READY bit of BD after the TDAR polling,
+ * which covers the mx6solox case and does not harm the other SoCs.
+ */
+ timeout = FEC_XFER_TIMEOUT;
+ while (--timeout) {
+ invalidate_dcache_range(addr, addr + size);
+ if (!(readw(&fec->tbd_base[fec->tbd_index].status) &
+ FEC_TBD_READY))
+ break;
+ }
+
+ if (!timeout)
ret = -EINVAL;
+out:
debug("fec_send: status 0x%x index %d ret %i\n",
readw(&fec->tbd_base[fec->tbd_index].status),
fec->tbd_index, ret);
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;
/*
* 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);
- NetReceive(buff, 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);
}
/*