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