Skip to content

Commit

Permalink
lan78xx: workaround of forced 100 Full/Half duplex mode error
Browse files Browse the repository at this point in the history
At forced 100 Full & Half duplex mode, chip may fail to set mode correctly
when cable is switched between long(~50+m) and short one.
As workaround, set to 10 before setting to 100 at forced 100 F/H mode.

Signed-off-by: Woojung Huh <woojung.huh@microchip.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Woojung Huh authored and David S. Miller committed Apr 28, 2016
1 parent 74d79a2 commit 14437e3
Showing 1 changed file with 28 additions and 1 deletion.
29 changes: 28 additions & 1 deletion drivers/net/usb/lan78xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1804,7 +1804,34 @@ static void lan78xx_remove_mdio(struct lan78xx_net *dev)

static void lan78xx_link_status_change(struct net_device *net)
{
/* nothing to do */
struct phy_device *phydev = net->phydev;
int ret, temp;

/* At forced 100 F/H mode, chip may fail to set mode correctly
* when cable is switched between long(~50+m) and short one.
* As workaround, set to 10 before setting to 100
* at forced 100 F/H mode.
*/
if (!phydev->autoneg && (phydev->speed == 100)) {
/* disable phy interrupt */
temp = phy_read(phydev, LAN88XX_INT_MASK);
temp &= ~LAN88XX_INT_MASK_MDINTPIN_EN_;
ret = phy_write(phydev, LAN88XX_INT_MASK, temp);

temp = phy_read(phydev, MII_BMCR);
temp &= ~(BMCR_SPEED100 | BMCR_SPEED1000);
phy_write(phydev, MII_BMCR, temp); /* set to 10 first */
temp |= BMCR_SPEED100;
phy_write(phydev, MII_BMCR, temp); /* set to 100 later */

/* clear pending interrupt generated while workaround */
temp = phy_read(phydev, LAN88XX_INT_STS);

/* enable phy interrupt back */
temp = phy_read(phydev, LAN88XX_INT_MASK);
temp |= LAN88XX_INT_MASK_MDINTPIN_EN_;
ret = phy_write(phydev, LAN88XX_INT_MASK, temp);
}
}

static int lan78xx_phy_init(struct lan78xx_net *dev)
Expand Down

0 comments on commit 14437e3

Please sign in to comment.