aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/phy/micrel.c
diff options
context:
space:
mode:
authorAlexandre Belloni <alexandre.belloni@free-electrons.com>2016-02-26 19:18:23 +0100
committerDavid S. Miller <davem@davemloft.net>2016-03-01 16:52:09 -0500
commit99f81afc139c6edd14d77a91ee91685a414a1c66 (patch)
tree9a5f0505739358bb9ad908e4d7a959849199cf00 /drivers/net/phy/micrel.c
parentphy: micrel: Ensure interrupts are reenabled on resume (diff)
downloadlinux-dev-99f81afc139c6edd14d77a91ee91685a414a1c66.tar.xz
linux-dev-99f81afc139c6edd14d77a91ee91685a414a1c66.zip
phy: micrel: Disable auto negotiation on startup
Disable auto negotiation on init to properly detect an already plugged cable at boot. At boot, when the phy is started, it is in the PHY_UP state. However, if a cable is plugged at boot, because auto negociation is already enabled at the time we get the first interrupt, the phy is already running. But the state machine then switches from PHY_UP to PHY_AN and calls phy_start_aneg(). phy_start_aneg() will not do anything because aneg is already enabled on the phy. It will then wait for a interrupt before going further. This interrupt will never happen unless the cable is unplugged and then replugged. It was working properly before 321beec5047a (net: phy: Use interrupts when available in NOLINK state) because switching to NOLINK meant starting polling the phy, even if IRQ were enabled. Fixes: 321beec5047a (net: phy: Use interrupts when available in NOLINK state) Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/phy/micrel.c')
-rw-r--r--drivers/net/phy/micrel.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index a5e265b2bbfb..dc85f7095e51 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -297,6 +297,17 @@ static int kszphy_config_init(struct phy_device *phydev)
if (priv->led_mode >= 0)
kszphy_setup_led(phydev, type->led_mode_reg, priv->led_mode);
+ if (phy_interrupt_is_valid(phydev)) {
+ int ctl = phy_read(phydev, MII_BMCR);
+
+ if (ctl < 0)
+ return ctl;
+
+ ret = phy_write(phydev, MII_BMCR, ctl & ~BMCR_ANENABLE);
+ if (ret < 0)
+ return ret;
+ }
+
return 0;
}