Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[firefly-linux-kernel-4.4.55.git] / drivers / net / ethernet / freescale / fec_main.c
index 2b78a1ebe9034afc7aabc03eef8ed20f60c30eda..2451ab1b5a83c46dc6c1bae24ad8bfee509f6eab 100644 (file)
 
 #include <asm/cacheflush.h>
 
-#ifndef CONFIG_ARM
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#endif
-
 #include "fec.h"
 
 #if defined(CONFIG_ARM)
@@ -105,6 +100,9 @@ static struct platform_device_id fec_devtype[] = {
                .name = "imx6q-fec",
                .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
                                FEC_QUIRK_HAS_BUFDESC_EX,
+       }, {
+               .name = "mvf-fec",
+               .driver_data = FEC_QUIRK_ENET_MAC,
        }, {
                /* sentinel */
        }
@@ -116,6 +114,7 @@ enum imx_fec_type {
        IMX27_FEC,      /* runs on i.mx27/35/51 */
        IMX28_FEC,
        IMX6Q_FEC,
+       MVF_FEC,
 };
 
 static const struct of_device_id fec_dt_ids[] = {
@@ -123,6 +122,7 @@ static const struct of_device_id fec_dt_ids[] = {
        { .compatible = "fsl,imx27-fec", .data = &fec_devtype[IMX27_FEC], },
        { .compatible = "fsl,imx28-fec", .data = &fec_devtype[IMX28_FEC], },
        { .compatible = "fsl,imx6q-fec", .data = &fec_devtype[IMX6Q_FEC], },
+       { .compatible = "fsl,mvf-fec", .data = &fec_devtype[MVF_FEC], },
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, fec_dt_ids);
@@ -261,7 +261,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
                /* Ooops.  All transmit buffers are full.  Bail out.
                 * This should not happen, since ndev->tbusy should be set.
                 */
-               printk("%s: tx queue full!.\n", ndev->name);
+               netdev_err(ndev, "tx queue full!\n");
                return NETDEV_TX_BUSY;
        }
 
@@ -344,6 +344,53 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        return NETDEV_TX_OK;
 }
 
+/* Init RX & TX buffer descriptors
+ */
+static void fec_enet_bd_init(struct net_device *dev)
+{
+       struct fec_enet_private *fep = netdev_priv(dev);
+       struct bufdesc *bdp;
+       unsigned int i;
+
+       /* Initialize the receive buffer descriptors. */
+       bdp = fep->rx_bd_base;
+       for (i = 0; i < RX_RING_SIZE; i++) {
+
+               /* Initialize the BD for every fragment in the page. */
+               if (bdp->cbd_bufaddr)
+                       bdp->cbd_sc = BD_ENET_RX_EMPTY;
+               else
+                       bdp->cbd_sc = 0;
+               bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+       }
+
+       /* Set the last buffer to wrap */
+       bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
+       bdp->cbd_sc |= BD_SC_WRAP;
+
+       fep->cur_rx = fep->rx_bd_base;
+
+       /* ...and the same for transmit */
+       bdp = fep->tx_bd_base;
+       fep->cur_tx = bdp;
+       for (i = 0; i < TX_RING_SIZE; i++) {
+
+               /* Initialize the BD for every fragment in the page. */
+               bdp->cbd_sc = 0;
+               if (bdp->cbd_bufaddr && fep->tx_skbuff[i]) {
+                       dev_kfree_skb_any(fep->tx_skbuff[i]);
+                       fep->tx_skbuff[i] = NULL;
+               }
+               bdp->cbd_bufaddr = 0;
+               bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+       }
+
+       /* Set the last buffer to wrap */
+       bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
+       bdp->cbd_sc |= BD_SC_WRAP;
+       fep->dirty_tx = bdp;
+}
+
 /* This function is called to start or restart the FEC during a link
  * change.  This only happens when switching between half and full
  * duplex.
@@ -387,6 +434,8 @@ fec_restart(struct net_device *ndev, int duplex)
        /* Set maximum receive buffer size. */
        writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE);
 
+       fec_enet_bd_init(ndev);
+
        /* Set receive and transmit descriptor base. */
        writel(fep->bd_dma, fep->hwp + FEC_R_DES_START);
        if (fep->bufdesc_ex)
@@ -396,7 +445,6 @@ fec_restart(struct net_device *ndev, int duplex)
                writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc)
                        * RX_RING_SIZE, fep->hwp + FEC_X_DES_START);
 
