]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00209520-03 - FEC : Add support for MX6SL MSL.
authorFugang Duan <B38611@freescale.com>
Wed, 16 May 2012 09:57:53 +0000 (17:57 +0800)
committerLothar Waßmann <LW@KARO-electronics.de>
Fri, 24 May 2013 06:34:38 +0000 (08:34 +0200)
- Modify the the platform macro define like as cpu_is_xxx()
  for supporting Mergrez chip.
- Config MIIGSK for FEC IP to enable RMII mode. MX25,MX53,
  and MX6Sololite use FEC IP, which need to config the MIIGSK
  registers memory map for RMII and MII.
- Correct device id_table entry name for differnt IP.
- Rewrite FEC MAC address by net_device address when reset FEC,
  which can avoid invalid MAC address to result in FEC cannot
  work.

Signed-off-by: Fugang Duan <B38611@freescale.com>
drivers/net/fec.c

index 6e710e11f1a4d7999851caa6391e5fe70b482a0f..acb2965ae77d7d5f8f26644f17eddbb5971d8b02 100755 (executable)
 #define FEC_QUIRK_SWAP_FRAME           (1 << 1)
 
 static struct platform_device_id fec_devtype[] = {
-#ifdef CONFIG_SOC_IMX6Q
        {
-               .name = DRIVER_NAME,
+               .name = "enet",
                .driver_data = FEC_QUIRK_ENET_MAC,
        },
-#else
        {
-               .name = DRIVER_NAME,
+               .name = "fec",
                .driver_data = 0,
        },
-#endif
        {
                .name = "imx28-fec",
                .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME,
@@ -146,12 +143,11 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
 #define FEC_ENET_MII_CLK       ((uint)2500000)
 #define FEC_ENET_HOLD_TIME     ((uint)0x100)  /* 2 internal clock cycle*/
 
-#if defined(CONFIG_FEC_1588) && (defined(CONFIG_ARCH_MX28) || \
-                               defined(CONFIG_ARCH_MX6))
-#define FEC_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII | \
-                               FEC_ENET_TS_AVAIL | FEC_ENET_TS_TIMER)
-#else
 #define FEC_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII)
+#if defined(CONFIG_FEC_1588)
+#define FEC_1588_IMASK   (FEC_ENET_TS_AVAIL | FEC_ENET_TS_TIMER)
+#else
+#define FEC_1588_IMASK 0
 #endif
 
 /* The FEC stores dest/src/type, data, and checksum for receive packets.
@@ -1032,7 +1028,7 @@ static int fec_enet_mii_probe(struct net_device *ndev)
        }
 
        /* mask with MAC supported features */
-       if (cpu_is_mx6())
+       if (cpu_is_mx6q() || cpu_is_mx6dl())
                phy_dev->supported &= PHY_GBIT_FEATURES;
        else
                phy_dev->supported &= PHY_BASIC_FEATURES;
@@ -1091,7 +1087,7 @@ static int fec_enet_mii_init(struct platform_device *pdev)
                                        (FEC_ENET_MII_CLK << 2)) << 1;
 
        /* set hold time to 2 internal clock cycle */
-       if (cpu_is_mx6())
+       if (cpu_is_mx6q() || cpu_is_mx6dl())
                fep->phy_speed |= FEC_ENET_HOLD_TIME;
 
        writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
@@ -1546,14 +1542,14 @@ fec_restart(struct net_device *dev, int duplex)
        udelay(10);
 
        /*
-        * enet-mac reset will reset mac address registers too,
-        * so need to reconfigure it.
+       /* if uboot don't set MAC address, get MAC address
+        * from command line; if command line don't set MAC
+        * address, get from OCOTP; otherwise, allocate random
+        * address.
         */
