From bcef81c5c6245e0f28465e28777811e31899af7a Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Tue, 3 Jan 2012 13:36:19 +0000 Subject: [PATCH] --- yaml --- r: 279403 b: refs/heads/master c: 6386994e03ebbe60338ded3d586308a41e81c0dc h: refs/heads/master i: 279401: 9dcdf55ff6995fa7158aecd52716eacd76f2688a 279399: 01457889c99ea633b311da1a51eb6122bc6d7e19 v: v3 --- [refs] | 2 +- trunk/drivers/net/ethernet/smsc/smsc911x.c | 92 ++++++++++++++++++++++ 2 files changed, 93 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index b8f7d14b6ddd..14dc8caeaeb2 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 43c6759e73907e4c8e6624f70f5c4a860518b203 +refs/heads/master: 6386994e03ebbe60338ded3d586308a41e81c0dc diff --git a/trunk/drivers/net/ethernet/smsc/smsc911x.c b/trunk/drivers/net/ethernet/smsc/smsc911x.c index 06d0df61bee6..9d0b8ced0234 100644 --- a/trunk/drivers/net/ethernet/smsc/smsc911x.c +++ b/trunk/drivers/net/ethernet/smsc/smsc911x.c @@ -1319,10 +1319,92 @@ static void smsc911x_rx_multicast_update_workaround(struct smsc911x_data *pdata) spin_unlock(&pdata->mac_lock); } +static int smsc911x_phy_disable_energy_detect(struct smsc911x_data *pdata) +{ + int rc = 0; + + if (!pdata->phy_dev) + return rc; + + rc = phy_read(pdata->phy_dev, MII_LAN83C185_CTRL_STATUS); + + if (rc < 0) { + SMSC_WARN(pdata, drv, "Failed reading PHY control reg"); + return rc; + } + + /* + * If energy is detected the PHY is already awake so is not necessary + * to disable the energy detect power-down mode. + */ + if ((rc & MII_LAN83C185_EDPWRDOWN) && + !(rc & MII_LAN83C185_ENERGYON)) { + /* Disable energy detect mode for this SMSC Transceivers */ + rc = phy_write(pdata->phy_dev, MII_LAN83C185_CTRL_STATUS, + rc & (~MII_LAN83C185_EDPWRDOWN)); + + if (rc < 0) { + SMSC_WARN(pdata, drv, "Failed writing PHY control reg"); + return rc; + } + + mdelay(1); + } + + return 0; +} + +static int smsc911x_phy_enable_energy_detect(struct smsc911x_data *pdata) +{ + int rc = 0; + + if (!pdata->phy_dev) + return rc; + + rc = phy_read(pdata->phy_dev, MII_LAN83C185_CTRL_STATUS); + + if (rc < 0) { + SMSC_WARN(pdata, drv, "Failed reading PHY control reg"); + return rc; + } + + /* Only enable if energy detect mode is already disabled */ + if (!(rc & MII_LAN83C185_EDPWRDOWN)) { + mdelay(100); + /* Enable energy detect mode for this SMSC Transceivers */ + rc = phy_write(pdata->phy_dev, MII_LAN83C185_CTRL_STATUS, + rc | MII_LAN83C185_EDPWRDOWN); + + if (rc < 0) { + SMSC_WARN(pdata, drv, "Failed writing PHY control reg"); + return rc; + } + + mdelay(1); + } + return 0; +} + static int smsc911x_soft_reset(struct smsc911x_data *pdata) { unsigned int timeout; unsigned int temp; + int ret; + + /* + * LAN9210/LAN9211/LAN9220/LAN9221 chips have an internal PHY that + * are initialized in a Energy Detect Power-Down mode that prevents + * the MAC chip to be software reseted. So we have to wakeup the PHY + * before. + */ + if (pdata->generation == 4) { + ret = smsc911x_phy_disable_energy_detect(pdata); + + if (ret) { + SMSC_WARN(pdata, drv, "Failed to wakeup the PHY chip"); + return ret; + } + } /* Reset the LAN911x */ smsc911x_reg_write(pdata, HW_CFG, HW_CFG_SRST_); @@ -1336,6 +1418,16 @@ static int smsc911x_soft_reset(struct smsc911x_data *pdata) SMSC_WARN(pdata, drv, "Failed to complete reset"); return -EIO; } + + if (pdata->generation == 4) { + ret = smsc911x_phy_enable_energy_detect(pdata); + + if (ret) { + SMSC_WARN(pdata, drv, "Failed to wakeup the PHY chip"); + return ret; + } + } + return 0; }