Browse Source

net: phy: Add Broadcom phy library for common interfaces

This patch adds the Broadcom phy library to consolidate common
interfaces shared by Broadcom phy's.

Moved the common interfaces to the 'bcm-phy-lib.c' and updated
the Broadcom PHY drivers to use the new APIs.

Signed-off-by: Arun Parameswaran <arunp@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Arun Parameswaran 10 years ago
parent
commit
a1cba5613e

+ 6 - 0
drivers/net/phy/Kconfig

@@ -69,8 +69,12 @@ config SMSC_PHY
 	---help---
 	---help---
 	  Currently supports the LAN83C185, LAN8187 and LAN8700 PHYs
 	  Currently supports the LAN83C185, LAN8187 and LAN8700 PHYs
 
 
+config BCM_NET_PHYLIB
+	tristate
+
 config BROADCOM_PHY
 config BROADCOM_PHY
 	tristate "Drivers for Broadcom PHYs"
 	tristate "Drivers for Broadcom PHYs"
+	select BCM_NET_PHYLIB
 	---help---
 	---help---
 	  Currently supports the BCM5411, BCM5421, BCM5461, BCM54616S, BCM5464,
 	  Currently supports the BCM5411, BCM5421, BCM5461, BCM54616S, BCM5464,
 	  BCM5481 and BCM5482 PHYs.
 	  BCM5481 and BCM5482 PHYs.
@@ -78,11 +82,13 @@ config BROADCOM_PHY
 config BCM63XX_PHY
 config BCM63XX_PHY
 	tristate "Drivers for Broadcom 63xx SOCs internal PHY"
 	tristate "Drivers for Broadcom 63xx SOCs internal PHY"
 	depends on BCM63XX
 	depends on BCM63XX
+	select BCM_NET_PHYLIB
 	---help---
 	---help---
 	  Currently supports the 6348 and 6358 PHYs.
 	  Currently supports the 6348 and 6358 PHYs.
 
 
 config BCM7XXX_PHY
 config BCM7XXX_PHY
 	tristate "Drivers for Broadcom 7xxx SOCs internal PHYs"
 	tristate "Drivers for Broadcom 7xxx SOCs internal PHYs"
+	select BCM_NET_PHYLIB
 	---help---
 	---help---
 	  Currently supports the BCM7366, BCM7439, BCM7445, and
 	  Currently supports the BCM7366, BCM7439, BCM7445, and
 	  40nm and 65nm generation of BCM7xxx Set Top Box SoCs.
 	  40nm and 65nm generation of BCM7xxx Set Top Box SoCs.

+ 1 - 0
drivers/net/phy/Makefile

@@ -12,6 +12,7 @@ obj-$(CONFIG_QSEMI_PHY)		+= qsemi.o
 obj-$(CONFIG_SMSC_PHY)		+= smsc.o
 obj-$(CONFIG_SMSC_PHY)		+= smsc.o
 obj-$(CONFIG_TERANETICS_PHY)	+= teranetics.o
 obj-$(CONFIG_TERANETICS_PHY)	+= teranetics.o
 obj-$(CONFIG_VITESSE_PHY)	+= vitesse.o
 obj-$(CONFIG_VITESSE_PHY)	+= vitesse.o
+obj-$(CONFIG_BCM_NET_PHYLIB)	+= bcm-phy-lib.o
 obj-$(CONFIG_BROADCOM_PHY)	+= broadcom.o
 obj-$(CONFIG_BROADCOM_PHY)	+= broadcom.o
 obj-$(CONFIG_BCM63XX_PHY)	+= bcm63xx.o
 obj-$(CONFIG_BCM63XX_PHY)	+= bcm63xx.o
 obj-$(CONFIG_BCM7XXX_PHY)	+= bcm7xxx.o
 obj-$(CONFIG_BCM7XXX_PHY)	+= bcm7xxx.o

+ 208 - 0
drivers/net/phy/bcm-phy-lib.c

