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 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 bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val) 34 { 35 return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val); 36 } 37 38 /* Needs SMDSP clock enabled via bcm54xx_phydsp_config() */ 39 static int bcm50610_a0_workaround(struct phy_device *phydev) 40 { 41 int err; 42 43 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_AADJ1CH0, 44 MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN | 45 MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF); 46 if (err < 0) 47 return err; 48 49 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_AADJ1CH3, 50 MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ); 51 if (err < 0) 52 return err; 53 54 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP75, 55 MII_BCM54XX_EXP_EXP75_VDACCTRL); 56 if (err < 0) 57 return err; 58 59 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP96, 60 MII_BCM54XX_EXP_EXP96_MYST); 61 if (err < 0) 62 return err; 63 64 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP97, 65 MII_BCM54XX_EXP_EXP97_MYST); 66 67 return err; 68 } 69 70 static int bcm54xx_phydsp_config(struct phy_device *phydev) 71 { 72 int err, err2; 73 74 /* Enable the SMDSP clock */ 75 err = bcm54xx_auxctl_write(phydev, 76 MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL, 77 MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA | 78 MII_BCM54XX_AUXCTL_ACTL_TX_6DB); 79 if (err < 0) 80 return err; 81 82 if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 || 83 BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) { 84 /* Clear bit 9 to fix a phy interop issue. */ 85 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP08, 86 MII_BCM54XX_EXP_EXP08_RJCT_2MHZ); 87 if (err < 0) 88 goto error; 89 90 if (phydev->drv->phy_id == PHY_ID_BCM50610) { 91 err = bcm50610_a0_workaround(phydev); 92 if (err < 0) 93 goto error; 94 } 95 } 96 97 if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM57780) { 98 int val; 99 100 val = bcm_phy_read_exp(phydev, MII_BCM54XX_EXP_EXP75); 101 if (val < 0) 102 goto error; 103 104 val |= MII_BCM54XX_EXP_EXP75_CM_OSC; 105 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP75, val); 106 } 107 108 error: 109 /* Disable the SMDSP clock */ 110 err2 = bcm54xx_auxctl_write(phydev, 111 MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL, 112 MII_BCM54XX_AUXCTL_ACTL_TX_6DB); 113 114 /* Return the first error reported. */ 115 return err ? err : err2; 116 } 117 118 static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev) 119 { 120 u32 orig; 121 int val; 122 bool clk125en = true; 123 124 /* Abort if we are using an untested phy. */ 125 if (BRCM_PHY_MODEL(phydev) != PHY_ID_BCM57780 && 126 BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610 && 127 BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610M) 128 return; 129 130 val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_SCR3); 131 if (val < 0) 132 return; 133 134 orig = val; 135 136 if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 || 137 BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) && 138 BRCM_PHY_REV(phydev) >= 0x3) { 139 /* 140 * Here, bit 0 _disables_ CLK125 when set. 141 * This bit is set by default. 142 */ 143 clk125en = false; 144 } else { 145 if (phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) { 146 /* Here, bit 0 _enables_ CLK125 when set */ 147 val &= ~BCM54XX_SHD_SCR3_DEF_CLK125; 148 clk125en = false; 149 } 150 } 151 152 if (!clk125en || (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE)) 153 val &= ~BCM54XX_SHD_SCR3_DLLAPD_DIS; 154 else 155 val |= BCM54XX_SHD_SCR3_DLLAPD_DIS; 156 157 if (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY) 158 val |= BCM54XX_SHD_SCR3_TRDDAPD; 159 160 if (orig != val) 161 bcm_phy_write_shadow(phydev, BCM54XX_SHD_SCR3, val); 162 163 val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_APD); 164 if (val < 0) 165 return; 166 167 orig = val; 168 169 if (!clk125en || (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE)) 170 val |= BCM54XX_SHD_APD_EN; 171 else 172 val &= ~BCM54XX_SHD_APD_EN; 173 174 if (orig != val) 175 bcm_phy_write_shadow(phydev, BCM54XX_SHD_APD, val); 176 } 177 178 static int bcm54xx_config_init(struct phy_device *phydev) 179 { 180 int reg, err; 181 182 reg = phy_read(phydev, MII_BCM54XX_ECR); 183 if (reg < 0) 184 return reg; 185 186 /* Mask interrupts globally. */ 187 reg |= MII_BCM54XX_ECR_IM; 188 err = phy_write(phydev, MII_BCM54XX_ECR, reg); 189 if (err < 0) 190 return err; 191 192 /* Unmask events we are interested in. */ 193 reg = ~(MII_BCM54XX_INT_DUPLEX | 194 MII_BCM54XX_INT_SPEED | 195 MII_BCM54XX_INT_LINK); 196 err = phy_write(phydev, MII_BCM54XX_IMR, reg); 197 if (err < 0) 198 return err; 199 200 if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 || 201 BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) && 202 (phydev->dev_flags & PHY_BRCM_CLEAR_RGMII_MODE)) 203 bcm_phy_write_shadow(phydev, BCM54XX_SHD_RGMII_MODE, 0); 204 205 if ((phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) || 206 (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY) || 207 (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE)) 208 bcm54xx_adjust_rxrefclk(phydev); 209 210 bcm54xx_phydsp_config(phydev); 211 212 return 0; 213 } 214 215 static int bcm5482_config_init(struct phy_device *phydev) 216 { 217 int err, reg; 218 219 err = bcm54xx_config_init(phydev); 220 221 if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) { 222 /* 223 * Enable secondary SerDes and its use as an LED source 224 */ 225 reg = bcm_phy_read_shadow(phydev, BCM5482_SHD_SSD); 226 bcm_phy_write_shadow(phydev, BCM5482_SHD_SSD, 227 reg | 228 BCM5482_SHD_SSD_LEDM | 229 BCM5482_SHD_SSD_EN); 230 231 /* 232 * Enable SGMII slave mode and auto-detection 233 */ 234 reg = BCM5482_SSD_SGMII_SLAVE | MII_BCM54XX_EXP_SEL_SSD; 235 err = bcm_phy_read_exp(phydev, reg); 236 if (err < 0) 237 return err; 238 err = bcm_phy_write_exp(phydev, reg, err | 239 BCM5482_SSD_SGMII_SLAVE_EN | 240 BCM5482_SSD_SGMII_SLAVE_AD); 241 if (err < 0) 242 return err; 243 244 /* 245 * Disable secondary SerDes powerdown 246 */ 247 reg = BCM5482_SSD_1000BX_CTL | MII_BCM54XX_EXP_SEL_SSD; 248 err = bcm_phy_read_exp(phydev, reg); 249 if (err < 0) 250 return err; 251 err = bcm_phy_write_exp(phydev, reg, 252 err & ~BCM5482_SSD_1000BX_CTL_PWRDOWN); 253 if (err < 0) 254 return err; 255 256 /* 257 * Select 1000BASE-X register set (primary SerDes) 258 */ 259 reg = bcm_phy_read_shadow(phydev, BCM5482_SHD_MODE); 260 bcm_phy_write_shadow(phydev, BCM5482_SHD_MODE, 261 reg | BCM5482_SHD_MODE_1000BX); 262 263 /* 264 * LED1=ACTIVITYLED, LED3=LINKSPD[2] 265 * (Use LED1 as secondary SerDes ACTIVITY LED) 266 */ 267 bcm_phy_write_shadow(phydev, BCM5482_SHD_LEDS1, 268 BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_ACTIVITYLED) | 269 BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_LINKSPD2)); 270 271 /* 272 * Auto-negotiation doesn't seem to work quite right 273 * in this mode, so we disable it and force it to the 274 * right speed/duplex setting. Only 'link status' 275 * is important. 276 */ 277 phydev->autoneg = AUTONEG_DISABLE; 278 phydev->speed = SPEED_1000; 279 phydev->duplex = DUPLEX_FULL; 280 } 281 282 return err; 283 } 284 285 static int bcm5482_read_status(struct phy_device *phydev) 286 { 287 int err; 288 289 err = genphy_read_status(phydev); 290 291 if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) { 292 /* 293 * Only link status matters for 1000Base-X mode, so force 294 * 1000 Mbit/s full-duplex status 295 */ 296 if (phydev->link) { 297 phydev->speed = SPEED_1000; 298 phydev->duplex = DUPLEX_FULL; 299 } 300 } 301 302 return err; 303 } 304 305 static int bcm5481_config_aneg(struct phy_device *phydev) 306 { 307 int ret; 308 309 /* Aneg firsly. */ 310 ret = genphy_config_aneg(phydev); 311 312 /* Then we can set up the delay. */ 313 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { 314 u16 reg; 315 316 /* 317 * There is no BCM5481 specification available, so down 318 * here is everything we know about "register 0x18". This 319 * at least helps BCM5481 to successfully receive packets 320 * on MPC8360E-RDK board. Peter Barada <peterb@logicpd.com> 321 * says: "This sets delay between the RXD and RXC signals 322 * instead of using trace lengths to achieve timing". 323 */ 324 325 /* Set RDX clk delay. */ 326 reg = 0x7 | (0x7 << 12); 327 phy_write(phydev, 0x18, reg); 328 329 reg = phy_read(phydev, 0x18); 330 /* Set RDX-RXC skew. */ 331 reg |= (1 << 8); 332 /* Write bits 14:0. */ 333 reg |= (1 << 15); 334 phy_write(phydev, 0x18, reg); 335 } 336 337 return ret; 338 } 339 340 static int brcm_phy_setbits(struct phy_device *phydev, int reg, int set) 341 { 342 int val; 343 344 val = phy_read(phydev, reg); 345 if (val < 0) 346 return val; 347 348 return phy_write(phydev, reg, val | set); 349 } 350 351 static int brcm_fet_config_init(struct phy_device *phydev) 352 { 353 int reg, err, err2, brcmtest; 354 355 /* Reset the PHY to bring it to a known state. */ 356 err = phy_write(phydev, MII_BMCR, BMCR_RESET); 357 if (err < 0) 358 return err; 359 360 reg = phy_read(phydev, MII_BRCM_FET_INTREG); 361 if (reg < 0) 362 return reg; 363 364 /* Unmask events we are interested in and mask interrupts globally. */ 365 reg = MII_BRCM_FET_IR_DUPLEX_EN | 366 MII_BRCM_FET_IR_SPEED_EN | 367 MII_BRCM_FET_IR_LINK_EN | 368 MII_BRCM_FET_IR_ENABLE | 369 MII_BRCM_FET_IR_MASK; 370 371 err = phy_write(phydev, MII_BRCM_FET_INTREG, reg); 372 if (err < 0) 373 return err; 374 375 /* Enable shadow register access */ 376 brcmtest = phy_read(phydev, MII_BRCM_FET_BRCMTEST); 377 if (brcmtest < 0) 378 return brcmtest; 379 380 reg = brcmtest | MII_BRCM_FET_BT_SRE; 381 382 err = phy_write(phydev, MII_BRCM_FET_BRCMTEST, reg); 383 if (err < 0) 384 return err; 385 386 /* Set the LED mode */ 387 reg = phy_read(phydev, MII_BRCM_FET_SHDW_AUXMODE4); 388 if (reg < 0) { 389 err = reg; 390 goto done; 391 } 392 393 reg &= ~MII_BRCM_FET_SHDW_AM4_LED_MASK; 394 reg |= MII_BRCM_FET_SHDW_AM4_LED_MODE1; 395 396 err = phy_write(phydev, MII_BRCM_FET_SHDW_AUXMODE4, reg); 397 if (err < 0) 398 goto done; 399 400 /* Enable auto MDIX */ 401 err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_MISCCTRL, 402 MII_BRCM_FET_SHDW_MC_FAME); 403 if (err < 0) 404 goto done; 405 406 if (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE) { 407 /* Enable auto power down */ 408 err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2, 409 MII_BRCM_FET_SHDW_AS2_APDE); 410 } 411 412 done: 413 /* Disable shadow register access */ 414 err2 = phy_write(phydev, MII_BRCM_FET_BRCMTEST, brcmtest); 415 if (!err) 416 err = err2; 417 418 return err; 419 } 420 421 static int brcm_fet_ack_interrupt(struct phy_device *phydev) 422 { 423 int reg; 424 425 /* Clear pending interrupts. */ 426 reg = phy_read(phydev, MII_BRCM_FET_INTREG); 427 if (reg < 0) 428 return reg; 429 430 return 0; 431 } 432 433 static int brcm_fet_config_intr(struct phy_device *phydev) 434 { 435 int reg, err; 436 437 reg = phy_read(phydev, MII_BRCM_FET_INTREG); 438 if (reg < 0) 439 return reg; 440 441 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 442 reg &= ~MII_BRCM_FET_IR_MASK; 443 else 444 reg |= MII_BRCM_FET_IR_MASK; 445 446 err = phy_write(phydev, MII_BRCM_FET_INTREG, reg); 447 return err; 448 } 449 450 static struct phy_driver broadcom_drivers[] = { 451 { 452 .phy_id = PHY_ID_BCM5411, 453 .phy_id_mask = 0xfffffff0, 454 .name = "Broadcom BCM5411", 455 .features = PHY_GBIT_FEATURES | 456 SUPPORTED_Pause | SUPPORTED_Asym_Pause, 457 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 458 .config_init = bcm54xx_config_init, 459 .config_aneg = genphy_config_aneg, 460 .read_status = genphy_read_status, 461 .ack_interrupt = bcm_phy_ack_intr, 462 .config_intr = bcm_phy_config_intr, 463 }, { 464 .phy_id = PHY_ID_BCM5421, 465 .phy_id_mask = 0xfffffff0, 466 .name = "Broadcom BCM5421", 467 .features = PHY_GBIT_FEATURES | 468 SUPPORTED_Pause | SUPPORTED_Asym_Pause, 469 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 470 .config_init = bcm54xx_config_init, 471 .config_aneg = genphy_config_aneg, 472 .read_status = genphy_read_status, 473 .ack_interrupt = bcm_phy_ack_intr, 474 .config_intr = bcm_phy_config_intr, 475 }, { 476 .phy_id = PHY_ID_BCM5461, 477 .phy_id_mask = 0xfffffff0, 478 .name = "Broadcom BCM5461", 479 .features = PHY_GBIT_FEATURES | 480 SUPPORTED_Pause | SUPPORTED_Asym_Pause, 481 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 482 .config_init = bcm54xx_config_init, 483 .config_aneg = genphy_config_aneg, 484 .read_status = genphy_read_status, 485 .ack_interrupt = bcm_phy_ack_intr, 486 .config_intr = bcm_phy_config_intr, 487 }, { 488 .phy_id = PHY_ID_BCM54616S, 489 .phy_id_mask = 0xfffffff0, 490 .name = "Broadcom BCM54616S", 491 .features = PHY_GBIT_FEATURES | 492 SUPPORTED_Pause | SUPPORTED_Asym_Pause, 493 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 494 .config_init = bcm54xx_config_init, 495 .config_aneg = genphy_config_aneg, 496 .read_status = genphy_read_status, 497 .ack_interrupt = bcm_phy_ack_intr, 498 .config_intr = bcm_phy_config_intr, 499 }, { 500 .phy_id = PHY_ID_BCM5464, 501 .phy_id_mask = 0xfffffff0, 502 .name = "Broadcom BCM5464", 503 .features = PHY_GBIT_FEATURES | 504 SUPPORTED_Pause | SUPPORTED_Asym_Pause, 505 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 506 .config_init = bcm54xx_config_init, 507 .config_aneg = genphy_config_aneg, 508 .read_status = genphy_read_status, 509 .ack_interrupt = bcm_phy_ack_intr, 510 .config_intr = bcm_phy_config_intr, 511 }, { 512 .phy_id = PHY_ID_BCM5481, 513 .phy_id_mask = 0xfffffff0, 514 .name = "Broadcom BCM5481", 515 .features = PHY_GBIT_FEATURES | 516 SUPPORTED_Pause | SUPPORTED_Asym_Pause, 517 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 518 .config_init = bcm54xx_config_init, 519 .config_aneg = bcm5481_config_aneg, 520 .read_status = genphy_read_status, 521 .ack_interrupt = bcm_phy_ack_intr, 522 .config_intr = bcm_phy_config_intr, 523 }, { 524 .phy_id = PHY_ID_BCM5482, 525 .phy_id_mask = 0xfffffff0, 526 .name = "Broadcom BCM5482", 527 .features = PHY_GBIT_FEATURES | 528 SUPPORTED_Pause | SUPPORTED_Asym_Pause, 529 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 530 .config_init = bcm5482_config_init, 531 .config_aneg = genphy_config_aneg, 532 .read_status = bcm5482_read_status, 533 .ack_interrupt = bcm_phy_ack_intr, 534 .config_intr = bcm_phy_config_intr, 535 }, { 536 .phy_id = PHY_ID_BCM50610, 537 .phy_id_mask = 0xfffffff0, 538 .name = "Broadcom BCM50610", 539 .features = PHY_GBIT_FEATURES | 540 SUPPORTED_Pause | SUPPORTED_Asym_Pause, 541 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 542 .config_init = bcm54xx_config_init, 543 .config_aneg = genphy_config_aneg, 544 .read_status = genphy_read_status, 545 .ack_interrupt = bcm_phy_ack_intr, 546 .config_intr = bcm_phy_config_intr, 547 }, { 548 .phy_id = PHY_ID_BCM50610M, 549 .phy_id_mask = 0xfffffff0, 550 .name = "Broadcom BCM50610M", 551 .features = PHY_GBIT_FEATURES | 552 SUPPORTED_Pause | SUPPORTED_Asym_Pause, 553 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 554 .config_init = bcm54xx_config_init, 555 .config_aneg = genphy_config_aneg, 556 .read_status = genphy_read_status, 557 .ack_interrupt = bcm_phy_ack_intr, 558 .config_intr = bcm_phy_config_intr, 559 }, { 560 .phy_id = PHY_ID_BCM57780, 561 .phy_id_mask = 0xfffffff0, 562 .name = "Broadcom BCM57780", 563 .features = PHY_GBIT_FEATURES | 564 SUPPORTED_Pause | SUPPORTED_Asym_Pause, 565 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 566 .config_init = bcm54xx_config_init, 567 .config_aneg = genphy_config_aneg, 568 .read_status = genphy_read_status, 569 .ack_interrupt = bcm_phy_ack_intr, 570 .config_intr = bcm_phy_config_intr, 571 }, { 572 .phy_id = PHY_ID_BCMAC131, 573 .phy_id_mask = 0xfffffff0, 574 .name = "Broadcom BCMAC131", 575 .features = PHY_BASIC_FEATURES | 576 SUPPORTED_Pause | SUPPORTED_Asym_Pause, 577 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 578 .config_init = brcm_fet_config_init, 579 .config_aneg = genphy_config_aneg, 580 .read_status = genphy_read_status, 581 .ack_interrupt = brcm_fet_ack_interrupt, 582 .config_intr = brcm_fet_config_intr, 583 }, { 584 .phy_id = PHY_ID_BCM5241, 585 .phy_id_mask = 0xfffffff0, 586 .name = "Broadcom BCM5241", 587 .features = PHY_BASIC_FEATURES | 588 SUPPORTED_Pause | SUPPORTED_Asym_Pause, 589 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, 590 .config_init = brcm_fet_config_init, 591 .config_aneg = genphy_config_aneg, 592 .read_status = genphy_read_status, 593 .ack_interrupt = brcm_fet_ack_interrupt, 594 .config_intr = brcm_fet_config_intr, 595 } }; 596 597 module_phy_driver(broadcom_drivers); 598 599 static struct mdio_device_id __maybe_unused broadcom_tbl[] = { 600 { PHY_ID_BCM5411, 0xfffffff0 }, 601 { PHY_ID_BCM5421, 0xfffffff0 }, 602 { PHY_ID_BCM5461, 0xfffffff0 }, 603 { PHY_ID_BCM54616S, 0xfffffff0 }, 604 { PHY_ID_BCM5464, 0xfffffff0 }, 605 { PHY_ID_BCM5481, 0xfffffff0 }, 606 { PHY_ID_BCM5482, 0xfffffff0 }, 607 { PHY_ID_BCM50610, 0xfffffff0 }, 608 { PHY_ID_BCM50610M, 0xfffffff0 }, 609 { PHY_ID_BCM57780, 0xfffffff0 }, 610 { PHY_ID_BCMAC131, 0xfffffff0 }, 611 { PHY_ID_BCM5241, 0xfffffff0 }, 612 { } 613 }; 614 615 MODULE_DEVICE_TABLE(mdio, broadcom_tbl); 616