X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fnet%2Ffec_mxc.c;h=b57247032fa85aaa65ec47c9fcf7668a4cd567df;hb=9d86c8dc960c6f4e7e349a41cd2757098da6a92f;hp=4cefda48e45b533453a1671e1c3618ae6d4ba853;hpb=6ba45cc0f8b46533965219cfd90864a60ec1009b;p=u-boot diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index 4cefda48e4..b57247032f 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "fec_mxc.h" @@ -28,6 +29,14 @@ DECLARE_GLOBAL_DATA_PTR; */ #define FEC_XFER_TIMEOUT 5000 +/* + * The standard 32-byte DMA alignment does not work on mx6solox, which requires + * 64-byte alignment in the DMA RX FEC buffer. + * Introduce the FEC_DMA_RX_MINALIGN which can cover mx6solox needs and also + * satisfies the alignment on other SoCs (32-bytes) + */ +#define FEC_DMA_RX_MINALIGN 64 + #ifndef CONFIG_MII #error "CONFIG_MII has to be defined!" #endif @@ -171,13 +180,14 @@ static int fec_mdio_write(struct ethernet_regs *eth, uint8_t phyAddr, 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); } @@ -711,13 +721,37 @@ static int fec_send(struct eth_device *dev, void *packet, int length) 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); @@ -881,9 +915,9 @@ static int fec_alloc_descs(struct fec_priv *fec) /* Allocate RX buffers. */ /* Maximum RX buffer size. */ - size = roundup(FEC_MAX_PKT_SIZE, ARCH_DMA_MINALIGN); + size = roundup(FEC_MAX_PKT_SIZE, FEC_DMA_RX_MINALIGN); for (i = 0; i < FEC_RBD_NUM; i++) { - data = memalign(ARCH_DMA_MINALIGN, size); + data = memalign(FEC_DMA_RX_MINALIGN, size); if (!data) { printf("%s: error allocating rxbuf %d\n", __func__, i); goto err_ring;