mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-31 05:54:26 -04:00 
			
		
		
		
	This PHY requires some extra programming to work reliably with all devices. Backport upstream fix for it. Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
		
			
				
	
	
		
			284 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			284 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
 | |
| Subject: [PATCH] net: phy: cherry-pick Broadcom drivers updates from v4.11
 | |
| MIME-Version: 1.0
 | |
| Content-Type: text/plain; charset=UTF-8
 | |
| Content-Transfer-Encoding: 8bit
 | |
| 
 | |
| This includes following upstream commits:
 | |
| 62e13097c46c net: phy: broadcom: rehook BCM54612E specific init
 | |
| 0fc9ae107669 net: phy: broadcom: add support for BCM54210E
 | |
| 5e7bfa6cb0a9 net: phy: bcm-phy-lib: clean up remaining AUXCTL register defines
 | |
| 8293c7bcdef1 net: phy: broadcom: drop duplicated define for RGMII SKEW delay
 | |
| 85b4685da52f net: phy: broadcom: use auxctl reading helper in BCM54612E code
 | |
| 039a7b8592ab net: phy: bcm7xxx: Implement EGPHY workaround for 7278
 | |
| 582d0ac397ca net: phy: bcm7xxx: Add entry for BCM7278
 | |
| 
 | |
| Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
 | |
| ---
 | |
| 
 | |
| --- a/drivers/net/phy/bcm7xxx.c
 | |
| +++ b/drivers/net/phy/bcm7xxx.c
 | |
| @@ -163,12 +163,43 @@ static int bcm7xxx_28nm_e0_plus_afe_conf
 | |
|  	return 0;
 | |
|  }
 | |
|  
 | |
| +static int bcm7xxx_28nm_a0_patch_afe_config_init(struct phy_device *phydev)
 | |
| +{
 | |
| +	/* +1 RC_CAL codes for RL centering for both LT and HT conditions */
 | |
| +	bcm_phy_write_misc(phydev, AFE_RXCONFIG_2, 0xd003);
 | |
| +
 | |
| +	/* Cut master bias current by 2% to compensate for RC_CAL offset */
 | |
| +	bcm_phy_write_misc(phydev, DSP_TAP10, 0x791b);
 | |
| +
 | |
| +	/* Improve hybrid leakage */
 | |
| +	bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x10e3);
 | |
| +
 | |
| +	/* Change rx_on_tune 8 to 0xf */
 | |
| +	bcm_phy_write_misc(phydev, 0x21, 0x2, 0x87f6);
 | |
| +
 | |
| +	/* Change 100Tx EEE bandwidth */
 | |
| +	bcm_phy_write_misc(phydev, 0x22, 0x2, 0x017d);
 | |
| +
 | |
| +	/* Enable ffe zero detection for Vitesse interoperability */
 | |
| +	bcm_phy_write_misc(phydev, 0x26, 0x2, 0x0015);
 | |
| +
 | |
| +	r_rc_cal_reset(phydev);
 | |
| +
 | |
| +	return 0;
 | |
| +}
 | |
| +
 | |
|  static int bcm7xxx_28nm_config_init(struct phy_device *phydev)
 | |
