4.16-stable review patch. If anyone has any objections, please let me know. ------------------ From: Alvaro Gamez Machado <alvaro.gamez@xxxxxxxxxx> [ Upstream commit b718e8c8f4f5920aaddc2e52d5e32f494c91129c ] DP83620 register set is compatible with the DP83848, but it also supports 100base-FX. When the hardware is configured such as that fiber mode is enabled, autonegotiation is not possible. The chip, however, doesn't expose this information via BMSR_ANEGCAPABLE. Instead, this bit is always set high, even if the particular hardware configuration makes it so that auto negotiation is not possible [1]. Under these circumstances, the phy subsystem keeps trying for autonegotiation to happen, without success. Hereby, we inspect BMCR_ANENABLE bit after genphy_config_init, which on reset is set to 0 when auto negotiation is disabled, and so we use this value instead of BMSR_ANEGCAPABLE. [1] https://e2e.ti.com/support/interface/ethernet/f/903/p/697165/2571170 Signed-off-by: Alvaro Gamez Machado <alvaro.gamez@xxxxxxxxxx> Signed-off-by: David S. Miller <davem@xxxxxxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- drivers/net/phy/dp83848.c | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) --- a/drivers/net/phy/dp83848.c +++ b/drivers/net/phy/dp83848.c @@ -74,6 +74,25 @@ static int dp83848_config_intr(struct ph return phy_write(phydev, DP83848_MICR, control); } +static int dp83848_config_init(struct phy_device *phydev) +{ + int err; + int val; + + err = genphy_config_init(phydev); + if (err < 0) + return err; + + /* DP83620 always reports Auto Negotiation Ability on BMSR. Instead, + * we check initial value of BMCR Auto negotiation enable bit + */ + val = phy_read(phydev, MII_BMCR); + if (!(val & BMCR_ANENABLE)) + phydev->autoneg = AUTONEG_DISABLE; + + return 0; +} + static struct mdio_device_id __maybe_unused dp83848_tbl[] = { { TI_DP83848C_PHY_ID, 0xfffffff0 }, { NS_DP83848C_PHY_ID, 0xfffffff0 }, @@ -83,7 +102,7 @@ static struct mdio_device_id __maybe_unu }; MODULE_DEVICE_TABLE(mdio, dp83848_tbl); -#define DP83848_PHY_DRIVER(_id, _name) \ +#define DP83848_PHY_DRIVER(_id, _name, _config_init) \ { \ .phy_id = _id, \ .phy_id_mask = 0xfffffff0, \ @@ -92,7 +111,7 @@ MODULE_DEVICE_TABLE(mdio, dp83848_tbl); .flags = PHY_HAS_INTERRUPT, \ \ .soft_reset = genphy_soft_reset, \ - .config_init = genphy_config_init, \ + .config_init = _config_init, \ .suspend = genphy_suspend, \ .resume = genphy_resume, \ \ @@ -102,10 +121,14 @@ MODULE_DEVICE_TABLE(mdio, dp83848_tbl); } static struct phy_driver dp83848_driver[] = { - DP83848_PHY_DRIVER(TI_DP83848C_PHY_ID, "TI DP83848C 10/100 Mbps PHY"), - DP83848_PHY_DRIVER(NS_DP83848C_PHY_ID, "NS DP83848C 10/100 Mbps PHY"), - DP83848_PHY_DRIVER(TI_DP83620_PHY_ID, "TI DP83620 10/100 Mbps PHY"), - DP83848_PHY_DRIVER(TLK10X_PHY_ID, "TI TLK10X 10/100 Mbps PHY"), + DP83848_PHY_DRIVER(TI_DP83848C_PHY_ID, "TI DP83848C 10/100 Mbps PHY", + genphy_config_init), + DP83848_PHY_DRIVER(NS_DP83848C_PHY_ID, "NS DP83848C 10/100 Mbps PHY", + genphy_config_init), + DP83848_PHY_DRIVER(TI_DP83620_PHY_ID, "TI DP83620 10/100 Mbps PHY", + dp83848_config_init), + DP83848_PHY_DRIVER(TLK10X_PHY_ID, "TI TLK10X 10/100 Mbps PHY", + genphy_config_init), }; module_phy_driver(dp83848_driver);