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