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