net: gem: Enable MDIO bus earlier
[oweals/u-boot.git] / drivers / net / fec_mxc.c
index d31001651642b2e8127e8274aee4485d87b17578..79f6737e8e9c9727c46591cfe543643c83b17d4e 100644 (file)
 
 #include <common.h>
 #include <malloc.h>
+#include <memalign.h>
 #include <net.h>
+#include <netdev.h>
 #include <miiphy.h>
 #include "fec_mxc.h"
 
 #include <asm/arch/clock.h>
 #include <asm/arch/imx-regs.h>
+#include <asm/imx-common/sys_proto.h>
 #include <asm/io.h>
 #include <asm/errno.h>
 #include <linux/compiler.h>
@@ -66,13 +69,6 @@ DECLARE_GLOBAL_DATA_PTR;
 
 #undef DEBUG
 
-struct nbuf {
-       uint8_t data[1500];     /**< actual data */
-       int length;             /**< actual length */
-       int used;               /**< buffer in use or not */
-       uint8_t head[16];       /**< MAC header(6 + 6 + 2) + 2(aligned) */
-};
-
 #ifdef CONFIG_FEC_MXC_SWAP_PACKET
 static void swap_packet(uint32_t *packet, int length)
 {
@@ -179,13 +175,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);
 }
@@ -355,7 +352,7 @@ static int fec_get_hwaddr(struct eth_device *dev, int dev_id,
                                                unsigned char *mac)
 {
        imx_get_mac_from_fuse(dev_id, mac);
-       return !is_valid_ether_addr(mac);
+       return !is_valid_ethaddr(mac);
 }
 
 static int fec_set_hwaddr(struct eth_device *dev)
@@ -556,12 +553,15 @@ static int fec_init(struct eth_device *dev, bd_t* bd)
        writel(0x00000000, &fec->eth->gaddr2);
 
 
-       /* clear MIB RAM */
-       for (i = mib_ptr; i <= mib_ptr + 0xfc; i += 4)
-               writel(0, i);
+       /* Do not access reserved register for i.MX6UL */
+       if (!is_cpu_type(MXC_CPU_MX6UL)) {
+               /* clear MIB RAM */
+               for (i = mib_ptr; i <= mib_ptr + 0xfc; i += 4)
+                       writel(0, i);
 
-       /* FIFO receive start register */
-       writel(0x520, &fec->eth->r_fstart);
+               /* FIFO receive start register */
+               writel(0x520, &fec->eth->r_fstart);
+       }
 
        /* size and address of each buffer */
        writel(FEC_MAX_PKT_SIZE, &fec->eth->emrbr);
@@ -719,13 +719,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);
@@ -749,7 +773,6 @@ static int fec_recv(struct eth_device *dev)
        struct fec_bd *rbd = &fec->rbd_base[fec->rbd_index];
        unsigned long ievent;
        int frame_length, len = 0;
-       struct nbuf *frame;
        uint16_t bd_status;
        uint32_t addr, size, end;
        int i;
@@ -809,12 +832,11 @@ static int fec_recv(struct eth_device *dev)
                        /*
                         * Get buffer address and size
                         */
-                       frame = (struct nbuf *)readl(&rbd->data_pointer);
+                       addr = readl(&rbd->data_pointer);
                        frame_length = readw(&rbd->data_length) - 4;
                        /*
                         * Invalidate data cache over the buffer
                         */
-                       addr = (uint32_t)frame;
                        end = roundup(addr + frame_length, ARCH_DMA_MINALIGN);
                        addr &= ~(ARCH_DMA_MINALIGN - 1);
                        invalidate_dcache_range(addr, end);
@@ -823,16 +845,15 @@ static int fec_recv(struct eth_device *dev)
                         *  Fill the buffer and pass it to upper layers
                         */
 #ifdef CONFIG_FEC_MXC_SWAP_PACKET
-                       swap_packet((uint32_t *)frame->data, frame_length);
+                       swap_packet((uint32_t *)addr, frame_length);
 #endif
-                       memcpy(buff, frame->data, frame_length);
-                       NetReceive(buff, frame_length);
+                       memcpy(buff, (char *)addr, frame_length);
+                       net_process_received_packet(buff, frame_length);
                        len = frame_length;
                } else {
                        if (bd_status & FEC_RBD_ERR)
-                               printf("error frame: 0x%08lx 0x%08x\n",
-                                               (ulong)rbd->data_pointer,
-                                               bd_status);
+                               printf("error frame: 0x%08x 0x%08x\n",
+                                      addr, bd_status);
                }
 
                /*