@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2015 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "bcm-phy-lib.h"
+#include <linux/brcmphy.h>
+#include <linux/export.h>
+#include <linux/mdio.h>
+#include <linux/phy.h>
+
+#define MII_BCM_CHANNEL_WIDTH     0x2000
+#define BCM_CL45VEN_EEE_ADV       0x3c
+
+int bcm_phy_write_exp(struct phy_device *phydev, u16 reg, u16 val)
+{
+	int rc;
+
+	rc = phy_write(phydev, MII_BCM54XX_EXP_SEL, reg);
+	if (rc < 0)
+		return rc;
+
+	return phy_write(phydev, MII_BCM54XX_EXP_DATA, val);
+}
+EXPORT_SYMBOL_GPL(bcm_phy_write_exp);
+
+int bcm_phy_read_exp(struct phy_device *phydev, u16 reg)
+{
+	int val;
+
+	val = phy_write(phydev, MII_BCM54XX_EXP_SEL, reg);
+	if (val < 0)
+		return val;
+
+	val = phy_read(phydev, MII_BCM54XX_EXP_DATA);
+
+	/* Restore default value.  It's O.K. if this write fails. */
+	phy_write(phydev, MII_BCM54XX_EXP_SEL, 0);
+
+	return val;
+}
+EXPORT_SYMBOL_GPL(bcm_phy_read_exp);
+
+int bcm_phy_write_misc(struct phy_device *phydev,
+		       u16 reg, u16 chl, u16 val)
+{
+	int rc;
+	int tmp;
+
+	rc = phy_write(phydev, MII_BCM54XX_AUX_CTL,
+		       MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
+	if (rc < 0)
+		return rc;
+
+	tmp = phy_read(phydev, MII_BCM54XX_AUX_CTL);
+	tmp |= MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA;
+	rc = phy_write(phydev, MII_BCM54XX_AUX_CTL, tmp);
+	if (rc < 0)
+		return rc;
+
+	tmp = (chl * MII_BCM_CHANNEL_WIDTH) | reg;
+	rc = bcm_phy_write_exp(phydev, tmp, val);
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(bcm_phy_write_misc);
+
+int bcm_phy_read_misc(struct phy_device *phydev,
+		      u16 reg, u16 chl)
+{
+	int rc;
+	int tmp;
+
+	rc = phy_write(phydev, MII_BCM54XX_AUX_CTL,
+		       MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
+	if (rc < 0)
+		return rc;
+
+	tmp = phy_read(phydev, MII_BCM54XX_AUX_CTL);
+	tmp |= MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA;
+	rc = phy_write(phydev, MII_BCM54XX_AUX_CTL, tmp);
+	if (rc < 0)
+		return rc;
+
+	tmp = (chl * MII_BCM_CHANNEL_WIDTH) | reg;
+	rc = bcm_phy_read_exp(phydev, tmp);
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(bcm_phy_read_misc);
+
+int bcm_phy_ack_intr(struct phy_device *phydev)
+{
+	int reg;
+
+	/* Clear pending interrupts.  */
+	reg = phy_read(phydev, MII_BCM54XX_ISR);
+	if (reg < 0)
+		return reg;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(bcm_phy_ack_intr);
+
+int bcm_phy_config_intr(struct phy_device *phydev)
+{
+	int reg;
+
+	reg = phy_read(phydev, MII_BCM54XX_ECR);
+	if (reg < 0)
+		return reg;
+
+	if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
+		reg &= ~MII_BCM54XX_ECR_IM;
+	else
+		reg |= MII_BCM54XX_ECR_IM;
+
+	return phy_write(phydev, MII_BCM54XX_ECR, reg);
+}
+EXPORT_SYMBOL_GPL(bcm_phy_config_intr);
+
+int bcm_phy_read_shadow(struct phy_device *phydev, u16 shadow)
+{
+	phy_write(phydev, MII_BCM54XX_SHD, MII_BCM54XX_SHD_VAL(shadow));
+	return MII_BCM54XX_SHD_DATA(phy_read(phydev, MII_BCM54XX_SHD));
+}
+EXPORT_SYMBOL_GPL(bcm_phy_read_shadow);
+
+int bcm_phy_write_shadow(struct phy_device *phydev, u16 shadow,
+			 u16 val)
+{
+	return phy_write(phydev, MII_BCM54XX_SHD,
+			 MII_BCM54XX_SHD_WRITE |
+			 MII_BCM54XX_SHD_VAL(shadow) |
+			 MII_BCM54XX_SHD_DATA(val));
+}
+EXPORT_SYMBOL_GPL(bcm_phy_write_shadow);
+
+int bcm_phy_enable_apd(struct phy_device *phydev, bool dll_pwr_down)
+{
+	int val;
+
+	if (dll_pwr_down) {
+		val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_SCR3);
+		if (val < 0)
+			return val;
+
+		val |= BCM54XX_SHD_SCR3_DLLAPD_DIS;
+		bcm_phy_write_shadow(phydev, BCM54XX_SHD_SCR3, val);
+	}
+
+	val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_APD);
+	if (val < 0)
+		return val;
+
+	/* Clear APD bits */
+	val &= BCM_APD_CLR_MASK;
+
+	if (phydev->autoneg == AUTONEG_ENABLE)
+		val |= BCM54XX_SHD_APD_EN;
+	else
+		val |= BCM_NO_ANEG_APD_EN;
+
+	/* Enable energy detect single link pulse for easy wakeup */
+	val |= BCM_APD_SINGLELP_EN;
+
+	/* Enable Auto Power-Down (APD) for the PHY */
+	return bcm_phy_write_shadow(phydev, BCM54XX_SHD_APD, val);
+}
+EXPORT_SYMBOL_GPL(bcm_phy_enable_apd);
+
+int bcm_phy_enable_eee(struct phy_device *phydev)
+{
+	int val;
+
+	/* Enable EEE at PHY level */
+	val = phy_read_mmd_indirect(phydev, BRCM_CL45VEN_EEE_CONTROL,
+				    MDIO_MMD_AN, phydev->addr);
+	if (val < 0)
+		return val;
+
+	val |= LPI_FEATURE_EN | LPI_FEATURE_EN_DIG1000X;
+
+	phy_write_mmd_indirect(phydev, BRCM_CL45VEN_EEE_CONTROL,
+			       MDIO_MMD_AN,  phydev->addr, (u32)val);
+
+	/* Advertise EEE */
+	val = phy_read_mmd_indirect(phydev, BCM_CL45VEN_EEE_ADV,
+				    MDIO_MMD_AN, phydev->addr);
+	if (val < 0)
+		return val;
+
+	val |= (MDIO_AN_EEE_ADV_100TX | MDIO_AN_EEE_ADV_1000T);
+
+	phy_write_mmd_indirect(phydev, BCM_CL45VEN_EEE_ADV,
+			       MDIO_MMD_AN,  phydev->addr, (u32)val);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(bcm_phy_enable_eee);

+ 37 - 0
drivers/net/phy/bcm-phy-lib.h

@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2015 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _LINUX_BCM_PHY_LIB_H
+#define _LINUX_BCM_PHY_LIB_H
+
+#include <linux/phy.h>
+
+int bcm_phy_write_exp(struct phy_device *phydev, u16 reg, u16 val);
+int bcm_phy_read_exp(struct phy_device *phydev, u16 reg);
+
+int bcm_phy_write_misc(struct phy_device *phydev,
+		       u16 reg, u16 chl, u16 value);
+int bcm_phy_read_misc(struct phy_device *phydev,
+		      u16 reg, u16 chl);
+
+int bcm_phy_write_shadow(struct phy_device *phydev, u16 shadow,
+			 u16 val);
+int bcm_phy_read_shadow(struct phy_device *phydev, u16 shadow);
+
+int bcm_phy_ack_intr(struct phy_device *phydev);
+int bcm_phy_config_intr(struct phy_device *phydev);
+
+int bcm_phy_enable_apd(struct phy_device *phydev, bool dll_pwr_down);
+
+int bcm_phy_enable_eee(struct phy_device *phydev);
+#endif /* _LINUX_BCM_PHY_LIB_H */

+ 5 - 33
drivers/net/phy/bcm63xx.c

@@ -6,6 +6,7 @@
  *	as published by the Free Software Foundation; either version
  *	as published by the Free Software Foundation; either version
  *	2 of the License, or (at your option) any later version.
  *	2 of the License, or (at your option) any later version.
  */
  */
+#include "bcm-phy-lib.h"
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/phy.h>
 #include <linux/phy.h>
 
 
@@ -42,35 +43,6 @@ static int bcm63xx_config_init(struct phy_device *phydev)
 	return phy_write(phydev, MII_BCM63XX_IR, reg);
 	return phy_write(phydev, MII_BCM63XX_IR, reg);
 }
 }
 
 
-static int bcm63xx_ack_interrupt(struct phy_device *phydev)
-{
-	int reg;
-
-	/* Clear pending interrupts.  */
-	reg = phy_read(phydev, MII_BCM63XX_IR);
-	if (reg < 0)
-		return reg;
-
-	return 0;
-}
-
-static int bcm63xx_config_intr(struct phy_device *phydev)
-{
-	int reg, err;
-
-	reg = phy_read(phydev, MII_BCM63XX_IR);
-	if (reg < 0)
-		return reg;
-
-	if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
-		reg &= ~MII_BCM63XX_IR_GMASK;
-	else
-		reg |= MII_BCM63XX_IR_GMASK;
-
-	err = phy_write(phydev, MII_BCM63XX_IR, reg);
-	return err;
-}
-
 static struct phy_driver bcm63xx_driver[] = {
 static struct phy_driver bcm63xx_driver[] = {
 {
 {
 	.phy_id		= 0x00406000,
 	.phy_id		= 0x00406000,
@@ -82,8 +54,8 @@ static struct phy_driver bcm63xx_driver[] = {
 	.config_init	= bcm63xx_config_init,
 	.config_init	= bcm63xx_config_init,
 	.config_aneg	= genphy_config_aneg,
 	.config_aneg	= genphy_config_aneg,
 	.read_status	= genphy_read_status,
 	.read_status	= genphy_read_status,
-	.ack_interrupt	= bcm63xx_ack_interrupt,
-	.config_intr	= bcm63xx_config_intr,
+	.ack_interrupt	= bcm_phy_ack_intr,
+	.config_intr	= bcm_phy_config_intr,
 	.driver		= { .owner = THIS_MODULE },
 	.driver		= { .owner = THIS_MODULE },
 }, {
 }, {
 	/* same phy as above, with just a different OUI */
 	/* same phy as above, with just a different OUI */
@@ -95,8 +67,8 @@ static struct phy_driver bcm63xx_driver[] = {
 	.config_init	= bcm63xx_config_init,
 	.config_init	= bcm63xx_config_init,
 	.config_aneg	= genphy_config_aneg,
 	.config_aneg	= genphy_config_aneg,
 	.read_status	= genphy_read_status,
 	.read_status	= genphy_read_status,
-	.ack_interrupt	= bcm63xx_ack_interrupt,
-	.config_intr	= bcm63xx_config_intr,
+	.ack_interrupt	= bcm_phy_ack_intr,
+	.config_intr	= bcm_phy_config_intr,
 	.driver		= { .owner = THIS_MODULE },
 	.driver		= { .owner = THIS_MODULE },
 } };
 } };
 
 

+ 28 - 99
drivers/net/phy/bcm7xxx.c

@@ -12,12 +12,12 @@
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/phy.h>
 #include <linux/phy.h>
 #include <linux/delay.h>
 #include <linux/delay.h>
+#include "bcm-phy-lib.h"
 #include <linux/bitops.h>
 #include <linux/bitops.h>
 #include <linux/brcmphy.h>
 #include <linux/brcmphy.h>
 #include <linux/mdio.h>
 #include <linux/mdio.h>
 
 
 /* Broadcom BCM7xxx internal PHY registers */
 /* Broadcom BCM7xxx internal PHY registers */
-#define MII_BCM7XXX_CHANNEL_WIDTH	0x2000
 
 
 /* 40nm only register definitions */
 /* 40nm only register definitions */
 #define MII_BCM7XXX_100TX_AUX_CTL	0x10
 #define MII_BCM7XXX_100TX_AUX_CTL	0x10
@@ -48,37 +48,13 @@
 
 
 #define CORE_EXPB0			0xb0
 #define CORE_EXPB0			0xb0
 
 
-static void phy_write_exp(struct phy_device *phydev,
-					u16 reg, u16 value)
-{
-	phy_write(phydev, MII_BCM54XX_EXP_SEL, MII_BCM54XX_EXP_SEL_ER | reg);
-	phy_write(phydev, MII_BCM54XX_EXP_DATA, value);
-}
-
-static void phy_write_misc(struct phy_device *phydev,
-					u16 reg, u16 chl, u16 value)
-{
-	int tmp;
-
-	phy_write(phydev, MII_BCM54XX_AUX_CTL, MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
-
-	tmp = phy_read(phydev, MII_BCM54XX_AUX_CTL);
-	tmp |= MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA;
-	phy_write(phydev, MII_BCM54XX_AUX_CTL, tmp);
-
-	tmp = (chl * MII_BCM7XXX_CHANNEL_WIDTH) | reg;
-	phy_write(phydev, MII_BCM54XX_EXP_SEL, tmp);
-
-	phy_write(phydev, MII_BCM54XX_EXP_DATA, value);
-}
-
 static void r_rc_cal_reset(struct phy_device *phydev)
 static void r_rc_cal_reset(struct phy_device *phydev)
 {
 {
 	/* Reset R_CAL/RC_CAL Engine */
 	/* Reset R_CAL/RC_CAL Engine */
-	phy_write_exp(phydev, 0x00b0, 0x0010);
+	bcm_phy_write_exp(phydev, 0x00b0, 0x0010);
 
 
 	/* Disable Reset R_AL/RC_CAL Engine */
 	/* Disable Reset R_AL/RC_CAL Engine */
-	phy_write_exp(phydev, 0x00b0, 0x0000);
+	bcm_phy_write_exp(phydev, 0x00b0, 0x0000);
 }
 }
 
 
 static int bcm7xxx_28nm_b0_afe_config_init(struct phy_device *phydev)
 static int bcm7xxx_28nm_b0_afe_config_init(struct phy_device *phydev)
@@ -86,18 +62,18 @@ static int bcm7xxx_28nm_b0_afe_config_init(struct phy_device *phydev)
 	/* Increase VCO range to prevent unlocking problem of PLL at low
 	/* Increase VCO range to prevent unlocking problem of PLL at low
 	 * temp
 	 * temp
 	 */
 	 */
-	phy_write_misc(phydev, PLL_PLLCTRL_1, 0x0048);
+	bcm_phy_write_misc(phydev, PLL_PLLCTRL_1, 0x0048);
 
 
 	/* Change Ki to 011 */
 	/* Change Ki to 011 */
-	phy_write_misc(phydev, PLL_PLLCTRL_2, 0x021b);
+	bcm_phy_write_misc(phydev, PLL_PLLCTRL_2, 0x021b);
 
 
 	/* Disable loading of TVCO buffer to bandgap, set bandgap trim
 	/* Disable loading of TVCO buffer to bandgap, set bandgap trim
 	 * to 111
 	 * to 111
 	 */
 	 */
-	phy_write_misc(phydev, PLL_PLLCTRL_4, 0x0e20);
+	bcm_phy_write_misc(phydev, PLL_PLLCTRL_4, 0x0e20);
 
 
 	/* Adjust bias current trim by -3 */
 	/* Adjust bias current trim by -3 */
-	phy_write_misc(phydev, DSP_TAP10, 0x690b);
+	bcm_phy_write_misc(phydev, DSP_TAP10, 0x690b);
 
 
 	/* Switch to CORE_BASE1E */
 	/* Switch to CORE_BASE1E */
 	phy_write(phydev, MII_BCM7XXX_CORE_BASE1E, 0xd);
 	phy_write(phydev, MII_BCM7XXX_CORE_BASE1E, 0xd);
@@ -105,19 +81,19 @@ static int bcm7xxx_28nm_b0_afe_config_init(struct phy_device *phydev)
 	r_rc_cal_reset(phydev);
 	r_rc_cal_reset(phydev);
 
 
 	/* write AFE_RXCONFIG_0 */
 	/* write AFE_RXCONFIG_0 */
-	phy_write_misc(phydev, AFE_RXCONFIG_0, 0xeb19);
+	bcm_phy_write_misc(phydev, AFE_RXCONFIG_0, 0xeb19);
 
 
 	/* write AFE_RXCONFIG_1 */
 	/* write AFE_RXCONFIG_1 */
-	phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9a3f);
+	bcm_phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9a3f);
 
 
 	/* write AFE_RX_LP_COUNTER */
 	/* write AFE_RX_LP_COUNTER */
-	phy_write_misc(phydev, AFE_RX_LP_COUNTER, 0x7fc0);
+	bcm_phy_write_misc(phydev, AFE_RX_LP_COUNTER, 0x7fc0);
 
 
 	/* write AFE_HPF_TRIM_OTHERS */
 	/* write AFE_HPF_TRIM_OTHERS */
-	phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x000b);
+	bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x000b);
 
 
 	/* write AFTE_TX_CONFIG */
 	/* write AFTE_TX_CONFIG */
-	phy_write_misc(phydev, AFE_TX_CONFIG, 0x0800);
+	bcm_phy_write_misc(phydev, AFE_TX_CONFIG, 0x0800);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -125,36 +101,36 @@ static int bcm7xxx_28nm_b0_afe_config_init(struct phy_device *phydev)
 static int bcm7xxx_28nm_d0_afe_config_init(struct phy_device *phydev)
 static int bcm7xxx_28nm_d0_afe_config_init(struct phy_device *phydev)
 {
 {
 	/* AFE_RXCONFIG_0 */
 	/* AFE_RXCONFIG_0 */
-	phy_write_misc(phydev, AFE_RXCONFIG_0, 0xeb15);
+	bcm_phy_write_misc(phydev, AFE_RXCONFIG_0, 0xeb15);
 
 
 	/* AFE_RXCONFIG_1 */
 	/* AFE_RXCONFIG_1 */
-	phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9b2f);
+	bcm_phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9b2f);
 
 
 	/* AFE_RXCONFIG_2, set rCal offset for HT=0 code and LT=-2 code */
 	/* AFE_RXCONFIG_2, set rCal offset for HT=0 code and LT=-2 code */
-	phy_write_misc(phydev, AFE_RXCONFIG_2, 0x2003);
+	bcm_phy_write_misc(phydev, AFE_RXCONFIG_2, 0x2003);
 
 
 	/* AFE_RX_LP_COUNTER, set RX bandwidth to maximum */
 	/* AFE_RX_LP_COUNTER, set RX bandwidth to maximum */
-	phy_write_misc(phydev, AFE_RX_LP_COUNTER, 0x7fc0);
+	bcm_phy_write_misc(phydev, AFE_RX_LP_COUNTER, 0x7fc0);
 
 
 	/* AFE_TX_CONFIG, set 100BT Cfeed=011 to improve rise/fall time */
 	/* AFE_TX_CONFIG, set 100BT Cfeed=011 to improve rise/fall time */
-	phy_write_misc(phydev, AFE_TX_CONFIG, 0x431);
+	bcm_phy_write_misc(phydev, AFE_TX_CONFIG, 0x431);
 
 
 	/* AFE_VDCA_ICTRL_0, set Iq=1101 instead of 0111 for AB symmetry */
 	/* AFE_VDCA_ICTRL_0, set Iq=1101 instead of 0111 for AB symmetry */
-	phy_write_misc(phydev, AFE_VDCA_ICTRL_0, 0xa7da);
+	bcm_phy_write_misc(phydev, AFE_VDCA_ICTRL_0, 0xa7da);
 
 
 	/* AFE_VDAC_OTHERS_0, set 1000BT Cidac=010 for all ports */
 	/* AFE_VDAC_OTHERS_0, set 1000BT Cidac=010 for all ports */
-	phy_write_misc(phydev, AFE_VDAC_OTHERS_0, 0xa020);
+	bcm_phy_write_misc(phydev, AFE_VDAC_OTHERS_0, 0xa020);
 
 
 	/* AFE_HPF_TRIM_OTHERS, set 100Tx/10BT to -4.5% swing and set rCal
 	/* AFE_HPF_TRIM_OTHERS, set 100Tx/10BT to -4.5% swing and set rCal
 	 * offset for HT=0 code
 	 * offset for HT=0 code
 	 */
 	 */
-	phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x00e3);
+	bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x00e3);
 
 
 	/* CORE_BASE1E, force trim to overwrite and set I_ext trim to 0000 */
 	/* CORE_BASE1E, force trim to overwrite and set I_ext trim to 0000 */
 	phy_write(phydev, MII_BCM7XXX_CORE_BASE1E, 0x0010);
 	phy_write(phydev, MII_BCM7XXX_CORE_BASE1E, 0x0010);
 
 
 	/* DSP_TAP10, adjust bias current trim (+0% swing, +0 tick) */
 	/* DSP_TAP10, adjust bias current trim (+0% swing, +0 tick) */