|  {
 | |
|  	u8 rev = PHY_BRCM_7XXX_REV(phydev->dev_flags);
 | |
|  	u8 patch = PHY_BRCM_7XXX_PATCH(phydev->dev_flags);
 | |
|  	int ret = 0;
 | |
|  
 | |
| +	/* Newer devices have moved the revision information back into a
 | |
| +	 * standard location in MII_PHYS_ID[23]
 | |
| +	 */
 | |
| +	if (rev == 0)
 | |
| +		rev = phydev->phy_id & ~phydev->drv->phy_id_mask;
 | |
| +
 | |
|  	pr_info_once("%s: %s PHY revision: 0x%02x, patch: %d\n",
 | |
|  		     dev_name(&phydev->dev), phydev->drv->name, rev, patch);
 | |
|  
 | |
| @@ -192,6 +223,9 @@ static int bcm7xxx_28nm_config_init(stru
 | |
|  	case 0x10:
 | |
|  		ret = bcm7xxx_28nm_e0_plus_afe_config_init(phydev);
 | |
|  		break;
 | |
| +	case 0x01:
 | |
| +		ret = bcm7xxx_28nm_a0_patch_afe_config_init(phydev);
 | |
| +		break;
 | |
|  	default:
 | |
|  		break;
 | |
|  	}
 | |
| @@ -336,6 +370,7 @@ static int bcm7xxx_suspend(struct phy_de
 | |
|  
 | |
|  static struct phy_driver bcm7xxx_driver[] = {
 | |
|  	BCM7XXX_28NM_GPHY(PHY_ID_BCM7250, "Broadcom BCM7250"),
 | |
| +	BCM7XXX_28NM_GPHY(PHY_ID_BCM7278, "Broadcom BCM7278"),
 | |
|  	BCM7XXX_28NM_GPHY(PHY_ID_BCM7364, "Broadcom BCM7364"),
 | |
|  	BCM7XXX_28NM_GPHY(PHY_ID_BCM7366, "Broadcom BCM7366"),
 | |
|  	BCM7XXX_28NM_GPHY(PHY_ID_BCM7439, "Broadcom BCM7439"),
 | |
| @@ -350,6 +385,7 @@ static struct phy_driver bcm7xxx_driver[
 | |
|  
 | |
|  static struct mdio_device_id __maybe_unused bcm7xxx_tbl[] = {
 | |
|  	{ PHY_ID_BCM7250, 0xfffffff0, },
 | |
| +	{ PHY_ID_BCM7278, 0xfffffff0, },
 | |
|  	{ PHY_ID_BCM7364, 0xfffffff0, },
 | |
|  	{ PHY_ID_BCM7366, 0xfffffff0, },
 | |
|  	{ PHY_ID_BCM7346, 0xfffffff0, },
 | |
| --- a/drivers/net/phy/broadcom.c
 | |
| +++ b/drivers/net/phy/broadcom.c
 | |
| @@ -30,6 +30,50 @@ MODULE_DESCRIPTION("Broadcom PHY driver"
 | |
|  MODULE_AUTHOR("Maciej W. Rozycki");
 | |
|  MODULE_LICENSE("GPL");
 | |
|  
 | |
| +static int bcm54210e_config_init(struct phy_device *phydev)
 | |
| +{
 | |
| +	int val;
 | |
| +
 | |
| +	val = bcm54xx_auxctl_read(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
 | |
| +	val &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN;
 | |
| +	val |= MII_BCM54XX_AUXCTL_MISC_WREN;
 | |
| +	bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC, val);
 | |
| +
 | |
| +	val = bcm_phy_read_shadow(phydev, BCM54810_SHD_CLK_CTL);
 | |
| +	val &= ~BCM54810_SHD_CLK_CTL_GTXCLK_EN;
 | |
| +	bcm_phy_write_shadow(phydev, BCM54810_SHD_CLK_CTL, val);
 | |
| +
 | |
| +	return 0;
 | |
| +}
 | |
| +
 | |
| +static int bcm54612e_config_init(struct phy_device *phydev)
 | |
| +{
 | |
| +	/* Clear TX internal delay unless requested. */
 | |
| +	if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) &&
 | |
| +	    (phydev->interface != PHY_INTERFACE_MODE_RGMII_TXID)) {
 | |
| +		/* Disable TXD to GTXCLK clock delay (default set) */
 | |
| +		/* Bit 9 is the only field in shadow register 00011 */
 | |
| +		bcm_phy_write_shadow(phydev, 0x03, 0);
 | |
| +	}
 | |
| +
 | |
| +	/* Clear RX internal delay unless requested. */
 | |
| +	if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) &&
 | |
| +	    (phydev->interface != PHY_INTERFACE_MODE_RGMII_RXID)) {
 | |
| +		u16 reg;
 | |
| +
 | |
| +		reg = bcm54xx_auxctl_read(phydev,
 | |
| +					  MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
 | |
| +		/* Disable RXD to RXC delay (default set) */
 | |
| +		reg &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN;
 | |
| +		/* Clear shadow selector field */
 | |
| +		reg &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MASK;
 | |
| +		bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
 | |
| +				     MII_BCM54XX_AUXCTL_MISC_WREN | reg);
 | |
| +	}
 | |
| +
 | |
| +	return 0;
 | |
| +}
 | |
| +
 | |
|  static int bcm54810_config(struct phy_device *phydev)
 | |
|  {
 | |
|  	int rc, val;
 | |
| @@ -230,7 +274,15 @@ static int bcm54xx_config_init(struct ph
 | |
|  	    (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
 | |
|  		bcm54xx_adjust_rxrefclk(phydev);
 | |
|  
 | |
| -	if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54810) {
 | |
| +	if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54210E) {
 | |
| +		err = bcm54210e_config_init(phydev);
 | |
| +		if (err)
 | |
| +			return err;
 | |
| +	} else if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54612E) {
 | |
| +		err = bcm54612e_config_init(phydev);
 | |
| +		if (err)
 | |
| +			return err;
 | |
| +	} else if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54810) {
 | |
|  		err = bcm54810_config(phydev);
 | |
|  		if (err)
 | |
|  			return err;
 | |
| @@ -375,41 +427,6 @@ static int bcm5481_config_aneg(struct ph
 | |
|  	return ret;
 | |
|  }
 | |
|  
 | |
| -static int bcm54612e_config_aneg(struct phy_device *phydev)
 | |
| -{
 | |
| -	int ret;
 | |
| -
 | |
| -	/* First, auto-negotiate. */
 | |
| -	ret = genphy_config_aneg(phydev);
 | |
| -
 | |
| -	/* Clear TX internal delay unless requested. */
 | |
| -	if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) &&
 | |
| -	    (phydev->interface != PHY_INTERFACE_MODE_RGMII_TXID)) {
 | |
| -		/* Disable TXD to GTXCLK clock delay (default set) */
 | |
| -		/* Bit 9 is the only field in shadow register 00011 */
 | |
| -		bcm_phy_write_shadow(phydev, 0x03, 0);
 | |
| -	}
 | |
| -
 | |
| -	/* Clear RX internal delay unless requested. */
 | |
| -	if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) &&
 | |
| -	    (phydev->interface != PHY_INTERFACE_MODE_RGMII_RXID)) {
 | |
| -		u16 reg;
 | |
| -
 | |
| -		/* Errata: reads require filling in the write selector field */
 | |
| -		bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
 | |
| -				     MII_BCM54XX_AUXCTL_MISC_RDSEL_MISC);
 | |
