]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - drivers/net/macb.c
Merge branch 'u-boot-sh/rmobile' into 'u-boot-arm/master'
[karo-tx-uboot.git] / drivers / net / macb.c
index 1f7cc322e0533b87d2da41f574e849244f4f8d73..01a94a4c4d117795fc6b2f42b8da701974b7e184 100644 (file)
 #include <asm/io.h>
 #include <asm/dma-mapping.h>
 #include <asm/arch/clk.h>
+#include <asm-generic/errno.h>
 
 #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
 
@@ -169,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);
@@ -183,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);
@@ -193,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)
 
@@ -207,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;
@@ -232,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)
@@ -252,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;
        }
 
@@ -265,6 +310,7 @@ static void reclaim_rx_buffers(struct macb_device *macb,
        }
 
        barrier();
+       macb_flush_ring_desc(macb, RX);
        macb->rx_tail = new_tail;
 }
 
@@ -278,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;
 
@@ -291,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],
@@ -305,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;
                        }
@@ -332,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;
@@ -384,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... */
@@ -397,9 +446,14 @@ static int macb_phy_init(struct macb_device *macb)
        }
 
 #ifdef CONFIG_PHYLIB
-       phydev->bus = macb->bus;
-       phydev->dev = netdev;
-       phydev->addr = macb->phy_addr;
+       /* need to consider other phy interface mode */
+       phydev = phy_connect(macb->bus, macb->phy_addr, netdev,
+                            PHY_INTERFACE_MODE_RGMII);
+       if (!phydev) {
+               printf("phy_connect failed\n");
+               return -ENODEV;
+       }
+
        phy_config(phydev);
 #endif
 
@@ -408,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;
@@ -493,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);
@@ -615,6 +676,24 @@ static u32 gem_mdc_clk_div(int id, struct macb_device *macb)
        return config;
 }
 
+/*
+ * Get the DMA bus width field of the network configuration register that we
+ * should program. We find the width from decoding the design configuration
+ * register to find the maximum supported data bus width.
+ */
+static u32 macb_dbw(struct macb_device *macb)
+{
+       switch (GEM_BFEXT(DBWDEF, gem_readl(macb, DCFG1))) {
+       case 4:
+               return GEM_BF(DBW, GEM_DBW128);
+       case 2:
+               return GEM_BF(DBW, GEM_DBW64);
+       case 1:
+       default:
+               return GEM_BF(DBW, GEM_DBW32);
+       }
+}
+
 int macb_eth_initialize(int id, void *regs, unsigned int phy_addr)
 {
        struct macb_device *macb;
@@ -630,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;
 
@@ -659,7 +738,7 @@ int macb_eth_initialize(int id, void *regs, unsigned int phy_addr)
         */
        if (macb_is_gem(macb)) {
                ncfgr = gem_mdc_clk_div(id, macb);
-               ncfgr |= GEM_BF(DBW, 1);
+               ncfgr |= macb_dbw(macb);
        } else {
                ncfgr = macb_mdc_clk_div(id, macb);
        }