-	phy_write_misc(phydev, DSP_TAP10, 0x011b);
+	bcm_phy_write_misc(phydev, DSP_TAP10, 0x011b);
 
 
 	/* Reset R_CAL/RC_CAL engine */
 	/* Reset R_CAL/RC_CAL engine */
 	r_rc_cal_reset(phydev);
 	r_rc_cal_reset(phydev);
@@ -165,24 +141,24 @@ static int bcm7xxx_28nm_d0_afe_config_init(struct phy_device *phydev)
 static int bcm7xxx_28nm_e0_plus_afe_config_init(struct phy_device *phydev)
 static int bcm7xxx_28nm_e0_plus_afe_config_init(struct phy_device *phydev)
 {
 {
 	/* AFE_RXCONFIG_1, provide more margin for INL/DNL measurement */
 	/* AFE_RXCONFIG_1, provide more margin for INL/DNL measurement */
-	phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9b2f);
+	bcm_phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9b2f);
 
 
 	/* AFE_TX_CONFIG, set 100BT Cfeed=011 to improve rise/fall time */
 	/* AFE_TX_CONFIG, set 100BT Cfeed=011 to improve rise/fall time */
-	phy_write_misc(phydev, AFE_TX_CONFIG, 0x431);
+	bcm_phy_write_misc(phydev, AFE_TX_CONFIG, 0x431);
 
 
 	/* AFE_VDCA_ICTRL_0, set Iq=1101 instead of 0111 for AB symmetry */
 	/* AFE_VDCA_ICTRL_0, set Iq=1101 instead of 0111 for AB symmetry */
