diff options
author | Albert ARIBAUD <albert.u.boot@aribaud.net> | 2014-06-24 19:54:20 +0200 |
---|---|---|
committer | Albert ARIBAUD <albert.u.boot@aribaud.net> | 2014-06-24 19:54:20 +0200 |
commit | 754466ac95e92ebf40e25c6af6f13ab9b4d7c87b (patch) | |
tree | a63da2cacba9786c93f209a7f44c663c50d768a7 /drivers/net | |
parent | aed39f354eb663bce7bfbf54c89397b14da2ed64 (diff) | |
parent | 6dbeb893c4a7668d0098318d6668ccf59bfbfdea (diff) | |
download | u-boot-imx-754466ac95e92ebf40e25c6af6f13ab9b4d7c87b.zip u-boot-imx-754466ac95e92ebf40e25c6af6f13ab9b4d7c87b.tar.gz u-boot-imx-754466ac95e92ebf40e25c6af6f13ab9b4d7c87b.tar.bz2 |
Merge branch 'u-boot-atmel/master' into 'u-boot-arm/master'
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/macb.c | 113 |
1 files changed, 84 insertions, 29 deletions
diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 781a272..01a94a4 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -40,17 +40,21 @@ #include "macb.h" -#define CONFIG_SYS_MACB_RX_BUFFER_SIZE 4096 -#define CONFIG_SYS_MACB_RX_RING_SIZE (CONFIG_SYS_MACB_RX_BUFFER_SIZE / 128) -#define CONFIG_SYS_MACB_TX_RING_SIZE 16 -#define CONFIG_SYS_MACB_TX_TIMEOUT 1000 -#define CONFIG_SYS_MACB_AUTONEG_TIMEOUT 5000000 +#define MACB_RX_BUFFER_SIZE 4096 +#define MACB_RX_RING_SIZE (MACB_RX_BUFFER_SIZE / 128) +#define MACB_TX_RING_SIZE 16 +#define MACB_TX_TIMEOUT 1000 +#define MACB_AUTONEG_TIMEOUT 5000000 struct macb_dma_desc { u32 addr; u32 ctrl; }; +#define DMA_DESC_BYTES(n) (n * sizeof(struct macb_dma_desc)) +#define MACB_TX_DMA_DESC_SIZE (DMA_DESC_BYTES(MACB_TX_RING_SIZE)) +#define MACB_RX_DMA_DESC_SIZE (DMA_DESC_BYTES(MACB_RX_RING_SIZE)) + #define RXADDR_USED 0x00000001 #define RXADDR_WRAP 0x00000002 @@ -170,7 +174,7 @@ int macb_miiphy_read(const char *devname, u8 phy_adr, u8 reg, u16 *value) struct eth_device *dev = eth_get_dev_by_name(devname); struct macb_device *macb = to_macb(dev); - if ( macb->phy_addr != phy_adr ) + if (macb->phy_addr != phy_adr) return -1; arch_get_mdio_control(devname); @@ -184,7 +188,7 @@ int macb_miiphy_write(const char *devname, u8 phy_adr, u8 reg, u16 value) struct eth_device *dev = eth_get_dev_by_name(devname); struct macb_device *macb = to_macb(dev); - if ( macb->phy_addr != phy_adr ) + if (macb->phy_addr != phy_adr) return -1; arch_get_mdio_control(devname); @@ -194,6 +198,39 @@ int macb_miiphy_write(const char *devname, u8 phy_adr, u8 reg, u16 value) } #endif +#define RX 1 +#define TX 0 +static inline void macb_invalidate_ring_desc(struct macb_device *macb, bool rx) +{ + if (rx) + invalidate_dcache_range(macb->rx_ring_dma, macb->rx_ring_dma + + MACB_RX_DMA_DESC_SIZE); + else + invalidate_dcache_range(macb->tx_ring_dma, macb->tx_ring_dma + + MACB_TX_DMA_DESC_SIZE); +} + +static inline void macb_flush_ring_desc(struct macb_device *macb, bool rx) +{ + if (rx) + flush_dcache_range(macb->rx_ring_dma, macb->rx_ring_dma + + MACB_RX_DMA_DESC_SIZE); + else + flush_dcache_range(macb->tx_ring_dma, macb->tx_ring_dma + + MACB_TX_DMA_DESC_SIZE); +} + +static inline void macb_flush_rx_buffer(struct macb_device *macb) +{ + flush_dcache_range(macb->rx_buffer_dma, macb->rx_buffer_dma + + MACB_RX_BUFFER_SIZE); +} + +static inline void macb_invalidate_rx_buffer(struct macb_device *macb) +{ + invalidate_dcache_range(macb->rx_buffer_dma, macb->rx_buffer_dma + + MACB_RX_BUFFER_SIZE); +} #if defined(CONFIG_CMD_NET) @@ -208,23 +245,28 @@ static int macb_send(struct eth_device *netdev, void *packet, int length) ctrl = length & TXBUF_FRMLEN_MASK; ctrl |= TXBUF_FRAME_END; - if (tx_head == (CONFIG_SYS_MACB_TX_RING_SIZE - 1)) { + if (tx_head == (MACB_TX_RING_SIZE - 1)) { ctrl |= TXBUF_WRAP; macb->tx_head = 0; - } else + } else { macb->tx_head++; + } macb->tx_ring[tx_head].ctrl = ctrl; macb->tx_ring[tx_head].addr = paddr; barrier(); + macb_flush_ring_desc(macb, TX); + /* Do we need check paddr and length is dcache line aligned? */ + flush_dcache_range(paddr, paddr + length); macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE) | MACB_BIT(TSTART)); /* * I guess this is necessary because the networking core may * re-use the transmit buffer as soon as we return... */ - for (i = 0; i <= CONFIG_SYS_MACB_TX_TIMEOUT; i++) { + for (i = 0; i <= MACB_TX_TIMEOUT; i++) { barrier(); + macb_invalidate_ring_desc(macb, TX); ctrl = macb->tx_ring[tx_head].ctrl; if (ctrl & TXBUF_USED) break; @@ -233,7 +275,7 @@ static int macb_send(struct eth_device *netdev, void *packet, int length) dma_unmap_single(packet, length, paddr); - if (i <= CONFIG_SYS_MACB_TX_TIMEOUT) { + if (i <= MACB_TX_TIMEOUT) { if (ctrl & TXBUF_UNDERRUN) printf("%s: TX underrun\n", netdev->name); if (ctrl & TXBUF_EXHAUSTED) @@ -253,10 +295,12 @@ static void reclaim_rx_buffers(struct macb_device *macb, unsigned int i; i = macb->rx_tail; + + macb_invalidate_ring_desc(macb, RX); while (i > new_tail) { macb->rx_ring[i].addr &= ~RXADDR_USED; i++; - if (i > CONFIG_SYS_MACB_RX_RING_SIZE) + if (i > MACB_RX_RING_SIZE) i = 0; } @@ -266,6 +310,7 @@ static void reclaim_rx_buffers(struct macb_device *macb, } barrier(); + macb_flush_ring_desc(macb, RX); macb->rx_tail = new_tail; } @@ -279,6 +324,8 @@ static int macb_recv(struct eth_device *netdev) u32 status; for (;;) { + macb_invalidate_ring_desc(macb, RX); + if (!(macb->rx_ring[rx_tail].addr & RXADDR_USED)) return -1; @@ -292,10 +339,12 @@ static int macb_recv(struct eth_device *netdev) if (status & RXBUF_FRAME_END) { buffer = macb->rx_buffer + 128 * macb->rx_tail; length = status & RXBUF_FRMLEN_MASK; + + macb_invalidate_rx_buffer(macb); if (wrapped) { unsigned int headlen, taillen; - headlen = 128 * (CONFIG_SYS_MACB_RX_RING_SIZE + headlen = 128 * (MACB_RX_RING_SIZE - macb->rx_tail); taillen = length - headlen; memcpy((void *)NetRxPackets[0], @@ -306,11 +355,11 @@ static int macb_recv(struct eth_device *netdev) } NetReceive(buffer, length); - if (++rx_tail >= CONFIG_SYS_MACB_RX_RING_SIZE) + if (++rx_tail >= MACB_RX_RING_SIZE) rx_tail = 0; reclaim_rx_buffers(macb, rx_tail); } else { - if (++rx_tail >= CONFIG_SYS_MACB_RX_RING_SIZE) { + if (++rx_tail >= MACB_RX_RING_SIZE) { wrapped = 1; rx_tail = 0; } @@ -333,7 +382,7 @@ static void macb_phy_reset(struct macb_device *macb) macb_mdio_write(macb, MII_BMCR, (BMCR_ANENABLE | BMCR_ANRESTART)); - for (i = 0; i < CONFIG_SYS_MACB_AUTONEG_TIMEOUT / 100; i++) { + for (i = 0; i < MACB_AUTONEG_TIMEOUT / 100; i++) { status = macb_mdio_read(macb, MII_BMSR); if (status & BMSR_ANEGCOMPLETE) break; @@ -385,9 +434,8 @@ static int macb_phy_init(struct macb_device *macb) arch_get_mdio_control(netdev->name); #ifdef CONFIG_MACB_SEARCH_PHY /* Auto-detect phy_addr */ - if (!macb_phy_find(macb)) { + if (!macb_phy_find(macb)) return 0; - } #endif /* CONFIG_MACB_SEARCH_PHY */ /* Check if the PHY is up to snuff... */ @@ -414,7 +462,7 @@ static int macb_phy_init(struct macb_device *macb) /* Try to re-negotiate if we don't have link already. */ macb_phy_reset(macb); - for (i = 0; i < CONFIG_SYS_MACB_AUTONEG_TIMEOUT / 100; i++) { + for (i = 0; i < MACB_AUTONEG_TIMEOUT / 100; i++) { status = macb_mdio_read(macb, MII_BMSR); if (status & BMSR_LSTATUS) break; @@ -499,21 +547,28 @@ static int macb_init(struct eth_device *netdev, bd_t *bd) /* initialize DMA descriptors */ paddr = macb->rx_buffer_dma; - for (i = 0; i < CONFIG_SYS_MACB_RX_RING_SIZE; i++) { - if (i == (CONFIG_SYS_MACB_RX_RING_SIZE - 1)) + for (i = 0; i < MACB_RX_RING_SIZE; i++) { + if (i == (MACB_RX_RING_SIZE - 1)) paddr |= RXADDR_WRAP; macb->rx_ring[i].addr = paddr; macb->rx_ring[i].ctrl = 0; paddr += 128; } - for (i = 0; i < CONFIG_SYS_MACB_TX_RING_SIZE; i++) { + macb_flush_ring_desc(macb, RX); + macb_flush_rx_buffer(macb); + + for (i = 0; i < MACB_TX_RING_SIZE; i++) { macb->tx_ring[i].addr = 0; - if (i == (CONFIG_SYS_MACB_TX_RING_SIZE - 1)) + if (i == (MACB_TX_RING_SIZE - 1)) macb->tx_ring[i].ctrl = TXBUF_USED | TXBUF_WRAP; else macb->tx_ring[i].ctrl = TXBUF_USED; } - macb->rx_tail = macb->tx_head = macb->tx_tail = 0; + macb_flush_ring_desc(macb, TX); + + macb->rx_tail = 0; + macb->tx_head = 0; + macb->tx_tail = 0; macb_writel(macb, RBQP, macb->rx_ring_dma); macb_writel(macb, TBQP, macb->tx_ring_dma); @@ -654,15 +709,15 @@ int macb_eth_initialize(int id, void *regs, unsigned int phy_addr) netdev = &macb->netdev; - macb->rx_buffer = dma_alloc_coherent(CONFIG_SYS_MACB_RX_BUFFER_SIZE, + macb->rx_buffer = dma_alloc_coherent(MACB_RX_BUFFER_SIZE, &macb->rx_buffer_dma); - macb->rx_ring = dma_alloc_coherent(CONFIG_SYS_MACB_RX_RING_SIZE - * sizeof(struct macb_dma_desc), + macb->rx_ring = dma_alloc_coherent(MACB_RX_DMA_DESC_SIZE, &macb->rx_ring_dma); - macb->tx_ring = dma_alloc_coherent(CONFIG_SYS_MACB_TX_RING_SIZE - * sizeof(struct macb_dma_desc), + macb->tx_ring = dma_alloc_coherent(MACB_TX_DMA_DESC_SIZE, &macb->tx_ring_dma); + /* TODO: we need check the rx/tx_ring_dma is dcache line aligned */ + macb->regs = regs; macb->phy_addr = phy_addr; |