1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Broadcom BCM7xxx internal transceivers support. 4 * 5 * Copyright (C) 2014-2017 Broadcom 6 */ 7 8 #include <linux/module.h> 9 #include <linux/phy.h> 10 #include <linux/delay.h> 11 #include "bcm-phy-lib.h" 12 #include <linux/bitops.h> 13 #include <linux/brcmphy.h> 14 #include <linux/clk.h> 15 #include <linux/mdio.h> 16 17 /* Broadcom BCM7xxx internal PHY registers */ 18 19 /* EPHY only register definitions */ 20 #define MII_BCM7XXX_100TX_AUX_CTL 0x10 21 #define MII_BCM7XXX_100TX_FALSE_CAR 0x13 22 #define MII_BCM7XXX_100TX_DISC 0x14 23 #define MII_BCM7XXX_AUX_MODE 0x1d 24 #define MII_BCM7XXX_64CLK_MDIO BIT(12) 25 #define MII_BCM7XXX_TEST 0x1f 26 #define MII_BCM7XXX_SHD_MODE_2 BIT(2) 27 #define MII_BCM7XXX_SHD_2_ADDR_CTRL 0xe 28 #define MII_BCM7XXX_SHD_2_CTRL_STAT 0xf 29 #define MII_BCM7XXX_SHD_2_BIAS_TRIM 0x1a 30 #define MII_BCM7XXX_SHD_3_AN_EEE_ADV 0x3 31 #define MII_BCM7XXX_SHD_3_PCS_CTRL_2 0x6 32 #define MII_BCM7XXX_PCS_CTRL_2_DEF 0x4400 33 #define MII_BCM7XXX_SHD_3_AN_STAT 0xb 34 #define MII_BCM7XXX_AN_NULL_MSG_EN BIT(0) 35 #define MII_BCM7XXX_AN_EEE_EN BIT(1) 36 #define MII_BCM7XXX_SHD_3_EEE_THRESH 0xe 37 #define MII_BCM7XXX_EEE_THRESH_DEF 0x50 38 #define MII_BCM7XXX_SHD_3_TL4 0x23 39 #define MII_BCM7XXX_TL4_RST_MSK (BIT(2) | BIT(1)) 40 41 struct bcm7xxx_phy_priv { 42 u64 *stats; 43 struct clk *clk; 44 }; 45 46 static int bcm7xxx_28nm_d0_afe_config_init(struct phy_device *phydev) 47 { 48 /* AFE_RXCONFIG_0 */ 49 bcm_phy_write_misc(phydev, AFE_RXCONFIG_0, 0xeb15); 50 51 /* AFE_RXCONFIG_1 */ 52 bcm_phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9b2f); 53 54 /* AFE_RXCONFIG_2, set rCal offset for HT=0 code and LT=-2 code */ 55 bcm_phy_write_misc(phydev, AFE_RXCONFIG_2, 0x2003); 56 57 /* AFE_RX_LP_COUNTER, set RX bandwidth to maximum */ 58 bcm_phy_write_misc(phydev, AFE_RX_LP_COUNTER, 0x7fc0); 59 60 /* AFE_TX_CONFIG, set 100BT Cfeed=011 to improve rise/fall time */ 61 bcm_phy_write_misc(phydev, AFE_TX_CONFIG, 0x431); 62 63 /* AFE_VDCA_ICTRL_0, set Iq=1101 instead of 0111 for AB symmetry */ 64 bcm_phy_write_misc(phydev, AFE_VDCA_ICTRL_0, 0xa7da); 65 66 /* AFE_VDAC_OTHERS_0, set 1000BT Cidac=010 for all ports */ 67 bcm_phy_write_misc(phydev, AFE_VDAC_OTHERS_0, 0xa020); 68 69 /* AFE_HPF_TRIM_OTHERS, set 100Tx/10BT to -4.5% swing and set rCal 70 * offset for HT=0 code 71 */ 72 bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x00e3); 73 74 /* CORE_BASE1E, force trim to overwrite and set I_ext trim to 0000 */ 75 phy_write(phydev, MII_BRCM_CORE_BASE1E, 0x0010); 76 77 /* DSP_TAP10, adjust bias current trim (+0% swing, +0 tick) */ 78 bcm_phy_write_misc(phydev, DSP_TAP10, 0x011b); 79 80 /* Reset R_CAL/RC_CAL engine */ 81 bcm_phy_r_rc_cal_reset(phydev); 82 83 return 0; 84 } 85 86 static int bcm7xxx_28nm_e0_plus_afe_config_init(struct phy_device *phydev) 87 { 88 /* AFE_RXCONFIG_1, provide more margin for INL/DNL measurement */ 89 bcm_phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9b2f); 90 91 /* AFE_TX_CONFIG, set 100BT Cfeed=011 to improve rise/fall time */ 92 bcm_phy_write_misc(phydev, AFE_TX_CONFIG, 0x431); 93 94 /* AFE_VDCA_ICTRL_0, set Iq=1101 instead of 0111 for AB symmetry */ 95 bcm_phy_write_misc(phydev, AFE_VDCA_ICTRL_0, 0xa7da); 96 97 /* AFE_HPF_TRIM_OTHERS, set 100Tx/10BT to -4.5% swing and set rCal 98 * offset for HT=0 code 99 */ 100 bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x00e3); 101 102 /* CORE_BASE1E, force trim to overwrite and set I_ext trim to 0000 */ 103 phy_write(phydev, MII_BRCM_CORE_BASE1E, 0x0010); 104 105 /* DSP_TAP10, adjust bias current trim (+0% swing, +0 tick) */ 106 bcm_phy_write_misc(phydev, DSP_TAP10, 0x011b); 107 108 /* Reset R_CAL/RC_CAL engine */ 109 bcm_phy_r_rc_cal_reset(phydev); 110 111 return 0; 112 } 113 114 static int bcm7xxx_28nm_a0_patch_afe_config_init(struct phy_device *phydev) 115 { 116 /* +1 RC_CAL codes for RL centering for both LT and HT conditions */ 117 bcm_phy_write_misc(phydev, AFE_RXCONFIG_2, 0xd003); 118 119 /* Cut master bias current by 2% to compensate for RC_CAL offset */ 120 bcm_phy_write_misc(phydev, DSP_TAP10, 0x791b); 121 122 /* Improve hybrid leakage */ 123 bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x10e3); 124 125 /* Change rx_on_tune 8 to 0xf */ 126 bcm_phy_write_misc(phydev, 0x21, 0x2, 0x87f6); 127 128 /* Change 100Tx EEE bandwidth */ 129 bcm_phy_write_misc(phydev, 0x22, 0x2, 0x017d); 130 131 /* Enable ffe zero detection for Vitesse interoperability */ 132 bcm_phy_write_misc(phydev, 0x26, 0x2, 0x0015); 133 134 bcm_phy_r_rc_cal_reset(phydev); 135 136 return 0; 137 } 138 139 static int bcm7xxx_28nm_config_init(struct phy_device *phydev) 140 { 141 u8 rev = PHY_BRCM_7XXX_REV(phydev->dev_flags); 142 u8 patch = PHY_BRCM_7XXX_PATCH(phydev->dev_flags); 143 u8 count; 144 int ret = 0; 145 146 /* Newer devices have moved the revision information back into a 147 * standard location in MII_PHYS_ID[23] 148 */ 149 if (rev == 0) 150 rev = phydev->phy_id & ~phydev->drv->phy_id_mask; 151 152 pr_info_once("%s: %s PHY revision: 0x%02x, patch: %d\n", 153 phydev_name(phydev), phydev->drv->name, rev, patch); 154 155 /* Dummy read to a register to workaround an issue upon reset where the 156 * internal inverter may not allow the first MDIO transaction to pass 157 * the MDIO management controller and make us return 0xffff for such 158 * reads. 159 */ 160 phy_read(phydev, MII_BMSR); 161 162 switch (rev) { 163 case 0xa0: 164 case 0xb0: 165 ret = bcm_phy_28nm_a0b0_afe_config_init(phydev); 166 break; 167 case 0xd0: 168 ret = bcm7xxx_28nm_d0_afe_config_init(phydev); 169 break; 170 case 0xe0: 171 case 0xf0: 172 /* Rev G0 introduces a roll over */ 173 case 0x10: 174 ret = bcm7xxx_28nm_e0_plus_afe_config_init(phydev); 175 break; 176 case 0x01: 177 ret = bcm7xxx_28nm_a0_patch_afe_config_init(phydev); 178 break; 179 default: 180 break; 181 } 182 183 if (ret) 184 return ret; 185 186 ret = bcm_phy_enable_jumbo(phydev); 187 if (ret) 188 return ret; 189 190 ret = bcm_phy_downshift_get(phydev, &count); 191 if (ret) 192 return ret; 193 194 /* Only enable EEE if Wirespeed/downshift is disabled */ 195 ret = bcm_phy_set_eee(phydev, count == DOWNSHIFT_DEV_DISABLE); 196 if (ret) 197 return ret; 198 199 return bcm_phy_enable_apd(phydev, true); 200 } 201 202 static int bcm7xxx_28nm_resume(struct phy_device *phydev) 203 { 204 int ret; 205 206 /* Re-apply workarounds coming out suspend/resume */ 207 ret = bcm7xxx_28nm_config_init(phydev); 208 if (ret) 209 return ret; 210 211 /* 28nm Gigabit PHYs come out of reset without any half-duplex 212 * or "hub" compliant advertised mode, fix that. This does not 213 * cause any problems with the PHY library since genphy_config_aneg() 214 * gracefully handles auto-negotiated and forced modes. 215 */ 216 return genphy_config_aneg(phydev); 217 } 218 219 static int phy_set_clr_bits(struct phy_device *dev, int location, 220 int set_mask, int clr_mask) 221 { 222 int v, ret; 223 224 v = phy_read(dev, location); 225 if (v < 0) 226 return v; 227 228 v &= ~clr_mask; 229 v |= set_mask; 230 231 ret = phy_write(dev, location, v); 232 if (ret < 0) 233 return ret; 234 235 return v; 236 } 237 238 static int bcm7xxx_28nm_ephy_01_afe_config_init(struct phy_device *phydev) 239 { 240 int ret; 241 242 /* set shadow mode 2 */ 243 ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 244 MII_BCM7XXX_SHD_MODE_2, 0); 245 if (ret < 0) 246 return ret; 247 248 /* Set current trim values INT_trim = -1, Ext_trim =0 */ 249 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_BIAS_TRIM, 0x3BE0); 250 if (ret < 0) 251 goto reset_shadow_mode; 252 253 /* Cal reset */ 254 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL, 255 MII_BCM7XXX_SHD_3_TL4); 256 if (ret < 0) 257 goto reset_shadow_mode; 258 ret = phy_set_clr_bits(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT, 259 MII_BCM7XXX_TL4_RST_MSK, 0); 260 if (ret < 0) 261 goto reset_shadow_mode; 262 263 /* Cal reset disable */ 264 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL, 265 MII_BCM7XXX_SHD_3_TL4); 266 if (ret < 0) 267 goto reset_shadow_mode; 268 ret = phy_set_clr_bits(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT, 269 0, MII_BCM7XXX_TL4_RST_MSK); 270 if (ret < 0) 271 goto reset_shadow_mode; 272 273 reset_shadow_mode: 274 /* reset shadow mode 2 */ 275 ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0, 276 MII_BCM7XXX_SHD_MODE_2); 277 if (ret < 0) 278 return ret; 279 280 return 0; 281 } 282 283 /* The 28nm EPHY does not support Clause 45 (MMD) used by bcm-phy-lib */ 284 static int bcm7xxx_28nm_ephy_apd_enable(struct phy_device *phydev) 285 { 286 int ret; 287 288 /* set shadow mode 1 */ 289 ret = phy_set_clr_bits(phydev, MII_BRCM_FET_BRCMTEST, 290 MII_BRCM_FET_BT_SRE, 0); 291 if (ret < 0) 292 return ret; 293 294 /* Enable auto-power down */ 295 ret = phy_set_clr_bits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2, 296 MII_BRCM_FET_SHDW_AS2_APDE, 0); 297 if (ret < 0) 298 return ret; 299 300 /* reset shadow mode 1 */ 301 ret = phy_set_clr_bits(phydev, MII_BRCM_FET_BRCMTEST, 0, 302 MII_BRCM_FET_BT_SRE); 303 if (ret < 0) 304 return ret; 305 306 return 0; 307 } 308 309 static int bcm7xxx_28nm_ephy_eee_enable(struct phy_device *phydev) 310 { 311 int ret; 312 313 /* set shadow mode 2 */ 314 ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 315 MII_BCM7XXX_SHD_MODE_2, 0); 316 if (ret < 0) 317 return ret; 318 319 /* Advertise supported modes */ 320 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL, 321 MII_BCM7XXX_SHD_3_AN_EEE_ADV); 322 if (ret < 0) 323 goto reset_shadow_mode; 324 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT, 325 MDIO_EEE_100TX); 326 if (ret < 0) 327 goto reset_shadow_mode; 328 329 /* Restore Defaults */ 330 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL, 331 MII_BCM7XXX_SHD_3_PCS_CTRL_2); 332 if (ret < 0) 333 goto reset_shadow_mode; 334 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT, 335 MII_BCM7XXX_PCS_CTRL_2_DEF); 336 if (ret < 0) 337 goto reset_shadow_mode; 338 339 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL, 340 MII_BCM7XXX_SHD_3_EEE_THRESH); 341 if (ret < 0) 342 goto reset_shadow_mode; 343 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT, 344 MII_BCM7XXX_EEE_THRESH_DEF); 345 if (ret < 0) 346 goto reset_shadow_mode; 347 348 /* Enable EEE autonegotiation */ 349 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL, 350 MII_BCM7XXX_SHD_3_AN_STAT); 351 if (ret < 0) 352 goto reset_shadow_mode; 353 ret = phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT, 354 (MII_BCM7XXX_AN_NULL_MSG_EN | MII_BCM7XXX_AN_EEE_EN)); 355 if (ret < 0) 356 goto reset_shadow_mode; 357 358 reset_shadow_mode: 359 /* reset shadow mode 2 */ 360 ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0, 361 MII_BCM7XXX_SHD_MODE_2); 362 if (ret < 0) 363 return ret; 364 365 /* Restart autoneg */ 366 phy_write(phydev, MII_BMCR, 367 (BMCR_SPEED100 | BMCR_ANENABLE | BMCR_ANRESTART)); 368 369 return 0; 370 } 371 372 static int bcm7xxx_28nm_ephy_config_init(struct phy_device *phydev) 373 { 374 u8 rev = phydev->phy_id & ~phydev->drv->phy_id_mask; 375 int ret = 0; 376 377 pr_info_once("%s: %s PHY revision: 0x%02x\n", 378 phydev_name(phydev), phydev->drv->name, rev); 379 380 /* Dummy read to a register to workaround a possible issue upon reset 381 * where the internal inverter may not allow the first MDIO transaction 382 * to pass the MDIO management controller and make us return 0xffff for 383 * such reads. 384 */ 385 phy_read(phydev, MII_BMSR); 386 387 /* Apply AFE software work-around if necessary */ 388 if (rev == 0x01) { 389 ret = bcm7xxx_28nm_ephy_01_afe_config_init(phydev); 390 if (ret) 391 return ret; 392 } 393 394 ret = bcm7xxx_28nm_ephy_eee_enable(phydev); 395 if (ret) 396 return ret; 397 398 return bcm7xxx_28nm_ephy_apd_enable(phydev); 399 } 400 401 static int bcm7xxx_28nm_ephy_resume(struct phy_device *phydev) 402 { 403 int ret; 404 405 /* Re-apply workarounds coming out suspend/resume */ 406 ret = bcm7xxx_28nm_ephy_config_init(phydev); 407 if (ret) 408 return ret; 409 410 return genphy_config_aneg(phydev); 411 } 412 413 static int bcm7xxx_config_init(struct phy_device *phydev) 414 { 415 int ret; 416 417 /* Enable 64 clock MDIO */ 418 phy_write(phydev, MII_BCM7XXX_AUX_MODE, MII_BCM7XXX_64CLK_MDIO); 419 phy_read(phydev, MII_BCM7XXX_AUX_MODE); 420 421 /* set shadow mode 2 */ 422 ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 423 MII_BCM7XXX_SHD_MODE_2, MII_BCM7XXX_SHD_MODE_2); 424 if (ret < 0) 425 return ret; 426 427 /* set iddq_clkbias */ 428 phy_write(phydev, MII_BCM7XXX_100TX_DISC, 0x0F00); 429 udelay(10); 430 431 /* reset iddq_clkbias */ 432 phy_write(phydev, MII_BCM7XXX_100TX_DISC, 0x0C00); 433 434 phy_write(phydev, MII_BCM7XXX_100TX_FALSE_CAR, 0x7555); 435 436 /* reset shadow mode 2 */ 437 ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0, MII_BCM7XXX_SHD_MODE_2); 438 if (ret < 0) 439 return ret; 440 441 return 0; 442 } 443 444 /* Workaround for putting the PHY in IDDQ mode, required 445 * for all BCM7XXX 40nm and 65nm PHYs 446 */ 447 static int bcm7xxx_suspend(struct phy_device *phydev) 448 { 449 int ret; 450 static const struct bcm7xxx_regs { 451 int reg; 452 u16 value; 453 } bcm7xxx_suspend_cfg[] = { 454 { MII_BCM7XXX_TEST, 0x008b }, 455 { MII_BCM7XXX_100TX_AUX_CTL, 0x01c0 }, 456 { MII_BCM7XXX_100TX_DISC, 0x7000 }, 457 { MII_BCM7XXX_TEST, 0x000f }, 458 { MII_BCM7XXX_100TX_AUX_CTL, 0x20d0 }, 459 { MII_BCM7XXX_TEST, 0x000b }, 460 }; 461 unsigned int i; 462 463 for (i = 0; i < ARRAY_SIZE(bcm7xxx_suspend_cfg); i++) { 464 ret = phy_write(phydev, 465 bcm7xxx_suspend_cfg[i].reg, 466 bcm7xxx_suspend_cfg[i].value); 467 if (ret) 468 return ret; 469 } 470 471 return 0; 472 } 473 474 static int bcm7xxx_28nm_get_tunable(struct phy_device *phydev, 475 struct ethtool_tunable *tuna, 476 void *data) 477 { 478 switch (tuna->id) { 479 case ETHTOOL_PHY_DOWNSHIFT: 480 return bcm_phy_downshift_get(phydev, (u8 *)data); 481 default: 482 return -EOPNOTSUPP; 483 } 484 } 485 486 static int bcm7xxx_28nm_set_tunable(struct phy_device *phydev, 487 struct ethtool_tunable *tuna, 488 const void *data) 489 { 490 u8 count = *(u8 *)data; 491 int ret; 492 493 switch (tuna->id) { 494 case ETHTOOL_PHY_DOWNSHIFT: 495 ret = bcm_phy_downshift_set(phydev, count); 496 break; 497 default: 498 return -EOPNOTSUPP; 499 } 500 501 if (ret) 502 return ret; 503 504 /* Disable EEE advertisement since this prevents the PHY 505 * from successfully linking up, trigger auto-negotiation restart 506 * to let the MAC decide what to do. 507 */ 508 ret = bcm_phy_set_eee(phydev, count == DOWNSHIFT_DEV_DISABLE); 509 if (ret) 510 return ret; 511 512 return genphy_restart_aneg(phydev); 513 } 514 515 static void bcm7xxx_28nm_get_phy_stats(struct phy_device *phydev, 516 struct ethtool_stats *stats, u64 *data) 517 { 518 struct bcm7xxx_phy_priv *priv = phydev->priv; 519 520 bcm_phy_get_stats(phydev, priv->stats, stats, data); 521 } 522 523 static int bcm7xxx_28nm_probe(struct phy_device *phydev) 524 { 525 struct bcm7xxx_phy_priv *priv; 526 int ret = 0; 527 528 priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL); 529 if (!priv) 530 return -ENOMEM; 531 532 phydev->priv = priv; 533 534 priv->stats = devm_kcalloc(&phydev->mdio.dev, 535 bcm_phy_get_sset_count(phydev), sizeof(u64), 536 GFP_KERNEL); 537 if (!priv->stats) 538 return -ENOMEM; 539 540 priv->clk = devm_clk_get_optional(&phydev->mdio.dev, NULL); 541 if (IS_ERR(priv->clk)) 542 return PTR_ERR(priv->clk); 543 544 ret = clk_prepare_enable(priv->clk); 545 if (ret) 546 return ret; 547 548 /* Dummy read to a register to workaround an issue upon reset where the 549 * internal inverter may not allow the first MDIO transaction to pass 550 * the MDIO management controller and make us return 0xffff for such 551 * reads. This is needed to ensure that any subsequent reads to the 552 * PHY will succeed. 553 */ 554 phy_read(phydev, MII_BMSR); 555 556 return ret; 557 } 558 559 static void bcm7xxx_28nm_remove(struct phy_device *phydev) 560 { 561 struct bcm7xxx_phy_priv *priv = phydev->priv; 562 563 clk_disable_unprepare(priv->clk); 564 } 565 566 #define BCM7XXX_28NM_GPHY(_oui, _name) \ 567 { \ 568 .phy_id = (_oui), \ 569 .phy_id_mask = 0xfffffff0, \ 570 .name = _name, \ 571 /* PHY_GBIT_FEATURES */ \ 572 .flags = PHY_IS_INTERNAL, \ 573 .config_init = bcm7xxx_28nm_config_init, \ 574 .resume = bcm7xxx_28nm_resume, \ 575 .get_tunable = bcm7xxx_28nm_get_tunable, \ 576 .set_tunable = bcm7xxx_28nm_set_tunable, \ 577 .get_sset_count = bcm_phy_get_sset_count, \ 578 .get_strings = bcm_phy_get_strings, \ 579 .get_stats = bcm7xxx_28nm_get_phy_stats, \ 580 .probe = bcm7xxx_28nm_probe, \ 581 .remove = bcm7xxx_28nm_remove, \ 582 } 583 584 #define BCM7XXX_28NM_EPHY(_oui, _name) \ 585 { \ 586 .phy_id = (_oui), \ 587 .phy_id_mask = 0xfffffff0, \ 588 .name = _name, \ 589 /* PHY_BASIC_FEATURES */ \ 590 .flags = PHY_IS_INTERNAL, \ 591 .config_init = bcm7xxx_28nm_ephy_config_init, \ 592 .resume = bcm7xxx_28nm_ephy_resume, \ 593 .get_sset_count = bcm_phy_get_sset_count, \ 594 .get_strings = bcm_phy_get_strings, \ 595 .get_stats = bcm7xxx_28nm_get_phy_stats, \ 596 .probe = bcm7xxx_28nm_probe, \ 597 .remove = bcm7xxx_28nm_remove, \ 598 } 599 600 #define BCM7XXX_40NM_EPHY(_oui, _name) \ 601 { \ 602 .phy_id = (_oui), \ 603 .phy_id_mask = 0xfffffff0, \ 604 .name = _name, \ 605 /* PHY_BASIC_FEATURES */ \ 606 .flags = PHY_IS_INTERNAL, \ 607 .soft_reset = genphy_soft_reset, \ 608 .config_init = bcm7xxx_config_init, \ 609 .suspend = bcm7xxx_suspend, \ 610 .resume = bcm7xxx_config_init, \ 611 } 612 613 static struct phy_driver bcm7xxx_driver[] = { 614 BCM7XXX_28NM_EPHY(PHY_ID_BCM72113, "Broadcom BCM72113"), 615 BCM7XXX_28NM_EPHY(PHY_ID_BCM72116, "Broadcom BCM72116"), 616 BCM7XXX_28NM_GPHY(PHY_ID_BCM7250, "Broadcom BCM7250"), 617 BCM7XXX_28NM_EPHY(PHY_ID_BCM7255, "Broadcom BCM7255"), 618 BCM7XXX_28NM_EPHY(PHY_ID_BCM7260, "Broadcom BCM7260"), 619 BCM7XXX_28NM_EPHY(PHY_ID_BCM7268, "Broadcom BCM7268"), 620 BCM7XXX_28NM_EPHY(PHY_ID_BCM7271, "Broadcom BCM7271"), 621 BCM7XXX_28NM_GPHY(PHY_ID_BCM7278, "Broadcom BCM7278"), 622 BCM7XXX_28NM_GPHY(PHY_ID_BCM7364, "Broadcom BCM7364"), 623 BCM7XXX_28NM_GPHY(PHY_ID_BCM7366, "Broadcom BCM7366"), 624 BCM7XXX_28NM_GPHY(PHY_ID_BCM74371, "Broadcom BCM74371"), 625 BCM7XXX_28NM_GPHY(PHY_ID_BCM7439, "Broadcom BCM7439"), 626 BCM7XXX_28NM_GPHY(PHY_ID_BCM7439_2, "Broadcom BCM7439 (2)"), 627 BCM7XXX_28NM_GPHY(PHY_ID_BCM7445, "Broadcom BCM7445"), 628 BCM7XXX_40NM_EPHY(PHY_ID_BCM7346, "Broadcom BCM7346"), 629 BCM7XXX_40NM_EPHY(PHY_ID_BCM7362, "Broadcom BCM7362"), 630 BCM7XXX_40NM_EPHY(PHY_ID_BCM7425, "Broadcom BCM7425"), 631 BCM7XXX_40NM_EPHY(PHY_ID_BCM7429, "Broadcom BCM7429"), 632 BCM7XXX_40NM_EPHY(PHY_ID_BCM7435, "Broadcom BCM7435"), 633 }; 634 635 static struct mdio_device_id __maybe_unused bcm7xxx_tbl[] = { 636 { PHY_ID_BCM72113, 0xfffffff0 }, 637 { PHY_ID_BCM72116, 0xfffffff0, }, 638 { PHY_ID_BCM7250, 0xfffffff0, }, 639 { PHY_ID_BCM7255, 0xfffffff0, }, 640 { PHY_ID_BCM7260, 0xfffffff0, }, 641 { PHY_ID_BCM7268, 0xfffffff0, }, 642 { PHY_ID_BCM7271, 0xfffffff0, }, 643 { PHY_ID_BCM7278, 0xfffffff0, }, 644 { PHY_ID_BCM7364, 0xfffffff0, }, 645 { PHY_ID_BCM7366, 0xfffffff0, }, 646 { PHY_ID_BCM7346, 0xfffffff0, }, 647 { PHY_ID_BCM7362, 0xfffffff0, }, 648 { PHY_ID_BCM7425, 0xfffffff0, }, 649 { PHY_ID_BCM7429, 0xfffffff0, }, 650 { PHY_ID_BCM74371, 0xfffffff0, }, 651 { PHY_ID_BCM7439, 0xfffffff0, }, 652 { PHY_ID_BCM7435, 0xfffffff0, }, 653 { PHY_ID_BCM7445, 0xfffffff0, }, 654 { } 655 }; 656 657 module_phy_driver(bcm7xxx_driver); 658 659 MODULE_DEVICE_TABLE(mdio, bcm7xxx_tbl); 660 661 MODULE_DESCRIPTION("Broadcom BCM7xxx internal PHY driver"); 662 MODULE_LICENSE("GPL"); 663 MODULE_AUTHOR("Broadcom Corporation"); 664