net: phy: smsc: force all capable mode if the phy is started in powerdown mode
authortrem <tremyfr@yahoo.fr>
Tue, 4 Dec 2012 08:52:10 +0000 (08:52 +0000)
committerDavid S. Miller <davem@davemloft.net>
Fri, 7 Dec 2012 17:48:00 +0000 (12:48 -0500)
A SMSC PHY in power down mode can't be used.
If a SMSC PHY is in this mode in the config_init
stage, the mode "all capable" is set. So the PHY
could then be used.

Signed-off-by: Philippe Reynes <tremyfr@yahoo.fr>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/phy/smsc.c
include/linux/smscphy.h

index 16dceed..ef883e3 100644 (file)
@@ -43,7 +43,31 @@ static int smsc_phy_ack_interrupt(struct phy_device *phydev)
 
 static int smsc_phy_config_init(struct phy_device *phydev)
 {
-       int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
+       int rc = phy_read(phydev, MII_LAN83C185_SPECIAL_MODES);
+       if (rc < 0)
+               return rc;
+
+       /* If the SMSC PHY is in power down mode, then set it
+        * in all capable mode before using it.
+        */
+       if ((rc & MII_LAN83C185_MODE_MASK) == MII_LAN83C185_MODE_POWERDOWN) {
+               int timeout = 50000;
+
+               /* set "all capable" mode and reset the phy */
+               rc |= MII_LAN83C185_MODE_ALL;
+               phy_write(phydev, MII_LAN83C185_SPECIAL_MODES, rc);
+               phy_write(phydev, MII_BMCR, BMCR_RESET);
+
+               /* wait end of reset (max 500 ms) */
+               do {
+                       udelay(10);
+                       if (timeout-- == 0)
+                               return -1;
+                       rc = phy_read(phydev, MII_BMCR);
+               } while (rc & BMCR_RESET);
+       }
+
+       rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
        if (rc < 0)
                return rc;
 
index ce718cb..f4bf16e 100644 (file)
@@ -4,6 +4,7 @@
 #define MII_LAN83C185_ISF 29 /* Interrupt Source Flags */
 #define MII_LAN83C185_IM  30 /* Interrupt Mask */
 #define MII_LAN83C185_CTRL_STATUS 17 /* Mode/Status Register */
+#define MII_LAN83C185_SPECIAL_MODES 18 /* Special Modes Register */
 
 #define MII_LAN83C185_ISF_INT1 (1<<1) /* Auto-Negotiation Page Received */
 #define MII_LAN83C185_ISF_INT2 (1<<2) /* Parallel Detection Fault */
@@ -22,4 +23,8 @@
 #define MII_LAN83C185_EDPWRDOWN (1 << 13) /* EDPWRDOWN */
 #define MII_LAN83C185_ENERGYON  (1 << 1)  /* ENERGYON */
 
+#define MII_LAN83C185_MODE_MASK      0xE0
+#define MII_LAN83C185_MODE_POWERDOWN 0xC0 /* Power Down mode */
+#define MII_LAN83C185_MODE_ALL       0xE0 /* All capable mode */
+
 #endif /* __LINUX_SMSCPHY_H__ */