diff options
Diffstat (limited to 'drivers/net/phy/phy.c')
| -rw-r--r-- | drivers/net/phy/phy.c | 101 | 
1 files changed, 68 insertions, 33 deletions
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index f7c61812ea4a..a854d38c231d 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -138,11 +138,31 @@ struct phy_setting {  /* A mapping of all SUPPORTED settings to speed/duplex */  static const struct phy_setting settings[] = {  	{ -		.speed = 10000, +		.speed = SPEED_10000, +		.duplex = DUPLEX_FULL, +		.setting = SUPPORTED_10000baseKR_Full, +	}, +	{ +		.speed = SPEED_10000, +		.duplex = DUPLEX_FULL, +		.setting = SUPPORTED_10000baseKX4_Full, +	}, +	{ +		.speed = SPEED_10000,  		.duplex = DUPLEX_FULL,  		.setting = SUPPORTED_10000baseT_Full,  	},  	{ +		.speed = SPEED_2500, +		.duplex = DUPLEX_FULL, +		.setting = SUPPORTED_2500baseX_Full, +	}, +	{ +		.speed = SPEED_1000, +		.duplex = DUPLEX_FULL, +		.setting = SUPPORTED_1000baseKX_Full, +	}, +	{  		.speed = SPEED_1000,  		.duplex = DUPLEX_FULL,  		.setting = SUPPORTED_1000baseT_Full, @@ -922,7 +942,7 @@ static inline void mmd_phy_indirect(struct mii_bus *bus, int prtad, int devad,  /**   * phy_read_mmd_indirect - reads data from the MMD registers - * @bus: the target MII bus + * @phydev: The PHY device bus   * @prtad: MMD Address   * @devad: MMD DEVAD   * @addr: PHY address on the MII bus @@ -935,18 +955,26 @@ static inline void mmd_phy_indirect(struct mii_bus *bus, int prtad, int devad,   * 3) Write reg 13 // MMD Data Command for MMD DEVAD   * 3) Read  reg 14 // Read MMD data   */ -static int phy_read_mmd_indirect(struct mii_bus *bus, int prtad, int devad, -				 int addr) +static int phy_read_mmd_indirect(struct phy_device *phydev, int prtad, +				 int devad, int addr)  { -	mmd_phy_indirect(bus, prtad, devad, addr); +	struct phy_driver *phydrv = phydev->drv; +	int value = -1; + +	if (phydrv->read_mmd_indirect == NULL) { +		mmd_phy_indirect(phydev->bus, prtad, devad, addr); -	/* Read the content of the MMD's selected register */ -	return bus->read(bus, addr, MII_MMD_DATA); +		/* Read the content of the MMD's selected register */ +		value = phydev->bus->read(phydev->bus, addr, MII_MMD_DATA); +	} else { +		value = phydrv->read_mmd_indirect(phydev, prtad, devad, addr); +	} +	return value;  }  /**   * phy_write_mmd_indirect - writes data to the MMD registers - * @bus: the target MII bus + * @phydev: The PHY device   * @prtad: MMD Address   * @devad: MMD DEVAD   * @addr: PHY address on the MII bus @@ -960,13 +988,19 @@ static int phy_read_mmd_indirect(struct mii_bus *bus, int prtad, int devad,   * 3) Write reg 13 // MMD Data Command for MMD DEVAD   * 3) Write reg 14 // Write MMD data   */ -static void phy_write_mmd_indirect(struct mii_bus *bus, int prtad, int devad, -				   int addr, u32 data) +static void phy_write_mmd_indirect(struct phy_device *phydev, int prtad, +				   int devad, int addr, u32 data)  { -	mmd_phy_indirect(bus, prtad, devad, addr); +	struct phy_driver *phydrv = phydev->drv; + +	if (phydrv->write_mmd_indirect == NULL) { +		mmd_phy_indirect(phydev->bus, prtad, devad, addr); -	/* Write the data into MMD's selected register */ -	bus->write(bus, addr, MII_MMD_DATA, data); +		/* Write the data into MMD's selected register */ +		phydev->bus->write(phydev->bus, addr, MII_MMD_DATA, data); +	} else { +		phydrv->write_mmd_indirect(phydev, prtad, devad, addr, data); +	}  }  /** @@ -1000,52 +1034,53 @@ int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable)  			return status;  		/* First check if the EEE ability is supported */ -		eee_cap = phy_read_mmd_indirect(phydev->bus, MDIO_PCS_EEE_ABLE, +		eee_cap = phy_read_mmd_indirect(phydev, MDIO_PCS_EEE_ABLE,  						MDIO_MMD_PCS, phydev->addr); -		if (eee_cap < 0) -			return eee_cap; +		if (eee_cap <= 0) +			goto eee_exit_err;  		cap = mmd_eee_cap_to_ethtool_sup_t(eee_cap);  		if (!cap) -			return -EPROTONOSUPPORT; +			goto eee_exit_err;  		/* Check which link settings negotiated and verify it in  		 * the EEE advertising registers.  		 */ -		eee_lp = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_LPABLE, +		eee_lp = phy_read_mmd_indirect(phydev, MDIO_AN_EEE_LPABLE,  					       MDIO_MMD_AN, phydev->addr); -		if (eee_lp < 0) -			return eee_lp; +		if (eee_lp <= 0) +			goto eee_exit_err; -		eee_adv = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_ADV, +		eee_adv = phy_read_mmd_indirect(phydev, MDIO_AN_EEE_ADV,  						MDIO_MMD_AN, phydev->addr); -		if (eee_adv < 0) -			return eee_adv; +		if (eee_adv <= 0) +			goto eee_exit_err;  		adv = mmd_eee_adv_to_ethtool_adv_t(eee_adv);  		lp = mmd_eee_adv_to_ethtool_adv_t(eee_lp);  		idx = phy_find_setting(phydev->speed, phydev->duplex);  		if (!(lp & adv & settings[idx].setting)) -			return -EPROTONOSUPPORT; +			goto eee_exit_err;  		if (clk_stop_enable) {  			/* Configure the PHY to stop receiving xMII  			 * clock while it is signaling LPI.  			 */ -			int val = phy_read_mmd_indirect(phydev->bus, MDIO_CTRL1, +			int val = phy_read_mmd_indirect(phydev, MDIO_CTRL1,  							MDIO_MMD_PCS,  							phydev->addr);  			if (val < 0)  				return val;  			val |= MDIO_PCS_CTRL1_CLKSTOP_EN; -			phy_write_mmd_indirect(phydev->bus, MDIO_CTRL1, -					       MDIO_MMD_PCS, phydev->addr, val); +			phy_write_mmd_indirect(phydev, MDIO_CTRL1, +					       MDIO_MMD_PCS, phydev->addr, +					       val);  		}  		return 0; /* EEE supported */  	} - +eee_exit_err:  	return -EPROTONOSUPPORT;  }  EXPORT_SYMBOL(phy_init_eee); @@ -1059,7 +1094,7 @@ EXPORT_SYMBOL(phy_init_eee);   */  int phy_get_eee_err(struct phy_device *phydev)  { -	return phy_read_mmd_indirect(phydev->bus, MDIO_PCS_EEE_WK_ERR, +	return phy_read_mmd_indirect(phydev, MDIO_PCS_EEE_WK_ERR,  				     MDIO_MMD_PCS, phydev->addr);  }  EXPORT_SYMBOL(phy_get_eee_err); @@ -1077,21 +1112,21 @@ int phy_ethtool_get_eee(struct phy_device *phydev, struct ethtool_eee *data)  	int val;  	/* Get Supported EEE */ -	val = phy_read_mmd_indirect(phydev->bus, MDIO_PCS_EEE_ABLE, +	val = phy_read_mmd_indirect(phydev, MDIO_PCS_EEE_ABLE,  				    MDIO_MMD_PCS, phydev->addr);  	if (val < 0)  		return val;  	data->supported = mmd_eee_cap_to_ethtool_sup_t(val);  	/* Get advertisement EEE */ -	val = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_ADV, +	val = phy_read_mmd_indirect(phydev, MDIO_AN_EEE_ADV,  				    MDIO_MMD_AN, phydev->addr);  	if (val < 0)  		return val;  	data->advertised = mmd_eee_adv_to_ethtool_adv_t(val);  	/* Get LP advertisement EEE */ -	val = phy_read_mmd_indirect(phydev->bus, MDIO_AN_EEE_LPABLE, +	val = phy_read_mmd_indirect(phydev, MDIO_AN_EEE_LPABLE,  				    MDIO_MMD_AN, phydev->addr);  	if (val < 0)  		return val; @@ -1112,7 +1147,7 @@ int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data)  {  	int val = ethtool_adv_to_mmd_eee_adv_t(data->advertised); -	phy_write_mmd_indirect(phydev->bus, MDIO_AN_EEE_ADV, MDIO_MMD_AN, +	phy_write_mmd_indirect(phydev, MDIO_AN_EEE_ADV, MDIO_MMD_AN,  			       phydev->addr, val);  	return 0;  |