Hi All,
after calling the smc_drv_resume function, I noticed that sometime the
PHY doesn't resume at all.
Has anybody never met this issue?
According to the SMSC LAN91C11 documentation, the device is guaranteed
to be ready for normal operation 500ms after power-down is de-asserted.
The smc_drv_resume function invokes the smc_phy_configure but, it seems,
50ms are not to sufficient to put the PHY in isolation mode (following
the reset procedure).
Note that the driver only requires to wait 50ms after the reset pin was
de-asserted.
The patch attached reviews the resume function.
Instead of calling the smc_phy_configure now the driver follows the
procedure described into the datasheet.
I've tested it with the STLinux kernel 2.6.23 16 on SH4 platforms
(www.stlinux.com <http://www.stlinux.com>).
So I'm able to resume the target and the network is up and stable enough.
Best regards,
Giuseppe
According to the SMSC LAN91C11 datasheet, the device is guaranteed to be
ready for normal operation 500ms after power-down is de-asserted.
The smc_drv_resume function invokes the smc_phy_configure but it seems 50ms are
not to sufficient to put the PHY in isolation mode.
Indeed, the driver requires to wait 50ms after the reset pin was de-asserted.
This patch reviews the resume function.
Instead of calling the smc_phy_configure now the driver follows the procedure
described into the datasheet.
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@xxxxxx>
--- linux/drivers/net/smc91x.c.orig 2008-05-10 02:11:07.000000000 +0200
+++ linux/drivers/net/smc91x.c 2008-05-13 15:46:18.330003000 +0200
@@ -1080,6 +1080,59 @@ static void smc_phy_powerdown(struct net
}
/*
+ * smc_phy_powerup - powerup phy
+ * @dev: net device
+ *
+ * Restore the device in normal power mode.
+ */
+static void smc_phy_powerup(struct net_device *dev)
+{
+ struct smc_local *lp = netdev_priv(dev);
+ unsigned int bmcr;
+ int phy = lp->mii.phy_id;
+ void __iomem *ioaddr = lp->base;
+
+ if (lp->phy_type == 0)
+ return;
+
+ bmcr = smc_phy_read(dev, phy, MII_BMCR);
+ DBG(2, "smc_phy_powerup: PHY Ctrl Reg: 0x%x\n", bmcr);
+
+ /* Write the PDN bit in PHY MI register 0 */
+ bmcr &= ~BMCR_PDOWN;
+ smc_phy_write(dev, phy, MII_BMCR, bmcr);
+
+ /* PHY should be in isolation mode */
+ while (!(bmcr = smc_phy_read(dev, phy, MII_BMCR) & BMCR_ISOLATE)){}
+
+ /* Clear MII_DIS bit.*/
+ bmcr &= ~BMCR_ISOLATE;
+ smc_phy_write(dev, phy, MII_BMCR, bmcr);
+
+ /* Wait 500ms for the PHY in order to restore normal operation mode */
+ msleep(500);
+
+ /* Reconfigure the device caps */
+ SMC_SELECT_BANK(0);
+ SMC_SET_RPC(lp->rpc_cur_mode);
+
+ if (lp->mii.force_media) {
+ smc_phy_fixed(dev);
+ goto smc_phy_powerup_exit;
+ }
+
+ smc_phy_read(dev, phy, MII_ADVERTISE);
+
+ bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
+ smc_phy_write(dev, phy, MII_BMCR, bmcr);
+
+smc_phy_powerup_exit:
+ SMC_SELECT_BANK(2);
+ lp->work_pending = 0;
+ return;
+}
+
+/*
* smc_phy_check_media - check the media status and adjust TCR
* @dev: net device
* @init: set true for initialisation
@@ -2456,9 +2509,9 @@ static int smc_drv_resume(struct platfor
smc_enable_device(dev);
if (netif_running(ndev)) {
smc_reset(ndev);
- smc_enable(ndev);
if (lp->phy_type != 0)
- smc_phy_configure(&lp->phy_configure);
+ smc_phy_powerup(ndev);
+ smc_enable(ndev);
netif_device_attach(ndev);
}
}