aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Carlson <mcarlson@broadcom.com>2009-11-02 09:31:39 -0500
committerDavid S. Miller <davem@davemloft.net>2009-11-03 02:39:13 -0500
commit32e5a8d651c0dbb02bf82ca954206282e44c4b11 (patch)
tree7d8508afb30951c46e3e1edab56f9e664e833275
parentcdd4e09d692bd4f3457b3789279005e112b7696d (diff)
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 <mcarlson@broadcom.com> Reviewed-by: Michael Chan <mchan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/phy/broadcom.c43
-rw-r--r--drivers/net/tg3.c3
-rw-r--r--include/linux/brcmphy.h2
3 files changed, 46 insertions, 2 deletions
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
index bddf4a42ae68..74914335f72c 100644
--- a/drivers/net/phy/broadcom.c
+++ b/drivers/net/phy/broadcom.c
@@ -25,6 +25,9 @@
25#define BRCM_PHY_MODEL(phydev) \ 25#define BRCM_PHY_MODEL(phydev) \
26 ((phydev)->drv->phy_id & (phydev)->drv->phy_id_mask) 26 ((phydev)->drv->phy_id & (phydev)->drv->phy_id_mask)
27 27
28#define BRCM_PHY_REV(phydev) \
29 ((phydev)->drv->phy_id & ~((phydev)->drv->phy_id_mask))
30
28 31
29#define MII_BCM54XX_ECR 0x10 /* BCM54xx extended control register */ 32#define MII_BCM54XX_ECR 0x10 /* BCM54xx extended control register */
30#define MII_BCM54XX_ECR_IM 0x1000 /* Interrupt mask */ 33#define MII_BCM54XX_ECR_IM 0x1000 /* Interrupt mask */
@@ -95,11 +98,16 @@
95#define BCM_LED_SRC_OFF 0xe /* Tied high */ 98#define BCM_LED_SRC_OFF 0xe /* Tied high */
96#define BCM_LED_SRC_ON 0xf /* Tied low */ 99#define BCM_LED_SRC_ON 0xf /* Tied low */
97 100
101
98/* 102/*
99 * BCM5482: Shadow registers 103 * BCM5482: Shadow registers
100 * Shadow values go into bits [14:10] of register 0x1c to select a shadow 104 * Shadow values go into bits [14:10] of register 0x1c to select a shadow
101 * register to access. 105 * register to access.
102 */ 106 */
107/* 00101: Spare Control Register 3 */
108#define BCM54XX_SHD_SCR3 0x05
109#define BCM54XX_SHD_SCR3_DEF_CLK125 0x0001
110
103#define BCM5482_SHD_LEDS1 0x0d /* 01101: LED Selector 1 */ 111#define BCM5482_SHD_LEDS1 0x0d /* 01101: LED Selector 1 */
104 /* LED3 / ~LINKSPD[2] selector */ 112 /* LED3 / ~LINKSPD[2] selector */
105#define BCM5482_SHD_LEDS1_LED3(src) ((src & 0xf) << 4) 113#define BCM5482_SHD_LEDS1_LED3(src) ((src & 0xf) << 4)
@@ -112,6 +120,7 @@
112#define BCM5482_SHD_MODE 0x1f /* 11111: Mode Control Register */ 120#define BCM5482_SHD_MODE 0x1f /* 11111: Mode Control Register */
113#define BCM5482_SHD_MODE_1000BX 0x0001 /* Enable 1000BASE-X registers */ 121#define BCM5482_SHD_MODE_1000BX 0x0001 /* Enable 1000BASE-X registers */
114 122
123
115/* 124/*
116 * EXPANSION SHADOW ACCESS REGISTERS. (PHY REG 0x15, 0x16, and 0x17) 125 * EXPANSION SHADOW ACCESS REGISTERS. (PHY REG 0x15, 0x16, and 0x17)
117 */ 126 */
@@ -309,6 +318,37 @@ error:
309 return err ? err : err2; 318 return err ? err : err2;
310} 319}
311 320
321static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev)
322{
323 u32 val, orig;
324
325 /* Abort if we are using an untested phy. */
326 if (BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610 ||
327 BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610M)
328 return;
329
330 val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_SCR3);
331 if (val < 0)
332 return;
333
334 orig = val;
335
336 if (phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) {
337 if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
338 BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) &&
339 BRCM_PHY_REV(phydev) >= 0x3) {
340 /* Here, bit 0 _disables_ CLK125 when set */
341 val |= BCM54XX_SHD_SCR3_DEF_CLK125;
342 } else {
343 /* Here, bit 0 _enables_ CLK125 when set */
344 val &= ~BCM54XX_SHD_SCR3_DEF_CLK125;
345 }
346 }
347
348 if (orig != val)
349 bcm54xx_shadow_write(phydev, BCM54XX_SHD_SCR3, val);
350}
351
312static int bcm54xx_config_init(struct phy_device *phydev) 352static int bcm54xx_config_init(struct phy_device *phydev)
313{ 353{
314 int reg, err; 354 int reg, err;
@@ -336,6 +376,9 @@ static int bcm54xx_config_init(struct phy_device *phydev)
336 (phydev->dev_flags & PHY_BRCM_CLEAR_RGMII_MODE)) 376 (phydev->dev_flags & PHY_BRCM_CLEAR_RGMII_MODE))
337 bcm54xx_shadow_write(phydev, BCM54XX_SHD_RGMII_MODE, 0); 377 bcm54xx_shadow_write(phydev, BCM54XX_SHD_RGMII_MODE, 0);
338 378
379 if (phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED)
380 bcm54xx_adjust_rxrefclk(phydev);
381
339 bcm54xx_phydsp_config(phydev); 382 bcm54xx_phydsp_config(phydev);
340 383
341 return 0; 384 return 0;
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 592b5bf09e40..369ddba95821 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -1100,7 +1100,8 @@ static int tg3_mdio_init(struct tg3 *tp)
1100 break; 1100 break;
1101 case TG3_PHY_ID_BCM50610: 1101 case TG3_PHY_ID_BCM50610:
1102 case TG3_PHY_ID_BCM50610M: 1102 case TG3_PHY_ID_BCM50610M:
1103 phydev->dev_flags |= PHY_BRCM_CLEAR_RGMII_MODE; 1103 phydev->dev_flags |= PHY_BRCM_CLEAR_RGMII_MODE |
1104 PHY_BRCM_RX_REFCLK_UNUSED;
1104 if (tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE) 1105 if (tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE)
1105 phydev->dev_flags |= PHY_BRCM_STD_IBND_DISABLE; 1106 phydev->dev_flags |= PHY_BRCM_STD_IBND_DISABLE;
1106 if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_RX_EN) 1107 if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_RX_EN)
diff --git a/include/linux/brcmphy.h b/include/linux/brcmphy.h
index 6e7ffcee9c80..59432278ded2 100644
--- a/include/linux/brcmphy.h
+++ b/include/linux/brcmphy.h
@@ -4,7 +4,7 @@
4#define PHY_BCM_FLAGS_INTF_XAUI 0x00000020 4#define PHY_BCM_FLAGS_INTF_XAUI 0x00000020
5#define PHY_BRCM_WIRESPEED_ENABLE 0x00000100 5#define PHY_BRCM_WIRESPEED_ENABLE 0x00000100
6#define PHY_BRCM_AUTO_PWRDWN_ENABLE 0x00000200 6#define PHY_BRCM_AUTO_PWRDWN_ENABLE 0x00000200
7#define PHY_BRCM_APD_CLK125_ENABLE 0x00000400 7#define PHY_BRCM_RX_REFCLK_UNUSED 0x00000400
8#define PHY_BRCM_STD_IBND_DISABLE 0x00000800 8#define PHY_BRCM_STD_IBND_DISABLE 0x00000800
9#define PHY_BRCM_EXT_IBND_RX_ENABLE 0x00001000 9#define PHY_BRCM_EXT_IBND_RX_ENABLE 0x00001000
10#define PHY_BRCM_EXT_IBND_TX_ENABLE 0x00002000 10#define PHY_BRCM_EXT_IBND_TX_ENABLE 0x00002000