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