-       fep->cur_rx = fep->rx_bd_base;
 
        for (i = 0; i <= TX_RING_MOD_MASK; i++) {
                if (fep->tx_skbuff[i]) {
@@ -525,7 +573,7 @@ fec_stop(struct net_device *ndev)
                writel(1, fep->hwp + FEC_X_CNTRL); /* Graceful transmit stop */
                udelay(10);
                if (!(readl(fep->hwp + FEC_IEVENT) & FEC_ENET_GRA))
-                       printk("fec_stop : Graceful transmit stop did not complete !\n");
+                       netdev_err(ndev, "Graceful transmit stop did not complete!\n");
        }
 
        /* Whack a reset.  We should wait for this. */
@@ -623,7 +671,7 @@ fec_enet_tx(struct net_device *ndev)
                }
 
                if (status & BD_ENET_TX_READY)
-                       printk("HEY! Enet xmit interrupt and TX_READY.\n");
+                       netdev_err(ndev, "HEY! Enet xmit interrupt and TX_READY\n");
 
                /* Deferred means some collisions occurred during transmit,
                 * but we eventually sent the packet OK.
@@ -691,7 +739,7 @@ fec_enet_rx(struct net_device *ndev, int budget)
                 * the last indicator should be set.
                 */
                if ((status & BD_ENET_RX_LAST) == 0)
-                       printk("FEC ENET: rcv is not +last\n");
+                       netdev_err(ndev, "rcv is not +last\n");
 
                if (!fep->opened)
                        goto rx_processing_done;
@@ -865,7 +913,6 @@ static void fec_get_mac(struct net_device *ndev)
         */
        iap = macaddr;
 
-#ifdef CONFIG_OF
        /*
         * 2) from device tree data
         */
@@ -877,7 +924,6 @@ static void fec_get_mac(struct net_device *ndev)
                                iap = (unsigned char *) mac;
                }
        }
-#endif
 
        /*
         * 3) from flash or fuse (via platform data)
@@ -951,6 +997,7 @@ static void fec_enet_adjust_link(struct net_device *ndev)
        } else {
                if (fep->link) {
                        fec_stop(ndev);
+                       fep->link = phy_dev->link;
                        status_change = 1;
                }
        }
@@ -980,7 +1027,7 @@ static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
                        usecs_to_jiffies(FEC_MII_TIMEOUT));
        if (time_left == 0) {
                fep->mii_timeout = 1;
-               printk(KERN_ERR "FEC: MDIO read timeout\n");
+               netdev_err(fep->netdev, "MDIO read timeout\n");
                return -ETIMEDOUT;
        }
 
@@ -1008,7 +1055,7 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
                        usecs_to_jiffies(FEC_MII_TIMEOUT));
        if (time_left == 0) {
                fep->mii_timeout = 1;
-               printk(KERN_ERR "FEC: MDIO write timeout\n");
+               netdev_err(fep->netdev, "MDIO write timeout\n");
                return -ETIMEDOUT;
        }
 
@@ -1048,9 +1095,7 @@ static int fec_enet_mii_probe(struct net_device *ndev)
        }
 
        if (phy_id >= PHY_MAX_ADDR) {
-               printk(KERN_INFO
-                       "%s: no PHY, assuming direct connection to switch\n",
-                       ndev->name);
+               netdev_info(ndev, "no PHY, assuming direct connection to switch\n");
                strncpy(mdio_bus_id, "fixed-0", MII_BUS_ID_SIZE);
                phy_id = 0;
        }
@@ -1059,7 +1104,7 @@ static int fec_enet_mii_probe(struct net_device *ndev)
        phy_dev = phy_connect(ndev, phy_name, &fec_enet_adjust_link,
                              fep->phy_interface);
        if (IS_ERR(phy_dev)) {
-               printk(KERN_ERR "%s: could not attach to PHY\n", ndev->name);
+               netdev_err(ndev, "could not attach to PHY\n");
                return PTR_ERR(phy_dev);
        }
 
@@ -1077,11 +1122,9 @@ static int fec_enet_mii_probe(struct net_device *ndev)
        fep->link = 0;
        fep->full_duplex = 0;
 
-       printk(KERN_INFO
-               "%s: Freescale FEC PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",
-               ndev->name,
-               fep->phy_dev->drv->name, dev_name(&fep->phy_dev->dev),
-               fep->phy_dev->irq);
+       netdev_info(ndev, "Freescale FEC PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",
+                   fep->phy_dev->drv->name, dev_name(&fep->phy_dev->dev),
+                   fep->phy_dev->irq);
 
        return 0;
 }
@@ -1594,8 +1637,6 @@ static int fec_enet_init(struct net_device *ndev)
 {
        struct fec_enet_private *fep = netdev_priv(ndev);
        struct bufdesc *cbd_base;
-       struct bufdesc *bdp;
-       unsigned int i;
 
        /* Allocate memory for buffer descriptors. */
        cbd_base = dma_alloc_coherent(NULL, PAGE_SIZE, &fep->bd_dma,
@@ -1603,6 +1644,7 @@ static int fec_enet_init(struct net_device *ndev)
        if (!cbd_base)
                return -ENOMEM;
 
+       memset(cbd_base, 0, PAGE_SIZE);
        spin_lock_init(&fep->hw_lock);
 
        fep->netdev = ndev;
@@ -1626,51 +1668,12 @@ static int fec_enet_init(struct net_device *ndev)
        writel(FEC_RX_DISABLED_IMASK, fep->hwp + FEC_IMASK);
        netif_napi_add(ndev, &fep->napi, fec_enet_rx_napi, FEC_NAPI_WEIGHT);
 
-       /* Initialize the receive buffer descriptors. */
-       bdp = fep->rx_bd_base;
-       for (i = 0; i < RX_RING_SIZE; i++) {
-
-               /* Initialize the BD for every fragment in the page. */
-               bdp->cbd_sc = 0;
-               bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
-       }
-
-       /* Set the last buffer to wrap */
-       bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
-       bdp->cbd_sc |= BD_SC_WRAP;
-
-       /* ...and the same for transmit */
-       bdp = fep->tx_bd_base;
-       fep->cur_tx = bdp;
-       for (i = 0; i < TX_RING_SIZE; i++) {
-
-               /* Initialize the BD for every fragment in the page. */
-               bdp->cbd_sc = 0;
-               bdp->cbd_bufaddr = 0;
-               bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
-       }
-
-       /* Set the last buffer to wrap */
-       bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
-       bdp->cbd_sc |= BD_SC_WRAP;
-       fep->dirty_tx = bdp;
-
        fec_restart(ndev, 0);
 
        return 0;
 }
 
 #ifdef CONFIG_OF
