net: fec: add fuse check
[oweals/u-boot.git] / drivers / net / fec_mxc.c
index a672250e16a166ab22d4cbc77793c53626beaa0a..3046305cfb65b827f306223af81f20392e699c14 100644 (file)
@@ -8,8 +8,9 @@
  */
 
 #include <common.h>
+#include <cpu_func.h>
 #include <dm.h>
-#include <environment.h>
+#include <env.h>
 #include <malloc.h>
 #include <memalign.h>
 #include <miiphy.h>
@@ -123,30 +124,38 @@ static int fec_mdio_read(struct ethernet_regs *eth, uint8_t phyaddr,
        return val;
 }
 
+#ifndef imx_get_fecclk
+u32 __weak imx_get_fecclk(void)
+{
+       return 0;
+}
+#endif
+
 static int fec_get_clk_rate(void *udev, int idx)
 {
-#if IS_ENABLED(CONFIG_IMX8)
        struct fec_priv *fec;
        struct udevice *dev;
        int ret;
 
-       dev = udev;
-       if (!dev) {
-               ret = uclass_get_device(UCLASS_ETH, idx, &dev);
-               if (ret < 0) {
-                       debug("Can't get FEC udev: %d\n", ret);
-                       return ret;
+       if (IS_ENABLED(CONFIG_IMX8) ||
+           CONFIG_IS_ENABLED(CLK_CCF)) {
+               dev = udev;
+               if (!dev) {
+                       ret = uclass_get_device(UCLASS_ETH, idx, &dev);
+                       if (ret < 0) {
+                               debug("Can't get FEC udev: %d\n", ret);
+                               return ret;
+                       }
                }
-       }
 
-       fec = dev_get_priv(dev);
-       if (fec)
-               return fec->clk_rate;
+               fec = dev_get_priv(dev);
+               if (fec)
+                       return fec->clk_rate;
 
-       return -EINVAL;
-#else
-       return imx_get_fecclk();
-#endif
+               return -EINVAL;
+       } else {
+               return imx_get_fecclk();
+       }
 }
 
 static void fec_mii_setspeed(struct ethernet_regs *eth)
@@ -494,6 +503,16 @@ static int fec_open(struct eth_device *edev)
        writel(readl(&fec->eth->ecntrl) | FEC_ECNTRL_ETHER_EN,
               &fec->eth->ecntrl);
 
+#ifdef FEC_ENET_ENABLE_TXC_DELAY
+       writel(readl(&fec->eth->ecntrl) | FEC_ECNTRL_TXC_DLY,
+              &fec->eth->ecntrl);
+#endif
+
+#ifdef FEC_ENET_ENABLE_RXC_DELAY
+       writel(readl(&fec->eth->ecntrl) | FEC_ECNTRL_RXC_DLY,
+              &fec->eth->ecntrl);
+#endif
+
 #if defined(CONFIG_MX25) || defined(CONFIG_MX53) || defined(CONFIG_MX6SL)
        udelay(100);
 
@@ -604,7 +623,7 @@ static int fec_init(struct eth_device *dev, bd_t *bd)
        writel(0x00000000, &fec->eth->gaddr2);
 
        /* Do not access reserved register */
-       if (!is_mx6ul() && !is_mx6ull() && !is_imx8m()) {
+       if (!is_mx6ul() && !is_mx6ull() && !is_imx8() && !is_imx8m()) {
                /* clear MIB RAM */
                for (i = mib_ptr; i <= mib_ptr + 0xfc; i += 4)
                        writel(0, i);
@@ -1185,6 +1204,13 @@ int fecmxc_initialize_multi(bd_t *bd, int dev_id, int phy_id, uint32_t addr)
 #endif
        int ret;
 
+       if (CONFIG_IS_ENABLED(IMX_MODULE_FUSE)) {
+               if (enet_fused((ulong)addr)) {
+                       printf("SoC fuse indicates Ethernet@0x%x is unavailable.\n", addr);
+                       return -ENODEV;
+               }
+       }
+
 #ifdef CONFIG_FEC_MXC_MDIO_BASE
        /*
         * The i.MX28 has two ethernet interfaces, but they are not equal.
@@ -1300,7 +1326,7 @@ static int fec_phy_init(struct fec_priv *priv, struct udevice *dev)
        return 0;
 }
 
-#ifdef CONFIG_DM_GPIO
+#if CONFIG_IS_ENABLED(DM_GPIO)
 /* FEC GPIO reset */
 static void fec_gpio_reset(struct fec_priv *priv)
 {
@@ -1323,6 +1349,13 @@ static int fecmxc_probe(struct udevice *dev)
        uint32_t start;
        int ret;
 
+       if (CONFIG_IS_ENABLED(IMX_MODULE_FUSE)) {
+               if (enet_fused((ulong)priv->eth)) {
+                       printf("SoC fuse indicates Ethernet@0x%lx is unavailable.\n", (ulong)priv->eth);
+                       return -ENODEV;
+               }
+       }
+
        if (IS_ENABLED(CONFIG_IMX8)) {
                ret = clk_get_by_name(dev, "ipg", &priv->ipg_clk);
                if (ret < 0) {
@@ -1335,6 +1368,47 @@ static int fecmxc_probe(struct udevice *dev)
                        return ret;
                }
 
+               priv->clk_rate = clk_get_rate(&priv->ipg_clk);
+       } else if (CONFIG_IS_ENABLED(CLK_CCF)) {
+               ret = clk_get_by_name(dev, "ipg", &priv->ipg_clk);
+               if (ret < 0) {
+                       debug("Can't get FEC ipg clk: %d\n", ret);
+                       return ret;
+               }
+               ret = clk_enable(&priv->ipg_clk);
+               if(ret)
+                       return ret;
+
+               ret = clk_get_by_name(dev, "ahb", &priv->ahb_clk);
+               if (ret < 0) {
+                       debug("Can't get FEC ahb clk: %d\n", ret);
+                       return ret;
+               }
+               ret = clk_enable(&priv->ahb_clk);
+               if (ret)
+                       return ret;
+
+               ret = clk_get_by_name(dev, "enet_out", &priv->clk_enet_out);
+               if (!ret) {
+                       ret = clk_enable(&priv->clk_enet_out);
+                       if (ret)
+                               return ret;
+               }
+
+               ret = clk_get_by_name(dev, "enet_clk_ref", &priv->clk_ref);
+               if (!ret) {
+                       ret = clk_enable(&priv->clk_ref);
+                       if (ret)
+                               return ret;
+               }
+
+               ret = clk_get_by_name(dev, "ptp", &priv->clk_ptp);
+               if (!ret) {
+                       ret = clk_enable(&priv->clk_ptp);
+                       if (ret)
+                               return ret;
+               }
+
                priv->clk_rate = clk_get_rate(&priv->ipg_clk);
        }
 
@@ -1352,7 +1426,7 @@ static int fecmxc_probe(struct udevice *dev)
        }
 #endif
 
-#ifdef CONFIG_DM_GPIO
+#if CONFIG_IS_ENABLED(DM_GPIO)
        fec_gpio_reset(priv);
 #endif
        /* Reset chip. */
@@ -1458,7 +1532,7 @@ static int fecmxc_ofdata_to_platdata(struct udevice *dev)
        device_get_supply_regulator(dev, "phy-supply", &priv->phy_supply);
 #endif
 
-#ifdef CONFIG_DM_GPIO
+#if CONFIG_IS_ENABLED(DM_GPIO)
        ret = gpio_request_by_name(dev, "phy-reset-gpios", 0,
                                   &priv->phy_reset_gpio, GPIOD_IS_OUT);
        if (ret < 0)
@@ -1485,6 +1559,7 @@ static int fecmxc_ofdata_to_platdata(struct udevice *dev)
 }
 
 static const struct udevice_id fecmxc_ids[] = {
+       { .compatible = "fsl,imx28-fec" },
        { .compatible = "fsl,imx6q-fec" },
        { .compatible = "fsl,imx6sl-fec" },
        { .compatible = "fsl,imx6sx-fec" },