#define CONFIG_FEC_XCV_TYPE MII100
#endif
+#if !defined(CONDIF_SYS_DCACHE_OFF) && !defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH)
+/* Due to multiple RX and TX buffer descriptors sharing a cache line
+ * the driver can only work with DMA coherent memory.
+ * Since U-Boot does not provide this, cache must be disabled or
+ * write-through.
+ */
+#error This driver cannot be used with Writeback DCACHE
+#endif
/*
* The i.MX28 operates with packets in big endian. We need to swap them before
* sending and after receiving.
}
#endif
-static int fec_rx_task_enable(struct fec_priv *fec)
+static inline void fec_rx_task_enable(struct fec_priv *fec)
{
writel(1 << 24, &fec->eth->r_des_active);
- return 0;
}
-static int fec_rx_task_disable(struct fec_priv *fec)
+static inline void fec_rx_task_disable(struct fec_priv *fec)
{
- return 0;
}
-static int fec_tx_task_enable(struct fec_priv *fec)
+static inline void fec_tx_task_enable(struct fec_priv *fec)
{
writel(1 << 24, &fec->eth->x_des_active);
- return 0;
}
-static int fec_tx_task_disable(struct fec_priv *fec)
+static inline void fec_tx_task_disable(struct fec_priv *fec)
{
- return 0;
+}
+
+static inline void fec_invalidate_bd(struct fec_bd *bd)
+{
+ invalidate_dcache_range((unsigned long)bd,
+ (unsigned long)bd + sizeof(*bd));
+}
+
+static inline void fec_flush_bd(struct fec_bd *bd)
+{
+ flush_dcache_range((unsigned long)bd,
+ (unsigned long)bd + sizeof(*bd));
}
/**
unsigned size = roundup(2 * sizeof(struct fec_bd),
ARCH_DMA_MINALIGN);
writew(0x0000, &fec->tbd_base[0].status);
+ fec_flush_bd(&fec->tbd_base[0]);
writew(FEC_TBD_WRAP, &fec->tbd_base[1].status);
+ fec_flush_bd(&fec->tbd_base[1]);
fec->tbd_index = 0;
flush_dcache_range(addr, addr+size);
}
*/
static int fec_open(struct eth_device *edev)
{
- struct fec_priv *fec = (struct fec_priv *)edev->priv;
+ struct fec_priv *fec = edev->priv;
int speed;
uint32_t addr, size;
int i;
static int fec_send(struct eth_device *dev, volatile void *packet, int length)
{
unsigned int status;
+ int timeout = 1000;
uint32_t size;
uint32_t addr;
* This routine transmits one frame. This routine only accepts
* 6-byte Ethernet addresses.
*/
- struct fec_priv *fec = (struct fec_priv *)dev->priv;
+ struct fec_priv *fec = dev->priv;
/*
* Check for valid length of data.
* update BD's status now
* This block:
* - is always the last in a chain (means no chain)
- * - should transmitt the CRC
+ * - should transmit the CRC
* - might be the last BD in the list, so the address counter should
* wrap (-> keep the WRAP flag)
*/
status = readw(&fec->tbd_base[fec->tbd_index].status) & FEC_TBD_WRAP;
status |= FEC_TBD_LAST | FEC_TBD_TC | FEC_TBD_READY;
writew(status, &fec->tbd_base[fec->tbd_index].status);
+ fec_flush_bd(&fec->tbd_base[fec->tbd_index]);
/*
* Flush data cache. This code flushes both TX descriptors to RAM.
*/
invalidate_dcache_range(addr, addr + size);
while (readw(&fec->tbd_base[fec->tbd_index].status) & FEC_TBD_READY) {
+ if (--timeout < 0)
+ return -ETIMEDOUT;
udelay(1);
invalidate_dcache_range(addr, addr + size);
}
*/
frame = (struct nbuf *)readl(&rbd->data_pointer);
frame_length = readw(&rbd->data_length) - 4;
+
+ invalidate_dcache_range((unsigned long)frame,
+ (unsigned long)frame +
+ sizeof(*frame));
+
/*
* Invalidate data cache over the buffer
*/
int ret = 0;
/* create and fill edev struct */
- edev = (struct eth_device *)malloc(sizeof(struct eth_device));
+ edev = calloc(sizeof(struct eth_device), 1);
if (!edev) {
puts("fec_mxc: not enough malloc memory for eth_device\n");
ret = -ENOMEM;
goto err1;
}
- fec = (struct fec_priv *)malloc(sizeof(struct fec_priv));
+ fec = calloc(sizeof(struct fec_priv), 1);
if (!fec) {
puts("fec_mxc: not enough malloc memory for fec_priv\n");
ret = -ENOMEM;
goto err2;
}
- memset(edev, 0, sizeof(*edev));
- memset(fec, 0, sizeof(*fec));
-
edev->priv = fec;
edev->init = fec_init;
edev->send = fec_send;