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