-	phy_write_misc(phydev, AFE_VDCA_ICTRL_0, 0xa7da);
+	bcm_phy_write_misc(phydev, AFE_VDCA_ICTRL_0, 0xa7da);
 
 
 	/* AFE_HPF_TRIM_OTHERS, set 100Tx/10BT to -4.5% swing and set rCal
 	/* AFE_HPF_TRIM_OTHERS, set 100Tx/10BT to -4.5% swing and set rCal
 	 * offset for HT=0 code
 	 * offset for HT=0 code
 	 */
 	 */
-	phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x00e3);
+	bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x00e3);
 
 
 	/* CORE_BASE1E, force trim to overwrite and set I_ext trim to 0000 */
 	/* CORE_BASE1E, force trim to overwrite and set I_ext trim to 0000 */
 	phy_write(phydev, MII_BCM7XXX_CORE_BASE1E, 0x0010);
 	phy_write(phydev, MII_BCM7XXX_CORE_BASE1E, 0x0010);
 
 
 	/* DSP_TAP10, adjust bias current trim (+0% swing, +0 tick) */
 	/* DSP_TAP10, adjust bias current trim (+0% swing, +0 tick) */
-	phy_write_misc(phydev, DSP_TAP10, 0x011b);
+	bcm_phy_write_misc(phydev, DSP_TAP10, 0x011b);
 
 
 	/* Reset R_CAL/RC_CAL engine */
 	/* Reset R_CAL/RC_CAL engine */
 	r_rc_cal_reset(phydev);
 	r_rc_cal_reset(phydev);
