Revert "ARM64: zynqmp: Added broken-tuning property to SD, eMMC nodes"
[oweals/u-boot.git] / drivers / net / fec_mxc.c
index c5dcbbbcedecf7302f0c68536c102af8aec6e77d..84021ea5bec553fba2469be9867ecf1af7abbcb7 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,8 +18,9 @@
 
 #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/errno.h>
 #include <linux/compiler.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -129,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));
 }
 
@@ -219,6 +233,7 @@ static int miiphy_restart_aneg(struct eth_device *dev)
        return ret;
 }
 
+#ifndef CONFIG_FEC_FIXED_SPEED
 static int miiphy_wait_aneg(struct eth_device *dev)
 {
        uint32_t start;
@@ -246,6 +261,7 @@ static int miiphy_wait_aneg(struct eth_device *dev)
 
        return 0;
 }
+#endif /* CONFIG_FEC_FIXED_SPEED */
 #endif
 
 static int fec_rx_task_enable(struct fec_priv *fec)
@@ -488,6 +504,8 @@ static int fec_open(struct eth_device *edev)
                }
                speed = fec->phydev->speed;
        }
+#elif CONFIG_FEC_FIXED_SPEED
+       speed = CONFIG_FEC_FIXED_SPEED;
 #else
        miiphy_wait_aneg(edev);
        speed = miiphy_speed(edev->name, fec->phy_id);
@@ -551,12 +569,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_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);
@@ -1003,7 +1024,7 @@ static int fec_probe(bd_t *bd, int dev_id, uint32_t base_addr,
        start = get_timer(0);
        while (readl(&fec->eth->ecntrl) & FEC_ECNTRL_RESET) {
                if (get_timer(start) > (CONFIG_SYS_HZ * 5)) {
-                       printf("FEC MXC: Timeout reseting chip\n");
+                       printf("FEC MXC: Timeout resetting chip\n");
                        goto err4;
                }
                udelay(10);
@@ -1092,6 +1113,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;
        }
@@ -1103,6 +1125,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;