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 "bcm-phy-lib.h" 18 #include <linux/module.h> 19 #include <linux/phy.h> 20 #include <linux/brcmphy.h> 21 #include <linux/of.h> 22 23 #define BRCM_PHY_MODEL(phydev) \ 24 ((phydev)->drv->phy_id & (phydev)->drv->phy_id_mask) 25 26 #define BRCM_PHY_REV(phydev) \ 27 ((phydev)->drv->phy_id & ~((phydev)->drv->phy_id_mask)) 28 29 MODULE_DESCRIPTION("Broadcom PHY driver"); 30 MODULE_AUTHOR("Maciej W. Rozycki"); 31 MODULE_LICENSE("GPL"); 32 33 static int bcm54210e_config_init(struct phy_device *phydev) 34 { 35 int val; 36 37 val = bcm54xx_auxctl_read(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC); 38 val &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN; 39 val |= MII_BCM54XX_AUXCTL_MISC_WREN; 40 bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC, val); 41 42 val = bcm_phy_read_shadow(phydev, BCM54810_SHD_CLK_CTL); 43 val &= ~BCM54810_SHD_CLK_CTL_GTXCLK_EN; 44 bcm_phy_write_shadow(phydev, BCM54810_SHD_CLK_CTL, val); 45 46 if (phydev->dev_flags & PHY_BRCM_EN_MASTER_MODE) { 47 val = phy_read(phydev, MII_CTRL1000); 48 val |= CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER; 49 phy_write(phydev, MII_CTRL1000, val); 50 } 51 52 return 0; 53 } 54 55 static int bcm54612e_config_init(struct phy_device *phydev) 56 { 57 /* Clear TX internal delay unless requested. */ 58 if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) && 59 (phydev->interface != PHY_INTERFACE_MODE_RGMII_TXID)) { 60 /* Disable TXD to GTXCLK clock delay (default set) */ 61 /* Bit 9 is the only field in shadow register 00011 */ 62 bcm_phy_write_shadow(phydev, 0x03, 0); 63 } 64 65 /* Clear RX internal delay unless requested. */ 66 if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) && 67 (phydev->interface != PHY_INTERFACE_MODE_RGMII_RXID)) { 68 u16 reg; 69 70 reg = bcm54xx_auxctl_read(phydev, 71 MII_BCM54XX_AUXCTL_SHDWSEL_MISC); 72 /* Disable RXD to RXC delay (default set) */ 73 reg &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN; 74 /* Clear shadow selector field */ 75 reg &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MASK; 76 bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC, 77 MII_BCM54XX_AUXCTL_MISC_WREN | reg); 78 } 79 80 return 0; 81 } 82 83 static int bcm5481x_config(struct phy_device *phydev) 84 { 85 int rc, val; 86 87 /* handling PHY's internal RX clock delay */ 88 val = bcm54xx_auxctl_read(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC); 89 val |= MII_BCM54XX_AUXCTL_MISC_WREN; 90 if (phydev->interface == PHY_INTERFACE_MODE_RGMII || 91 phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { 92 /* Disable RGMII RXC-RXD skew */ 93 val &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN; 94 } 95 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || 96 phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { 97 /* Enable RGMII RXC-RXD skew */ 98 val |= MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN; 99 } 100 rc = bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC, 101 val); 102 if (rc < 0) 103 return rc; 104 105 /* handling PHY's internal TX clock delay */ 106 val = bcm_phy_read_shadow(phydev, BCM54810_SHD_CLK_CTL); 107 if (phydev->interface == PHY_INTERFACE_MODE_RGMII || 108 phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { 109 /* Disable internal TX clock delay */ 110 val &= ~BCM54810_SHD_CLK_CTL_GTXCLK_EN; 111 } 112 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || 113 phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { 114 /* Enable internal TX clock delay */ 115 val |= BCM54810_SHD_CLK_CTL_GTXCLK_EN; 116 } 117 rc = bcm_phy_write_shadow(phydev, BCM54810_SHD_CLK_CTL, val); 118 if (rc < 0) 119 return rc; 120 121 return 0; 122 } 123 124 /* Needs SMDSP clock enabled via bcm54xx_phydsp_config() */ 125 static int bcm50610_a0_workaround(struct phy_device *phydev) 126 { 127 int err; 128 129 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_AADJ1CH0, 130 MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN | 131 MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF); 132 if (err < 0) 133 return err; 134 135 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_AADJ1CH3, 136 MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ); 137 if (err < 0) 138 return err; 139 140 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP75, 141 MII_BCM54XX_EXP_EXP75_VDACCTRL); 142 if (err < 0) 143 return err; 144 145 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP96, 146 MII_BCM54XX_EXP_EXP96_MYST); 147 if (err < 0) 148 return err; 149 150 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP97, 151 MII_BCM54XX_EXP_EXP97_MYST); 152 153 return err; 154 } 155 156 static int bcm54xx_phydsp_config(struct phy_device *phydev) 157 { 158 int err, err2; 159 160 /* Enable the SMDSP clock */ 161 err = bcm54xx_auxctl_write(phydev, 162 MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL, 163 MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA | 164 MII_BCM54XX_AUXCTL_ACTL_TX_6DB); 165 if (err < 0) 166 return err; 167 168 if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 || 169 BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) { 170 /* Clear bit 9 to fix a phy interop issue. */ 171 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP08, 172 MII_BCM54XX_EXP_EXP08_RJCT_2MHZ); 173 if (err < 0) 174 goto error; 175 176 if (phydev->drv->phy_id == PHY_ID_BCM50610) { 177 err = bcm50610_a0_workaround(phydev); 178 if (err < 0) 179 goto error; 180 } 181 } 182 183 if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM57780) { 184 int val; 185 186 val = bcm_phy_read_exp(phydev, MII_BCM54XX_EXP_EXP75); 187 if (val < 0) 188 goto error; 189 190 val |= MII_BCM54XX_EXP_EXP75_CM_OSC; 191 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP75, val); 192 } 193 194 error: 195 /* Disable the SMDSP clock */ 196 err2 = bcm54xx_auxctl_write(phydev, 197 MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL, 198 MII_BCM54XX_AUXCTL_ACTL_TX_6DB); 199 200 /* Return the first error reported. */ 201 return err ? err : err2; 202 } 203 204 static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev) 205 { 206 u32 orig; 207 int val; 208 bool clk125en = true; 209 210 /* Abort if we are using an untested phy. */ 211 if (BRCM_PHY_MODEL(phydev) != PHY_ID_BCM57780 && 212 BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610 && 213 BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610M) 214 return; 215 216 val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_SCR3); 217 if (val < 0) 218 return; 219 220 orig = val; 221 222 if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 || 223 BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) && 224 BRCM_PHY_REV(phydev) >= 0x3) { 225 /* 226 * Here, bit 0 _disables_ CLK125 when set. 227 * This bit is set by default. 228 */ 229 clk125en = false; 230 } else { 231 if (phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) { 232 /* Here, bit 0 _enables_ CLK125 when set */ 233 val &= ~BCM54XX_SHD_SCR3_DEF_CLK125; 234 clk125en = false; 235 } 236 } 237 238 if (!clk125en || (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE)) 239 val &= ~BCM54XX_SHD_SCR3_DLLAPD_DIS; 240 else 241 val |= BCM54XX_SHD_SCR3_DLLAPD_DIS; 242 243 if (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY) 244 val |= BCM54XX_SHD_SCR3_TRDDAPD; 245 246 if (orig != val) 247 bcm_phy_write_shadow(phydev, BCM54XX_SHD_SCR3, val); 248 249 val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_APD); 250 if (val < 0) 251 return; 252 253 orig = val; 254 255 if (!clk125en || (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE)) 256 val |= BCM54XX_SHD_APD_EN; 257 else 258 val &= ~BCM54XX_SHD_APD_EN; 259 260 if (orig != val) 261 bcm_phy_write_shadow(phydev, BCM54XX_SHD_APD, val); 262 } 263 264 static int bcm54xx_config_init(struct phy_device *phydev) 265 { 266 int reg, err, val; 267 268 reg = phy_read(phydev, MII_BCM54XX_ECR); 269 if (reg < 0) 270 return reg; 271 272 /* Mask interrupts globally. */ 273 reg |= MII_BCM54XX_ECR_IM; 274 err = phy_write(phydev, MII_BCM54XX_ECR, reg); 275 if (err < 0) 276 return err; 277 278 /* Unmask events we are interested in. */ 279 reg = ~(MII_BCM54XX_INT_DUPLEX | 280 MII_BCM54XX_INT_SPEED | 281 MII_BCM54XX_INT_LINK); 282 err = phy_write(phydev, MII_BCM54XX_IMR, reg); 283 if (err < 0) 284 return err; 285 286 if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 || 287 BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) && 288 (phydev->dev_flags & PHY_BRCM_CLEAR_RGMII_MODE)) 289 bcm_phy_write_shadow(phydev, BCM54XX_SHD_RGMII_MODE, 0); 290 291 if ((phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) || 292 (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY) || 293 (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE)) 294 bcm54xx_adjust_rxrefclk(phydev); 295 296 if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54210E) { 297 err = bcm54210e_config_init(phydev); 298 if (err) 299 return err; 300 } else if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54612E) { 301 err = bcm54612e_config_init(phydev); 302 if (err) 303 return err; 304 } else if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54810) { 305 /* For BCM54810, we need to disable BroadR-Reach function */ 306 val = bcm_phy_read_exp(phydev, 307 BCM54810_EXP_BROADREACH_LRE_MISC_CTL); 308 val &= ~BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN; 309 err = bcm_phy_write_exp(phydev, 310 BCM54810_EXP_BROADREACH_LRE_MISC_CTL, 311 val); 312 if (err < 0) 313 return err; 314 } 315 316 bcm54xx_phydsp_config(phydev); 317 318 return 0; 319 } 320 321 static int bcm5482_config_init(struct phy_device *phydev) 322 { 323 int err, reg; 324 325 err = bcm54xx_config_init(phydev); 326 327 if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) { 328 /* 329 * Enable secondary SerDes and its use as an LED source 330 */ 331 reg = bcm_phy_read_shadow(phydev, BCM5482_SHD_SSD); 332 bcm_phy_write_shadow(phydev, BCM5482_SHD_SSD, 333 reg | 334 BCM5482_SHD_SSD_LEDM | 335 BCM5482_SHD_SSD_EN); 336 337 /* 338 * Enable SGMII slave mode and auto-detection 339 */ 340 reg = BCM5482_SSD_SGMII_SLAVE | MII_BCM54XX_EXP_SEL_SSD; 341 err = bcm_phy_read_exp(phydev, reg); 342 if (err < 0) 343 return err; 344 err = bcm_phy_write_exp(phydev, reg, err | 345 BCM5482_SSD_SGMII_SLAVE_EN | 346 BCM5482_SSD_SGMII_SLAVE_AD); 347 if (err < 0) 348 return err; 349 350 /* 351 * Disable secondary SerDes powerdown 352 */ 353 reg = BCM5482_SSD_1000BX_CTL | MII_BCM54XX_EXP_SEL_SSD; 354 err = bcm_phy_read_exp(phydev, reg); 355 if (err < 0) 356 return err; 357 err = bcm_phy_write_exp(phydev, reg, 358 err & ~BCM5482_SSD_1000BX_CTL_PWRDOWN); 359 if (err < 0) 360 return err; 361 362 /* 363 * Select 1000BASE-X register set (primary SerDes) 364 */ 365 reg = bcm_phy_read_shadow(phydev, BCM5482_SHD_MODE); 366 bcm_phy_write_shadow(phydev, BCM5482_SHD_MODE, 367 reg | BCM5482_SHD_MODE_1000BX); 368 369 /* 370 * LED1=ACTIVITYLED, LED3=LINKSPD[2] 371 * (Use LED1 as secondary SerDes ACTIVITY LED) 372 */ 373 bcm_phy_write_shadow(phydev, BCM5482_SHD_LEDS1, 374 BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_ACTIVITYLED) | 375 BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_LINKSPD2)); 376 377 /* 378 * Auto-negotiation doesn't seem to work quite right 379 * in this mode, so we disable it and force it to the 380 * right speed/duplex setting. Only 'link status' 381 * is important. 382 */ 383 phydev->autoneg = AUTONEG_DISABLE; 384 phydev->speed = SPEED_1000; 385 phydev->duplex = DUPLEX_FULL; 386 } 387 388 return err; 389 } 390 391 static int bcm5482_read_status(struct phy_device *phydev) 392 { 393 int err; 394 395 err = genphy_read_status(phydev); 396 397 if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) { 398 /* 399 * Only link status matters for 1000Base-X mode, so force 400 * 1000 Mbit/s full-duplex status 401 */ 402 if (phydev->link) { 403 phydev->speed = SPEED_1000; 404 phydev->duplex = DUPLEX_FULL; 405 } 406 } 407 408 return err; 409 } 410 411 static int bcm5481_config_aneg(struct phy_device *phydev) 412 { 413 struct device_node *np = phydev->mdio.dev.of_node; 414 int ret; 415 416 /* Aneg firsly. */ 417 ret = genphy_config_aneg(phydev); 418 419 /* Then we can set up the delay. */ 420 bcm5481x_config(phydev); 421 422 if (of_property_read_bool(np, "enet-phy-lane-swap")) { 423 /* Lane Swap - Undocumented register...magic! */ 424 ret = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_SEL_ER + 0x9, 425 0x11B); 426 if (ret < 0) 427 return ret; 428 } 429 430 return ret; 431 } 432 433 static int brcm_phy_setbits(struct phy_device *phydev, int reg, int set) 434 { 435 int val; 436 437 val = phy_read(phydev, reg); 438 if (val < 0) 439 return val; 440 441 return phy_write(phydev, reg, val | set); 442 } 443 444 static int brcm_fet_config_init(struct phy_device *phydev) 445 { 446 int reg, err, err2, brcmtest; 447 448 /* Reset the PHY to bring it to a known state. */ 449 err = phy_write(phydev, MII_BMCR, BMCR_RESET); 450 if (err < 0) 451 return err; 452 453 reg = phy_read(phydev, MII_BRCM_FET_INTREG); 454 if (reg < 0) 455 return reg; 456 457 /* Unmask events we are interested in and mask interrupts globally. */ 458 reg = MII_BRCM_FET_IR_DUPLEX_EN | 459 MII_BRCM_FET_IR_SPEED_EN | 460 MII_BRCM_FET_IR_LINK_EN | 461 MII_BRCM_FET_IR_ENABLE | 462 MII_BRCM_FET_IR_MASK; 463 464 err = phy_write(phydev, MII_BRCM_FET_INTREG, reg); 465 if (err < 0) 466 return err; 467 468 /* Enable shadow register access */ 469 brcmtest = phy_read(phydev, MII_BRCM_FET_BRCMTEST); 470 if (brcmtest < 0) 471 return brcmtest; 472 473 reg = brcmtest | MII_BRCM_FET_BT_SRE; 474 475 err = phy_write(phydev, MII_BRCM_FET_BRCMTEST, reg); 476 if (err < 0) 477 return err; 478 479 /* Set the LED mode */ 480 reg = phy_read(phydev, MII_BRCM_FET_SHDW_AUXMODE4); 481 if (reg < 0) { 482 err = reg; 483 goto done; 484 } 485 486 reg &= ~MII_BRCM_FET_SHDW_AM4_LED_MASK; 487 reg |= MII_BRCM_FET_SHDW_AM4_LED_MODE1; 488 489 err = phy_write(phydev, MII_BRCM_FET_SHDW_AUXMODE4, reg); 490 if (err < 0) 491 goto done; 492 493 /* Enable auto MDIX */ 494 err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_MISCCTRL, 495 MII_BRCM_FET_SHDW_MC_FAME); 496 if (err < 0) 497 goto done; 498 499 if (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE) { 500 /* Enable auto power down */ 501 err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2, 502 MII_BRCM_FET_SHDW_AS2_APDE); 503 } 504 505 done: 506 /* Disable shadow register access */ 507 err2 = phy_write(phydev, MII_BRCM_FET_BRCMTEST, brcmtest); 508 if (!err) 509 err = err2; 510 511 return err; 512 } 513 514 static int brcm_fet_ack_interrupt(struct phy_device *phydev) 515 { 516 int reg; 517 518 /* Clear pending interrupts. */ 519 reg = phy_read(phydev, MII_BRCM_FET_INTREG); 520 if (reg < 0) 521 return reg; 522 523 return 0; 524 } 525 526 static int brcm_fet_config_intr(struct phy_device *phydev) 527 { 528 int reg, err; 529 530 reg = phy_read(phydev, MII_BRCM_FET_INTREG); 531 if (reg < 0) 532 return reg; 533 534 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 535 reg &= ~MII_BRCM_FET_IR_MASK; 536 else 537 reg |= MII_BRCM_FET_IR_MASK; 538 539 err = phy_write(phydev, MII_BRCM_FET_INTREG, reg); 540 return err; 541 } 542 543 static struct phy_driver broadcom_drivers[] = { 544 { 545 .phy_id = PHY_ID_BCM5411, 546 .phy_id_mask = 0xfffffff0, 547 .name = "Broadcom BCM5411", 548 .features = PHY_GBIT_FEATURES, 549 .flags = PHY_HAS_INTERRUPT, 550 .config_init = bcm54xx_config_init, 551 .config_aneg = genphy_config_aneg, 552 .read_status = genphy_read_status, 553 .ack_interrupt = bcm_phy_ack_intr, 554 .config_intr = bcm_phy_config_intr, 555 }, { 556 .phy_id = PHY_ID_BCM5421, 557 .phy_id_mask = 0xfffffff0, 558 .name = "Broadcom BCM5421", 559 .features = PHY_GBIT_FEATURES, 560 .flags = PHY_HAS_INTERRUPT, 561 .config_init = bcm54xx_config_init, 562 .config_aneg = genphy_config_aneg, 563 .read_status = genphy_read_status, 564 .ack_interrupt = bcm_phy_ack_intr, 565 .config_intr = bcm_phy_config_intr, 566 }, { 567 .phy_id = PHY_ID_BCM54210E, 568 .phy_id_mask = 0xfffffff0, 569 .name = "Broadcom BCM54210E", 570 .features = PHY_GBIT_FEATURES, 571 .flags = PHY_HAS_INTERRUPT, 572 .config_init = bcm54xx_config_init, 573 .config_aneg = genphy_config_aneg, 574 .read_status = genphy_read_status, 575 .ack_interrupt = bcm_phy_ack_intr, 576 .config_intr = bcm_phy_config_intr, 577 }, { 578 .phy_id = PHY_ID_BCM5461, 579 .phy_id_mask = 0xfffffff0, 580 .name = "Broadcom BCM5461", 581 .features = PHY_GBIT_FEATURES, 582 .flags = PHY_HAS_INTERRUPT, 583 .config_init = bcm54xx_config_init, 584 .config_aneg = genphy_config_aneg, 585 .read_status = genphy_read_status, 586 .ack_interrupt = bcm_phy_ack_intr, 587 .config_intr = bcm_phy_config_intr, 588 }, { 589 .phy_id = PHY_ID_BCM54612E, 590 .phy_id_mask = 0xfffffff0, 591 .name = "Broadcom BCM54612E", 592 .features = PHY_GBIT_FEATURES, 593 .flags = PHY_HAS_INTERRUPT, 594 .config_init = bcm54xx_config_init, 595 .config_aneg = genphy_config_aneg, 596 .read_status = genphy_read_status, 597 .ack_interrupt = bcm_phy_ack_intr, 598 .config_intr = bcm_phy_config_intr, 599 }, { 600 .phy_id = PHY_ID_BCM54616S, 601 .phy_id_mask = 0xfffffff0, 602 .name = "Broadcom BCM54616S", 603 .features = PHY_GBIT_FEATURES, 604 .flags = PHY_HAS_INTERRUPT, 605 .config_init = bcm54xx_config_init, 606 .config_aneg = genphy_config_aneg, 607 .read_status = genphy_read_status, 608 .ack_interrupt = bcm_phy_ack_intr, 609 .config_intr = bcm_phy_config_intr, 610 }, { 611 .phy_id = PHY_ID_BCM5464, 612 .phy_id_mask = 0xfffffff0, 613 .name = "Broadcom BCM5464", 614 .features = PHY_GBIT_FEATURES, 615 .flags = PHY_HAS_INTERRUPT, 616 .config_init = bcm54xx_config_init, 617 .config_aneg = genphy_config_aneg, 618 .read_status = genphy_read_status, 619 .ack_interrupt = bcm_phy_ack_intr, 620 .config_intr = bcm_phy_config_intr, 621 }, { 622 .phy_id = PHY_ID_BCM5481, 623 .phy_id_mask = 0xfffffff0, 624 .name = "Broadcom BCM5481", 625 .features = PHY_GBIT_FEATURES, 626 .flags = PHY_HAS_INTERRUPT, 627 .config_init = bcm54xx_config_init, 628 .config_aneg = bcm5481_config_aneg, 629 .read_status = genphy_read_status, 630 .ack_interrupt = bcm_phy_ack_intr, 631 .config_intr = bcm_phy_config_intr, 632 }, { 633 .phy_id = PHY_ID_BCM54810, 634 .phy_id_mask = 0xfffffff0, 635 .name = "Broadcom BCM54810", 636 .features = PHY_GBIT_FEATURES, 637 .flags = PHY_HAS_INTERRUPT, 638 .config_init = bcm54xx_config_init, 639 .config_aneg = bcm5481_config_aneg, 640 .read_status = genphy_read_status, 641 .ack_interrupt = bcm_phy_ack_intr, 642 .config_intr = bcm_phy_config_intr, 643 }, { 644 .phy_id = PHY_ID_BCM5482, 645 .phy_id_mask = 0xfffffff0, 646 .name = "Broadcom BCM5482", 647 .features = PHY_GBIT_FEATURES, 648 .flags = PHY_HAS_INTERRUPT, 649 .config_init = bcm5482_config_init, 650 .config_aneg = genphy_config_aneg, 651 .read_status = bcm5482_read_status, 652 .ack_interrupt = bcm_phy_ack_intr, 653 .config_intr = bcm_phy_config_intr, 654 }, { 655 .phy_id = PHY_ID_BCM50610, 656 .phy_id_mask = 0xfffffff0, 657 .name = "Broadcom BCM50610", 658 .features = PHY_GBIT_FEATURES, 659 .flags = PHY_HAS_INTERRUPT, 660 .config_init = bcm54xx_config_init, 661 .config_aneg = genphy_config_aneg, 662 .read_status = genphy_read_status, 663 .ack_interrupt = bcm_phy_ack_intr, 664 .config_intr = bcm_phy_config_intr, 665 }, { 666 .phy_id = PHY_ID_BCM50610M, 667 .phy_id_mask = 0xfffffff0, 668 .name = "Broadcom BCM50610M", 669 .features = PHY_GBIT_FEATURES, 670 .flags = PHY_HAS_INTERRUPT, 671 .config_init = bcm54xx_config_init, 672 .config_aneg = genphy_config_aneg, 673 .read_status = genphy_read_status, 674 .ack_interrupt = bcm_phy_ack_intr, 675 .config_intr = bcm_phy_config_intr, 676 }, { 677 .phy_id = PHY_ID_BCM57780, 678 .phy_id_mask = 0xfffffff0, 679 .name = "Broadcom BCM57780", 680 .features = PHY_GBIT_FEATURES, 681 .flags = PHY_HAS_INTERRUPT, 682 .config_init = bcm54xx_config_init, 683 .config_aneg = genphy_config_aneg, 684 .read_status = genphy_read_status, 685 .ack_interrupt = bcm_phy_ack_intr, 686 .config_intr = bcm_phy_config_intr, 687 }, { 688 .phy_id = PHY_ID_BCMAC131, 689 .phy_id_mask = 0xfffffff0, 690 .name = "Broadcom BCMAC131", 691 .features = PHY_BASIC_FEATURES, 692 .flags = PHY_HAS_INTERRUPT, 693 .config_init = brcm_fet_config_init, 694 .config_aneg = genphy_config_aneg, 695 .read_status = genphy_read_status, 696 .ack_interrupt = brcm_fet_ack_interrupt, 697 .config_intr = brcm_fet_config_intr, 698 }, { 699 .phy_id = PHY_ID_BCM5241, 700 .phy_id_mask = 0xfffffff0, 701 .name = "Broadcom BCM5241", 702 .features = PHY_BASIC_FEATURES, 703 .flags = PHY_HAS_INTERRUPT, 704 .config_init = brcm_fet_config_init, 705 .config_aneg = genphy_config_aneg, 706 .read_status = genphy_read_status, 707 .ack_interrupt = brcm_fet_ack_interrupt, 708 .config_intr = brcm_fet_config_intr, 709 } }; 710 711 module_phy_driver(broadcom_drivers); 712 713 static struct mdio_device_id __maybe_unused broadcom_tbl[] = { 714 { PHY_ID_BCM5411, 0xfffffff0 }, 715 { PHY_ID_BCM5421, 0xfffffff0 }, 716 { PHY_ID_BCM54210E, 0xfffffff0 }, 717 { PHY_ID_BCM5461, 0xfffffff0 }, 718 { PHY_ID_BCM54612E, 0xfffffff0 }, 719 { PHY_ID_BCM54616S, 0xfffffff0 }, 720 { PHY_ID_BCM5464, 0xfffffff0 }, 721 { PHY_ID_BCM5481, 0xfffffff0 }, 722 { PHY_ID_BCM54810, 0xfffffff0 }, 723 { PHY_ID_BCM5482, 0xfffffff0 }, 724 { PHY_ID_BCM50610, 0xfffffff0 }, 725 { PHY_ID_BCM50610M, 0xfffffff0 }, 726 { PHY_ID_BCM57780, 0xfffffff0 }, 727 { PHY_ID_BCMAC131, 0xfffffff0 }, 728 { PHY_ID_BCM5241, 0xfffffff0 }, 729 { } 730 }; 731 732 MODULE_DEVICE_TABLE(mdio, broadcom_tbl); 733