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 bcm5481x_config(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 bcm5481x_config(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 brcm_phy_setbits(struct phy_device *phydev, int reg, int set) 446 { 447 int val; 448 449 val = phy_read(phydev, reg); 450 if (val < 0) 451 return val; 452 453 return phy_write(phydev, reg, val | set); 454 } 455 456 static int brcm_fet_config_init(struct phy_device *phydev) 457 { 458 int reg, err, err2, brcmtest; 459 460 /* Reset the PHY to bring it to a known state. */ 461 err = phy_write(phydev, MII_BMCR, BMCR_RESET); 462 if (err < 0) 463 return err; 464 465 reg = phy_read(phydev, MII_BRCM_FET_INTREG); 466 if (reg < 0) 467 return reg; 468 469 /* Unmask events we are interested in and mask interrupts globally. */ 470 reg = MII_BRCM_FET_IR_DUPLEX_EN | 471 MII_BRCM_FET_IR_SPEED_EN | 472 MII_BRCM_FET_IR_LINK_EN | 473 MII_BRCM_FET_IR_ENABLE | 474 MII_BRCM_FET_IR_MASK; 475 476 err = phy_write(phydev, MII_BRCM_FET_INTREG, reg); 477 if (err < 0) 478 return err; 479 480 /* Enable shadow register access */ 481 brcmtest = phy_read(phydev, MII_BRCM_FET_BRCMTEST); 482 if (brcmtest < 0) 483 return brcmtest; 484 485 reg = brcmtest | MII_BRCM_FET_BT_SRE; 486 487 err = phy_write(phydev, MII_BRCM_FET_BRCMTEST, reg); 488 if (err < 0) 489 return err; 490 491 /* Set the LED mode */ 492 reg = phy_read(phydev, MII_BRCM_FET_SHDW_AUXMODE4); 493 if (reg < 0) { 494 err = reg; 495 goto done; 496 } 497 498 reg &= ~MII_BRCM_FET_SHDW_AM4_LED_MASK; 499 reg |= MII_BRCM_FET_SHDW_AM4_LED_MODE1; 500 501 err = phy_write(phydev, MII_BRCM_FET_SHDW_AUXMODE4, reg); 502 if (err < 0) 503 goto done; 504 505 /* Enable auto MDIX */ 506 err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_MISCCTRL, 507 MII_BRCM_FET_SHDW_MC_FAME); 508 if (err < 0) 509 goto done; 510 511 if (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE) { 512 /* Enable auto power down */ 513 err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2, 514 MII_BRCM_FET_SHDW_AS2_APDE); 515 } 516 517 done: 518 /* Disable shadow register access */ 519 err2 = phy_write(phydev, MII_BRCM_FET_BRCMTEST, brcmtest); 520 if (!err) 521 err = err2; 522 523 return err; 524 } 525 526 static int brcm_fet_ack_interrupt(struct phy_device *phydev) 527 { 528 int reg; 529 530 /* Clear pending interrupts. */ 531 reg = phy_read(phydev, MII_BRCM_FET_INTREG); 532 if (reg < 0) 533 return reg; 534 535 return 0; 536 } 537 538 static int brcm_fet_config_intr(struct phy_device *phydev) 539 { 540 int reg, err; 541 542 reg = phy_read(phydev, MII_BRCM_FET_INTREG); 543 if (reg < 0) 544 return reg; 545 546 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 547 reg &= ~MII_BRCM_FET_IR_MASK; 548 else 549 reg |= MII_BRCM_FET_IR_MASK; 550 551 err = phy_write(phydev, MII_BRCM_FET_INTREG, reg); 552 return err; 553 } 554 555 struct bcm53xx_phy_priv { 556 u64 *stats; 557 }; 558 559 static int bcm53xx_phy_probe(struct phy_device *phydev) 560 { 561 struct bcm53xx_phy_priv *priv; 562 563 priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL); 564 if (!priv) 565 return -ENOMEM; 566 567 phydev->priv = priv; 568 569 priv->stats = devm_kcalloc(&phydev->mdio.dev, 570 bcm_phy_get_sset_count(phydev), sizeof(u64), 571 GFP_KERNEL); 572 if (!priv->stats) 573 return -ENOMEM; 574 575 return 0; 576 } 577 578 static void bcm53xx_phy_get_stats(struct phy_device *phydev, 579 struct ethtool_stats *stats, u64 *data) 580 { 581 struct bcm53xx_phy_priv *priv = phydev->priv; 582 583 bcm_phy_get_stats(phydev, priv->stats, stats, data); 584 } 585 586 static struct phy_driver broadcom_drivers[] = { 587 { 588 .phy_id = PHY_ID_BCM5411, 589 .phy_id_mask = 0xfffffff0, 590 .name = "Broadcom BCM5411", 591 .features = PHY_GBIT_FEATURES, 592 .flags = PHY_HAS_INTERRUPT, 593 .config_init = bcm54xx_config_init, 594 .ack_interrupt = bcm_phy_ack_intr, 595 .config_intr = bcm_phy_config_intr, 596 }, { 597 .phy_id = PHY_ID_BCM5421, 598 .phy_id_mask = 0xfffffff0, 599 .name = "Broadcom BCM5421", 600 .features = PHY_GBIT_FEATURES, 601 .flags = PHY_HAS_INTERRUPT, 602 .config_init = bcm54xx_config_init, 603 .ack_interrupt = bcm_phy_ack_intr, 604 .config_intr = bcm_phy_config_intr, 605 }, { 606 .phy_id = PHY_ID_BCM54210E, 607 .phy_id_mask = 0xfffffff0, 608 .name = "Broadcom BCM54210E", 609 .features = PHY_GBIT_FEATURES, 610 .flags = PHY_HAS_INTERRUPT, 611 .config_init = bcm54xx_config_init, 612 .ack_interrupt = bcm_phy_ack_intr, 613 .config_intr = bcm_phy_config_intr, 614 }, { 615 .phy_id = PHY_ID_BCM5461, 616 .phy_id_mask = 0xfffffff0, 617 .name = "Broadcom BCM5461", 618 .features = PHY_GBIT_FEATURES, 619 .flags = PHY_HAS_INTERRUPT, 620 .config_init = bcm54xx_config_init, 621 .ack_interrupt = bcm_phy_ack_intr, 622 .config_intr = bcm_phy_config_intr, 623 }, { 624 .phy_id = PHY_ID_BCM54612E, 625 .phy_id_mask = 0xfffffff0, 626 .name = "Broadcom BCM54612E", 627 .features = PHY_GBIT_FEATURES, 628 .flags = PHY_HAS_INTERRUPT, 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_BCM54616S, 634 .phy_id_mask = 0xfffffff0, 635 .name = "Broadcom BCM54616S", 636 .features = PHY_GBIT_FEATURES, 637 .flags = PHY_HAS_INTERRUPT, 638 .config_init = bcm54xx_config_init, 639 .ack_interrupt = bcm_phy_ack_intr, 640 .config_intr = bcm_phy_config_intr, 641 }, { 642 .phy_id = PHY_ID_BCM5464, 643 .phy_id_mask = 0xfffffff0, 644 .name = "Broadcom BCM5464", 645 .features = PHY_GBIT_FEATURES, 646 .flags = PHY_HAS_INTERRUPT, 647 .config_init = bcm54xx_config_init, 648 .ack_interrupt = bcm_phy_ack_intr, 649 .config_intr = bcm_phy_config_intr, 650 }, { 651 .phy_id = PHY_ID_BCM5481, 652 .phy_id_mask = 0xfffffff0, 653 .name = "Broadcom BCM5481", 654 .features = PHY_GBIT_FEATURES, 655 .flags = PHY_HAS_INTERRUPT, 656 .config_init = bcm54xx_config_init, 657 .config_aneg = bcm5481_config_aneg, 658 .ack_interrupt = bcm_phy_ack_intr, 659 .config_intr = bcm_phy_config_intr, 660 }, { 661 .phy_id = PHY_ID_BCM54810, 662 .phy_id_mask = 0xfffffff0, 663 .name = "Broadcom BCM54810", 664 .features = PHY_GBIT_FEATURES, 665 .flags = PHY_HAS_INTERRUPT, 666 .config_init = bcm54xx_config_init, 667 .config_aneg = bcm5481_config_aneg, 668 .ack_interrupt = bcm_phy_ack_intr, 669 .config_intr = bcm_phy_config_intr, 670 }, { 671 .phy_id = PHY_ID_BCM5482, 672 .phy_id_mask = 0xfffffff0, 673 .name = "Broadcom BCM5482", 674 .features = PHY_GBIT_FEATURES, 675 .flags = PHY_HAS_INTERRUPT, 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 .flags = PHY_HAS_INTERRUPT, 686 .config_init = bcm54xx_config_init, 687 .ack_interrupt = bcm_phy_ack_intr, 688 .config_intr = bcm_phy_config_intr, 689 }, { 690 .phy_id = PHY_ID_BCM50610M, 691 .phy_id_mask = 0xfffffff0, 692 .name = "Broadcom BCM50610M", 693 .features = PHY_GBIT_FEATURES, 694 .flags = PHY_HAS_INTERRUPT, 695 .config_init = bcm54xx_config_init, 696 .ack_interrupt = bcm_phy_ack_intr, 697 .config_intr = bcm_phy_config_intr, 698 }, { 699 .phy_id = PHY_ID_BCM57780, 700 .phy_id_mask = 0xfffffff0, 701 .name = "Broadcom BCM57780", 702 .features = PHY_GBIT_FEATURES, 703 .flags = PHY_HAS_INTERRUPT, 704 .config_init = bcm54xx_config_init, 705 .ack_interrupt = bcm_phy_ack_intr, 706 .config_intr = bcm_phy_config_intr, 707 }, { 708 .phy_id = PHY_ID_BCMAC131, 709 .phy_id_mask = 0xfffffff0, 710 .name = "Broadcom BCMAC131", 711 .features = PHY_BASIC_FEATURES, 712 .flags = PHY_HAS_INTERRUPT, 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 .flags = PHY_HAS_INTERRUPT, 722 .config_init = brcm_fet_config_init, 723 .ack_interrupt = brcm_fet_ack_interrupt, 724 .config_intr = brcm_fet_config_intr, 725 }, { 726 .phy_id = PHY_ID_BCM5395, 727 .phy_id_mask = 0xfffffff0, 728 .name = "Broadcom BCM5395", 729 .flags = PHY_IS_INTERNAL, 730 .features = PHY_GBIT_FEATURES, 731 .get_sset_count = bcm_phy_get_sset_count, 732 .get_strings = bcm_phy_get_strings, 733 .get_stats = bcm53xx_phy_get_stats, 734 .probe = bcm53xx_phy_probe, 735 }, { 736 .phy_id = PHY_ID_BCM89610, 737 .phy_id_mask = 0xfffffff0, 738 .name = "Broadcom BCM89610", 739 .features = PHY_GBIT_FEATURES, 740 .flags = PHY_HAS_INTERRUPT, 741 .config_init = bcm54xx_config_init, 742 .ack_interrupt = bcm_phy_ack_intr, 743 .config_intr = bcm_phy_config_intr, 744 } }; 745 746 module_phy_driver(broadcom_drivers); 747 748 static struct mdio_device_id __maybe_unused broadcom_tbl[] = { 749 { PHY_ID_BCM5411, 0xfffffff0 }, 750 { PHY_ID_BCM5421, 0xfffffff0 }, 751 { PHY_ID_BCM54210E, 0xfffffff0 }, 752 { PHY_ID_BCM5461, 0xfffffff0 }, 753 { PHY_ID_BCM54612E, 0xfffffff0 }, 754 { PHY_ID_BCM54616S, 0xfffffff0 }, 755 { PHY_ID_BCM5464, 0xfffffff0 }, 756 { PHY_ID_BCM5481, 0xfffffff0 }, 757 { PHY_ID_BCM54810, 0xfffffff0 }, 758 { PHY_ID_BCM5482, 0xfffffff0 }, 759 { PHY_ID_BCM50610, 0xfffffff0 }, 760 { PHY_ID_BCM50610M, 0xfffffff0 }, 761 { PHY_ID_BCM57780, 0xfffffff0 }, 762 { PHY_ID_BCMAC131, 0xfffffff0 }, 763 { PHY_ID_BCM5241, 0xfffffff0 }, 764 { PHY_ID_BCM5395, 0xfffffff0 }, 765 { PHY_ID_BCM89610, 0xfffffff0 }, 766 { } 767 }; 768 769 MODULE_DEVICE_TABLE(mdio, broadcom_tbl); 770