@@ -190,53 +166,6 @@ static int bcm7xxx_28nm_e0_plus_afe_config_init(struct phy_device *phydev)
 	return 0;
 	return 0;
 }
 }
 
 
-static int bcm7xxx_apd_enable(struct phy_device *phydev)
-{
-	int val;
-
-	/* Enable powering down of the DLL during auto-power down */
-	val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_SCR3);
-	if (val < 0)
-		return val;
-
-	val |= BCM54XX_SHD_SCR3_DLLAPD_DIS;
-	bcm54xx_shadow_write(phydev, BCM54XX_SHD_SCR3, val);
-
-	/* Enable auto-power down */
-	val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_APD);
-	if (val < 0)
-		return val;
-
-	val |= BCM54XX_SHD_APD_EN;
-	return bcm54xx_shadow_write(phydev, BCM54XX_SHD_APD, val);
-}
-
-static int bcm7xxx_eee_enable(struct phy_device *phydev)
-{
-	int val;
-
-	val = phy_read_mmd_indirect(phydev, BRCM_CL45VEN_EEE_CONTROL,
-				    MDIO_MMD_AN, phydev->addr);
-	if (val < 0)
-		return val;
-
-	/* Enable general EEE feature at the PHY level */
-	val |= LPI_FEATURE_EN | LPI_FEATURE_EN_DIG1000X;
-
-	phy_write_mmd_indirect(phydev, BRCM_CL45VEN_EEE_CONTROL,
-			       MDIO_MMD_AN, phydev->addr, val);
-
-	/* Advertise supported modes */
-	val = phy_read_mmd_indirect(phydev, MDIO_AN_EEE_ADV,
-				    MDIO_MMD_AN, phydev->addr);
-
-	val |= (MDIO_AN_EEE_ADV_100TX | MDIO_AN_EEE_ADV_1000T);
-	phy_write_mmd_indirect(phydev, MDIO_AN_EEE_ADV,
-			       MDIO_MMD_AN, phydev->addr, val);
-
-	return 0;
-}
-
 static int bcm7xxx_28nm_config_init(struct phy_device *phydev)
 static int bcm7xxx_28nm_config_init(struct phy_device *phydev)
 {
 {
 	u8 rev = PHY_BRCM_7XXX_REV(phydev->dev_flags);
 	u8 rev = PHY_BRCM_7XXX_REV(phydev->dev_flags);
@@ -273,11 +202,11 @@ static int bcm7xxx_28nm_config_init(struct phy_device *phydev)
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;
 
 
-	ret = bcm7xxx_eee_enable(phydev);
+	ret = bcm_phy_enable_eee(phydev);
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;
 
 
-	return bcm7xxx_apd_enable(phydev);
+	return bcm_phy_enable_apd(phydev, true);
 }
 }
 
 
 static int bcm7xxx_28nm_resume(struct phy_device *phydev)
 static int bcm7xxx_28nm_resume(struct phy_device *phydev)

+ 44 - 105
drivers/net/phy/broadcom.c

@@ -14,6 +14,7 @@
  *	2 of the License, or (at your option) any later version.
  *	2 of the License, or (at your option) any later version.
  */
  */
 
 
+#include "bcm-phy-lib.h"
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/phy.h>
 #include <linux/phy.h>
 #include <linux/brcmphy.h>
 #include <linux/brcmphy.h>
@@ -29,39 +30,6 @@ MODULE_DESCRIPTION("Broadcom PHY driver");
 MODULE_AUTHOR("Maciej W. Rozycki");
 MODULE_AUTHOR("Maciej W. Rozycki");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 
 
-/* Indirect register access functions for the Expansion Registers */
-static int bcm54xx_exp_read(struct phy_device *phydev, u16 regnum)
-{
-	int val;
-
-	val = phy_write(phydev, MII_BCM54XX_EXP_SEL, regnum);
-	if (val < 0)
-		return val;
-
-	val = phy_read(phydev, MII_BCM54XX_EXP_DATA);
-
-	/* Restore default value.  It's O.K. if this write fails. */
-	phy_write(phydev, MII_BCM54XX_EXP_SEL, 0);
-
-	return val;
-}
-
-static int bcm54xx_exp_write(struct phy_device *phydev, u16 regnum, u16 val)
-{
-	int ret;
-
-	ret = phy_write(phydev, MII_BCM54XX_EXP_SEL, regnum);
-	if (ret < 0)
-		return ret;
-
-	ret = phy_write(phydev, MII_BCM54XX_EXP_DATA, val);
-
-	/* Restore default value.  It's O.K. if this write fails. */
-	phy_write(phydev, MII_BCM54XX_EXP_SEL, 0);
-
-	return ret;
-}
-
 static int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val)
 static int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val)
 {
 {
 	return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val);
 	return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val);
@@ -72,28 +40,28 @@ static int bcm50610_a0_workaround(struct phy_device *phydev)
 {
 {
 	int err;
 	int err;
 
 
-	err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH0,
+	err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_AADJ1CH0,
 				MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN |
 				MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN |
 				MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF);
 				MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF);
 	if (err < 0)
 	if (err < 0)
 		return err;
 		return err;
 
 
-	err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH3,
-					MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ);
+	err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_AADJ1CH3,
+				MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ);
 	if (err < 0)
 	if (err < 0)
 		return err;
 		return err;
 
 
-	err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP75,
+	err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP75,
 				MII_BCM54XX_EXP_EXP75_VDACCTRL);
 				MII_BCM54XX_EXP_EXP75_VDACCTRL);
 	if (err < 0)
 	if (err < 0)
 		return err;
 		return err;
 
 
-	err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP96,
+	err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP96,
 				MII_BCM54XX_EXP_EXP96_MYST);
 				MII_BCM54XX_EXP_EXP96_MYST);
 	if (err < 0)
 	if (err < 0)
 		return err;
 		return err;
 
 
-	err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP97,
+	err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP97,
 				MII_BCM54XX_EXP_EXP97_MYST);
 				MII_BCM54XX_EXP_EXP97_MYST);
 
 
 	return err;
 	return err;
