bcm7xxx.c (27053B)
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 46struct bcm7xxx_phy_priv { 47 u64 *stats; 48 struct clk *clk; 49}; 50 51static 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 91static 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 119static 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 144static 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 207static 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 224static 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 243static 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 255static 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 290reset_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 */ 301static 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 326static 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 375reset_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 389static 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 418static int bcm7xxx_16nm_ephy_afe_config(struct phy_device *phydev) 419{ 420 int tmp, rcalcode, rcalnewcodelp, rcalnewcode11, rcalnewcode11d2; 421 422 /* Reset PHY */ 423 tmp = genphy_soft_reset(phydev); 424 if (tmp) 425 return tmp; 426 427 /* Reset AFE and PLL */ 428 bcm_phy_write_exp_sel(phydev, 0x0003, 0x0006); 429 /* Clear reset */ 430 bcm_phy_write_exp_sel(phydev, 0x0003, 0x0000); 431 432 /* Write PLL/AFE control register to select 54MHz crystal */ 433 bcm_phy_write_misc(phydev, 0x0030, 0x0001, 0x0000); 434 bcm_phy_write_misc(phydev, 0x0031, 0x0000, 0x044a); 435 436 /* Change Ka,Kp,Ki to pdiv=1 */ 437 bcm_phy_write_misc(phydev, 0x0033, 0x0002, 0x71a1); 438 /* Configuration override */ 439 bcm_phy_write_misc(phydev, 0x0033, 0x0001, 0x8000); 440 441 /* Change PLL_NDIV and PLL_NUDGE */ 442 bcm_phy_write_misc(phydev, 0x0031, 0x0001, 0x2f68); 443 bcm_phy_write_misc(phydev, 0x0031, 0x0002, 0x0000); 444 445 /* Reference frequency is 54Mhz, config_mode[15:14] = 3 (low 446 * phase) 447 */ 448 bcm_phy_write_misc(phydev, 0x0030, 0x0003, 0xc036); 449 450 /* Initialize bypass mode */ 451 bcm_phy_write_misc(phydev, 0x0032, 0x0003, 0x0000); 452 /* Bypass code, default: VCOCLK enabled */ 453 bcm_phy_write_misc(phydev, 0x0033, 0x0000, 0x0002); 454 /* LDOs at default setting */ 455 bcm_phy_write_misc(phydev, 0x0030, 0x0002, 0x01c0); 456 /* Release PLL reset */ 457 bcm_phy_write_misc(phydev, 0x0030, 0x0001, 0x0001); 458 459 /* Bandgap curvature correction to correct default */ 460 bcm_phy_write_misc(phydev, 0x0038, 0x0000, 0x0010); 461 462 /* Run RCAL */ 463 bcm_phy_write_misc(phydev, 0x0039, 0x0003, 0x0038); 464 bcm_phy_write_misc(phydev, 0x0039, 0x0003, 0x003b); 465 udelay(2); 466 bcm_phy_write_misc(phydev, 0x0039, 0x0003, 0x003f); 467 mdelay(5); 468 469 /* AFE_CAL_CONFIG_0, Vref=1000, Target=10, averaging enabled */ 470 bcm_phy_write_misc(phydev, 0x0039, 0x0001, 0x1c82); 471 /* AFE_CAL_CONFIG_0, no reset and analog powerup */ 472 bcm_phy_write_misc(phydev, 0x0039, 0x0001, 0x9e82); 473 udelay(2); 474 /* AFE_CAL_CONFIG_0, start calibration */ 475 bcm_phy_write_misc(phydev, 0x0039, 0x0001, 0x9f82); 476 udelay(100); 477 /* AFE_CAL_CONFIG_0, clear start calibration, set HiBW */ 478 bcm_phy_write_misc(phydev, 0x0039, 0x0001, 0x9e86); 479 udelay(2); 480 /* AFE_CAL_CONFIG_0, start calibration with hi BW mode set */ 481 bcm_phy_write_misc(phydev, 0x0039, 0x0001, 0x9f86); 482 udelay(100); 483 484 /* Adjust 10BT amplitude additional +7% and 100BT +2% */ 485 bcm_phy_write_misc(phydev, 0x0038, 0x0001, 0xe7ea); 486 /* Adjust 1G mode amplitude and 1G testmode1 */ 487 bcm_phy_write_misc(phydev, 0x0038, 0x0002, 0xede0); 488 489 /* Read CORE_EXPA9 */ 490 tmp = bcm_phy_read_exp(phydev, 0x00a9); 491 /* CORE_EXPA9[6:1] is rcalcode[5:0] */ 492 rcalcode = (tmp & 0x7e) / 2; 493 /* Correct RCAL code + 1 is -1% rprogr, LP: +16 */ 494 rcalnewcodelp = rcalcode + 16; 495 /* Correct RCAL code + 1 is -15 rprogr, 11: +10 */ 496 rcalnewcode11 = rcalcode + 10; 497 /* Saturate if necessary */ 498 if (rcalnewcodelp > 0x3f) 499 rcalnewcodelp = 0x3f; 500 if (rcalnewcode11 > 0x3f) 501 rcalnewcode11 = 0x3f; 502 /* REXT=1 BYP=1 RCAL_st1<5:0>=new rcal code */ 503 tmp = 0x00f8 + rcalnewcodelp * 256; 504 /* Program into AFE_CAL_CONFIG_2 */ 505 bcm_phy_write_misc(phydev, 0x0039, 0x0003, tmp); 506 /* AFE_BIAS_CONFIG_0 10BT bias code (Bias: E4) */ 507 bcm_phy_write_misc(phydev, 0x0038, 0x0001, 0xe7e4); 508 /* invert adc clock output and 'adc refp ldo current To correct 509 * default 510 */ 511 bcm_phy_write_misc(phydev, 0x003b, 0x0000, 0x8002); 512 /* 100BT stair case, high BW, 1G stair case, alternate encode */ 513 bcm_phy_write_misc(phydev, 0x003c, 0x0003, 0xf882); 514 /* 1000BT DAC transition method per Erol, bits[32], DAC Shuffle 515 * sequence 1 + 10BT imp adjust bits 516 */ 517 bcm_phy_write_misc(phydev, 0x003d, 0x0000, 0x3201); 518 /* Non-overlap fix */ 519 bcm_phy_write_misc(phydev, 0x003a, 0x0002, 0x0c00); 520 521 /* pwdb override (rxconfig<5>) to turn on RX LDO indpendent of 522 * pwdb controls from DSP_TAP10 523 */ 524 bcm_phy_write_misc(phydev, 0x003a, 0x0001, 0x0020); 525 526 /* Remove references to channel 2 and 3 */ 527 bcm_phy_write_misc(phydev, 0x003b, 0x0002, 0x0000); 528 bcm_phy_write_misc(phydev, 0x003b, 0x0003, 0x0000); 529 530 /* Set cal_bypassb bit rxconfig<43> */ 531 bcm_phy_write_misc(phydev, 0x003a, 0x0003, 0x0800); 532 udelay(2); 533 534 /* Revert pwdb_override (rxconfig<5>) to 0 so that the RX pwr 535 * is controlled by DSP. 536 */ 537 bcm_phy_write_misc(phydev, 0x003a, 0x0001, 0x0000); 538 539 /* Drop LSB */ 540 rcalnewcode11d2 = (rcalnewcode11 & 0xfffe) / 2; 541 tmp = bcm_phy_read_misc(phydev, 0x003d, 0x0001); 542 /* Clear bits [11:5] */ 543 tmp &= ~0xfe0; 544 /* set txcfg_ch0<5>=1 (enable + set local rcal) */ 545 tmp |= 0x0020 | (rcalnewcode11d2 * 64); 546 bcm_phy_write_misc(phydev, 0x003d, 0x0001, tmp); 547 bcm_phy_write_misc(phydev, 0x003d, 0x0002, tmp); 548 549 tmp = bcm_phy_read_misc(phydev, 0x003d, 0x0000); 550 /* set txcfg<45:44>=11 (enable Rextra + invert fullscaledetect) 551 */ 552 tmp &= ~0x3000; 553 tmp |= 0x3000; 554 bcm_phy_write_misc(phydev, 0x003d, 0x0000, tmp); 555 556 return 0; 557} 558 559static int bcm7xxx_16nm_ephy_config_init(struct phy_device *phydev) 560{ 561 int ret, val; 562 563 ret = bcm7xxx_16nm_ephy_afe_config(phydev); 564 if (ret) 565 return ret; 566 567 ret = bcm_phy_set_eee(phydev, true); 568 if (ret) 569 return ret; 570 571 ret = bcm_phy_read_shadow(phydev, BCM54XX_SHD_SCR3); 572 if (ret < 0) 573 return ret; 574 575 val = ret; 576 577 /* Auto power down of DLL enabled, 578 * TXC/RXC disabled during auto power down. 579 */ 580 val &= ~BCM54XX_SHD_SCR3_DLLAPD_DIS; 581 val |= BIT(8); 582 583 ret = bcm_phy_write_shadow(phydev, BCM54XX_SHD_SCR3, val); 584 if (ret < 0) 585 return ret; 586 587 return bcm_phy_enable_apd(phydev, true); 588} 589 590static int bcm7xxx_16nm_ephy_resume(struct phy_device *phydev) 591{ 592 int ret; 593 594 /* Re-apply workarounds coming out suspend/resume */ 595 ret = bcm7xxx_16nm_ephy_config_init(phydev); 596 if (ret) 597 return ret; 598 599 return genphy_config_aneg(phydev); 600} 601 602#define MII_BCM7XXX_REG_INVALID 0xff 603 604static u8 bcm7xxx_28nm_ephy_regnum_to_shd(u16 regnum) 605{ 606 switch (regnum) { 607 case MDIO_CTRL1: 608 return MII_BCM7XXX_SHD_3_PCS_CTRL; 609 case MDIO_STAT1: 610 return MII_BCM7XXX_SHD_3_PCS_STATUS; 611 case MDIO_PCS_EEE_ABLE: 612 return MII_BCM7XXX_SHD_3_EEE_CAP; 613 case MDIO_AN_EEE_ADV: 614 return MII_BCM7XXX_SHD_3_AN_EEE_ADV; 615 case MDIO_AN_EEE_LPABLE: 616 return MII_BCM7XXX_SHD_3_EEE_LP; 617 case MDIO_PCS_EEE_WK_ERR: 618 return MII_BCM7XXX_SHD_3_EEE_WK_ERR; 619 default: 620 return MII_BCM7XXX_REG_INVALID; 621 } 622} 623 624static bool bcm7xxx_28nm_ephy_dev_valid(int devnum) 625{ 626 return devnum == MDIO_MMD_AN || devnum == MDIO_MMD_PCS; 627} 628 629static int bcm7xxx_28nm_ephy_read_mmd(struct phy_device *phydev, 630 int devnum, u16 regnum) 631{ 632 u8 shd = bcm7xxx_28nm_ephy_regnum_to_shd(regnum); 633 int ret; 634 635 if (!bcm7xxx_28nm_ephy_dev_valid(devnum) || 636 shd == MII_BCM7XXX_REG_INVALID) 637 return -EOPNOTSUPP; 638 639 /* set shadow mode 2 */ 640 ret = __phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 641 MII_BCM7XXX_SHD_MODE_2, 0); 642 if (ret < 0) 643 return ret; 644 645 /* Access the desired shadow register address */ 646 ret = __phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL, shd); 647 if (ret < 0) 648 goto reset_shadow_mode; 649 650 ret = __phy_read(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT); 651 652reset_shadow_mode: 653 /* reset shadow mode 2 */ 654 __phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0, 655 MII_BCM7XXX_SHD_MODE_2); 656 return ret; 657} 658 659static int bcm7xxx_28nm_ephy_write_mmd(struct phy_device *phydev, 660 int devnum, u16 regnum, u16 val) 661{ 662 u8 shd = bcm7xxx_28nm_ephy_regnum_to_shd(regnum); 663 int ret; 664 665 if (!bcm7xxx_28nm_ephy_dev_valid(devnum) || 666 shd == MII_BCM7XXX_REG_INVALID) 667 return -EOPNOTSUPP; 668 669 /* set shadow mode 2 */ 670 ret = __phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 671 MII_BCM7XXX_SHD_MODE_2, 0); 672 if (ret < 0) 673 return ret; 674 675 /* Access the desired shadow register address */ 676 ret = __phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL, shd); 677 if (ret < 0) 678 goto reset_shadow_mode; 679 680 /* Write the desired value in the shadow register */ 681 __phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT, val); 682 683reset_shadow_mode: 684 /* reset shadow mode 2 */ 685 return __phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0, 686 MII_BCM7XXX_SHD_MODE_2); 687} 688 689static int bcm7xxx_28nm_ephy_resume(struct phy_device *phydev) 690{ 691 int ret; 692 693 /* Re-apply workarounds coming out suspend/resume */ 694 ret = bcm7xxx_28nm_ephy_config_init(phydev); 695 if (ret) 696 return ret; 697 698 return genphy_config_aneg(phydev); 699} 700 701static int bcm7xxx_config_init(struct phy_device *phydev) 702{ 703 int ret; 704 705 /* Enable 64 clock MDIO */ 706 phy_write(phydev, MII_BCM7XXX_AUX_MODE, MII_BCM7XXX_64CLK_MDIO); 707 phy_read(phydev, MII_BCM7XXX_AUX_MODE); 708 709 /* set shadow mode 2 */ 710 ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 711 MII_BCM7XXX_SHD_MODE_2, MII_BCM7XXX_SHD_MODE_2); 712 if (ret < 0) 713 return ret; 714 715 /* set iddq_clkbias */ 716 phy_write(phydev, MII_BCM7XXX_100TX_DISC, 0x0F00); 717 udelay(10); 718 719 /* reset iddq_clkbias */ 720 phy_write(phydev, MII_BCM7XXX_100TX_DISC, 0x0C00); 721 722 phy_write(phydev, MII_BCM7XXX_100TX_FALSE_CAR, 0x7555); 723 724 /* reset shadow mode 2 */ 725 ret = phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0, MII_BCM7XXX_SHD_MODE_2); 726 if (ret < 0) 727 return ret; 728 729 return 0; 730} 731 732/* Workaround for putting the PHY in IDDQ mode, required 733 * for all BCM7XXX 40nm and 65nm PHYs 734 */ 735static int bcm7xxx_suspend(struct phy_device *phydev) 736{ 737 int ret; 738 static const struct bcm7xxx_regs { 739 int reg; 740 u16 value; 741 } bcm7xxx_suspend_cfg[] = { 742 { MII_BCM7XXX_TEST, 0x008b }, 743 { MII_BCM7XXX_100TX_AUX_CTL, 0x01c0 }, 744 { MII_BCM7XXX_100TX_DISC, 0x7000 }, 745 { MII_BCM7XXX_TEST, 0x000f }, 746 { MII_BCM7XXX_100TX_AUX_CTL, 0x20d0 }, 747 { MII_BCM7XXX_TEST, 0x000b }, 748 }; 749 unsigned int i; 750 751 for (i = 0; i < ARRAY_SIZE(bcm7xxx_suspend_cfg); i++) { 752 ret = phy_write(phydev, 753 bcm7xxx_suspend_cfg[i].reg, 754 bcm7xxx_suspend_cfg[i].value); 755 if (ret) 756 return ret; 757 } 758 759 return 0; 760} 761 762static int bcm7xxx_28nm_get_tunable(struct phy_device *phydev, 763 struct ethtool_tunable *tuna, 764 void *data) 765{ 766 switch (tuna->id) { 767 case ETHTOOL_PHY_DOWNSHIFT: 768 return bcm_phy_downshift_get(phydev, (u8 *)data); 769 default: 770 return -EOPNOTSUPP; 771 } 772} 773 774static int bcm7xxx_28nm_set_tunable(struct phy_device *phydev, 775 struct ethtool_tunable *tuna, 776 const void *data) 777{ 778 u8 count = *(u8 *)data; 779 int ret; 780 781 switch (tuna->id) { 782 case ETHTOOL_PHY_DOWNSHIFT: 783 ret = bcm_phy_downshift_set(phydev, count); 784 break; 785 default: 786 return -EOPNOTSUPP; 787 } 788 789 if (ret) 790 return ret; 791 792 /* Disable EEE advertisement since this prevents the PHY 793 * from successfully linking up, trigger auto-negotiation restart 794 * to let the MAC decide what to do. 795 */ 796 ret = bcm_phy_set_eee(phydev, count == DOWNSHIFT_DEV_DISABLE); 797 if (ret) 798 return ret; 799 800 return genphy_restart_aneg(phydev); 801} 802 803static void bcm7xxx_28nm_get_phy_stats(struct phy_device *phydev, 804 struct ethtool_stats *stats, u64 *data) 805{ 806 struct bcm7xxx_phy_priv *priv = phydev->priv; 807 808 bcm_phy_get_stats(phydev, priv->stats, stats, data); 809} 810 811static int bcm7xxx_28nm_probe(struct phy_device *phydev) 812{ 813 struct bcm7xxx_phy_priv *priv; 814 int ret = 0; 815 816 priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL); 817 if (!priv) 818 return -ENOMEM; 819 820 phydev->priv = priv; 821 822 priv->stats = devm_kcalloc(&phydev->mdio.dev, 823 bcm_phy_get_sset_count(phydev), sizeof(u64), 824 GFP_KERNEL); 825 if (!priv->stats) 826 return -ENOMEM; 827 828 priv->clk = devm_clk_get_optional(&phydev->mdio.dev, NULL); 829 if (IS_ERR(priv->clk)) 830 return PTR_ERR(priv->clk); 831 832 ret = clk_prepare_enable(priv->clk); 833 if (ret) 834 return ret; 835 836 /* Dummy read to a register to workaround an issue upon reset where the 837 * internal inverter may not allow the first MDIO transaction to pass 838 * the MDIO management controller and make us return 0xffff for such 839 * reads. This is needed to ensure that any subsequent reads to the 840 * PHY will succeed. 841 */ 842 phy_read(phydev, MII_BMSR); 843 844 return ret; 845} 846 847static void bcm7xxx_28nm_remove(struct phy_device *phydev) 848{ 849 struct bcm7xxx_phy_priv *priv = phydev->priv; 850 851 clk_disable_unprepare(priv->clk); 852} 853 854#define BCM7XXX_28NM_GPHY(_oui, _name) \ 855{ \ 856 .phy_id = (_oui), \ 857 .phy_id_mask = 0xfffffff0, \ 858 .name = _name, \ 859 /* PHY_GBIT_FEATURES */ \ 860 .flags = PHY_IS_INTERNAL, \ 861 .config_init = bcm7xxx_28nm_config_init, \ 862 .resume = bcm7xxx_28nm_resume, \ 863 .get_tunable = bcm7xxx_28nm_get_tunable, \ 864 .set_tunable = bcm7xxx_28nm_set_tunable, \ 865 .get_sset_count = bcm_phy_get_sset_count, \ 866 .get_strings = bcm_phy_get_strings, \ 867 .get_stats = bcm7xxx_28nm_get_phy_stats, \ 868 .probe = bcm7xxx_28nm_probe, \ 869 .remove = bcm7xxx_28nm_remove, \ 870} 871 872#define BCM7XXX_28NM_EPHY(_oui, _name) \ 873{ \ 874 .phy_id = (_oui), \ 875 .phy_id_mask = 0xfffffff0, \ 876 .name = _name, \ 877 /* PHY_BASIC_FEATURES */ \ 878 .flags = PHY_IS_INTERNAL, \ 879 .config_init = bcm7xxx_28nm_ephy_config_init, \ 880 .resume = bcm7xxx_28nm_ephy_resume, \ 881 .get_sset_count = bcm_phy_get_sset_count, \ 882 .get_strings = bcm_phy_get_strings, \ 883 .get_stats = bcm7xxx_28nm_get_phy_stats, \ 884 .probe = bcm7xxx_28nm_probe, \ 885 .remove = bcm7xxx_28nm_remove, \ 886 .read_mmd = bcm7xxx_28nm_ephy_read_mmd, \ 887 .write_mmd = bcm7xxx_28nm_ephy_write_mmd, \ 888} 889 890#define BCM7XXX_40NM_EPHY(_oui, _name) \ 891{ \ 892 .phy_id = (_oui), \ 893 .phy_id_mask = 0xfffffff0, \ 894 .name = _name, \ 895 /* PHY_BASIC_FEATURES */ \ 896 .flags = PHY_IS_INTERNAL, \ 897 .soft_reset = genphy_soft_reset, \ 898 .config_init = bcm7xxx_config_init, \ 899 .suspend = bcm7xxx_suspend, \ 900 .resume = bcm7xxx_config_init, \ 901} 902 903#define BCM7XXX_16NM_EPHY(_oui, _name) \ 904{ \ 905 .phy_id = (_oui), \ 906 .phy_id_mask = 0xfffffff0, \ 907 .name = _name, \ 908 /* PHY_BASIC_FEATURES */ \ 909 .flags = PHY_IS_INTERNAL, \ 910 .probe = bcm7xxx_28nm_probe, \ 911 .remove = bcm7xxx_28nm_remove, \ 912 .config_init = bcm7xxx_16nm_ephy_config_init, \ 913 .config_aneg = genphy_config_aneg, \ 914 .read_status = genphy_read_status, \ 915 .resume = bcm7xxx_16nm_ephy_resume, \ 916} 917 918static struct phy_driver bcm7xxx_driver[] = { 919 BCM7XXX_28NM_EPHY(PHY_ID_BCM72113, "Broadcom BCM72113"), 920 BCM7XXX_28NM_EPHY(PHY_ID_BCM72116, "Broadcom BCM72116"), 921 BCM7XXX_16NM_EPHY(PHY_ID_BCM72165, "Broadcom BCM72165"), 922 BCM7XXX_28NM_GPHY(PHY_ID_BCM7250, "Broadcom BCM7250"), 923 BCM7XXX_28NM_EPHY(PHY_ID_BCM7255, "Broadcom BCM7255"), 924 BCM7XXX_28NM_EPHY(PHY_ID_BCM7260, "Broadcom BCM7260"), 925 BCM7XXX_28NM_EPHY(PHY_ID_BCM7268, "Broadcom BCM7268"), 926 BCM7XXX_28NM_EPHY(PHY_ID_BCM7271, "Broadcom BCM7271"), 927 BCM7XXX_28NM_GPHY(PHY_ID_BCM7278, "Broadcom BCM7278"), 928 BCM7XXX_28NM_GPHY(PHY_ID_BCM7364, "Broadcom BCM7364"), 929 BCM7XXX_28NM_GPHY(PHY_ID_BCM7366, "Broadcom BCM7366"), 930 BCM7XXX_28NM_GPHY(PHY_ID_BCM74371, "Broadcom BCM74371"), 931 BCM7XXX_28NM_GPHY(PHY_ID_BCM7439, "Broadcom BCM7439"), 932 BCM7XXX_28NM_GPHY(PHY_ID_BCM7439_2, "Broadcom BCM7439 (2)"), 933 BCM7XXX_28NM_GPHY(PHY_ID_BCM7445, "Broadcom BCM7445"), 934 BCM7XXX_40NM_EPHY(PHY_ID_BCM7346, "Broadcom BCM7346"), 935 BCM7XXX_40NM_EPHY(PHY_ID_BCM7362, "Broadcom BCM7362"), 936 BCM7XXX_40NM_EPHY(PHY_ID_BCM7425, "Broadcom BCM7425"), 937 BCM7XXX_40NM_EPHY(PHY_ID_BCM7429, "Broadcom BCM7429"), 938 BCM7XXX_40NM_EPHY(PHY_ID_BCM7435, "Broadcom BCM7435"), 939 BCM7XXX_16NM_EPHY(PHY_ID_BCM7712, "Broadcom BCM7712"), 940}; 941 942static struct mdio_device_id __maybe_unused bcm7xxx_tbl[] = { 943 { PHY_ID_BCM72113, 0xfffffff0 }, 944 { PHY_ID_BCM72116, 0xfffffff0, }, 945 { PHY_ID_BCM72165, 0xfffffff0, }, 946 { PHY_ID_BCM7250, 0xfffffff0, }, 947 { PHY_ID_BCM7255, 0xfffffff0, }, 948 { PHY_ID_BCM7260, 0xfffffff0, }, 949 { PHY_ID_BCM7268, 0xfffffff0, }, 950 { PHY_ID_BCM7271, 0xfffffff0, }, 951 { PHY_ID_BCM7278, 0xfffffff0, }, 952 { PHY_ID_BCM7364, 0xfffffff0, }, 953 { PHY_ID_BCM7366, 0xfffffff0, }, 954 { PHY_ID_BCM7346, 0xfffffff0, }, 955 { PHY_ID_BCM7362, 0xfffffff0, }, 956 { PHY_ID_BCM7425, 0xfffffff0, }, 957 { PHY_ID_BCM7429, 0xfffffff0, }, 958 { PHY_ID_BCM74371, 0xfffffff0, }, 959 { PHY_ID_BCM7439, 0xfffffff0, }, 960 { PHY_ID_BCM7435, 0xfffffff0, }, 961 { PHY_ID_BCM7445, 0xfffffff0, }, 962 { PHY_ID_BCM7712, 0xfffffff0, }, 963 { } 964}; 965 966module_phy_driver(bcm7xxx_driver); 967 968MODULE_DEVICE_TABLE(mdio, bcm7xxx_tbl); 969 970MODULE_DESCRIPTION("Broadcom BCM7xxx internal PHY driver"); 971MODULE_LICENSE("GPL"); 972MODULE_AUTHOR("Broadcom Corporation");