1 /* 2 * drivers/net/phy/broadcom.c 3 * 4 * Broadcom BCM5411, BCM5421 and BCM5461 Gigabit Ethernet 5 * transceivers. 6 * 7 * Copyright (c) 2006 Maciej W. Rozycki 8 * 9 * Inspired by code written by Amy Fong. 10 * 11 * This program is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU General Public License 13 * as published by the Free Software Foundation; either version 14 * 2 of the License, or (at your option) any later version. 15 */ 16 17 #include <linux/module.h> 18 #include <linux/phy.h> 19 #include <linux/brcmphy.h> 20 21 22 #define BRCM_PHY_MODEL(phydev) \ 23 ((phydev)->drv->phy_id & (phydev)->drv->phy_id_mask) 24 25 #define BRCM_PHY_REV(phydev) \ 26 ((phydev)->drv->phy_id & ~((phydev)->drv->phy_id_mask)) 27 28 29 #define MII_BCM54XX_ECR 0x10 /* BCM54xx extended control register */ 30 #define MII_BCM54XX_ECR_IM 0x1000 /* Interrupt mask */ 31 #define MII_BCM54XX_ECR_IF 0x0800 /* Interrupt force */ 32 33 #define MII_BCM54XX_ESR 0x11 /* BCM54xx extended status register */ 34 #define MII_BCM54XX_ESR_IS 0x1000 /* Interrupt status */ 35 36 #define MII_BCM54XX_EXP_DATA 0x15 /* Expansion register data */ 37 #define MII_BCM54XX_EXP_SEL 0x17 /* Expansion register select */ 38 #define MII_BCM54XX_EXP_SEL_SSD 0x0e00 /* Secondary SerDes select */ 39 #define MII_BCM54XX_EXP_SEL_ER 0x0f00 /* Expansion register select */ 40 41 #define MII_BCM54XX_AUX_CTL 0x18 /* Auxiliary control register */ 42 #define MII_BCM54XX_ISR 0x1a /* BCM54xx interrupt status register */ 43 #define MII_BCM54XX_IMR 0x1b /* BCM54xx interrupt mask register */ 44 #define MII_BCM54XX_INT_CRCERR 0x0001 /* CRC error */ 45 #define MII_BCM54XX_INT_LINK 0x0002 /* Link status changed */ 46 #define MII_BCM54XX_INT_SPEED 0x0004 /* Link speed change */ 47 #define MII_BCM54XX_INT_DUPLEX 0x0008 /* Duplex mode changed */ 48 #define MII_BCM54XX_INT_LRS 0x0010 /* Local receiver status changed */ 49 #define MII_BCM54XX_INT_RRS 0x0020 /* Remote receiver status changed */ 50 #define MII_BCM54XX_INT_SSERR 0x0040 /* Scrambler synchronization error */ 51 #define MII_BCM54XX_INT_UHCD 0x0080 /* Unsupported HCD negotiated */ 52 #define MII_BCM54XX_INT_NHCD 0x0100 /* No HCD */ 53 #define MII_BCM54XX_INT_NHCDL 0x0200 /* No HCD link */ 54 #define MII_BCM54XX_INT_ANPR 0x0400 /* Auto-negotiation page received */ 55 #define MII_BCM54XX_INT_LC 0x0800 /* All counters below 128 */ 56 #define MII_BCM54XX_INT_HC 0x1000 /* Counter above 32768 */ 57 #define MII_BCM54XX_INT_MDIX 0x2000 /* MDIX status change */ 58 #define MII_BCM54XX_INT_PSERR 0x4000 /* Pair swap error */ 59 60 #define MII_BCM54XX_SHD 0x1c /* 0x1c shadow registers */ 61 #define MII_BCM54XX_SHD_WRITE 0x8000 62 #define MII_BCM54XX_SHD_VAL(x) ((x & 0x1f) << 10) 63 #define MII_BCM54XX_SHD_DATA(x) ((x & 0x3ff) << 0) 64 65 /* 66 * AUXILIARY CONTROL SHADOW ACCESS REGISTERS. (PHY REG 0x18) 67 */ 68 #define MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL 0x0000 69 #define MII_BCM54XX_AUXCTL_ACTL_TX_6DB 0x0400 70 #define MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA 0x0800 71 72 #define MII_BCM54XX_AUXCTL_MISC_WREN 0x8000 73 #define MII_BCM54XX_AUXCTL_MISC_FORCE_AMDIX 0x0200 74 #define MII_BCM54XX_AUXCTL_MISC_RDSEL_MISC 0x7000 75 #define MII_BCM54XX_AUXCTL_SHDWSEL_MISC 0x0007 76 77 #define MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL 0x0000 78 79 80 /* 81 * Broadcom LED source encodings. These are used in BCM5461, BCM5481, 82 * BCM5482, and possibly some others. 83 */ 84 #define BCM_LED_SRC_LINKSPD1 0x0 85 #define BCM_LED_SRC_LINKSPD2 0x1 86 #define BCM_LED_SRC_XMITLED 0x2 87 #define BCM_LED_SRC_ACTIVITYLED 0x3 88 #define BCM_LED_SRC_FDXLED 0x4 89 #define BCM_LED_SRC_SLAVE 0x5 90 #define BCM_LED_SRC_INTR 0x6 91 #define BCM_LED_SRC_QUALITY 0x7 92 #define BCM_LED_SRC_RCVLED 0x8 93 #define BCM_LED_SRC_MULTICOLOR1 0xa 94 #define BCM_LED_SRC_OPENSHORT 0xb 95 #define BCM_LED_SRC_OFF 0xe /* Tied high */ 96 #define BCM_LED_SRC_ON 0xf /* Tied low */ 97 98 99 /* 100 * BCM5482: Shadow registers 101 * Shadow values go into bits [14:10] of register 0x1c to select a shadow 102 * register to access. 103 */ 104 /* 00101: Spare Control Register 3 */ 105 #define BCM54XX_SHD_SCR3 0x05 106 #define BCM54XX_SHD_SCR3_DEF_CLK125 0x0001 107 #define BCM54XX_SHD_SCR3_DLLAPD_DIS 0x0002 108 #define BCM54XX_SHD_SCR3_TRDDAPD 0x0004 109 110 /* 01010: Auto Power-Down */ 111 #define BCM54XX_SHD_APD 0x0a 112 #define BCM54XX_SHD_APD_EN 0x0020 113 114 #define BCM5482_SHD_LEDS1 0x0d /* 01101: LED Selector 1 */ 115 /* LED3 / ~LINKSPD[2] selector */ 116 #define BCM5482_SHD_LEDS1_LED3(src) ((src & 0xf) << 4) 117 /* LED1 / ~LINKSPD[1] selector */ 118 #define BCM5482_SHD_LEDS1_LED1(src) ((src & 0xf) << 0) 119 #define BCM54XX_SHD_RGMII_MODE 0x0b /* 01011: RGMII Mode Selector */ 120 #define BCM5482_SHD_SSD 0x14 /* 10100: Secondary SerDes control */ 121 #define BCM5482_SHD_SSD_LEDM 0x0008 /* SSD LED Mode enable */ 122 #define BCM5482_SHD_SSD_EN 0x0001 /* SSD enable */ 123 #define BCM5482_SHD_MODE 0x1f /* 11111: Mode Control Register */ 124 #define BCM5482_SHD_MODE_1000BX 0x0001 /* Enable 1000BASE-X registers */ 125 126 127 /* 128 * EXPANSION SHADOW ACCESS REGISTERS. (PHY REG 0x15, 0x16, and 0x17) 129 */ 130 #define MII_BCM54XX_EXP_AADJ1CH0 0x001f 131 #define MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN 0x0200 132 #define MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF 0x0100 133 #define MII_BCM54XX_EXP_AADJ1CH3 0x601f 134 #define MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ 0x0002 135 #define MII_BCM54XX_EXP_EXP08 0x0F08 136 #define MII_BCM54XX_EXP_EXP08_RJCT_2MHZ 0x0001 137 #define MII_BCM54XX_EXP_EXP08_EARLY_DAC_WAKE 0x0200 138 #define MII_BCM54XX_EXP_EXP75 0x0f75 139 #define MII_BCM54XX_EXP_EXP75_VDACCTRL 0x003c 140 #define MII_BCM54XX_EXP_EXP75_CM_OSC 0x0001 141 #define MII_BCM54XX_EXP_EXP96 0x0f96 142 #define MII_BCM54XX_EXP_EXP96_MYST 0x0010 143 #define MII_BCM54XX_EXP_EXP97 0x0f97 144 #define MII_BCM54XX_EXP_EXP97_MYST 0x0c0c 145 146 /* 147 * BCM5482: Secondary SerDes registers 148 */ 149 #define BCM5482_SSD_1000BX_CTL 0x00 /* 1000BASE-X Control */ 150 #define BCM5482_SSD_1000BX_CTL_PWRDOWN 0x0800 /* Power-down SSD */ 151 #define BCM5482_SSD_SGMII_SLAVE 0x15 /* SGMII Slave Register */ 152 #define BCM5482_SSD_SGMII_SLAVE_EN 0x0002 /* Slave mode enable */ 153 #define BCM5482_SSD_SGMII_SLAVE_AD 0x0001 /* Slave auto-detection */ 154 155 156 /*****************************************************************************/ 157 /* Fast Ethernet Transceiver definitions. */ 158 /*****************************************************************************/ 159 160 #define MII_BRCM_FET_INTREG 0x1a /* Interrupt register */ 161 #define MII_BRCM_FET_IR_MASK 0x0100 /* Mask all interrupts */ 162 #define MII_BRCM_FET_IR_LINK_EN 0x0200 /* Link status change enable */ 163 #define MII_BRCM_FET_IR_SPEED_EN 0x0400 /* Link speed change enable */ 164 #define MII_BRCM_FET_IR_DUPLEX_EN 0x0800 /* Duplex mode change enable */ 165 #define MII_BRCM_FET_IR_ENABLE 0x4000 /* Interrupt enable */ 166 167 #define MII_BRCM_FET_BRCMTEST 0x1f /* Brcm test register */ 168 #define MII_BRCM_FET_BT_SRE 0x0080 /* Shadow register enable */ 169 170 171 /*** Shadow register definitions ***/ 172 173 #define MII_BRCM_FET_SHDW_MISCCTRL 0x10 /* Shadow misc ctrl */ 174 #define MII_BRCM_FET_SHDW_MC_FAME 0x4000 /* Force Auto MDIX enable */ 175 176 #define MII_BRCM_FET_SHDW_AUXMODE4 0x1a /* Auxiliary mode 4 */ 177 #define MII_BRCM_FET_SHDW_AM4_LED_MASK 0x0003 178 #define MII_BRCM_FET_SHDW_AM4_LED_MODE1 0x0001 179 180 #define MII_BRCM_FET_SHDW_AUXSTAT2 0x1b /* Auxiliary status 2 */ 181 #define MII_BRCM_FET_SHDW_AS2_APDE 0x0020 /* Auto power down enable */ 182 183 184 MODULE_DESCRIPTION("Broadcom PHY driver"); 185 MODULE_AUTHOR("Maciej W. Rozycki"); 186 MODULE_LICENSE("GPL"); 187 188 /* 189 * Indirect register access functions for the 1000BASE-T/100BASE-TX/10BASE-T 190 * 0x1c shadow registers. 191 */ 192 static int bcm54xx_shadow_read(struct phy_device *phydev, u16 shadow) 193 { 194 phy_write(phydev, MII_BCM54XX_SHD, MII_BCM54XX_SHD_VAL(shadow)); 195 return MII_BCM54XX_SHD_DATA(phy_read(phydev, MII_BCM54XX_SHD)); 196 } 197 198 static int bcm54xx_shadow_write(struct phy_device *phydev, u16 shadow, u16 val) 199 { 200 return phy_write(phydev, MII_BCM54XX_SHD, 201 MII_BCM54XX_SHD_WRITE | 202 MII_BCM54XX_SHD_VAL(shadow) | 203 MII_BCM54XX_SHD_DATA(val)); 204 } 205 206 /* Indirect register access functions for the Expansion Registers */ 207 static int bcm54xx_exp_read(struct phy_device *phydev, u16 regnum) 208 { 209 int val; 210 211 val = phy_write(phydev, MII_BCM54XX_EXP_SEL, regnum); 212 if (val < 0) 213 return val; 214 215 val = phy_read(phydev, MII_BCM54XX_EXP_DATA); 216 217 /* Restore default value. It's O.K. if this write fails. */ 218 phy_write(phydev, MII_BCM54XX_EXP_SEL, 0); 219 220 return val; 221 } 222 223 static int bcm54xx_exp_write(struct phy_device *phydev, u16 regnum, u16 val) 224 { 225 int ret; 226 227 ret = phy_write(phydev, MII_BCM54XX_EXP_SEL, regnum); 228 if (ret < 0) 229 return ret; 230 231 ret = phy_write(phydev, MII_BCM54XX_EXP_DATA, val); 232 233 /* Restore default value. It's O.K. if this write fails. */ 234 phy_write(phydev, MII_BCM54XX_EXP_SEL, 0); 235 236 return ret; 237 } 238 239 static int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val) 240 { 241 return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val); 242 } 243 244 /* Needs SMDSP clock enabled via bcm54xx_phydsp_config() */ 245 static int bcm50610_a0_workaround(struct phy_device *phydev) 246 { 247 int err; 248 249 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH0, 250 MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN | 251 MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF); 252 if (err < 0) 253 return err; 254 255 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH3, 256 MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ); 257 if (err < 0) 258 return err; 259 260 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP75, 261 MII_BCM54XX_EXP_EXP75_VDACCTRL); 262 if (err < 0) 263 return err; 264 265 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP96, 266 MII_BCM54XX_EXP_EXP96_MYST); 267 if (err < 0) 268 return err; 269 270 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP97, 271 MII_BCM54XX_EXP_EXP97_MYST); 272 273 return err; 274 } 275 276 static int bcm54xx_phydsp_config(struct phy_device *phydev) 277 { 278 int err, err2; 279 280 /* Enable the SMDSP clock */ 281 err = bcm54xx_auxctl_write(phydev, 282 MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL, 283 MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA | 284 MII_BCM54XX_AUXCTL_ACTL_TX_6DB); 285 if (err < 0) 286 return err; 287 288 if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 || 289 BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) { 290 /* Clear bit 9 to fix a phy interop issue. */ 291 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP08, 292 MII_BCM54XX_EXP_EXP08_RJCT_2MHZ); 293 if (err < 0) 294 goto error; 295 296 if (phydev->drv->phy_id == PHY_ID_BCM50610) { 297 err = bcm50610_a0_workaround(phydev); 298 if (err < 0) 299 goto error; 300 } 301 } 302 303 if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM57780) { 304 int val; 305 306 val = bcm54xx_exp_read(phydev, MII_BCM54XX_EXP_EXP75); 307 if (val < 0) 308 goto error; 309 310 val |= MII_BCM54XX_EXP_EXP75_CM_OSC; 311 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP75, val); 312 } 313 314 error: 315 /* Disable the SMDSP clock */ 316 err2 = bcm54xx_auxctl_write(phydev, 317 MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL, 318 MII_BCM54XX_AUXCTL_ACTL_TX_6DB); 319 320 /* Return the first error reported. */ 321 return err ? err : err2; 322 } 323 324 static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev) 325 { 326 u32 orig; 327 int val; 328 bool clk125en = true; 329 330 /* Abort if we are using an untested phy. */ 331 if (BRCM_PHY_MODEL(phydev) != PHY_ID_BCM57780 && 332 BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610 && 333 BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610M) 334 return; 335 336 val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_SCR3); 337 if (val < 0) 338 return; 339 340 orig = val; 341 342 if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 || 343 BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) && 344 BRCM_PHY_REV(phydev) >= 0x3) { 345 /* 346 * Here, bit 0 _disables_ CLK125 when set. 347 * This bit is set by default. 348 */ 349 clk125en = false; 350 } else { 351 if (phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) { 352 /* Here, bit 0 _enables_ CLK125 when set */ 353 val &= ~BCM54XX_SHD_SCR3_DEF_CLK125; 354 clk125en = false; 355 } 356 } 357 358 if (!clk125en || (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE)) 359 val &= ~BCM54XX_SHD_SCR3_DLLAPD_DIS; 360 else 361 val |= BCM54XX_SHD_SCR3_DLLAPD_DIS; 362 363 if (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY) 364 val |= BCM54XX_SHD_SCR3_TRDDAPD; 365 366 if (orig != val) 367 bcm54xx_shadow_write(phydev, BCM54XX_SHD_SCR3, val); 368 369 val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_APD); 370 if (val < 0) 371 return; 372 373 orig = val; 374 375 if (!clk125en || (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE)) 376 val |= BCM54XX_SHD_APD_EN; 377 else 378 val &= ~BCM54XX_SHD_APD_EN; 379 380 if (orig != val) 381 bcm54xx_shadow_write(phydev, BCM54XX_SHD_APD, val); 382 } 383 384 static int bcm54xx_config_init(struct phy_device *phydev) 385 { 386 int reg, err; 387 388 reg = phy_read(phydev, MII_BCM54XX_ECR); 389 if (reg < 0) 390 return reg; 391 392 /* Mask interrupts globally. */ 393 reg |= MII_BCM54XX_ECR_IM; 394 err = phy_write(phydev, MII_BCM54XX_ECR, reg); 395 if (err < 0) 396 return err; 397 398 /* Unmask events we are interested in. */ 399 reg = ~(MII_BCM54XX_INT_DUPLEX | 400 MII_BCM54XX_INT_SPEED | 401 MII_BCM54XX_INT_LINK); 402 err = phy_write(phydev, MII_BCM54XX_IMR, reg); 403 if (err < 0) 404 return err; 405 406 if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 || 407 BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) && 408 (phydev->dev_flags & PHY_BRCM_CLEAR_RGMII_MODE)) 409 bcm54xx_shadow_write(phydev, BCM54XX_SHD_RGMII_MODE, 0); 410 411 if ((phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) || 412 (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY) || 413 (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE)) 414 bcm54xx_adjust_rxrefclk(phydev); 415 416 bcm54xx_phydsp_config(phydev); 417 418 return 0; 419 } 420 421 static int bcm5482_config_init(struct phy_device *phydev) 422 { 423 int err, reg; 424 425 err = bcm54xx_config_init(phydev); 426 427 if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) { 428 /* 429 * Enable secondary SerDes and its use as an LED source 430 */ 431 reg = bcm54xx_shadow_read(phydev, BCM5482_SHD_SSD); 432 bcm54xx_shadow_write(phydev, BCM5482_SHD_SSD, 433 reg | 434 BCM5482_SHD_SSD_LEDM | 435 BCM5482_SHD_SSD_EN); 436 437 /* 438 * Enable SGMII slave mode and auto-detection 439 */ 440 reg = BCM5482_SSD_SGMII_SLAVE | MII_BCM54XX_EXP_SEL_SSD; 441 err = bcm54xx_exp_read(phydev, reg); 442 if (err < 0) 443 return err; 444 err = bcm54xx_exp_write(phydev, reg, err | 445 BCM5482_SSD_SGMII_SLAVE_EN | 446 BCM5482_SSD_SGMII_SLAVE_AD); 447 if (err < 0) 448 return err; 449 450 /* 451 * Disable secondary SerDes powerdown 452 */ 453 reg = BCM5482_SSD_1000BX_CTL | MII_BCM54XX_EXP_SEL_SSD; 454 err = bcm54xx_exp_read(phydev, reg); 455 if (err < 0) 456 return err; 457 err = bcm54xx_exp_write(phydev, reg, 458 err & ~BCM5482_SSD_1000BX_CTL_PWRDOWN); 459 if (err < 0) 460 return err; 461 462 /* 463 * Select 1000BASE-X register set (primary SerDes) 464 */ 465 reg = bcm54xx_shadow_read(phydev, BCM5482_SHD_MODE); 466 bcm54xx_shadow_write(phydev, BCM5482_SHD_MODE, 467 reg | BCM5482_SHD_MODE_1000BX); 468 469 /* 470 * LED1=ACTIVITYLED, LED3=LINKSPD[2] 471 * (Use LED1 as secondary SerDes ACTIVITY LED) 472 */ 473 bcm54xx_shadow_write(phydev, BCM5482_SHD_LEDS1, 474 BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_ACTIVITYLED) | 475 BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_LINKSPD2)); 476 477 /* 478 * Auto-negotiation doesn't seem to work quite right 479 * in this mode, so we disable it and force it to the 480 * right speed/duplex setting. Only 'link status' 481 * is important. 482 */ 483 phydev->autoneg = AUTONEG_DISABLE; 484 phydev->speed = SPEED_1000; 485 phydev->duplex = DUPLEX_FULL; 486 } 487 488 return err; 489 } 490 491 static int bcm5482_read_status(struct phy_device *phydev) 492 { 493 int err; 494 495 err = genphy_read_status(phydev); 496 497 if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) { 498 /* 499 * Only link status matters for 1000Base-X mode, so force 500 * 1000 Mbit/s full-duplex status 501 */ 502 if (phydev->link) { 503 phydev->speed = SPEED_1000; 504 phydev->duplex = DUPLEX_FULL; 505 } 506 } 507 508 return err; 509 } 510 511 static int bcm54xx_ack_interrupt(struct phy_device *phydev) 512 { 513 int reg; 514 515 /* Clear pending interrupts. */ 516 reg = phy_read(phydev, MII_BCM54XX_ISR); 517 if (reg < 0) 518 return reg; 519 520 return 0; 521 } 522 523 static int bcm54xx_config_intr(struct phy_device *phydev) 524 { 525 int reg, err; 526 527 reg = phy_read(phydev, MII_BCM54XX_ECR); 528 if (reg < 0) 529 return reg; 530 531 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 532 reg &= ~MII_BCM54XX_ECR_IM; 533 else 534 reg |= MII_BCM54XX_ECR_IM; 535 536 err = phy_write(phydev, MII_BCM54XX_ECR, reg); 537 return err; 538 } 539 540 static int bcm5481_config_aneg(struct phy_device *phydev) 541 { 542 int ret; 543 544 /* Aneg firsly. */ 545 ret = genphy_config_aneg(phydev); 546 547 /* Then we can set up the delay. */ 548 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { 549 u16 reg; 550 551 /* 552 * There is no BCM5481 specification available, so down 553 * here is everything we know about "register 0x18". This 554 * at least helps BCM5481 to successfully receive packets 555 * on MPC8360E-RDK board. Peter Barada <peterb@logicpd.com> 556 * says: "This sets delay between the RXD and RXC signals 557 * instead of using trace lengths to achieve timing". 558 */ 559 560 /* Set RDX clk delay. */ 561 reg = 0x7 | (0x7 << 12); 562 phy_write(phydev, 0x18, reg); 563 564 reg = phy_read(phydev, 0x18); 565 /* Set RDX-RXC skew. */ 566 reg |= (1 << 8); 567 /* Write bits 14:0. */ 568 reg |= (1 << 15); 569 phy_write(phydev, 0x18, reg); 570 } 571 572 return ret; 573 } 574 575 static int brcm_phy_setbits(struct phy_device *phydev, int reg, int set) 576 { 577 int val; 578 579 val = phy_read(phydev, reg); 580 if (val < 0) 581 return val; 582 583 return phy_write(phydev, reg, val | set); 584 } 585 586 static int brcm_fet_config_init(struct phy_device *phydev) 587 { 588 int reg, err, err2, brcmtest; 589 590 /* Reset the PHY to bring it to a known state. */ 591 err = phy_write(phydev, MII_BMCR, BMCR_RESET); 592 if (err < 0) 593 return err; 594 595 reg = phy_read(phydev, MII_BRCM_FET_INTREG); 596 if (reg < 0) 597 return reg; 598 599 /* Unmask events we are interested in and mask interrupts globally. */ 600 reg = MII_BRCM_FET_IR_DUPLEX_EN | 601 MII_BRCM_FET_IR_SPEED_EN | 602 MII_BRCM_FET_IR_LINK_EN | 603 MII_BRCM_FET_IR_ENABLE | 604 MII_BRCM_FET_IR_MASK; 605 606 err = phy_write(phydev, MII_BRCM_FET_INTREG, reg); 607 if (err < 0) 608 return err; 609 610 /* Enable shadow register access */ 611 brcmtest = phy_read(phydev, MII_BRCM_FET_BRCMTEST); 612 if (brcmtest < 0) 613 return brcmtest; 614 615 reg = brcmtest | MII_BRCM_FET_BT_SRE; 616 617 err = phy_write(phydev, MII_BRCM_FET_BRCMTEST, reg); 618 if (err < 0) 619 return err; 620 621 /* Set the LED mode */ 622 reg = phy_read(phydev, MII_BRCM_FET_SHDW_AUXMODE4); 623 if (reg < 0) { 624 err = reg; 625 goto done; 626 } 627 628 reg &= ~MII_BRCM_FET_SHDW_AM4_LED_MASK; 629 reg |= MII_BRCM_FET_SHDW_AM4_LED_MODE1; 630 631 err = phy_write(phydev, MII_BRCM_FET_SHDW_AUXMODE4, reg); 632 if (err < 0) 633 goto done; 634 635 /* Enable auto MDIX */ 636 err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_MISCCTRL, 637 MII_BRCM_FET_SHDW_MC_FAME); 638 if (err < 0) 639 goto done; 640 641 if (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE) { 642 /* Enable auto power down */ 643 err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2, 644 MII_BRCM_FET_SHDW_AS2_APDE); 645 } 646 647 done: 648 /* Disable shadow register access */ 649 err2 = phy_write(phydev, MII_BRCM_FET_BRCMTEST, brcmtest); 650 if (!err) 651 err = err2; 652 653 return err; 654 } 655 656 static int brcm_fet_ack_interrupt(struct phy_device *phydev) 657 { 658 int reg; 659 660 /* Clear pending interrupts. */ 661 reg = phy_read(phydev, MII_BRCM_FET_INTREG); 662 if (reg < 0) 663 return reg; 664 665 return 0; 666 } 667 668 static int brcm_fet_config_intr(struct phy_device *phydev) 669 { 670 int reg, err; 671 672 reg = phy_read(phydev, MII_BRCM_FET_INTREG); 673 if (reg < 0) 674 return reg; 675 676 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 677 reg &= ~MII_BRCM_FET_IR_MASK; 678 else 679 reg |= MII_BRCM_FET_IR_MASK; 680 681 err = phy_write(phydev, MII_BRCM_FET_INTREG, reg); 682 return err; 683 } 684 685 static struct phy_driver bcm5411_driver = { 686 .phy_id = PHY_ID_BCM5411, 687 .phy_id_mask = 0xfffffff0, 688 .name = "Broadcom BCM5411", 689 .features = PHY_GBIT_FEATURES | 690 SUPPORTED_Pause | SUPPORTED_Asym_Pause, 691 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 692 .config_init = bcm54xx_config_init, 693 .config_aneg = genphy_config_aneg, 694 .read_status = genphy_read_status, 695 .ack_interrupt = bcm54xx_ack_interrupt, 696 .config_intr = bcm54xx_config_intr, 697 .driver = { .owner = THIS_MODULE }, 698 }; 699 700 static struct phy_driver bcm5421_driver = { 701 .phy_id = PHY_ID_BCM5421, 702 .phy_id_mask = 0xfffffff0, 703 .name = "Broadcom BCM5421", 704 .features = PHY_GBIT_FEATURES | 705 SUPPORTED_Pause | SUPPORTED_Asym_Pause, 706 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 707 .config_init = bcm54xx_config_init, 708 .config_aneg = genphy_config_aneg, 709 .read_status = genphy_read_status, 710 .ack_interrupt = bcm54xx_ack_interrupt, 711 .config_intr = bcm54xx_config_intr, 712 .driver = { .owner = THIS_MODULE }, 713 }; 714 715 static struct phy_driver bcm5461_driver = { 716 .phy_id = PHY_ID_BCM5461, 717 .phy_id_mask = 0xfffffff0, 718 .name = "Broadcom BCM5461", 719 .features = PHY_GBIT_FEATURES | 720 SUPPORTED_Pause | SUPPORTED_Asym_Pause, 721 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 722 .config_init = bcm54xx_config_init, 723 .config_aneg = genphy_config_aneg, 724 .read_status = genphy_read_status, 725 .ack_interrupt = bcm54xx_ack_interrupt, 726 .config_intr = bcm54xx_config_intr, 727 .driver = { .owner = THIS_MODULE }, 728 }; 729 730 static struct phy_driver bcm5464_driver = { 731 .phy_id = PHY_ID_BCM5464, 732 .phy_id_mask = 0xfffffff0, 733 .name = "Broadcom BCM5464", 734 .features = PHY_GBIT_FEATURES | 735 SUPPORTED_Pause | SUPPORTED_Asym_Pause, 736 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 737 .config_init = bcm54xx_config_init, 738 .config_aneg = genphy_config_aneg, 739 .read_status = genphy_read_status, 740 .ack_interrupt = bcm54xx_ack_interrupt, 741 .config_intr = bcm54xx_config_intr, 742 .driver = { .owner = THIS_MODULE }, 743 }; 744 745 static struct phy_driver bcm5481_driver = { 746 .phy_id = PHY_ID_BCM5481, 747 .phy_id_mask = 0xfffffff0, 748 .name = "Broadcom BCM5481", 749 .features = PHY_GBIT_FEATURES | 750 SUPPORTED_Pause | SUPPORTED_Asym_Pause, 751 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 752 .config_init = bcm54xx_config_init, 753 .config_aneg = bcm5481_config_aneg, 754 .read_status = genphy_read_status, 755 .ack_interrupt = bcm54xx_ack_interrupt, 756 .config_intr = bcm54xx_config_intr, 757 .driver = { .owner = THIS_MODULE }, 758 }; 759 760 static struct phy_driver bcm5482_driver = { 761 .phy_id = PHY_ID_BCM5482, 762 .phy_id_mask = 0xfffffff0, 763 .name = "Broadcom BCM5482", 764 .features = PHY_GBIT_FEATURES | 765 SUPPORTED_Pause | SUPPORTED_Asym_Pause, 766 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 767 .config_init = bcm5482_config_init, 768 .config_aneg = genphy_config_aneg, 769 .read_status = bcm5482_read_status, 770 .ack_interrupt = bcm54xx_ack_interrupt, 771 .config_intr = bcm54xx_config_intr, 772 .driver = { .owner = THIS_MODULE }, 773 }; 774 775 static struct phy_driver bcm50610_driver = { 776 .phy_id = PHY_ID_BCM50610, 777 .phy_id_mask = 0xfffffff0, 778 .name = "Broadcom BCM50610", 779 .features = PHY_GBIT_FEATURES | 780 SUPPORTED_Pause | SUPPORTED_Asym_Pause, 781 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 782 .config_init = bcm54xx_config_init, 783 .config_aneg = genphy_config_aneg, 784 .read_status = genphy_read_status, 785 .ack_interrupt = bcm54xx_ack_interrupt, 786 .config_intr = bcm54xx_config_intr, 787 .driver = { .owner = THIS_MODULE }, 788 }; 789 790 static struct phy_driver bcm50610m_driver = { 791 .phy_id = PHY_ID_BCM50610M, 792 .phy_id_mask = 0xfffffff0, 793 .name = "Broadcom BCM50610M", 794 .features = PHY_GBIT_FEATURES | 795 SUPPORTED_Pause | SUPPORTED_Asym_Pause, 796 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 797 .config_init = bcm54xx_config_init, 798 .config_aneg = genphy_config_aneg, 799 .read_status = genphy_read_status, 800 .ack_interrupt = bcm54xx_ack_interrupt, 801 .config_intr = bcm54xx_config_intr, 802 .driver = { .owner = THIS_MODULE }, 803 }; 804 805 static struct phy_driver bcm57780_driver = { 806 .phy_id = PHY_ID_BCM57780, 807 .phy_id_mask = 0xfffffff0, 808 .name = "Broadcom BCM57780", 809 .features = PHY_GBIT_FEATURES | 810 SUPPORTED_Pause | SUPPORTED_Asym_Pause, 811 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 812 .config_init = bcm54xx_config_init, 813 .config_aneg = genphy_config_aneg, 814 .read_status = genphy_read_status, 815 .ack_interrupt = bcm54xx_ack_interrupt, 816 .config_intr = bcm54xx_config_intr, 817 .driver = { .owner = THIS_MODULE }, 818 }; 819 820 static struct phy_driver bcmac131_driver = { 821 .phy_id = PHY_ID_BCMAC131, 822 .phy_id_mask = 0xfffffff0, 823 .name = "Broadcom BCMAC131", 824 .features = PHY_BASIC_FEATURES | 825 SUPPORTED_Pause | SUPPORTED_Asym_Pause, 826 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 827 .config_init = brcm_fet_config_init, 828 .config_aneg = genphy_config_aneg, 829 .read_status = genphy_read_status, 830 .ack_interrupt = brcm_fet_ack_interrupt, 831 .config_intr = brcm_fet_config_intr, 832 .driver = { .owner = THIS_MODULE }, 833 }; 834 835 static struct phy_driver bcm5241_driver = { 836 .phy_id = PHY_ID_BCM5241, 837 .phy_id_mask = 0xfffffff0, 838 .name = "Broadcom BCM5241", 839 .features = PHY_BASIC_FEATURES | 840 SUPPORTED_Pause | SUPPORTED_Asym_Pause, 841 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 842 .config_init = brcm_fet_config_init, 843 .config_aneg = genphy_config_aneg, 844 .read_status = genphy_read_status, 845 .ack_interrupt = brcm_fet_ack_interrupt, 846 .config_intr = brcm_fet_config_intr, 847 .driver = { .owner = THIS_MODULE }, 848 }; 849 850 static int __init broadcom_init(void) 851 { 852 int ret; 853 854 ret = phy_driver_register(&bcm5411_driver); 855 if (ret) 856 goto out_5411; 857 ret = phy_driver_register(&bcm5421_driver); 858 if (ret) 859 goto out_5421; 860 ret = phy_driver_register(&bcm5461_driver); 861 if (ret) 862 goto out_5461; 863 ret = phy_driver_register(&bcm5464_driver); 864 if (ret) 865 goto out_5464; 866 ret = phy_driver_register(&bcm5481_driver); 867 if (ret) 868 goto out_5481; 869 ret = phy_driver_register(&bcm5482_driver); 870 if (ret) 871 goto out_5482; 872 ret = phy_driver_register(&bcm50610_driver); 873 if (ret) 874 goto out_50610; 875 ret = phy_driver_register(&bcm50610m_driver); 876 if (ret) 877 goto out_50610m; 878 ret = phy_driver_register(&bcm57780_driver); 879 if (ret) 880 goto out_57780; 881 ret = phy_driver_register(&bcmac131_driver); 882 if (ret) 883 goto out_ac131; 884 ret = phy_driver_register(&bcm5241_driver); 885 if (ret) 886 goto out_5241; 887 return ret; 888 889 out_5241: 890 phy_driver_unregister(&bcmac131_driver); 891 out_ac131: 892 phy_driver_unregister(&bcm57780_driver); 893 out_57780: 894 phy_driver_unregister(&bcm50610m_driver); 895 out_50610m: 896 phy_driver_unregister(&bcm50610_driver); 897 out_50610: 898 phy_driver_unregister(&bcm5482_driver); 899 out_5482: 900 phy_driver_unregister(&bcm5481_driver); 901 out_5481: 902 phy_driver_unregister(&bcm5464_driver); 903 out_5464: 904 phy_driver_unregister(&bcm5461_driver); 905 out_5461: 906 phy_driver_unregister(&bcm5421_driver); 907 out_5421: 908 phy_driver_unregister(&bcm5411_driver); 909 out_5411: 910 return ret; 911 } 912 913 static void __exit broadcom_exit(void) 914 { 915 phy_driver_unregister(&bcm5241_driver); 916 phy_driver_unregister(&bcmac131_driver); 917 phy_driver_unregister(&bcm57780_driver); 918 phy_driver_unregister(&bcm50610m_driver); 919 phy_driver_unregister(&bcm50610_driver); 920 phy_driver_unregister(&bcm5482_driver); 921 phy_driver_unregister(&bcm5481_driver); 922 phy_driver_unregister(&bcm5464_driver); 923 phy_driver_unregister(&bcm5461_driver); 924 phy_driver_unregister(&bcm5421_driver); 925 phy_driver_unregister(&bcm5411_driver); 926 } 927 928 module_init(broadcom_init); 929 module_exit(broadcom_exit); 930 931 static struct mdio_device_id __maybe_unused broadcom_tbl[] = { 932 { PHY_ID_BCM5411, 0xfffffff0 }, 933 { PHY_ID_BCM5421, 0xfffffff0 }, 934 { PHY_ID_BCM5461, 0xfffffff0 }, 935 { PHY_ID_BCM5464, 0xfffffff0 }, 936 { PHY_ID_BCM5482, 0xfffffff0 }, 937 { PHY_ID_BCM5482, 0xfffffff0 }, 938 { PHY_ID_BCM50610, 0xfffffff0 }, 939 { PHY_ID_BCM50610M, 0xfffffff0 }, 940 { PHY_ID_BCM57780, 0xfffffff0 }, 941 { PHY_ID_BCMAC131, 0xfffffff0 }, 942 { PHY_ID_BCM5241, 0xfffffff0 }, 943 { } 944 }; 945 946 MODULE_DEVICE_TABLE(mdio, broadcom_tbl); 947