| -		reg = phy_read(phydev, MII_BCM54XX_AUX_CTL);
 | |
| -		/* Disable RXD to RXC delay (default set) */
 | |
| -		reg &= ~MII_BCM54XX_AUXCTL_MISC_RXD_RXC_SKEW;
 | |
| -		/* Clear shadow selector field */
 | |
| -		reg &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MASK;
 | |
| -		bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
 | |
| -				     MII_BCM54XX_AUXCTL_MISC_WREN | reg);
 | |
| -	}
 | |
| -
 | |
| -	return ret;
 | |
| -}
 | |
| -
 | |
|  static int brcm_phy_setbits(struct phy_device *phydev, int reg, int set)
 | |
|  {
 | |
|  	int val;
 | |
| @@ -548,6 +565,19 @@ static struct phy_driver broadcom_driver
 | |
|  	.config_intr	= bcm_phy_config_intr,
 | |
|  	.driver		= { .owner = THIS_MODULE },
 | |
|  }, {
 | |
| +	.phy_id		= PHY_ID_BCM54210E,
 | |
| +	.phy_id_mask	= 0xfffffff0,
 | |
| +	.name		= "Broadcom BCM54210E",
 | |
| +	.features	= PHY_GBIT_FEATURES |
 | |
| +			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
 | |
| +	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 | |
| +	.config_init	= bcm54xx_config_init,
 | |
| +	.config_aneg	= genphy_config_aneg,
 | |
| +	.read_status	= genphy_read_status,
 | |
| +	.ack_interrupt	= bcm_phy_ack_intr,
 | |
| +	.config_intr	= bcm_phy_config_intr,
 | |
| +	.driver		= { .owner = THIS_MODULE },
 | |
| +}, {
 | |
|  	.phy_id		= PHY_ID_BCM5461,
 | |
|  	.phy_id_mask	= 0xfffffff0,
 | |
|  	.name		= "Broadcom BCM5461",
 | |
| @@ -568,7 +598,7 @@ static struct phy_driver broadcom_driver
 | |
|  			  SUPPORTED_Pause | SUPPORTED_Asym_Pause,
 | |
|  	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
 | |
|  	.config_init	= bcm54xx_config_init,
 | |
| -	.config_aneg	= bcm54612e_config_aneg,
 | |
| +	.config_aneg	= genphy_config_aneg,
 | |
|  	.read_status	= genphy_read_status,
 | |
|  	.ack_interrupt	= bcm_phy_ack_intr,
 | |
|  	.config_intr	= bcm_phy_config_intr,
 | |
| @@ -708,6 +738,7 @@ module_phy_driver(broadcom_drivers);
 | |
|  static struct mdio_device_id __maybe_unused broadcom_tbl[] = {
 | |
|  	{ PHY_ID_BCM5411, 0xfffffff0 },
 | |
|  	{ PHY_ID_BCM5421, 0xfffffff0 },
 | |
| +	{ PHY_ID_BCM54210E, 0xfffffff0 },
 | |
|  	{ PHY_ID_BCM5461, 0xfffffff0 },
 | |
|  	{ PHY_ID_BCM54612E, 0xfffffff0 },
 | |
|  	{ PHY_ID_BCM54616S, 0xfffffff0 },
 | |
| --- a/include/linux/brcmphy.h
 | |
| +++ b/include/linux/brcmphy.h
 | |
| @@ -17,6 +17,7 @@
 | |
|  #define PHY_ID_BCM5482			0x0143bcb0
 | |
|  #define PHY_ID_BCM5411			0x00206070
 | |
|  #define PHY_ID_BCM5421			0x002060e0
 | |
| +#define PHY_ID_BCM54210E		0x600d84a0
 | |
|  #define PHY_ID_BCM5464			0x002060b0
 | |
|  #define PHY_ID_BCM5461			0x002060c0
 | |
|  #define PHY_ID_BCM54612E		0x03625e60
 | |
| @@ -24,6 +25,7 @@
 | |
|  #define PHY_ID_BCM57780			0x03625d90
 | |
|  
 | |
|  #define PHY_ID_BCM7250			0xae025280
 | |
| +#define PHY_ID_BCM7278			0xae0251a0
 | |
|  #define PHY_ID_BCM7364			0xae025260
 | |
|  #define PHY_ID_BCM7366			0x600d8490
 | |
|  #define PHY_ID_BCM7346			0x600d8650
 | |
| @@ -103,18 +105,17 @@
 | |
|  /*
 | |
|   * AUXILIARY CONTROL SHADOW ACCESS REGISTERS.  (PHY REG 0x18)
 | |
|   */
 | |
| -#define MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL	0x0000
 | |
| +#define MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL	0x00
 | |
|  #define MII_BCM54XX_AUXCTL_ACTL_TX_6DB		0x0400
 | |
|  #define MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA	0x0800
 | |
|  
 | |
| -#define MII_BCM54XX_AUXCTL_MISC_WREN	0x8000
 | |
| -#define MII_BCM54XX_AUXCTL_MISC_RXD_RXC_SKEW	0x0100
 | |
| -#define MII_BCM54XX_AUXCTL_MISC_FORCE_AMDIX	0x0200
 | |
| -#define MII_BCM54XX_AUXCTL_MISC_RDSEL_MISC	0x7000
 | |
| -#define MII_BCM54XX_AUXCTL_SHDWSEL_MISC	0x0007
 | |
| -#define MII_BCM54XX_AUXCTL_SHDWSEL_READ_SHIFT	12
 | |
| -#define MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN	(1 << 8)
 | |
| +#define MII_BCM54XX_AUXCTL_SHDWSEL_MISC			0x07
 | |
| +#define MII_BCM54XX_AUXCTL_SHDWSEL_MISC_WIRESPEED_EN	0x0010
 | |
| +#define MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN	0x0100
 | |
| +#define MII_BCM54XX_AUXCTL_MISC_FORCE_AMDIX		0x0200
 | |
| +#define MII_BCM54XX_AUXCTL_MISC_WREN			0x8000
 | |
|  
 | |
| +#define MII_BCM54XX_AUXCTL_SHDWSEL_READ_SHIFT	12
 | |
|  #define MII_BCM54XX_AUXCTL_SHDWSEL_MASK	0x0007
 | |
|  
 | |
|  /*
 |