summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFugang Duan <b38611@freescale.com>2014-11-26 15:40:51 +0800
committerFugang Duan <b38611@freescale.com>2014-11-26 20:06:45 +0800
commit646d0d174050dabd13eb79dd47501d0f8d7d33e3 (patch)
tree6bc1fa95c76645be83c3c525120710f914101360
parentba38ade316ecc3766ec97ff4e029e17852160855 (diff)
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. (cherry-picked from commit: 8ab1562923ef47d523e76db06af0aa3e704c5316) Signed-off-by: Fugang Duan <B38611@freescale.com>
-rw-r--r--drivers/net/ethernet/freescale/fec.h4
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c30
2 files changed, 30 insertions, 4 deletions
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index f8e9d5763b9e..11b7d61251ea 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -293,6 +293,7 @@ struct bufdesc_ex {
#define FALSE 0
#define TRUE 1
+#define FEC0_MII_BUS_SHARE_TRUE 1
/* Interrupt events/masks. */
#define FEC_ENET_HBERR ((uint)0x80000000) /* Heartbeat error */
@@ -318,6 +319,8 @@ struct bufdesc_ex {
#define FEC_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII | FEC_ENET_TS_TIMER)
#define FEC_RX_DISABLED_IMASK (FEC_DEFAULT_IMASK & (~(FEC_ENET_RXF | FEC_ENET_TXF)))
+#define FEC_ENET_ETHEREN ((uint)0x00000002)
+
/* ENET AVB related macros define */
#define FEC_R_DES_START(X) ((X == 1) ? FEC_R_DES_START_1 : \
((X == 2) ? FEC_R_DES_START_2 : FEC_R_DES_START_0))
@@ -586,6 +589,7 @@ struct fec_enet_private {
struct mii_bus *mii_bus;
struct phy_device *phy_dev;
int mii_timeout;
+ int mii_bus_share;
uint phy_speed;
uint phy_id;
phy_interface_t phy_interface;
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 7659f86325b2..be158a610155 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -931,7 +931,7 @@ fec_restart(struct net_device *ndev, int duplex)
u32 val;
u32 temp_mac[2];
u32 rcntl = OPT_FRAME_SIZE | 0x04;
- u32 ecntl = 0x2; /* ETHEREN */
+ u32 ecntl = FEC_ENET_ETHEREN; /* ETHEREN */
if (netif_running(ndev)) {
netif_device_detach(ndev);
@@ -1847,6 +1847,17 @@ static inline void fec_enet_clk_enable(struct net_device *ndev, bool enable)
}
}
+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);
@@ -1919,6 +1930,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);
const struct platform_device_id *id_entry =
@@ -1945,6 +1957,7 @@ static int fec_enet_mii_init(struct platform_device *pdev)
/* 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;
}
@@ -1997,8 +2010,10 @@ static int fec_enet_mii_init(struct platform_device *pdev)
mii_cnt++;
/* save fec0 mii_bus */
- if (id_entry->driver_data & FEC_QUIRK_ENET_MAC)
+ if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
fec0_mii_bus = fep->mii_bus;
+ fec_mii_bus_share = &fep->mii_bus_share;
+ }
return 0;
@@ -2583,8 +2598,8 @@ fec_enet_open(struct net_device *ndev)
ret = fec_enet_mii_probe(ndev);
if (ret) {
fec_enet_free_buffers(ndev);
- fec_enet_clk_enable(ndev, false);
- pinctrl_pm_select_sleep_state(&fep->pdev->dev);
+ if (!fep->mii_bus_share)
+ pinctrl_pm_select_sleep_state(&fep->pdev->dev);
return ret;
}
@@ -3315,6 +3330,9 @@ fec_suspend(struct device *dev)
fec_enet_clk_enable(ndev, false);
pinctrl_pm_select_sleep_state(&fep->pdev->dev);
phy_stop(fep->phy_dev);
+ } else if (fep->mii_bus_share && !fep->phy_dev) {
+ fec_enet_clk_enable(ndev, false);
+ pinctrl_pm_select_sleep_state(&fep->pdev->dev);
}
if (fep->reg_phy)
@@ -3355,12 +3373,16 @@ fec_resume(struct device *dev)
writel(val, fep->hwp + FEC_ECNTRL);
fep->wol_flag &= ~FEC_WOL_FLAG_SLEEP_ON;
} else {
+ pinctrl_pm_select_default_state(&fep->pdev->dev);
fec_enet_clk_enable(ndev, true);
}
fec_restart(ndev, fep->full_duplex);
phy_start(fep->phy_dev);
netif_device_attach(ndev);
+ } else if (fep->mii_bus_share) {
+ pinctrl_pm_select_default_state(&fep->pdev->dev);
+ fec_restore_mii_bus(ndev);
}
return 0;