summaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
authorAlbert ARIBAUD <albert.u.boot@aribaud.net>2014-06-24 19:54:20 +0200
committerAlbert ARIBAUD <albert.u.boot@aribaud.net>2014-06-24 19:54:20 +0200
commit754466ac95e92ebf40e25c6af6f13ab9b4d7c87b (patch)
treea63da2cacba9786c93f209a7f44c663c50d768a7 /drivers/net
parentaed39f354eb663bce7bfbf54c89397b14da2ed64 (diff)
parent6dbeb893c4a7668d0098318d6668ccf59bfbfdea (diff)
downloadu-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.c113
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;