aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/phy
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/phy')
-rw-r--r--drivers/net/phy/broadcom.c43
1 files changed, 43 insertions, 0 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;