From: Fugang Duan Date: Wed, 10 Dec 2014 05:46:08 +0000 (+0800) Subject: MLK-9919 net: fec: reinit MAC0 MII bus for MAC1 use after resume back X-Git-Tag: C0P2-H0.0--20200415~4790 X-Git-Url: https://git.somdevices.com/?a=commitdiff_plain;h=eeae96fd46a9940c4b22e724b510713520bc18e7;p=linux.git MLK-9919 net: fec: reinit MAC0 MII bus for MAC1 use after resume back 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 (cherry picked from commit: b730adeef4f9b44e302c793cbef35ea74f24fbef) --- diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index a6a977bb1345..4f3f5e9c4a9d 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -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; diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 0cbf188bc644..2580f113b1fd 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -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();