[PATCH] lan91c111 phy power-up

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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);
 		}
 	}

[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux 802.1Q VLAN]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Git]     [Bugtraq]     [Yosemite News and Information]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux PCI]     [Linux Admin]     [Samba]

  Powered by Linux