-static int fec_get_phy_mode_dt(struct platform_device *pdev)
-{
-       struct device_node *np = pdev->dev.of_node;
-
-       if (np)
-               return of_get_phy_mode(np);
-
-       return -ENODEV;
-}
-
 static void fec_reset_phy(struct platform_device *pdev)
 {
        int err, phy_reset;
@@ -1699,11 +1702,6 @@ static void fec_reset_phy(struct platform_device *pdev)
        gpio_set_value(phy_reset, 1);
 }
 #else /* CONFIG_OF */
-static int fec_get_phy_mode_dt(struct platform_device *pdev)
-{
-       return -ENODEV;
-}
-
 static void fec_reset_phy(struct platform_device *pdev)
 {
        /*
@@ -1762,7 +1760,7 @@ fec_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, ndev);
 
-       ret = fec_get_phy_mode_dt(pdev);
+       ret = of_get_phy_mode(pdev->dev.of_node);
        if (ret < 0) {
                pdata = pdev->dev.platform_data;
                if (pdata)
@@ -1852,6 +1850,9 @@ fec_probe(struct platform_device *pdev)
        if (ret)
                goto failed_register;
 
+       if (fep->bufdesc_ex && fep->ptp_clock)
+               netdev_info(ndev, "registered PHC device %d\n", fep->dev_id);
+
        return 0;
 
 failed_register:
@@ -1904,7 +1905,7 @@ fec_drv_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int
 fec_suspend(struct device *dev)
 {
@@ -1936,24 +1937,15 @@ fec_resume(struct device *dev)
 
        return 0;
 }
+#endif /* CONFIG_PM_SLEEP */
 
-static const struct dev_pm_ops fec_pm_ops = {
-       .suspend        = fec_suspend,
-       .resume         = fec_resume,
-       .freeze         = fec_suspend,
-       .thaw           = fec_resume,
-       .poweroff       = fec_suspend,
-       .restore        = fec_resume,
-};
-#endif
+static SIMPLE_DEV_PM_OPS(fec_pm_ops, fec_suspend, fec_resume);
 
 static struct platform_driver fec_driver = {
        .driver = {
                .name   = DRIVER_NAME,
                .owner  = THIS_MODULE,
-#ifdef CONFIG_PM
                .pm     = &fec_pm_ops,
-#endif
                .of_match_table = fec_dt_ids,
        },
        .id_table = fec_devtype,