@@ -114,7 +82,7 @@ static int bcm54xx_phydsp_config(struct phy_device *phydev)
 	if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
 	if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
 	    BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) {
 	    BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) {
 		/* Clear bit 9 to fix a phy interop issue. */
 		/* Clear bit 9 to fix a phy interop issue. */
-		err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP08,
+		err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP08,
 					MII_BCM54XX_EXP_EXP08_RJCT_2MHZ);
 					MII_BCM54XX_EXP_EXP08_RJCT_2MHZ);
 		if (err < 0)
 		if (err < 0)
 			goto error;
 			goto error;
@@ -129,12 +97,12 @@ static int bcm54xx_phydsp_config(struct phy_device *phydev)
 	if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM57780) {
 	if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM57780) {
 		int val;
 		int val;
 
 
-		val = bcm54xx_exp_read(phydev, MII_BCM54XX_EXP_EXP75);
+		val = bcm_phy_read_exp(phydev, MII_BCM54XX_EXP_EXP75);
 		if (val < 0)
 		if (val < 0)
 			goto error;
 			goto error;
 
 
 		val |= MII_BCM54XX_EXP_EXP75_CM_OSC;
 		val |= MII_BCM54XX_EXP_EXP75_CM_OSC;
-		err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP75, val);
+		err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP75, val);
 	}
 	}
 
 
 error:
 error:
@@ -159,7 +127,7 @@ static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev)
 	    BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610M)
 	    BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610M)
 		return;
 		return;
 
 
-	val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_SCR3);
+	val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_SCR3);
 	if (val < 0)
 	if (val < 0)
 		return;
 		return;
 
 
@@ -190,9 +158,9 @@ static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev)
 		val |= BCM54XX_SHD_SCR3_TRDDAPD;
 		val |= BCM54XX_SHD_SCR3_TRDDAPD;
 
 
 	if (orig != val)
 	if (orig != val)
-		bcm54xx_shadow_write(phydev, BCM54XX_SHD_SCR3, val);
+		bcm_phy_write_shadow(phydev, BCM54XX_SHD_SCR3, val);
 
 
-	val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_APD);
+	val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_APD);
 	if (val < 0)
 	if (val < 0)
 		return;
 		return;
 
 
@@ -204,7 +172,7 @@ static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev)
 		val &= ~BCM54XX_SHD_APD_EN;
 		val &= ~BCM54XX_SHD_APD_EN;
 
 
 	if (orig != val)
 	if (orig != val)
-		bcm54xx_shadow_write(phydev, BCM54XX_SHD_APD, val);
+		bcm_phy_write_shadow(phydev, BCM54XX_SHD_APD, val);
 }
 }
 
 
 static int bcm54xx_config_init(struct phy_device *phydev)
 static int bcm54xx_config_init(struct phy_device *phydev)
@@ -232,7 +200,7 @@ static int bcm54xx_config_init(struct phy_device *phydev)
 	if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
 	if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
 	     BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) &&
 	     BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) &&
 	    (phydev->dev_flags & PHY_BRCM_CLEAR_RGMII_MODE))
 	    (phydev->dev_flags & PHY_BRCM_CLEAR_RGMII_MODE))
-		bcm54xx_shadow_write(phydev, BCM54XX_SHD_RGMII_MODE, 0);
+		bcm_phy_write_shadow(phydev, BCM54XX_SHD_RGMII_MODE, 0);
 
 
 	if ((phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) ||
 	if ((phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) ||
 	    (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY) ||
 	    (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY) ||
@@ -254,8 +222,8 @@ static int bcm5482_config_init(struct phy_device *phydev)
 		/*
 		/*
 		 * Enable secondary SerDes and its use as an LED source
 		 * Enable secondary SerDes and its use as an LED source
 		 */
 		 */
-		reg = bcm54xx_shadow_read(phydev, BCM5482_SHD_SSD);
-		bcm54xx_shadow_write(phydev, BCM5482_SHD_SSD,
+		reg = bcm_phy_read_shadow(phydev, BCM5482_SHD_SSD);
+		bcm_phy_write_shadow(phydev, BCM5482_SHD_SSD,
 				     reg |
 				     reg |
 				     BCM5482_SHD_SSD_LEDM |
 				     BCM5482_SHD_SSD_LEDM |
 				     BCM5482_SHD_SSD_EN);
 				     BCM5482_SHD_SSD_EN);
@@ -264,10 +232,10 @@ static int bcm5482_config_init(struct phy_device *phydev)
 		 * Enable SGMII slave mode and auto-detection
 		 * Enable SGMII slave mode and auto-detection
 		 */
 		 */
 		reg = BCM5482_SSD_SGMII_SLAVE | MII_BCM54XX_EXP_SEL_SSD;
 		reg = BCM5482_SSD_SGMII_SLAVE | MII_BCM54XX_EXP_SEL_SSD;
-		err = bcm54xx_exp_read(phydev, reg);
+		err = bcm_phy_read_exp(phydev, reg);
 		if (err < 0)
 		if (err < 0)
 			return err;
 			return err;
-		err = bcm54xx_exp_write(phydev, reg, err |
+		err = bcm_phy_write_exp(phydev, reg, err |
 					BCM5482_SSD_SGMII_SLAVE_EN |
 					BCM5482_SSD_SGMII_SLAVE_EN |
 					BCM5482_SSD_SGMII_SLAVE_AD);
 					BCM5482_SSD_SGMII_SLAVE_AD);
 		if (err < 0)
 		if (err < 0)
@@ -277,10 +245,10 @@ static int bcm5482_config_init(struct phy_device *phydev)
 		 * Disable secondary SerDes powerdown
 		 * Disable secondary SerDes powerdown
 		 */
 		 */
 		reg = BCM5482_SSD_1000BX_CTL | MII_BCM54XX_EXP_SEL_SSD;
 		reg = BCM5482_SSD_1000BX_CTL | MII_BCM54XX_EXP_SEL_SSD;
-		err = bcm54xx_exp_read(phydev, reg);
+		err = bcm_phy_read_exp(phydev, reg);
 		if (err < 0)
 		if (err < 0)
 			return err;
 			return err;
-		err = bcm54xx_exp_write(phydev, reg,
+		err = bcm_phy_write_exp(phydev, reg,
 					err & ~BCM5482_SSD_1000BX_CTL_PWRDOWN);
 					err & ~BCM5482_SSD_1000BX_CTL_PWRDOWN);
 		if (err < 0)
 		if (err < 0)
 			return err;
 			return err;
@@ -288,15 +256,15 @@ static int bcm5482_config_init(struct phy_device *phydev)
 		/*
 		/*
 		 * Select 1000BASE-X register set (primary SerDes)
 		 * Select 1000BASE-X register set (primary SerDes)
 		 */
 		 */
-		reg = bcm54xx_shadow_read(phydev, BCM5482_SHD_MODE);
-		bcm54xx_shadow_write(phydev, BCM5482_SHD_MODE,
+		reg = bcm_phy_read_shadow(phydev, BCM5482_SHD_MODE);
+		bcm_phy_write_shadow(phydev, BCM5482_SHD_MODE,
 				     reg | BCM5482_SHD_MODE_1000BX);
 				     reg | BCM5482_SHD_MODE_1000BX);
 
 
 		/*
 		/*
 		 * LED1=ACTIVITYLED, LED3=LINKSPD[2]
 		 * LED1=ACTIVITYLED, LED3=LINKSPD[2]
 		 * (Use LED1 as secondary SerDes ACTIVITY LED)
 		 * (Use LED1 as secondary SerDes ACTIVITY LED)
 		 */
 		 */
-		bcm54xx_shadow_write(phydev, BCM5482_SHD_LEDS1,
+		bcm_phy_write_shadow(phydev, BCM5482_SHD_LEDS1,
 			BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_ACTIVITYLED) |
 			BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_ACTIVITYLED) |
 			BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_LINKSPD2));
 			BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_LINKSPD2));
 
 
