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