Merge branch 'master' of git://www.denx.de/git/u-boot-microblaze
[oweals/u-boot.git] / drivers / net / fec_mxc.c
index b57247032fa85aaa65ec47c9fcf7668a4cd567df..3340dd256f6ed1db06f876305092eb9447a6cf1b 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <common.h>
 #include <malloc.h>
+#include <memalign.h>
 #include <net.h>
 #include <netdev.h>
 #include <miiphy.h>
@@ -17,6 +18,7 @@
 
 #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>
@@ -67,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)
 {
@@ -136,13 +131,25 @@ static void fec_mii_setspeed(struct ethernet_regs *eth)
        /*
         * Set MII_SPEED = (1/(mii_speed * 2)) * System Clock
         * and do not drop the Preamble.
+        *
+        * The i.MX28 and i.MX6 types have another field in the MSCR (aka
+        * MII_SPEED) register that defines the MDIO output hold time. Earlier
+        * versions are RAZ there, so just ignore the difference and write the
+        * register always.
+        * The minimal hold time according to IEE802.3 (clause 22) is 10 ns.
+        * HOLDTIME + 1 is the number of clk cycles the fec is holding the
+        * output.
+        * The HOLDTIME bitfield takes values between 0 and 7 (inclusive).
+        * Given that ceil(clkrate / 5000000) <= 64, the calculation for
+        * holdtime cannot result in a value greater than 3.
         */
-       register u32 speed = DIV_ROUND_UP(imx_get_fecclk(), 5000000);
+       u32 pclk = imx_get_fecclk();
+       u32 speed = DIV_ROUND_UP(pclk, 5000000);
+       u32 hold = DIV_ROUND_UP(pclk, 100000000) - 1;
 #ifdef FEC_QUIRK_ENET_MAC
        speed--;
 #endif
-       speed <<= 1;
-       writel(speed, &eth->mii_speed);
+       writel(speed << 1 | hold << 8, &eth->mii_speed);
        debug("%s: mii_speed %08x\n", __func__, readl(&eth->mii_speed));
 }
 
@@ -357,7 +364,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)
@@ -558,12 +565,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);
@@ -775,7 +785,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;
@@ -835,12 +844,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);
@@ -849,16 +857,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);
                }
 
                /*
@@ -1102,6 +1109,7 @@ int fecmxc_initialize_multi(bd_t *bd, int dev_id, int phy_id, uint32_t addr)
 #ifdef CONFIG_PHYLIB
        phydev = phy_find_by_mask(bus, 1 << phy_id, PHY_INTERFACE_MODE_RGMII);
        if (!phydev) {
+               mdio_unregister(bus);
                free(bus);
                return -ENOMEM;
        }
@@ -1113,6 +1121,7 @@ int fecmxc_initialize_multi(bd_t *bd, int dev_id, int phy_id, uint32_t addr)
 #ifdef CONFIG_PHYLIB
                free(phydev);
 #endif
+               mdio_unregister(bus);
                free(bus);
        }
        return ret;