@@ -334,35 +302,6 @@ static int bcm5482_read_status(struct phy_device *phydev)
 	return err;
 	return err;
 }
 }
 
 
-static int bcm54xx_ack_interrupt(struct phy_device *phydev)
-{
-	int reg;
-
-	/* Clear pending interrupts.  */
-	reg = phy_read(phydev, MII_BCM54XX_ISR);
-	if (reg < 0)
-		return reg;
-
-	return 0;
-}
-
-static int bcm54xx_config_intr(struct phy_device *phydev)
-{
-	int reg, err;
-
-	reg = phy_read(phydev, MII_BCM54XX_ECR);
-	if (reg < 0)
-		return reg;
-
-	if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
-		reg &= ~MII_BCM54XX_ECR_IM;
-	else
-		reg |= MII_BCM54XX_ECR_IM;
-
-	err = phy_write(phydev, MII_BCM54XX_ECR, reg);
-	return err;
-}
-
 static int bcm5481_config_aneg(struct phy_device *phydev)
 static int bcm5481_config_aneg(struct phy_device *phydev)
 {
 {
 	int ret;
 	int ret;
@@ -519,8 +458,8 @@ static struct phy_driver broadcom_drivers[] = {
 	.config_init	= bcm54xx_config_init,
 	.config_init	= bcm54xx_config_init,
 	.config_aneg	= genphy_config_aneg,
 	.config_aneg	= genphy_config_aneg,
 	.read_status	= genphy_read_status,
 	.read_status	= genphy_read_status,
-	.ack_interrupt	= bcm54xx_ack_interrupt,
-	.config_intr	= bcm54xx_config_intr,
+	.ack_interrupt	= bcm_phy_ack_intr,
+	.config_intr	= bcm_phy_config_intr,
 	.driver		= { .owner = THIS_MODULE },
 	.driver		= { .owner = THIS_MODULE },
 }, {
 }, {
 	.phy_id		= PHY_ID_BCM5421,
 	.phy_id		= PHY_ID_BCM5421,
@@ -532,8 +471,8 @@ static struct phy_driver broadcom_drivers[] = {
 	.config_init	= bcm54xx_config_init,
 	.config_init	= bcm54xx_config_init,
 	.config_aneg	= genphy_config_aneg,
 	.config_aneg	= genphy_config_aneg,
 	.read_status	= genphy_read_status,
 	.read_status	= genphy_read_status,
-	.ack_interrupt	= bcm54xx_ack_interrupt,
-	.config_intr	= bcm54xx_config_intr,
+	.ack_interrupt	= bcm_phy_ack_intr,
+	.config_intr	= bcm_phy_config_intr,
 	.driver		= { .owner = THIS_MODULE },
 	.driver		= { .owner = THIS_MODULE },
 }, {
 }, {
 	.phy_id		= PHY_ID_BCM5461,
 	.phy_id		= PHY_ID_BCM5461,
@@ -545,8 +484,8 @@ static struct phy_driver broadcom_drivers[] = {
 	.config_init	= bcm54xx_config_init,
 	.config_init	= bcm54xx_config_init,
 	.config_aneg	= genphy_config_aneg,
 	.config_aneg	= genphy_config_aneg,
 	.read_status	= genphy_read_status,
 	.read_status	= genphy_read_status,
-	.ack_interrupt	= bcm54xx_ack_interrupt,
-	.config_intr	= bcm54xx_config_intr,
+	.ack_interrupt	= bcm_phy_ack_intr,
+	.config_intr	= bcm_phy_config_intr,
 	.driver		= { .owner = THIS_MODULE },
 	.driver		= { .owner = THIS_MODULE },
 }, {
 }, {
 	.phy_id		= PHY_ID_BCM54616S,
 	.phy_id		= PHY_ID_BCM54616S,
@@ -558,8 +497,8 @@ static struct phy_driver broadcom_drivers[] = {
 	.config_init	= bcm54xx_config_init,
 	.config_init	= bcm54xx_config_init,
 	.config_aneg	= genphy_config_aneg,
 	.config_aneg	= genphy_config_aneg,
 	.read_status	= genphy_read_status,
 	.read_status	= genphy_read_status,
-	.ack_interrupt	= bcm54xx_ack_interrupt,
-	.config_intr	= bcm54xx_config_intr,
+	.ack_interrupt	= bcm_phy_ack_intr,
+	.config_intr	= bcm_phy_config_intr,
 	.driver		= { .owner = THIS_MODULE },
 	.driver		= { .owner = THIS_MODULE },
 }, {
 }, {
 	.phy_id		= PHY_ID_BCM5464,
 	.phy_id		= PHY_ID_BCM5464,
@@ -571,8 +510,8 @@ static struct phy_driver broadcom_drivers[] = {
 	.config_init	= bcm54xx_config_init,
 	.config_init	= bcm54xx_config_init,
 	.config_aneg	= genphy_config_aneg,
 	.config_aneg	= genphy_config_aneg,
 	.read_status	= genphy_read_status,
 	.read_status	= genphy_read_status,
-	.ack_interrupt	= bcm54xx_ack_interrupt,
-	.config_intr	= bcm54xx_config_intr,
+	.ack_interrupt	= bcm_phy_ack_intr,
+	.config_intr	= bcm_phy_config_intr,
 	.driver		= { .owner = THIS_MODULE },
 	.driver		= { .owner = THIS_MODULE },
 }, {
 }, {
 	.phy_id		= PHY_ID_BCM5481,
 	.phy_id		= PHY_ID_BCM5481,
@@ -584,8 +523,8 @@ static struct phy_driver broadcom_drivers[] = {
 	.config_init	= bcm54xx_config_init,
 	.config_init	= bcm54xx_config_init,
 	.config_aneg	= bcm5481_config_aneg,
 	.config_aneg	= bcm5481_config_aneg,
 	.read_status	= genphy_read_status,
 	.read_status	= genphy_read_status,
-	.ack_interrupt	= bcm54xx_ack_interrupt,
-	.config_intr	= bcm54xx_config_intr,
+	.ack_interrupt	= bcm_phy_ack_intr,
+	.config_intr	= bcm_phy_config_intr,
 	.driver		= { .owner = THIS_MODULE },
 	.driver		= { .owner = THIS_MODULE },
 }, {
 }, {
 	.phy_id		= PHY_ID_BCM5482,
 	.phy_id		= PHY_ID_BCM5482,
@@ -597,8 +536,8 @@ static struct phy_driver broadcom_drivers[] = {
 	.config_init	= bcm5482_config_init,
 	.config_init	= bcm5482_config_init,
 	.config_aneg	= genphy_config_aneg,
 	.config_aneg	= genphy_config_aneg,
 	.read_status	= bcm5482_read_status,
 	.read_status	= bcm5482_read_status,
-	.ack_interrupt	= bcm54xx_ack_interrupt,
-	.config_intr	= bcm54xx_config_intr,
+	.ack_interrupt	= bcm_phy_ack_intr,
+	.config_intr	= bcm_phy_config_intr,
 	.driver		= { .owner = THIS_MODULE },
 	.driver		= { .owner = THIS_MODULE },
 }, {
 }, {
 	.phy_id		= PHY_ID_BCM50610,
 	.phy_id		= PHY_ID_BCM50610,
@@ -610,8 +549,8 @@ static struct phy_driver broadcom_drivers[] = {
 	.config_init	= bcm54xx_config_init,
 	.config_init	= bcm54xx_config_init,
 	.config_aneg	= genphy_config_aneg,
 	.config_aneg	= genphy_config_aneg,
 	.read_status	= genphy_read_status,
 	.read_status	= genphy_read_status,
-	.ack_interrupt	= bcm54xx_ack_interrupt,
-	.config_intr	= bcm54xx_config_intr,
+	.ack_interrupt	= bcm_phy_ack_intr,
+	.config_intr	= bcm_phy_config_intr,
 	.driver		= { .owner = THIS_MODULE },
 	.driver		= { .owner = THIS_MODULE },
 }, {
 }, {
 	.phy_id		= PHY_ID_BCM50610M,
 	.phy_id		= PHY_ID_BCM50610M,
@@ -623,8 +562,8 @@ static struct phy_driver broadcom_drivers[] = {
 	.config_init	= bcm54xx_config_init,
 	.config_init	= bcm54xx_config_init,
 	.config_aneg	= genphy_config_aneg,
 	.config_aneg	= genphy_config_aneg,
 	.read_status	= genphy_read_status,
 	.read_status	= genphy_read_status,
-	.ack_interrupt	= bcm54xx_ack_interrupt,
-	.config_intr	= bcm54xx_config_intr,
+	.ack_interrupt	= bcm_phy_ack_intr,
+	.config_intr	= bcm_phy_config_intr,
 	.driver		= { .owner = THIS_MODULE },
 	.driver		= { .owner = THIS_MODULE },
 }, {
 }, {
 	.phy_id		= PHY_ID_BCM57780,
 	.phy_id		= PHY_ID_BCM57780,
@@ -636,8 +575,8 @@ static struct phy_driver broadcom_drivers[] = {
 	.config_init	= bcm54xx_config_init,
 	.config_init	= bcm54xx_config_init,
 	.config_aneg	= genphy_config_aneg,
 	.config_aneg	= genphy_config_aneg,
 	.read_status	= genphy_read_status,
 	.read_status	= genphy_read_status,
-	.ack_interrupt	= bcm54xx_ack_interrupt,
-	.config_intr	= bcm54xx_config_intr,
+	.ack_interrupt	= bcm_phy_ack_intr,
+	.config_intr	= bcm_phy_config_intr,
 	.driver		= { .owner = THIS_MODULE },
 	.driver		= { .owner = THIS_MODULE },
 }, {
 }, {
 	.phy_id		= PHY_ID_BCMAC131,
 	.phy_id		= PHY_ID_BCMAC131,

+ 3 - 19
include/linux/brcmphy.h

@@ -138,7 +138,10 @@
 
 
 /* 01010: Auto Power-Down */
 /* 01010: Auto Power-Down */
 #define BCM54XX_SHD_APD			0x0a
 #define BCM54XX_SHD_APD			0x0a
+#define  BCM_APD_CLR_MASK		0xFE9F /* clear bits 5, 6 & 8 */
 #define  BCM54XX_SHD_APD_EN		0x0020
 #define  BCM54XX_SHD_APD_EN		0x0020
+#define  BCM_NO_ANEG_APD_EN		0x0060 /* bits 5 & 6 */
+#define  BCM_APD_SINGLELP_EN	0x0100 /* Bit 8 */
 
 
 #define BCM5482_SHD_LEDS1	0x0d	/* 01101: LED Selector 1 */
 #define BCM5482_SHD_LEDS1	0x0d	/* 01101: LED Selector 1 */
 					/* LED3 / ~LINKSPD[2] selector */
 					/* LED3 / ~LINKSPD[2] selector */
@@ -209,25 +212,6 @@
 #define MII_BRCM_FET_SHDW_AUXSTAT2	0x1b	/* Auxiliary status 2 */
 #define MII_BRCM_FET_SHDW_AUXSTAT2	0x1b	/* Auxiliary status 2 */
 #define MII_BRCM_FET_SHDW_AS2_APDE	0x0020	/* Auto power down enable */
 #define MII_BRCM_FET_SHDW_AS2_APDE	0x0020	/* Auto power down enable */
 
 
-/*
- * Indirect register access functions for the 1000BASE-T/100BASE-TX/10BASE-T
- * 0x1c shadow registers.
- */
-static inline int bcm54xx_shadow_read(struct phy_device *phydev, u16 shadow)
-{
-	phy_write(phydev, MII_BCM54XX_SHD, MII_BCM54XX_SHD_VAL(shadow));
-	return MII_BCM54XX_SHD_DATA(phy_read(phydev, MII_BCM54XX_SHD));
-}
-
-static inline int bcm54xx_shadow_write(struct phy_device *phydev, u16 shadow,
-				       u16 val)
-{
-	return phy_write(phydev, MII_BCM54XX_SHD,
-			 MII_BCM54XX_SHD_WRITE |
-			 MII_BCM54XX_SHD_VAL(shadow) |
-			 MII_BCM54XX_SHD_DATA(val));
-}
-
 #define BRCM_CL45VEN_EEE_CONTROL	0x803d
 #define BRCM_CL45VEN_EEE_CONTROL	0x803d
 #define LPI_FEATURE_EN			0x8000
 #define LPI_FEATURE_EN			0x8000
 #define LPI_FEATURE_EN_DIG1000X		0x4000
 #define LPI_FEATURE_EN_DIG1000X		0x4000