diff options
| author | Alvaro Gamez Machado <alvaro.gamez@hazent.com> | 2018-06-08 12:23:39 +0200 | 
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2018-06-10 12:38:03 -0700 | 
| commit | b718e8c8f4f5920aaddc2e52d5e32f494c91129c (patch) | |
| tree | f7147d1b843d1f8219bba61bb006f3e0da6f6fec | |
| parent | 6d8c50dcb029872b298eea68cc6209c866fd3e14 (diff) | |
net: phy: dp83822: use BMCR_ANENABLE instead of BMSR_ANEGCAPABLE for DP83620
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@hazent.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | drivers/net/phy/dp83848.c | 35 | 
1 files changed, 29 insertions, 6 deletions
| diff --git a/drivers/net/phy/dp83848.c b/drivers/net/phy/dp83848.c index cd09c3af2117..6e8e42361fd5 100644 --- a/drivers/net/phy/dp83848.c +++ b/drivers/net/phy/dp83848.c @@ -74,6 +74,25 @@ static int dp83848_config_intr(struct phy_device *phydev)  	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_unused dp83848_tbl[] = {  };  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); | 
