From 47b1b53b41d63f27b308981fde307d415e514431 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Mon, 2 Nov 2009 14:28:04 +0000 Subject: broadcom: Isolate phy dsp accesses This patch consolidates the code that requires the SMDSP clock to be enabled into a single function that (hopefully) makes the dependency obvious. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/phy/broadcom.c | 90 ++++++++++++++++++++++------------------------ 1 file changed, 42 insertions(+), 48 deletions(-) (limited to 'drivers/net/phy/broadcom.c') diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index f81e5322223..9e574ceacf4 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c @@ -237,53 +237,78 @@ static int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val) return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val); } +/* Needs SMDSP clock enabled via bcm54xx_phydsp_config() */ static int bcm50610_a0_workaround(struct phy_device *phydev) { int err; - err = bcm54xx_auxctl_write(phydev, - MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL, - MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA | - MII_BCM54XX_AUXCTL_ACTL_TX_6DB); - if (err < 0) - return err; - err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP08, MII_BCM54XX_EXP_EXP08_RJCT_2MHZ | MII_BCM54XX_EXP_EXP08_EARLY_DAC_WAKE); if (err < 0) - goto error; + return err; err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH0, MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN | MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF); if (err < 0) - goto error; + return err; err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH3, MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ); if (err < 0) - goto error; + return err; err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP75, MII_BCM54XX_EXP_EXP75_VDACCTRL); if (err < 0) - goto error; + return err; err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP96, MII_BCM54XX_EXP_EXP96_MYST); if (err < 0) - goto error; + return err; err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP97, MII_BCM54XX_EXP_EXP97_MYST); + return err; +} + +static int bcm54xx_phydsp_config(struct phy_device *phydev) +{ + int err, err2; + + /* Enable the SMDSP clock */ + err = bcm54xx_auxctl_write(phydev, + MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL, + MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA | + MII_BCM54XX_AUXCTL_ACTL_TX_6DB); + if (err < 0) + return err; + + if (phydev->drv->phy_id == PHY_ID_BCM50610) + err = bcm50610_a0_workaround(phydev); + + if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM57780) { + int val; + + val = bcm54xx_exp_read(phydev, MII_BCM54XX_EXP_EXP75); + if (val < 0) + goto error; + + val |= MII_BCM54XX_EXP_EXP75_CM_OSC; + err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP75, val); + } + error: - bcm54xx_auxctl_write(phydev, - MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL, - MII_BCM54XX_AUXCTL_ACTL_TX_6DB); + /* Disable the SMDSP clock */ + err2 = bcm54xx_auxctl_write(phydev, + MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL, + MII_BCM54XX_AUXCTL_ACTL_TX_6DB); - return err; + /* Return the first error reported. */ + return err ? err : err2; } static int bcm54xx_config_init(struct phy_device *phydev) @@ -308,38 +333,7 @@ static int bcm54xx_config_init(struct phy_device *phydev) if (err < 0) return err; - if (phydev->drv->phy_id == PHY_ID_BCM50610) { - err = bcm50610_a0_workaround(phydev); - if (err < 0) - return err; - } - - if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM57780) { - int err2; - - err = bcm54xx_auxctl_write(phydev, - MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL, - MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA | - MII_BCM54XX_AUXCTL_ACTL_TX_6DB); - if (err < 0) - return err; - - reg = bcm54xx_exp_read(phydev, MII_BCM54XX_EXP_EXP75); - if (reg < 0) - goto error; - - reg |= MII_BCM54XX_EXP_EXP75_CM_OSC; - err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP75, reg); - -error: - err2 = bcm54xx_auxctl_write(phydev, - MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL, - MII_BCM54XX_AUXCTL_ACTL_TX_6DB); - if (err) - return err; - if (err2) - return err2; - } + bcm54xx_phydsp_config(phydev); return 0; } -- cgit v1.2.3-70-g09d2 From 219c6efefaa3f5cd05db52cda50402b2e1c9ae21 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Mon, 2 Nov 2009 14:28:33 +0000 Subject: broadcom: Fix slow link problem When a 50610 or 50610M is paired against particular remote partners, link is slow to come up. This patch works around the problem. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/phy/broadcom.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'drivers/net/phy/broadcom.c') diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index 9e574ceacf4..1a2b2f2a273 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c @@ -242,12 +242,6 @@ static int bcm50610_a0_workaround(struct phy_device *phydev) { int err; - err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP08, - MII_BCM54XX_EXP_EXP08_RJCT_2MHZ | - MII_BCM54XX_EXP_EXP08_EARLY_DAC_WAKE); - if (err < 0) - return err; - err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH0, MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN | MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF); @@ -287,8 +281,20 @@ static int bcm54xx_phydsp_config(struct phy_device *phydev) if (err < 0) return err; - if (phydev->drv->phy_id == PHY_ID_BCM50610) - err = bcm50610_a0_workaround(phydev); + if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 || + BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) { + /* Clear bit 9 to fix a phy interop issue. */ + err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP08, + MII_BCM54XX_EXP_EXP08_RJCT_2MHZ); + if (err < 0) + goto error; + + if (phydev->drv->phy_id == PHY_ID_BCM50610) { + err = bcm50610_a0_workaround(phydev); + if (err < 0) + goto error; + } + } if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM57780) { int val; -- cgit v1.2.3-70-g09d2 From 8649f13d2d810406da444a6101906041b796fbde Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Mon, 2 Nov 2009 14:30:00 +0000 Subject: broadcom: Consolidate dev_flags definitions This patch moves all the dev_flags enumerations outside the broadcom.c file to include/linux/brcmphy.h. The existing flags were not used yet and have been re-enumerated to avoid conflicts. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/phy/broadcom.c | 11 +---------- include/linux/brcmphy.h | 17 +++++++++++------ 2 files changed, 12 insertions(+), 16 deletions(-) (limited to 'drivers/net/phy/broadcom.c') diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index 1a2b2f2a273..ace0ccc87a0 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c @@ -16,6 +16,7 @@ #include #include +#include #define PHY_ID_BCM50610 0x0143bd60 #define PHY_ID_BCM50610M 0x0143bd70 @@ -138,16 +139,6 @@ #define BCM5482_SSD_SGMII_SLAVE_EN 0x0002 /* Slave mode enable */ #define BCM5482_SSD_SGMII_SLAVE_AD 0x0001 /* Slave auto-detection */ -/* - * Device flags for PHYs that can be configured for different operating - * modes. - */ -#define PHY_BCM_FLAGS_VALID 0x80000000 -#define PHY_BCM_FLAGS_INTF_XAUI 0x00000020 -#define PHY_BCM_FLAGS_INTF_SGMII 0x00000010 -#define PHY_BCM_FLAGS_MODE_1000BX 0x00000002 -#define PHY_BCM_FLAGS_MODE_COPPER 0x00000001 - /*****************************************************************************/ /* Fast Ethernet Transceiver definitions. */ diff --git a/include/linux/brcmphy.h b/include/linux/brcmphy.h index 9b64b6d6787..daa1480fcf4 100644 --- a/include/linux/brcmphy.h +++ b/include/linux/brcmphy.h @@ -1,6 +1,11 @@ -#define PHY_BRCM_WIRESPEED_ENABLE 0x00000001 -#define PHY_BRCM_AUTO_PWRDWN_ENABLE 0x00000002 -#define PHY_BRCM_APD_CLK125_ENABLE 0x00000004 -#define PHY_BRCM_STD_IBND_DISABLE 0x00000008 -#define PHY_BRCM_EXT_IBND_RX_ENABLE 0x00000010 -#define PHY_BRCM_EXT_IBND_TX_ENABLE 0x00000020 +#define PHY_BCM_FLAGS_MODE_COPPER 0x00000001 +#define PHY_BCM_FLAGS_MODE_1000BX 0x00000002 +#define PHY_BCM_FLAGS_INTF_SGMII 0x00000010 +#define PHY_BCM_FLAGS_INTF_XAUI 0x00000020 +#define PHY_BRCM_WIRESPEED_ENABLE 0x00000100 +#define PHY_BRCM_AUTO_PWRDWN_ENABLE 0x00000200 +#define PHY_BRCM_APD_CLK125_ENABLE 0x00000400 +#define PHY_BRCM_STD_IBND_DISABLE 0x00000800 +#define PHY_BRCM_EXT_IBND_RX_ENABLE 0x00001000 +#define PHY_BRCM_EXT_IBND_TX_ENABLE 0x00002000 +#define PHY_BCM_FLAGS_VALID 0x80000000 -- cgit v1.2.3-70-g09d2 From 63a14ce449dd6d647de2725809159eb072b2c44f Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Mon, 2 Nov 2009 14:30:40 +0000 Subject: tg3 / broadcom: Add PHY_BRCM_CLEAR_RGMII_MODE flag Broadcom 50610M parts changed the default definitions of the RGMII mode shadow register. The 5785 needs the RGMII mode selection bits [4:3] cleared. The default value of the remaining bits in this register are zero. Rather than unnecessarily burn an extra bit in the dev_flags member in an attempt to enumerate all possible combinations, this patch take a more course grained approach and labels the option as "clear all bits". Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/phy/broadcom.c | 6 ++++++ drivers/net/tg3.c | 1 + include/linux/brcmphy.h | 1 + 3 files changed, 8 insertions(+) (limited to 'drivers/net/phy/broadcom.c') diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index ace0ccc87a0..5d2a2e90aba 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c @@ -105,6 +105,7 @@ #define BCM5482_SHD_LEDS1_LED3(src) ((src & 0xf) << 4) /* LED1 / ~LINKSPD[1] selector */ #define BCM5482_SHD_LEDS1_LED1(src) ((src & 0xf) << 0) +#define BCM54XX_SHD_RGMII_MODE 0x0b /* 01011: RGMII Mode Selector */ #define BCM5482_SHD_SSD 0x14 /* 10100: Secondary SerDes control */ #define BCM5482_SHD_SSD_LEDM 0x0008 /* SSD LED Mode enable */ #define BCM5482_SHD_SSD_EN 0x0001 /* SSD enable */ @@ -330,6 +331,11 @@ static int bcm54xx_config_init(struct phy_device *phydev) if (err < 0) return err; + if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 || + BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) && + (phydev->dev_flags & PHY_BRCM_CLEAR_RGMII_MODE)) + bcm54xx_shadow_write(phydev, BCM54XX_SHD_RGMII_MODE, 0); + bcm54xx_phydsp_config(phydev); return 0; diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 0aecd07d3f6..e7128f6ae2d 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -1100,6 +1100,7 @@ static int tg3_mdio_init(struct tg3 *tp) break; case TG3_PHY_ID_BCM50610: case TG3_PHY_ID_BCM50610M: + phydev->dev_flags |= PHY_BRCM_CLEAR_RGMII_MODE; if (tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE) phydev->dev_flags |= PHY_BRCM_STD_IBND_DISABLE; if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_RX_EN) diff --git a/include/linux/brcmphy.h b/include/linux/brcmphy.h index daa1480fcf4..6e7ffcee9c8 100644 --- a/include/linux/brcmphy.h +++ b/include/linux/brcmphy.h @@ -8,4 +8,5 @@ #define PHY_BRCM_STD_IBND_DISABLE 0x00000800 #define PHY_BRCM_EXT_IBND_RX_ENABLE 0x00001000 #define PHY_BRCM_EXT_IBND_TX_ENABLE 0x00002000 +#define PHY_BRCM_CLEAR_RGMII_MODE 0x00004000 #define PHY_BCM_FLAGS_VALID 0x80000000 -- cgit v1.2.3-70-g09d2 From cdd4e09d692bd4f3457b3789279005e112b7696d Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Mon, 2 Nov 2009 14:31:11 +0000 Subject: tg3 / broadcom: Refine AC131 APD support Auto power-down (APD) support is a power-saving feature. It should be selectively enabled since it might expose MAC bugs. This patch changes the code to enable APD only if the PHY_BRCM_AUTO_PWRDWN_ENABLE flag is set. The tg3 driver was changed to set this bit. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/phy/broadcom.c | 8 +++++--- drivers/net/tg3.c | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/net/phy/broadcom.c') diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index 5d2a2e90aba..bddf4a42ae6 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c @@ -561,9 +561,11 @@ static int brcm_fet_config_init(struct phy_device *phydev) if (err < 0) goto done; - /* Enable auto power down */ - err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2, - MII_BRCM_FET_SHDW_AS2_APDE); + if (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE) { + /* Enable auto power down */ + err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2, + MII_BRCM_FET_SHDW_AS2_APDE); + } done: /* Disable shadow register access */ diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index e7128f6ae2d..592b5bf09e4 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -1114,6 +1114,7 @@ static int tg3_mdio_init(struct tg3 *tp) case TG3_PHY_ID_RTL8201E: case TG3_PHY_ID_BCMAC131: phydev->interface = PHY_INTERFACE_MODE_MII; + phydev->dev_flags |= PHY_BRCM_AUTO_PWRDWN_ENABLE; tp->tg3_flags3 |= TG3_FLG3_PHY_IS_FET; break; } -- cgit v1.2.3-70-g09d2 From 32e5a8d651c0dbb02bf82ca954206282e44c4b11 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Mon, 2 Nov 2009 14:31:39 +0000 Subject: tg3 / broadcom: Add code to disable rxc refclk The 5785 does not use the RXC reference clock. Turning it off is desirable as it saves power. By default, the 50610 enables the RXC reference clock and the 50610M disables it. Presumably this is one of the reasons why the hardware architect chose one over the other. Adding a "rx reference clock disable" flag is not the ideal way to describe the option, as it would force the MAC using a 50610M to set the flag. Ideally we want the flags to represent opt-in behavior that deviates from hardware defaults. Furthermore, the lack of a "disable" flag implies that the requester wants the rx reference clock enabled, which doesn't necessarily follow. By presenting the option as a passive statement (rx reference clock unused) rather than a command, I hope to convey an opt-in option to disable the rx reference clock that falls back to hardware defaults if not set. A secondary benefit of this is that it keeps the intelligence about phy defaults in the broadcom module where it belongs and allows the broadcom module more latitude should a bug arise. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/phy/broadcom.c | 43 +++++++++++++++++++++++++++++++++++++++++++ drivers/net/tg3.c | 3 ++- include/linux/brcmphy.h | 2 +- 3 files changed, 46 insertions(+), 2 deletions(-) (limited to 'drivers/net/phy/broadcom.c') diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index bddf4a42ae6..74914335f72 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c @@ -25,6 +25,9 @@ #define BRCM_PHY_MODEL(phydev) \ ((phydev)->drv->phy_id & (phydev)->drv->phy_id_mask) +#define BRCM_PHY_REV(phydev) \ + ((phydev)->drv->phy_id & ~((phydev)->drv->phy_id_mask)) + #define MII_BCM54XX_ECR 0x10 /* BCM54xx extended control register */ #define MII_BCM54XX_ECR_IM 0x1000 /* Interrupt mask */ @@ -95,11 +98,16 @@ #define BCM_LED_SRC_OFF 0xe /* Tied high */ #define BCM_LED_SRC_ON 0xf /* Tied low */ + /* * BCM5482: Shadow registers * Shadow values go into bits [14:10] of register 0x1c to select a shadow * register to access. */ +/* 00101: Spare Control Register 3 */ +#define BCM54XX_SHD_SCR3 0x05 +#define BCM54XX_SHD_SCR3_DEF_CLK125 0x0001 + #define BCM5482_SHD_LEDS1 0x0d /* 01101: LED Selector 1 */ /* LED3 / ~LINKSPD[2] selector */ #define BCM5482_SHD_LEDS1_LED3(src) ((src & 0xf) << 4) @@ -112,6 +120,7 @@ #define BCM5482_SHD_MODE 0x1f /* 11111: Mode Control Register */ #define BCM5482_SHD_MODE_1000BX 0x0001 /* Enable 1000BASE-X registers */ + /* * EXPANSION SHADOW ACCESS REGISTERS. (PHY REG 0x15, 0x16, and 0x17) */ @@ -309,6 +318,37 @@ error: return err ? err : err2; } +static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev) +{ + u32 val, orig; + + /* Abort if we are using an untested phy. */ + if (BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610 || + BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610M) + return; + + val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_SCR3); + if (val < 0) + return; + + orig = val; + + if (phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) { + if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 || + BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) && + BRCM_PHY_REV(phydev) >= 0x3) { + /* Here, bit 0 _disables_ CLK125 when set */ + val |= BCM54XX_SHD_SCR3_DEF_CLK125; + } else { + /* Here, bit 0 _enables_ CLK125 when set */ + val &= ~BCM54XX_SHD_SCR3_DEF_CLK125; + } + } + + if (orig != val) + bcm54xx_shadow_write(phydev, BCM54XX_SHD_SCR3, val); +} + static int bcm54xx_config_init(struct phy_device *phydev) { int reg, err; @@ -336,6 +376,9 @@ static int bcm54xx_config_init(struct phy_device *phydev) (phydev->dev_flags & PHY_BRCM_CLEAR_RGMII_MODE)) bcm54xx_shadow_write(phydev, BCM54XX_SHD_RGMII_MODE, 0); + if (phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) + bcm54xx_adjust_rxrefclk(phydev); + bcm54xx_phydsp_config(phydev); return 0; diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 592b5bf09e4..369ddba9582 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -1100,7 +1100,8 @@ static int tg3_mdio_init(struct tg3 *tp) break; case TG3_PHY_ID_BCM50610: case TG3_PHY_ID_BCM50610M: - phydev->dev_flags |= PHY_BRCM_CLEAR_RGMII_MODE; + phydev->dev_flags |= PHY_BRCM_CLEAR_RGMII_MODE | + PHY_BRCM_RX_REFCLK_UNUSED; if (tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE) phydev->dev_flags |= PHY_BRCM_STD_IBND_DISABLE; if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_RX_EN) diff --git a/include/linux/brcmphy.h b/include/linux/brcmphy.h index 6e7ffcee9c8..59432278ded 100644 --- a/include/linux/brcmphy.h +++ b/include/linux/brcmphy.h @@ -4,7 +4,7 @@ #define PHY_BCM_FLAGS_INTF_XAUI 0x00000020 #define PHY_BRCM_WIRESPEED_ENABLE 0x00000100 #define PHY_BRCM_AUTO_PWRDWN_ENABLE 0x00000200 -#define PHY_BRCM_APD_CLK125_ENABLE 0x00000400 +#define PHY_BRCM_RX_REFCLK_UNUSED 0x00000400 #define PHY_BRCM_STD_IBND_DISABLE 0x00000800 #define PHY_BRCM_EXT_IBND_RX_ENABLE 0x00001000 #define PHY_BRCM_EXT_IBND_TX_ENABLE 0x00002000 -- cgit v1.2.3-70-g09d2 From c704dc23cac0e433796bfe0a1fe2f1a64da11ac7 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Mon, 2 Nov 2009 14:32:12 +0000 Subject: tg3 / broadcom: Add APD support for GPHYs This patch adds an RXC auto power-down feature to the code that supports the gphys. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/phy/broadcom.c | 51 ++++++++++++++++++++++++++++++++++++++-------- drivers/net/tg3.c | 4 +++- 2 files changed, 45 insertions(+), 10 deletions(-) (limited to 'drivers/net/phy/broadcom.c') diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index 74914335f72..7b10495fe8f 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c @@ -107,6 +107,11 @@ /* 00101: Spare Control Register 3 */ #define BCM54XX_SHD_SCR3 0x05 #define BCM54XX_SHD_SCR3_DEF_CLK125 0x0001 +#define BCM54XX_SHD_SCR3_DLLAPD_DIS 0x0002 + +/* 01010: Auto Power-Down */ +#define BCM54XX_SHD_APD 0x0a +#define BCM54XX_SHD_APD_EN 0x0020 #define BCM5482_SHD_LEDS1 0x0d /* 01101: LED Selector 1 */ /* LED3 / ~LINKSPD[2] selector */ @@ -321,9 +326,11 @@ error: static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev) { u32 val, orig; + bool clk125en = true; /* Abort if we are using an untested phy. */ - if (BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610 || + if (BRCM_PHY_MODEL(phydev) != PHY_ID_BCM57780 || + BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610 || BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610M) return; @@ -333,20 +340,45 @@ static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev) orig = val; - if (phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) { - if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 || - BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) && - BRCM_PHY_REV(phydev) >= 0x3) { - /* Here, bit 0 _disables_ CLK125 when set */ - val |= BCM54XX_SHD_SCR3_DEF_CLK125; - } else { + if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 || + BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) && + BRCM_PHY_REV(phydev) >= 0x3) { + /* + * Here, bit 0 _disables_ CLK125 when set. + * This bit is set by default. + */ + clk125en = false; + } else { + if (phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) { /* Here, bit 0 _enables_ CLK125 when set */ val &= ~BCM54XX_SHD_SCR3_DEF_CLK125; + clk125en = false; } } + if (clk125en == false || + (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE)) + val &= ~BCM54XX_SHD_SCR3_DLLAPD_DIS; + else + val |= BCM54XX_SHD_SCR3_DLLAPD_DIS; + if (orig != val) bcm54xx_shadow_write(phydev, BCM54XX_SHD_SCR3, val); + + val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_APD); + if (val < 0) + return; + + orig = val; + + if (clk125en == false || + (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE)) + val |= BCM54XX_SHD_APD_EN; + else + val &= ~BCM54XX_SHD_APD_EN; + + if (orig != val) + bcm54xx_shadow_write(phydev, BCM54XX_SHD_APD, val); } static int bcm54xx_config_init(struct phy_device *phydev) @@ -376,7 +408,8 @@ static int bcm54xx_config_init(struct phy_device *phydev) (phydev->dev_flags & PHY_BRCM_CLEAR_RGMII_MODE)) bcm54xx_shadow_write(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_AUTO_PWRDWN_ENABLE)) bcm54xx_adjust_rxrefclk(phydev); bcm54xx_phydsp_config(phydev); diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 369ddba9582..f74bf91e78c 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -1097,11 +1097,13 @@ static int tg3_mdio_init(struct tg3 *tp) switch (phydev->drv->phy_id & phydev->drv->phy_id_mask) { case TG3_PHY_ID_BCM57780: phydev->interface = PHY_INTERFACE_MODE_GMII; + phydev->dev_flags |= PHY_BRCM_AUTO_PWRDWN_ENABLE; break; case TG3_PHY_ID_BCM50610: case TG3_PHY_ID_BCM50610M: phydev->dev_flags |= PHY_BRCM_CLEAR_RGMII_MODE | - PHY_BRCM_RX_REFCLK_UNUSED; + PHY_BRCM_RX_REFCLK_UNUSED | + PHY_BRCM_AUTO_PWRDWN_ENABLE; if (tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE) phydev->dev_flags |= PHY_BRCM_STD_IBND_DISABLE; if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_RX_EN) -- cgit v1.2.3-70-g09d2 From 52fae0837153e86e4dabaf5df517a0b8b7a20bd7 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Mon, 2 Nov 2009 14:32:38 +0000 Subject: tg3 / broadcom: Optionally disable TXC if no link This patch adds code to disable the TXC and RXC reference clocks if link is not available. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/phy/broadcom.c | 5 +++++ drivers/net/tg3.c | 1 + include/linux/brcmphy.h | 1 + 3 files changed, 7 insertions(+) (limited to 'drivers/net/phy/broadcom.c') diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index 7b10495fe8f..f63c96a4ecb 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c @@ -108,6 +108,7 @@ #define BCM54XX_SHD_SCR3 0x05 #define BCM54XX_SHD_SCR3_DEF_CLK125 0x0001 #define BCM54XX_SHD_SCR3_DLLAPD_DIS 0x0002 +#define BCM54XX_SHD_SCR3_TRDDAPD 0x0004 /* 01010: Auto Power-Down */ #define BCM54XX_SHD_APD 0x0a @@ -362,6 +363,9 @@ static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev) else val |= BCM54XX_SHD_SCR3_DLLAPD_DIS; + if (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY) + val |= BCM54XX_SHD_SCR3_TRDDAPD; + if (orig != val) bcm54xx_shadow_write(phydev, BCM54XX_SHD_SCR3, val); @@ -409,6 +413,7 @@ static int bcm54xx_config_init(struct phy_device *phydev) bcm54xx_shadow_write(phydev, BCM54XX_SHD_RGMII_MODE, 0); if ((phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) || + (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY) || (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE)) bcm54xx_adjust_rxrefclk(phydev); diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index f74bf91e78c..50bb53de5eb 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -1103,6 +1103,7 @@ static int tg3_mdio_init(struct tg3 *tp) case TG3_PHY_ID_BCM50610M: phydev->dev_flags |= PHY_BRCM_CLEAR_RGMII_MODE | PHY_BRCM_RX_REFCLK_UNUSED | + PHY_BRCM_DIS_TXCRXC_NOENRGY | PHY_BRCM_AUTO_PWRDWN_ENABLE; if (tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE) phydev->dev_flags |= PHY_BRCM_STD_IBND_DISABLE; diff --git a/include/linux/brcmphy.h b/include/linux/brcmphy.h index 59432278ded..2b31b91f587 100644 --- a/include/linux/brcmphy.h +++ b/include/linux/brcmphy.h @@ -9,4 +9,5 @@ #define PHY_BRCM_EXT_IBND_RX_ENABLE 0x00001000 #define PHY_BRCM_EXT_IBND_TX_ENABLE 0x00002000 #define PHY_BRCM_CLEAR_RGMII_MODE 0x00004000 +#define PHY_BRCM_DIS_TXCRXC_NOENRGY 0x00008000 #define PHY_BCM_FLAGS_VALID 0x80000000 -- cgit v1.2.3-70-g09d2