-       if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
-               memcpy(&temp_mac, dev->dev_addr, ETH_ALEN);
-               writel(cpu_to_be32(temp_mac[0]), fep->hwp + FEC_ADDR_LOW);
-               writel(cpu_to_be32(temp_mac[1]), fep->hwp + FEC_ADDR_HIGH);
-       }
+       memcpy(&temp_mac, dev->dev_addr, ETH_ALEN);
+       writel(cpu_to_be32(temp_mac[0]), fep->hwp + FEC_ADDR_LOW);
+       writel(cpu_to_be32(temp_mac[1]), fep->hwp + FEC_ADDR_HIGH);
 
        /* Clear any outstanding interrupt. */
        writel(0xffc00000, fep->hwp + FEC_IEVENT);
@@ -1623,23 +1619,24 @@ fec_restart(struct net_device *dev, int duplex)
                        val |= (1 << 9);
 
                writel(val, fep->hwp + FEC_R_CNTRL);
+       }
 
-               if (fep->ptimer_present) {
-                       /* Set Timer count */
-                       ret = fec_ptp_start(fep->ptp_priv);
-                       if (ret) {
-                               fep->ptimer_present = 0;
-                               reg = 0x0;
-                       } else
+       if (fep->ptimer_present) {
+               /* Set Timer count */
+               ret = fec_ptp_start(fep->ptp_priv);
+               if (ret) {
+                       fep->ptimer_present = 0;
+                       reg = 0x0;
+               } else
 #if defined(CONFIG_SOC_IMX28) || defined(CONFIG_ARCH_MX6)
-                               reg = 0x00000010;
+                       reg = 0x00000010;
 #else
-                               reg = 0x0;
+                       reg = 0x0;
 #endif
        } else
                reg = 0x0;
 
-#ifdef FEC_MIIGSK_ENR
+       if (cpu_is_mx25() || cpu_is_mx53() || cpu_is_mx6sl()) {
                if (fep->phy_interface == PHY_INTERFACE_MODE_RMII) {
                        /* disable the gasket and wait */
                        writel(0, fep->hwp + FEC_MIIGSK_ENR);
@@ -1654,8 +1651,14 @@ fec_restart(struct net_device *dev, int duplex)
 
                        /* re-enable the gasket */
                        writel(2, fep->hwp + FEC_MIIGSK_ENR);
+                       udelay(10);
+                       if (!(readl(fep->hwp + FEC_MIIGSK_ENR) & 4)) {
+                               udelay(100);
+                               if (!(readl(fep->hwp + FEC_MIIGSK_ENR) & 4))
+                                       dev_err(&fep->pdev->dev,
+                                               "switch to RMII failed!\n");
+                       }
                }
-#endif
        }
 
        /* ENET enable */
@@ -1668,7 +1671,7 @@ fec_restart(struct net_device *dev, int duplex)
                fep->phy_dev->speed == SPEED_1000)
                val |= (0x1 << 5);
 
-       if (cpu_is_mx6()) {
+       if (cpu_is_mx6q() || cpu_is_mx6dl()) {
                /* enable endian swap */
                val |= (0x1 << 8);
                /* enable ENET store and forward mode */
@@ -1679,7 +1682,11 @@ fec_restart(struct net_device *dev, int duplex)
        writel(0, fep->hwp + FEC_R_DES_ACTIVE);
 
        /* Enable interrupts we wish to service */
-       writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
+       if (cpu_is_mx6q() || cpu_is_mx6dl() || cpu_is_mx2() || cpu_is_mx3())
+               val = (FEC_1588_IMASK | FEC_DEFAULT_IMASK);
+       else
+               val = FEC_DEFAULT_IMASK;
+       writel(val, fep->hwp + FEC_IMASK);
 }
 
 static void
@@ -1699,7 +1706,7 @@ fec_stop(struct net_device *dev)
        writel(1, fep->hwp + FEC_ECNTRL);
        udelay(10);
 
-       if (cpu_is_mx6())
+       if (cpu_is_mx6q() || cpu_is_mx6dl())
                /* FIXME: we have to enable enet to keep mii interrupt works. */
                writel(2, fep->hwp + FEC_ECNTRL);
 
@@ -1707,6 +1714,8 @@ fec_stop(struct net_device *dev)
        if (fep->ptimer_present)
                fec_ptp_stop(fep->ptp_priv);
        writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
+       netif_stop_queue(dev);
+       fep->link = 0;
 }
 
 static int __devinit