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 if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54810) 230 val |= BCM54810_SHD_SCR3_TRDDAPD; 231 else 232 val |= BCM54XX_SHD_SCR3_TRDDAPD; 233 } 234 235 if (orig != val) 236 bcm_phy_write_shadow(phydev, BCM54XX_SHD_SCR3, val); 237 238 val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_APD); 239 if (val < 0) 240 return; 241 242 orig = val; 243 244 if (!clk125en || (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE)) 245 val |= BCM54XX_SHD_APD_EN; 246 else 247 val &= ~BCM54XX_SHD_APD_EN; 248 249 if (orig != val) 250 bcm_phy_write_shadow(phydev, BCM54XX_SHD_APD, val); 251 } 252 253 static int bcm54xx_config_init(struct phy_device *phydev) 254 { 255 int reg, err, val; 256 257 reg = phy_read(phydev, MII_BCM54XX_ECR); 258 if (reg < 0) 259 return reg; 260 261 /* Mask interrupts globally. */ 262 reg |= MII_BCM54XX_ECR_IM; 263 err = phy_write(phydev, MII_BCM54XX_ECR, reg); 264 if (err < 0) 265 return err; 266 267 /* Unmask events we are interested in. */ 268 reg = ~(MII_BCM54XX_INT_DUPLEX | 269 MII_BCM54XX_INT_SPEED | 270 MII_BCM54XX_INT_LINK); 271 err = phy_write(phydev, MII_BCM54XX_IMR, reg); 272 if (err < 0) 273 return err; 274 275 if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 || 276 BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) && 277 (phydev->dev_flags & PHY_BRCM_CLEAR_RGMII_MODE)) 278 bcm_phy_write_shadow(phydev, BCM54XX_SHD_RGMII_MODE, 0); 279 280 bcm54xx_adjust_rxrefclk(phydev); 281 282 if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54210E) { 283 err = bcm54210e_config_init(phydev); 284 if (err) 285 return err; 286 } else if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54612E) { 287 err = bcm54612e_config_init(phydev); 288 if (err) 289 return err; 290 } else if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54810) { 291 /* For BCM54810, we need to disable BroadR-Reach function */ 292 val = bcm_phy_read_exp(phydev, 293 BCM54810_EXP_BROADREACH_LRE_MISC_CTL); 294 val &= ~BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN; 295 err = bcm_phy_write_exp(phydev, 296 BCM54810_EXP_BROADREACH_LRE_MISC_CTL, 297 val); 298 if (err < 0) 299 return err; 300 } 301 302 bcm54xx_phydsp_config(phydev); 303 304 /* Encode link speed into LED1 and LED3 pair (green/amber). 305 * Also flash these two LEDs on activity. This means configuring 306 * them for MULTICOLOR and encoding link/activity into them. 307 */ 308 val = BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_MULTICOLOR1) | 309 BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_MULTICOLOR1); 310 bcm_phy_write_shadow(phydev, BCM5482_SHD_LEDS1, val); 311 312 val = BCM_LED_MULTICOLOR_IN_PHASE | 313 BCM5482_SHD_LEDS1_LED1(BCM_LED_MULTICOLOR_LINK_ACT) | 314 BCM5482_SHD_LEDS1_LED3(BCM_LED_MULTICOLOR_LINK_ACT); 315 bcm_phy_write_exp(phydev, BCM_EXP_MULTICOLOR, val); 316 317 return 0; 318 } 319 320 static int bcm54xx_resume(struct phy_device *phydev) 321 { 322 int ret; 323 324 /* Writes to register other than BMCR would be ignored 325 * unless we clear the PDOWN bit first 326 */ 327 ret = genphy_resume(phydev); 328 if (ret < 0) 329 return ret; 330 331 return bcm54xx_config_init(phydev); 332 } 333 334 static int bcm5482_config_init(struct phy_device *phydev) 335 { 336 int err, reg; 337 338 err = bcm54xx_config_init(phydev); 339 340 if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) { 341 /* 342 * Enable secondary SerDes and its use as an LED source 343 */ 344 reg = bcm_phy_read_shadow(phydev, BCM5482_SHD_SSD); 345 bcm_phy_write_shadow(phydev, BCM5482_SHD_SSD, 346 reg | 347 BCM5482_SHD_SSD_LEDM | 348 BCM5482_SHD_SSD_EN); 349 350 /* 351 * Enable SGMII slave mode and auto-detection 352 */ 353 reg = BCM5482_SSD_SGMII_SLAVE | 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, err | 358 BCM5482_SSD_SGMII_SLAVE_EN | 359 BCM5482_SSD_SGMII_SLAVE_AD); 360 if (err < 0) 361 return err; 362 363 /* 364 * Disable secondary SerDes powerdown 365 */ 366 reg = BCM5482_SSD_1000BX_CTL | MII_BCM54XX_EXP_SEL_SSD; 367 err = bcm_phy_read_exp(phydev, reg); 368 if (err < 0) 369 return err; 370 err = bcm_phy_write_exp(phydev, reg, 371 err & ~BCM5482_SSD_1000BX_CTL_PWRDOWN); 372 if (err < 0) 373 return err; 374 375 /* 376 * Select 1000BASE-X register set (primary SerDes) 377 */ 378 reg = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE); 379 bcm_phy_write_shadow(phydev, BCM54XX_SHD_MODE, 380 reg | BCM54XX_SHD_MODE_1000BX); 381 382 /* 383 * LED1=ACTIVITYLED, LED3=LINKSPD[2] 384 * (Use LED1 as secondary SerDes ACTIVITY LED) 385 */ 386 bcm_phy_write_shadow(phydev, BCM5482_SHD_LEDS1, 387 BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_ACTIVITYLED) | 388 BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_LINKSPD2)); 389 390 /* 391 * Auto-negotiation doesn't seem to work quite right 392 * in this mode, so we disable it and force it to the 393 * right speed/duplex setting. Only 'link status' 394 * is important. 395 */ 396 phydev->autoneg = AUTONEG_DISABLE; 397 phydev->speed = SPEED_1000; 398 phydev->duplex = DUPLEX_FULL; 399 } 400 401 return err; 402 } 403 404 static int bcm5482_read_status(struct phy_device *phydev) 405 { 406 int err; 407 408 err = genphy_read_status(phydev); 409 410 if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) { 411 /* 412 * Only link status matters for 1000Base-X mode, so force 413 * 1000 Mbit/s full-duplex status 414 */ 415 if (phydev->link) { 416 phydev->speed = SPEED_1000; 417 phydev->duplex = DUPLEX_FULL; 418 } 419 } 420 421 return err; 422 } 423 424 static int bcm5481_config_aneg(struct phy_device *phydev) 425 { 426 struct device_node *np = phydev->mdio.dev.of_node; 427 int ret; 428 429 /* Aneg firstly. */ 430 ret = genphy_config_aneg(phydev); 431 432 /* Then we can set up the delay. */ 433 bcm54xx_config_clock_delay(phydev); 434 435 if (of_property_read_bool(np, "enet-phy-lane-swap")) { 436 /* Lane Swap - Undocumented register...magic! */ 437 ret = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_SEL_ER + 0x9, 438 0x11B); 439 if (ret < 0) 440 return ret; 441 } 442 443 return ret; 444 } 445 446 static int bcm54616s_probe(struct phy_device *phydev) 447 { 448 int val, intf_sel; 449 450 val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE); 451 if (val < 0) 452 return val; 453 454 /* The PHY is strapped in RGMII-fiber mode when INTERF_SEL[1:0] 455 * is 01b, and the link between PHY and its link partner can be 456 * either 1000Base-X or 100Base-FX. 457 * RGMII-1000Base-X is properly supported, but RGMII-100Base-FX 458 * support is still missing as of now. 459 */ 460 intf_sel = (val & BCM54XX_SHD_INTF_SEL_MASK) >> 1; 461 if (intf_sel == 1) { 462 val = bcm_phy_read_shadow(phydev, BCM54616S_SHD_100FX_CTRL); 463 if (val < 0) 464 return val; 465 466 /* Bit 0 of the SerDes 100-FX Control register, when set 467 * to 1, sets the MII/RGMII -> 100BASE-FX configuration. 468 * When this bit is set to 0, it sets the GMII/RGMII -> 469 * 1000BASE-X configuration. 470 */ 471 if (!(val & BCM54616S_100FX_MODE)) 472 phydev->dev_flags |= PHY_BCM_FLAGS_MODE_1000BX; 473 } 474 475 return 0; 476 } 477 478 static int bcm54616s_config_aneg(struct phy_device *phydev) 479 { 480 int ret; 481 482 /* Aneg firstly. */ 483 if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) 484 ret = genphy_c37_config_aneg(phydev); 485 else 486 ret = genphy_config_aneg(phydev); 487 488 /* Then we can set up the delay. */ 489 bcm54xx_config_clock_delay(phydev); 490 491 return ret; 492 } 493 494 static int bcm54616s_read_status(struct phy_device *phydev) 495 { 496 int err; 497 498 if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) 499 err = genphy_c37_read_status(phydev); 500 else 501 err = genphy_read_status(phydev); 502 503 return err; 504 } 505 506 static int brcm_phy_setbits(struct phy_device *phydev, int reg, int set) 507 { 508 int val; 509 510 val = phy_read(phydev, reg); 511 if (val < 0) 512 return val; 513 514 return phy_write(phydev, reg, val | set); 515 } 516 517 static int brcm_fet_config_init(struct phy_device *phydev) 518 { 519 int reg, err, err2, brcmtest; 520 521 /* Reset the PHY to bring it to a known state. */ 522 err = phy_write(phydev, MII_BMCR, BMCR_RESET); 523 if (err < 0) 524 return err; 525 526 reg = phy_read(phydev, MII_BRCM_FET_INTREG); 527 if (reg < 0) 528 return reg; 529 530 /* Unmask events we are interested in and mask interrupts globally. */ 531 reg = MII_BRCM_FET_IR_DUPLEX_EN | 532 MII_BRCM_FET_IR_SPEED_EN | 533 MII_BRCM_FET_IR_LINK_EN | 534 MII_BRCM_FET_IR_ENABLE | 535 MII_BRCM_FET_IR_MASK; 536 537 err = phy_write(phydev, MII_BRCM_FET_INTREG, reg); 538 if (err < 0) 539 return err; 540 541 /* Enable shadow register access */ 542 brcmtest = phy_read(phydev, MII_BRCM_FET_BRCMTEST); 543 if (brcmtest < 0) 544 return brcmtest; 545 546 reg = brcmtest | MII_BRCM_FET_BT_SRE; 547 548 err = phy_write(phydev, MII_BRCM_FET_BRCMTEST, reg); 549 if (err < 0) 550 return err; 551 552 /* Set the LED mode */ 553 reg = phy_read(phydev, MII_BRCM_FET_SHDW_AUXMODE4); 554 if (reg < 0) { 555 err = reg; 556 goto done; 557 } 558 559 reg &= ~MII_BRCM_FET_SHDW_AM4_LED_MASK; 560 reg |= MII_BRCM_FET_SHDW_AM4_LED_MODE1; 561 562 err = phy_write(phydev, MII_BRCM_FET_SHDW_AUXMODE4, reg); 563 if (err < 0) 564 goto done; 565 566 /* Enable auto MDIX */ 567 err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_MISCCTRL, 568 MII_BRCM_FET_SHDW_MC_FAME); 569 if (err < 0) 570 goto done; 571 572 if (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE) { 573 /* Enable auto power down */ 574 err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2, 575 MII_BRCM_FET_SHDW_AS2_APDE); 576 } 577 578 done: 579 /* Disable shadow register access */ 580 err2 = phy_write(phydev, MII_BRCM_FET_BRCMTEST, brcmtest); 581 if (!err) 582 err = err2; 583 584 return err; 585 } 586 587 static int brcm_fet_ack_interrupt(struct phy_device *phydev) 588 { 589 int reg; 590 591 /* Clear pending interrupts. */ 592 reg = phy_read(phydev, MII_BRCM_FET_INTREG); 593 if (reg < 0) 594 return reg; 595 596 return 0; 597 } 598 599 static int brcm_fet_config_intr(struct phy_device *phydev) 600 { 601 int reg, err; 602 603 reg = phy_read(phydev, MII_BRCM_FET_INTREG); 604 if (reg < 0) 605 return reg; 606 607 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 608 reg &= ~MII_BRCM_FET_IR_MASK; 609 else 610 reg |= MII_BRCM_FET_IR_MASK; 611 612 err = phy_write(phydev, MII_BRCM_FET_INTREG, reg); 613 return err; 614 } 615 616 struct bcm53xx_phy_priv { 617 u64 *stats; 618 }; 619 620 static int bcm53xx_phy_probe(struct phy_device *phydev) 621 { 622 struct bcm53xx_phy_priv *priv; 623 624 priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL); 625 if (!priv) 626 return -ENOMEM; 627 628 phydev->priv = priv; 629 630 priv->stats = devm_kcalloc(&phydev->mdio.dev, 631 bcm_phy_get_sset_count(phydev), sizeof(u64), 632 GFP_KERNEL); 633 if (!priv->stats) 634 return -ENOMEM; 635 636 return 0; 637 } 638 639 static void bcm53xx_phy_get_stats(struct phy_device *phydev, 640 struct ethtool_stats *stats, u64 *data) 641 { 642 struct bcm53xx_phy_priv *priv = phydev->priv; 643 644 bcm_phy_get_stats(phydev, priv->stats, stats, data); 645 } 646 647 static struct phy_driver broadcom_drivers[] = { 648 { 649 .phy_id = PHY_ID_BCM5411, 650 .phy_id_mask = 0xfffffff0, 651 .name = "Broadcom BCM5411", 652 /* PHY_GBIT_FEATURES */ 653 .config_init = bcm54xx_config_init, 654 .ack_interrupt = bcm_phy_ack_intr, 655 .config_intr = bcm_phy_config_intr, 656 }, { 657 .phy_id = PHY_ID_BCM5421, 658 .phy_id_mask = 0xfffffff0, 659 .name = "Broadcom BCM5421", 660 /* PHY_GBIT_FEATURES */ 661 .config_init = bcm54xx_config_init, 662 .ack_interrupt = bcm_phy_ack_intr, 663 .config_intr = bcm_phy_config_intr, 664 }, { 665 .phy_id = PHY_ID_BCM54210E, 666 .phy_id_mask = 0xfffffff0, 667 .name = "Broadcom BCM54210E", 668 /* PHY_GBIT_FEATURES */ 669 .config_init = bcm54xx_config_init, 670 .ack_interrupt = bcm_phy_ack_intr, 671 .config_intr = bcm_phy_config_intr, 672 }, { 673 .phy_id = PHY_ID_BCM5461, 674 .phy_id_mask = 0xfffffff0, 675 .name = "Broadcom BCM5461", 676 /* PHY_GBIT_FEATURES */ 677 .config_init = bcm54xx_config_init, 678 .ack_interrupt = bcm_phy_ack_intr, 679 .config_intr = bcm_phy_config_intr, 680 }, { 681 .phy_id = PHY_ID_BCM54612E, 682 .phy_id_mask = 0xfffffff0, 683 .name = "Broadcom BCM54612E", 684 /* 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_BCM54616S, 690 .phy_id_mask = 0xfffffff0, 691 .name = "Broadcom BCM54616S", 692 /* PHY_GBIT_FEATURES */ 693 .config_init = bcm54xx_config_init, 694 .config_aneg = bcm54616s_config_aneg, 695 .ack_interrupt = bcm_phy_ack_intr, 696 .config_intr = bcm_phy_config_intr, 697 .read_status = bcm54616s_read_status, 698 .probe = bcm54616s_probe, 699 }, { 700 .phy_id = PHY_ID_BCM5464, 701 .phy_id_mask = 0xfffffff0, 702 .name = "Broadcom BCM5464", 703 /* PHY_GBIT_FEATURES */ 704 .config_init = bcm54xx_config_init, 705 .ack_interrupt = bcm_phy_ack_intr, 706 .config_intr = bcm_phy_config_intr, 707 .suspend = genphy_suspend, 708 .resume = genphy_resume, 709 }, { 710 .phy_id = PHY_ID_BCM5481, 711 .phy_id_mask = 0xfffffff0, 712 .name = "Broadcom BCM5481", 713 /* PHY_GBIT_FEATURES */ 714 .config_init = bcm54xx_config_init, 715 .config_aneg = bcm5481_config_aneg, 716 .ack_interrupt = bcm_phy_ack_intr, 717 .config_intr = bcm_phy_config_intr, 718 }, { 719 .phy_id = PHY_ID_BCM54810, 720 .phy_id_mask = 0xfffffff0, 721 .name = "Broadcom BCM54810", 722 /* PHY_GBIT_FEATURES */ 723 .config_init = bcm54xx_config_init, 724 .config_aneg = bcm5481_config_aneg, 725 .ack_interrupt = bcm_phy_ack_intr, 726 .config_intr = bcm_phy_config_intr, 727 .suspend = genphy_suspend, 728 .resume = bcm54xx_resume, 729 }, { 730 .phy_id = PHY_ID_BCM5482, 731 .phy_id_mask = 0xfffffff0, 732 .name = "Broadcom BCM5482", 733 /* PHY_GBIT_FEATURES */ 734 .config_init = bcm5482_config_init, 735 .read_status = bcm5482_read_status, 736 .ack_interrupt = bcm_phy_ack_intr, 737 .config_intr = bcm_phy_config_intr, 738 }, { 739 .phy_id = PHY_ID_BCM50610, 740 .phy_id_mask = 0xfffffff0, 741 .name = "Broadcom BCM50610", 742 /* PHY_GBIT_FEATURES */ 743 .config_init = bcm54xx_config_init, 744 .ack_interrupt = bcm_phy_ack_intr, 745 .config_intr = bcm_phy_config_intr, 746 }, { 747 .phy_id = PHY_ID_BCM50610M, 748 .phy_id_mask = 0xfffffff0, 749 .name = "Broadcom BCM50610M", 750 /* PHY_GBIT_FEATURES */ 751 .config_init = bcm54xx_config_init, 752 .ack_interrupt = bcm_phy_ack_intr, 753 .config_intr = bcm_phy_config_intr, 754 }, { 755 .phy_id = PHY_ID_BCM57780, 756 .phy_id_mask = 0xfffffff0, 757 .name = "Broadcom BCM57780", 758 /* PHY_GBIT_FEATURES */ 759 .config_init = bcm54xx_config_init, 760 .ack_interrupt = bcm_phy_ack_intr, 761 .config_intr = bcm_phy_config_intr, 762 }, { 763 .phy_id = PHY_ID_BCMAC131, 764 .phy_id_mask = 0xfffffff0, 765 .name = "Broadcom BCMAC131", 766 /* PHY_BASIC_FEATURES */ 767 .config_init = brcm_fet_config_init, 768 .ack_interrupt = brcm_fet_ack_interrupt, 769 .config_intr = brcm_fet_config_intr, 770 }, { 771 .phy_id = PHY_ID_BCM5241, 772 .phy_id_mask = 0xfffffff0, 773 .name = "Broadcom BCM5241", 774 /* PHY_BASIC_FEATURES */ 775 .config_init = brcm_fet_config_init, 776 .ack_interrupt = brcm_fet_ack_interrupt, 777 .config_intr = brcm_fet_config_intr, 778 }, { 779 .phy_id = PHY_ID_BCM5395, 780 .phy_id_mask = 0xfffffff0, 781 .name = "Broadcom BCM5395", 782 .flags = PHY_IS_INTERNAL, 783 /* PHY_GBIT_FEATURES */ 784 .get_sset_count = bcm_phy_get_sset_count, 785 .get_strings = bcm_phy_get_strings, 786 .get_stats = bcm53xx_phy_get_stats, 787 .probe = bcm53xx_phy_probe, 788 }, { 789 .phy_id = PHY_ID_BCM89610, 790 .phy_id_mask = 0xfffffff0, 791 .name = "Broadcom BCM89610", 792 /* PHY_GBIT_FEATURES */ 793 .config_init = bcm54xx_config_init, 794 .ack_interrupt = bcm_phy_ack_intr, 795 .config_intr = bcm_phy_config_intr, 796 } }; 797 798 module_phy_driver(broadcom_drivers); 799 800 static struct mdio_device_id __maybe_unused broadcom_tbl[] = { 801 { PHY_ID_BCM5411, 0xfffffff0 }, 802 { PHY_ID_BCM5421, 0xfffffff0 }, 803 { PHY_ID_BCM54210E, 0xfffffff0 }, 804 { PHY_ID_BCM5461, 0xfffffff0 }, 805 { PHY_ID_BCM54612E, 0xfffffff0 }, 806 { PHY_ID_BCM54616S, 0xfffffff0 }, 807 { PHY_ID_BCM5464, 0xfffffff0 }, 808 { PHY_ID_BCM5481, 0xfffffff0 }, 809 { PHY_ID_BCM54810, 0xfffffff0 }, 810 { PHY_ID_BCM5482, 0xfffffff0 }, 811 { PHY_ID_BCM50610, 0xfffffff0 }, 812 { PHY_ID_BCM50610M, 0xfffffff0 }, 813 { PHY_ID_BCM57780, 0xfffffff0 }, 814 { PHY_ID_BCMAC131, 0xfffffff0 }, 815 { PHY_ID_BCM5241, 0xfffffff0 }, 816 { PHY_ID_BCM5395, 0xfffffff0 }, 817 { PHY_ID_BCM89610, 0xfffffff0 }, 818 { } 819 }; 820 821 MODULE_DEVICE_TABLE(mdio, broadcom_tbl); 822