MLK-9919 net: fec: reinit MAC0 MII bus for MAC1 use after resume back
authorFugang Duan <b38611@freescale.com>
Wed, 10 Dec 2014 05:46:08 +0000 (13:46 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 19:46:48 +0000 (14:46 -0500)
i.MX6SX-AI board has two enet MACs (MAC0 and MAC1), they share MAC0 MII
bus. When PHY0 don't connect to enet MAC0, MAC0 mii bus probe phy0 failed,
and the net interface is set to unattach mode. During suspend resume test,
driver don't reinit MAC0 after resume back, so MII bus don't work that causes
MAC1 also cannot access PHY1.

The patch just is workaround that reinit MAC0 MII bus for MAC1 using.

Signed-off-by: Fugang Duan <B38611@freescale.com>
(cherry picked from commit: b730adeef4f9b44e302c793cbef35ea74f24fbef)

drivers/net/ethernet/freescale/fec.h
drivers/net/ethernet/freescale/fec_main.c

index a6a977b..4f3f5e9 100644 (file)
@@ -354,6 +354,8 @@ struct bufdesc_ex {
 #define FLAG_RX_CSUM_ENABLED   (BD_ENET_RX_ICE | BD_ENET_RX_PCR)
 #define FLAG_RX_CSUM_ERROR     (BD_ENET_RX_ICE | BD_ENET_RX_PCR)
 
+#define FEC0_MII_BUS_SHARE_TRUE        1
+
 /* Interrupt events/masks. */
 #define FEC_ENET_HBERR  ((uint)0x80000000)      /* Heartbeat error */
 #define FEC_ENET_BABR   ((uint)0x40000000)      /* Babbling receiver */
@@ -379,6 +381,8 @@ struct bufdesc_ex {
 #define FEC_NAPI_IMASK (FEC_ENET_MII | FEC_ENET_TS_TIMER)
 #define FEC_RX_DISABLED_IMASK (FEC_DEFAULT_IMASK & (~FEC_ENET_RXF))
 
+#define FEC_ENET_ETHEREN       ((uint)0x00000002)
+
 /* ENET interrupt coalescing macro define */
 #define FEC_ITR_CLK_SEL                (0x1 << 30)
 #define FEC_ITR_EN             (0x1 << 31)
@@ -529,6 +533,7 @@ struct fec_enet_private {
        /* Phylib and MDIO interface */
        struct  mii_bus *mii_bus;
        int     mii_timeout;
+       int     mii_bus_share;
        uint    phy_speed;
        phy_interface_t phy_interface;
        struct device_node *phy_node;
index 0cbf188..2580f11 100644 (file)
@@ -905,7 +905,7 @@ fec_restart(struct net_device *ndev)
        u32 val;
        u32 temp_mac[2];
        u32 rcntl = OPT_FRAME_SIZE | 0x04;
-       u32 ecntl = 0x2; /* ETHEREN */
+       u32 ecntl = FEC_ENET_ETHEREN; /* ETHEREN */
 
        /* Whack a reset.  We should wait for this.
         * For i.MX6SX SOC, enet use AXI bus, we use disable MAC
@@ -1899,6 +1899,17 @@ failed_clk_enet_out:
        return ret;
 }
 
+static void fec_restore_mii_bus(struct net_device *ndev)
+{
+       struct fec_enet_private *fep = netdev_priv(ndev);
+
+       fec_enet_clk_enable(ndev, true);
+       writel(0xffc00000, fep->hwp + FEC_IEVENT);
+       writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
+       writel(FEC_ENET_MII, fep->hwp + FEC_IMASK);
+       writel(FEC_ENET_ETHEREN, fep->hwp + FEC_ECNTRL);
+}
+
 static int fec_enet_mii_probe(struct net_device *ndev)
 {
        struct fec_enet_private *fep = netdev_priv(ndev);
@@ -1966,6 +1977,7 @@ static int fec_enet_mii_probe(struct net_device *ndev)
 static int fec_enet_mii_init(struct platform_device *pdev)
 {
        static struct mii_bus *fec0_mii_bus;
+       static int *fec_mii_bus_share;
        struct net_device *ndev = platform_get_drvdata(pdev);
        struct fec_enet_private *fep = netdev_priv(ndev);
        struct device_node *node;
@@ -1988,10 +2000,11 @@ static int fec_enet_mii_init(struct platform_device *pdev)
         * mdio interface in board design, and need to be configured by
         * fec0 mii_bus.
         */
-       if ((fep->quirks & FEC_QUIRK_SINGLE_MDIO) && fep->dev_id > 0) {
+       if ((fep->quirks & FEC_QUIRK_ENET_MAC) && fep->dev_id > 0) {
                /* fec1 uses fec0 mii_bus */
                if (mii_cnt && fec0_mii_bus) {
                        fep->mii_bus = fec0_mii_bus;
+                       *fec_mii_bus_share = FEC0_MII_BUS_SHARE_TRUE;
                        mii_cnt++;
                        return 0;
                }
@@ -2065,8 +2078,10 @@ static int fec_enet_mii_init(struct platform_device *pdev)
        mii_cnt++;
 
        /* save fec0 mii_bus */
-       if (fep->quirks & FEC_QUIRK_SINGLE_MDIO)
+       if (fep->quirks & FEC_QUIRK_ENET_MAC) {
                fec0_mii_bus = fep->mii_bus;
+               fec_mii_bus_share = &fep->mii_bus_share;
+       }
 
        return 0;
 
@@ -2904,11 +2919,13 @@ fec_enet_open(struct net_device *ndev)
 err_enet_mii_probe:
        fec_enet_free_buffers(ndev);
 err_enet_alloc:
-       fec_enet_clk_enable(ndev, false);
+       if (!fep->mii_bus_share)
+               fec_enet_clk_enable(ndev, false);
 clk_enable:
        pm_runtime_mark_last_busy(&fep->pdev->dev);
        pm_runtime_put_autosuspend(&fep->pdev->dev);
-       pinctrl_pm_select_sleep_state(&fep->pdev->dev);
+       if (!fep->mii_bus_share)
+               pinctrl_pm_select_sleep_state(&fep->pdev->dev);
        return ret;
 }
 
@@ -3612,6 +3629,10 @@ static int __maybe_unused fec_suspend(struct device *dev)
                fec_enet_clk_enable(ndev, false);
                if (!(fep->wol_flag & FEC_WOL_FLAG_ENABLE))
                        pinctrl_pm_select_sleep_state(&fep->pdev->dev);
+               pinctrl_pm_select_sleep_state(&fep->pdev->dev);
+       } else if (fep->mii_bus_share && !ndev->phydev) {
+               fec_enet_clk_enable(ndev, false);
+               pinctrl_pm_select_sleep_state(&fep->pdev->dev);
        }
        rtnl_unlock();
 
@@ -3664,6 +3685,9 @@ static int __maybe_unused fec_resume(struct device *dev)
                netif_tx_unlock_bh(ndev);
                napi_enable(&fep->napi);
                phy_start(ndev->phydev);
+       } else if (fep->mii_bus_share && !ndev->phydev) {
+               pinctrl_pm_select_default_state(&fep->pdev->dev);
+               fec_restore_mii_bus(ndev);
        }
        rtnl_unlock();