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