diff options
| author | Dmitry Torokhov <[email protected]> | 2023-08-30 16:06:38 -0700 | 
|---|---|---|
| committer | Dmitry Torokhov <[email protected]> | 2023-08-30 16:06:38 -0700 | 
| commit | 1ac731c529cd4d6adbce134754b51ff7d822b145 (patch) | |
| tree | 143ab3f35ca5f3b69f583c84e6964b17139c2ec1 /drivers/net/phy/mscc/mscc_main.c | |
| parent | 07b4c950f27bef0362dc6ad7ee713aab61d58149 (diff) | |
| parent | 54116d442e001e1b6bd482122043b1870998a1f3 (diff) | |
Merge branch 'next' into for-linus
Prepare input updates for 6.6 merge window.
Diffstat (limited to 'drivers/net/phy/mscc/mscc_main.c')
| -rw-r--r-- | drivers/net/phy/mscc/mscc_main.c | 106 | 
1 files changed, 61 insertions, 45 deletions
diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_main.c index 8a13b1ad9a33..28df8a2e4230 100644 --- a/drivers/net/phy/mscc/mscc_main.c +++ b/drivers/net/phy/mscc/mscc_main.c @@ -280,12 +280,9 @@ static int vsc85xx_wol_set(struct phy_device *phydev,  	u16 pwd[3] = {0, 0, 0};  	struct ethtool_wolinfo *wol_conf = wol; -	mutex_lock(&phydev->lock);  	rc = phy_select_page(phydev, MSCC_PHY_PAGE_EXTENDED_2); -	if (rc < 0) { -		rc = phy_restore_page(phydev, rc, rc); -		goto out_unlock; -	} +	if (rc < 0) +		return phy_restore_page(phydev, rc, rc);  	if (wol->wolopts & WAKE_MAGIC) {  		/* Store the device address for the magic packet */ @@ -323,7 +320,7 @@ static int vsc85xx_wol_set(struct phy_device *phydev,  	rc = phy_restore_page(phydev, rc, rc > 0 ? 0 : rc);  	if (rc < 0) -		goto out_unlock; +		return rc;  	if (wol->wolopts & WAKE_MAGIC) {  		/* Enable the WOL interrupt */ @@ -331,22 +328,19 @@ static int vsc85xx_wol_set(struct phy_device *phydev,  		reg_val |= MII_VSC85XX_INT_MASK_WOL;  		rc = phy_write(phydev, MII_VSC85XX_INT_MASK, reg_val);  		if (rc) -			goto out_unlock; +			return rc;  	} else {  		/* Disable the WOL interrupt */  		reg_val = phy_read(phydev, MII_VSC85XX_INT_MASK);  		reg_val &= (~MII_VSC85XX_INT_MASK_WOL);  		rc = phy_write(phydev, MII_VSC85XX_INT_MASK, reg_val);  		if (rc) -			goto out_unlock; +			return rc;  	}  	/* Clear WOL iterrupt status */  	reg_val = phy_read(phydev, MII_VSC85XX_INT_STATUS); -out_unlock: -	mutex_unlock(&phydev->lock); - -	return rc; +	return 0;  }  static void vsc85xx_wol_get(struct phy_device *phydev, @@ -358,10 +352,9 @@ static void vsc85xx_wol_get(struct phy_device *phydev,  	u16 pwd[3] = {0, 0, 0};  	struct ethtool_wolinfo *wol_conf = wol; -	mutex_lock(&phydev->lock);  	rc = phy_select_page(phydev, MSCC_PHY_PAGE_EXTENDED_2);  	if (rc < 0) -		goto out_unlock; +		goto out_restore_page;  	reg_val = __phy_read(phydev, MSCC_PHY_WOL_MAC_CONTROL);  	if (reg_val & SECURE_ON_ENABLE) @@ -377,9 +370,8 @@ static void vsc85xx_wol_get(struct phy_device *phydev,  		}  	} -out_unlock: +out_restore_page:  	phy_restore_page(phydev, rc, rc > 0 ? 0 : rc); -	mutex_unlock(&phydev->lock);  }  #if IS_ENABLED(CONFIG_OF_MDIO) @@ -527,16 +519,27 @@ out_unlock:   *  * 2.0 ns (which causes the data to be sampled at exactly half way between   *    clock transitions at 1000 Mbps) if delays should be enabled   */ -static int vsc85xx_rgmii_set_skews(struct phy_device *phydev, u32 rgmii_cntl, -				   u16 rgmii_rx_delay_mask, -				   u16 rgmii_tx_delay_mask) +static int vsc85xx_update_rgmii_cntl(struct phy_device *phydev, u32 rgmii_cntl, +				     u16 rgmii_rx_delay_mask, +				     u16 rgmii_tx_delay_mask)  {  	u16 rgmii_rx_delay_pos = ffs(rgmii_rx_delay_mask) - 1;  	u16 rgmii_tx_delay_pos = ffs(rgmii_tx_delay_mask) - 1;  	u16 reg_val = 0; -	int rc; +	u16 mask = 0; +	int rc = 0; -	mutex_lock(&phydev->lock); +	/* For traffic to pass, the VSC8502 family needs the RX_CLK disable bit +	 * to be unset for all PHY modes, so do that as part of the paged +	 * register modification. +	 * For some family members (like VSC8530/31/40/41) this bit is reserved +	 * and read-only, and the RX clock is enabled by default. +	 */ +	if (rgmii_cntl == VSC8502_RGMII_CNTL) +		mask |= VSC8502_RGMII_RX_CLK_DISABLE; + +	if (phy_interface_is_rgmii(phydev)) +		mask |= rgmii_rx_delay_mask | rgmii_tx_delay_mask;  	if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID ||  	    phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) @@ -545,31 +548,20 @@ static int vsc85xx_rgmii_set_skews(struct phy_device *phydev, u32 rgmii_cntl,  	    phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)  		reg_val |= RGMII_CLK_DELAY_2_0_NS << rgmii_tx_delay_pos; -	rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_2, -			      rgmii_cntl, -			      rgmii_rx_delay_mask | rgmii_tx_delay_mask, -			      reg_val); - -	mutex_unlock(&phydev->lock); +	if (mask) +		rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_2, +				      rgmii_cntl, mask, reg_val);  	return rc;  }  static int vsc85xx_default_config(struct phy_device *phydev)  { -	int rc; -  	phydev->mdix_ctrl = ETH_TP_MDI_AUTO; -	if (phy_interface_mode_is_rgmii(phydev->interface)) { -		rc = vsc85xx_rgmii_set_skews(phydev, VSC8502_RGMII_CNTL, -					     VSC8502_RGMII_RX_DELAY_MASK, -					     VSC8502_RGMII_TX_DELAY_MASK); -		if (rc) -			return rc; -	} - -	return 0; +	return vsc85xx_update_rgmii_cntl(phydev, VSC8502_RGMII_CNTL, +					 VSC8502_RGMII_RX_DELAY_MASK, +					 VSC8502_RGMII_TX_DELAY_MASK);  }  static int vsc85xx_get_tunable(struct phy_device *phydev, @@ -1766,13 +1758,11 @@ static int vsc8584_config_init(struct phy_device *phydev)  	if (ret)  		return ret; -	if (phy_interface_is_rgmii(phydev)) { -		ret = vsc85xx_rgmii_set_skews(phydev, VSC8572_RGMII_CNTL, -					      VSC8572_RGMII_RX_DELAY_MASK, -					      VSC8572_RGMII_TX_DELAY_MASK); -		if (ret) -			return ret; -	} +	ret = vsc85xx_update_rgmii_cntl(phydev, VSC8572_RGMII_CNTL, +					VSC8572_RGMII_RX_DELAY_MASK, +					VSC8572_RGMII_TX_DELAY_MASK); +	if (ret) +		return ret;  	ret = genphy_soft_reset(phydev);  	if (ret) @@ -2325,6 +2315,30 @@ static int vsc85xx_probe(struct phy_device *phydev)  /* Microsemi VSC85xx PHYs */  static struct phy_driver vsc85xx_driver[] = {  { +	.phy_id		= PHY_ID_VSC8501, +	.name		= "Microsemi GE VSC8501 SyncE", +	.phy_id_mask	= 0xfffffff0, +	/* PHY_BASIC_FEATURES */ +	.soft_reset	= &genphy_soft_reset, +	.config_init	= &vsc85xx_config_init, +	.config_aneg    = &vsc85xx_config_aneg, +	.read_status	= &vsc85xx_read_status, +	.handle_interrupt = vsc85xx_handle_interrupt, +	.config_intr	= &vsc85xx_config_intr, +	.suspend	= &genphy_suspend, +	.resume		= &genphy_resume, +	.probe		= &vsc85xx_probe, +	.set_wol	= &vsc85xx_wol_set, +	.get_wol	= &vsc85xx_wol_get, +	.get_tunable	= &vsc85xx_get_tunable, +	.set_tunable	= &vsc85xx_set_tunable, +	.read_page	= &vsc85xx_phy_read_page, +	.write_page	= &vsc85xx_phy_write_page, +	.get_sset_count = &vsc85xx_get_sset_count, +	.get_strings    = &vsc85xx_get_strings, +	.get_stats      = &vsc85xx_get_stats, +}, +{  	.phy_id		= PHY_ID_VSC8502,  	.name		= "Microsemi GE VSC8502 SyncE",  	.phy_id_mask	= 0xfffffff0, @@ -2664,6 +2678,8 @@ static struct phy_driver vsc85xx_driver[] = {  module_phy_driver(vsc85xx_driver);  static struct mdio_device_id __maybe_unused vsc85xx_tbl[] = { +	{ PHY_ID_VSC8501, 0xfffffff0, }, +	{ PHY_ID_VSC8502, 0xfffffff0, },  	{ PHY_ID_VSC8504, 0xfffffff0, },  	{ PHY_ID_VSC8514, 0xfffffff0, },  	{ PHY_ID_VSC8530, 0xfffffff0, },  |