1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2015-2017 Broadcom 4 */ 5 6 #include "bcm-phy-lib.h" 7 #include <linux/bitfield.h> 8 #include <linux/brcmphy.h> 9 #include <linux/etherdevice.h> 10 #include <linux/export.h> 11 #include <linux/mdio.h> 12 #include <linux/module.h> 13 #include <linux/phy.h> 14 #include <linux/ethtool.h> 15 #include <linux/ethtool_netlink.h> 16 #include <linux/netdevice.h> 17 18 #define MII_BCM_CHANNEL_WIDTH 0x2000 19 #define BCM_CL45VEN_EEE_ADV 0x3c 20 21 int __bcm_phy_write_exp(struct phy_device *phydev, u16 reg, u16 val) 22 { 23 int rc; 24 25 rc = __phy_write(phydev, MII_BCM54XX_EXP_SEL, reg); 26 if (rc < 0) 27 return rc; 28 29 return __phy_write(phydev, MII_BCM54XX_EXP_DATA, val); 30 } 31 EXPORT_SYMBOL_GPL(__bcm_phy_write_exp); 32 33 int bcm_phy_write_exp(struct phy_device *phydev, u16 reg, u16 val) 34 { 35 int rc; 36 37 phy_lock_mdio_bus(phydev); 38 rc = __bcm_phy_write_exp(phydev, reg, val); 39 phy_unlock_mdio_bus(phydev); 40 41 return rc; 42 } 43 EXPORT_SYMBOL_GPL(bcm_phy_write_exp); 44 45 int __bcm_phy_read_exp(struct phy_device *phydev, u16 reg) 46 { 47 int val; 48 49 val = __phy_write(phydev, MII_BCM54XX_EXP_SEL, reg); 50 if (val < 0) 51 return val; 52 53 val = __phy_read(phydev, MII_BCM54XX_EXP_DATA); 54 55 /* Restore default value. It's O.K. if this write fails. */ 56 __phy_write(phydev, MII_BCM54XX_EXP_SEL, 0); 57 58 return val; 59 } 60 EXPORT_SYMBOL_GPL(__bcm_phy_read_exp); 61 62 int bcm_phy_read_exp(struct phy_device *phydev, u16 reg) 63 { 64 int rc; 65 66 phy_lock_mdio_bus(phydev); 67 rc = __bcm_phy_read_exp(phydev, reg); 68 phy_unlock_mdio_bus(phydev); 69 70 return rc; 71 } 72 EXPORT_SYMBOL_GPL(bcm_phy_read_exp); 73 74 int __bcm_phy_modify_exp(struct phy_device *phydev, u16 reg, u16 mask, u16 set) 75 { 76 int new, ret; 77 78 ret = __phy_write(phydev, MII_BCM54XX_EXP_SEL, reg); 79 if (ret < 0) 80 return ret; 81 82 ret = __phy_read(phydev, MII_BCM54XX_EXP_DATA); 83 if (ret < 0) 84 return ret; 85 86 new = (ret & ~mask) | set; 87 if (new == ret) 88 return 0; 89 90 return __phy_write(phydev, MII_BCM54XX_EXP_DATA, new); 91 } 92 EXPORT_SYMBOL_GPL(__bcm_phy_modify_exp); 93 94 int bcm_phy_modify_exp(struct phy_device *phydev, u16 reg, u16 mask, u16 set) 95 { 96 int ret; 97 98 phy_lock_mdio_bus(phydev); 99 ret = __bcm_phy_modify_exp(phydev, reg, mask, set); 100 phy_unlock_mdio_bus(phydev); 101 102 return ret; 103 } 104 EXPORT_SYMBOL_GPL(bcm_phy_modify_exp); 105 106 int bcm54xx_auxctl_read(struct phy_device *phydev, u16 regnum) 107 { 108 /* The register must be written to both the Shadow Register Select and 109 * the Shadow Read Register Selector 110 */ 111 phy_write(phydev, MII_BCM54XX_AUX_CTL, MII_BCM54XX_AUXCTL_SHDWSEL_MASK | 112 regnum << MII_BCM54XX_AUXCTL_SHDWSEL_READ_SHIFT); 113 return phy_read(phydev, MII_BCM54XX_AUX_CTL); 114 } 115 EXPORT_SYMBOL_GPL(bcm54xx_auxctl_read); 116 117 int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val) 118 { 119 return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val); 120 } 121 EXPORT_SYMBOL(bcm54xx_auxctl_write); 122 123 int bcm_phy_write_misc(struct phy_device *phydev, 124 u16 reg, u16 chl, u16 val) 125 { 126 int rc; 127 int tmp; 128 129 rc = phy_write(phydev, MII_BCM54XX_AUX_CTL, 130 MII_BCM54XX_AUXCTL_SHDWSEL_MISC); 131 if (rc < 0) 132 return rc; 133 134 tmp = phy_read(phydev, MII_BCM54XX_AUX_CTL); 135 tmp |= MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA; 136 rc = phy_write(phydev, MII_BCM54XX_AUX_CTL, tmp); 137 if (rc < 0) 138 return rc; 139 140 tmp = (chl * MII_BCM_CHANNEL_WIDTH) | reg; 141 rc = bcm_phy_write_exp(phydev, tmp, val); 142 143 return rc; 144 } 145 EXPORT_SYMBOL_GPL(bcm_phy_write_misc); 146 147 int bcm_phy_read_misc(struct phy_device *phydev, 148 u16 reg, u16 chl) 149 { 150 int rc; 151 int tmp; 152 153 rc = phy_write(phydev, MII_BCM54XX_AUX_CTL, 154 MII_BCM54XX_AUXCTL_SHDWSEL_MISC); 155 if (rc < 0) 156 return rc; 157 158 tmp = phy_read(phydev, MII_BCM54XX_AUX_CTL); 159 tmp |= MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA; 160 rc = phy_write(phydev, MII_BCM54XX_AUX_CTL, tmp); 161 if (rc < 0) 162 return rc; 163 164 tmp = (chl * MII_BCM_CHANNEL_WIDTH) | reg; 165 rc = bcm_phy_read_exp(phydev, tmp); 166 167 return rc; 168 } 169 EXPORT_SYMBOL_GPL(bcm_phy_read_misc); 170 171 int bcm_phy_ack_intr(struct phy_device *phydev) 172 { 173 int reg; 174 175 /* Clear pending interrupts. */ 176 reg = phy_read(phydev, MII_BCM54XX_ISR); 177 if (reg < 0) 178 return reg; 179 180 return 0; 181 } 182 EXPORT_SYMBOL_GPL(bcm_phy_ack_intr); 183 184 int bcm_phy_config_intr(struct phy_device *phydev) 185 { 186 int reg, err; 187 188 reg = phy_read(phydev, MII_BCM54XX_ECR); 189 if (reg < 0) 190 return reg; 191 192 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { 193 err = bcm_phy_ack_intr(phydev); 194 if (err) 195 return err; 196 197 reg &= ~MII_BCM54XX_ECR_IM; 198 err = phy_write(phydev, MII_BCM54XX_ECR, reg); 199 } else { 200 reg |= MII_BCM54XX_ECR_IM; 201 err = phy_write(phydev, MII_BCM54XX_ECR, reg); 202 if (err) 203 return err; 204 205 err = bcm_phy_ack_intr(phydev); 206 } 207 return err; 208 } 209 EXPORT_SYMBOL_GPL(bcm_phy_config_intr); 210 211 irqreturn_t bcm_phy_handle_interrupt(struct phy_device *phydev) 212 { 213 int irq_status, irq_mask; 214 215 irq_status = phy_read(phydev, MII_BCM54XX_ISR); 216 if (irq_status < 0) { 217 phy_error(phydev); 218 return IRQ_NONE; 219 } 220 221 /* If a bit from the Interrupt Mask register is set, the corresponding 222 * bit from the Interrupt Status register is masked. So read the IMR 223 * and then flip the bits to get the list of possible interrupt 224 * sources. 225 */ 226 irq_mask = phy_read(phydev, MII_BCM54XX_IMR); 227 if (irq_mask < 0) { 228 phy_error(phydev); 229 return IRQ_NONE; 230 } 231 irq_mask = ~irq_mask; 232 233 if (!(irq_status & irq_mask)) 234 return IRQ_NONE; 235 236 phy_trigger_machine(phydev); 237 238 return IRQ_HANDLED; 239 } 240 EXPORT_SYMBOL_GPL(bcm_phy_handle_interrupt); 241 242 int bcm_phy_read_shadow(struct phy_device *phydev, u16 shadow) 243 { 244 phy_write(phydev, MII_BCM54XX_SHD, MII_BCM54XX_SHD_VAL(shadow)); 245 return MII_BCM54XX_SHD_DATA(phy_read(phydev, MII_BCM54XX_SHD)); 246 } 247 EXPORT_SYMBOL_GPL(bcm_phy_read_shadow); 248 249 int bcm_phy_write_shadow(struct phy_device *phydev, u16 shadow, 250 u16 val) 251 { 252 return phy_write(phydev, MII_BCM54XX_SHD, 253 MII_BCM54XX_SHD_WRITE | 254 MII_BCM54XX_SHD_VAL(shadow) | 255 MII_BCM54XX_SHD_DATA(val)); 256 } 257 EXPORT_SYMBOL_GPL(bcm_phy_write_shadow); 258 259 int __bcm_phy_read_rdb(struct phy_device *phydev, u16 rdb) 260 { 261 int val; 262 263 val = __phy_write(phydev, MII_BCM54XX_RDB_ADDR, rdb); 264 if (val < 0) 265 return val; 266 267 return __phy_read(phydev, MII_BCM54XX_RDB_DATA); 268 } 269 EXPORT_SYMBOL_GPL(__bcm_phy_read_rdb); 270 271 int bcm_phy_read_rdb(struct phy_device *phydev, u16 rdb) 272 { 273 int ret; 274 275 phy_lock_mdio_bus(phydev); 276 ret = __bcm_phy_read_rdb(phydev, rdb); 277 phy_unlock_mdio_bus(phydev); 278 279 return ret; 280 } 281 EXPORT_SYMBOL_GPL(bcm_phy_read_rdb); 282 283 int __bcm_phy_write_rdb(struct phy_device *phydev, u16 rdb, u16 val) 284 { 285 int ret; 286 287 ret = __phy_write(phydev, MII_BCM54XX_RDB_ADDR, rdb); 288 if (ret < 0) 289 return ret; 290 291 return __phy_write(phydev, MII_BCM54XX_RDB_DATA, val); 292 } 293 EXPORT_SYMBOL_GPL(__bcm_phy_write_rdb); 294 295 int bcm_phy_write_rdb(struct phy_device *phydev, u16 rdb, u16 val) 296 { 297 int ret; 298 299 phy_lock_mdio_bus(phydev); 300 ret = __bcm_phy_write_rdb(phydev, rdb, val); 301 phy_unlock_mdio_bus(phydev); 302 303 return ret; 304 } 305 EXPORT_SYMBOL_GPL(bcm_phy_write_rdb); 306 307 int __bcm_phy_modify_rdb(struct phy_device *phydev, u16 rdb, u16 mask, u16 set) 308 { 309 int new, ret; 310 311 ret = __phy_write(phydev, MII_BCM54XX_RDB_ADDR, rdb); 312 if (ret < 0) 313 return ret; 314 315 ret = __phy_read(phydev, MII_BCM54XX_RDB_DATA); 316 if (ret < 0) 317 return ret; 318 319 new = (ret & ~mask) | set; 320 if (new == ret) 321 return 0; 322 323 return __phy_write(phydev, MII_BCM54XX_RDB_DATA, new); 324 } 325 EXPORT_SYMBOL_GPL(__bcm_phy_modify_rdb); 326 327 int bcm_phy_modify_rdb(struct phy_device *phydev, u16 rdb, u16 mask, u16 set) 328 { 329 int ret; 330 331 phy_lock_mdio_bus(phydev); 332 ret = __bcm_phy_modify_rdb(phydev, rdb, mask, set); 333 phy_unlock_mdio_bus(phydev); 334 335 return ret; 336 } 337 EXPORT_SYMBOL_GPL(bcm_phy_modify_rdb); 338 339 int bcm_phy_enable_apd(struct phy_device *phydev, bool dll_pwr_down) 340 { 341 int val; 342 343 if (dll_pwr_down) { 344 val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_SCR3); 345 if (val < 0) 346 return val; 347 348 val |= BCM54XX_SHD_SCR3_DLLAPD_DIS; 349 bcm_phy_write_shadow(phydev, BCM54XX_SHD_SCR3, val); 350 } 351 352 val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_APD); 353 if (val < 0) 354 return val; 355 356 /* Clear APD bits */ 357 val &= BCM_APD_CLR_MASK; 358 359 if (phydev->autoneg == AUTONEG_ENABLE) 360 val |= BCM54XX_SHD_APD_EN; 361 else 362 val |= BCM_NO_ANEG_APD_EN; 363 364 /* Enable energy detect single link pulse for easy wakeup */ 365 val |= BCM_APD_SINGLELP_EN; 366 367 /* Enable Auto Power-Down (APD) for the PHY */ 368 return bcm_phy_write_shadow(phydev, BCM54XX_SHD_APD, val); 369 } 370 EXPORT_SYMBOL_GPL(bcm_phy_enable_apd); 371 372 int bcm_phy_set_eee(struct phy_device *phydev, bool enable) 373 { 374 int val, mask = 0; 375 376 /* Enable EEE at PHY level */ 377 val = phy_read_mmd(phydev, MDIO_MMD_AN, BRCM_CL45VEN_EEE_CONTROL); 378 if (val < 0) 379 return val; 380 381 if (enable) 382 val |= LPI_FEATURE_EN | LPI_FEATURE_EN_DIG1000X; 383 else 384 val &= ~(LPI_FEATURE_EN | LPI_FEATURE_EN_DIG1000X); 385 386 phy_write_mmd(phydev, MDIO_MMD_AN, BRCM_CL45VEN_EEE_CONTROL, (u32)val); 387 388 /* Advertise EEE */ 389 val = phy_read_mmd(phydev, MDIO_MMD_AN, BCM_CL45VEN_EEE_ADV); 390 if (val < 0) 391 return val; 392 393 if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, 394 phydev->supported)) 395 mask |= MDIO_EEE_1000T; 396 if (linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, 397 phydev->supported)) 398 mask |= MDIO_EEE_100TX; 399 400 if (enable) 401 val |= mask; 402 else 403 val &= ~mask; 404 405 phy_write_mmd(phydev, MDIO_MMD_AN, BCM_CL45VEN_EEE_ADV, (u32)val); 406 407 return 0; 408 } 409 EXPORT_SYMBOL_GPL(bcm_phy_set_eee); 410 411 int bcm_phy_downshift_get(struct phy_device *phydev, u8 *count) 412 { 413 int val; 414 415 val = bcm54xx_auxctl_read(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC); 416 if (val < 0) 417 return val; 418 419 /* Check if wirespeed is enabled or not */ 420 if (!(val & MII_BCM54XX_AUXCTL_SHDWSEL_MISC_WIRESPEED_EN)) { 421 *count = DOWNSHIFT_DEV_DISABLE; 422 return 0; 423 } 424 425 val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_SCR2); 426 if (val < 0) 427 return val; 428 429 /* Downgrade after one link attempt */ 430 if (val & BCM54XX_SHD_SCR2_WSPD_RTRY_DIS) { 431 *count = 1; 432 } else { 433 /* Downgrade after configured retry count */ 434 val >>= BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_SHIFT; 435 val &= BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_MASK; 436 *count = val + BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_OFFSET; 437 } 438 439 return 0; 440 } 441 EXPORT_SYMBOL_GPL(bcm_phy_downshift_get); 442 443 int bcm_phy_downshift_set(struct phy_device *phydev, u8 count) 444 { 445 int val = 0, ret = 0; 446 447 /* Range check the number given */ 448 if (count - BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_OFFSET > 449 BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_MASK && 450 count != DOWNSHIFT_DEV_DEFAULT_COUNT) { 451 return -ERANGE; 452 } 453 454 val = bcm54xx_auxctl_read(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC); 455 if (val < 0) 456 return val; 457 458 /* Se the write enable bit */ 459 val |= MII_BCM54XX_AUXCTL_MISC_WREN; 460 461 if (count == DOWNSHIFT_DEV_DISABLE) { 462 val &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_WIRESPEED_EN; 463 return bcm54xx_auxctl_write(phydev, 464 MII_BCM54XX_AUXCTL_SHDWSEL_MISC, 465 val); 466 } else { 467 val |= MII_BCM54XX_AUXCTL_SHDWSEL_MISC_WIRESPEED_EN; 468 ret = bcm54xx_auxctl_write(phydev, 469 MII_BCM54XX_AUXCTL_SHDWSEL_MISC, 470 val); 471 if (ret < 0) 472 return ret; 473 } 474 475 val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_SCR2); 476 val &= ~(BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_MASK << 477 BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_SHIFT | 478 BCM54XX_SHD_SCR2_WSPD_RTRY_DIS); 479 480 switch (count) { 481 case 1: 482 val |= BCM54XX_SHD_SCR2_WSPD_RTRY_DIS; 483 break; 484 case DOWNSHIFT_DEV_DEFAULT_COUNT: 485 val |= 1 << BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_SHIFT; 486 break; 487 default: 488 val |= (count - BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_OFFSET) << 489 BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_SHIFT; 490 break; 491 } 492 493 return bcm_phy_write_shadow(phydev, BCM54XX_SHD_SCR2, val); 494 } 495 EXPORT_SYMBOL_GPL(bcm_phy_downshift_set); 496 497 struct bcm_phy_hw_stat { 498 const char *string; 499 int devad; 500 u16 reg; 501 u8 shift; 502 u8 bits; 503 }; 504 505 /* Counters freeze at either 0xffff or 0xff, better than nothing */ 506 static const struct bcm_phy_hw_stat bcm_phy_hw_stats[] = { 507 { "phy_receive_errors", -1, MII_BRCM_CORE_BASE12, 0, 16 }, 508 { "phy_serdes_ber_errors", -1, MII_BRCM_CORE_BASE13, 8, 8 }, 509 { "phy_false_carrier_sense_errors", -1, MII_BRCM_CORE_BASE13, 0, 8 }, 510 { "phy_local_rcvr_nok", -1, MII_BRCM_CORE_BASE14, 8, 8 }, 511 { "phy_remote_rcv_nok", -1, MII_BRCM_CORE_BASE14, 0, 8 }, 512 { "phy_lpi_count", MDIO_MMD_AN, BRCM_CL45VEN_EEE_LPI_CNT, 0, 16 }, 513 }; 514 515 int bcm_phy_get_sset_count(struct phy_device *phydev) 516 { 517 return ARRAY_SIZE(bcm_phy_hw_stats); 518 } 519 EXPORT_SYMBOL_GPL(bcm_phy_get_sset_count); 520 521 void bcm_phy_get_strings(struct phy_device *phydev, u8 *data) 522 { 523 unsigned int i; 524 525 for (i = 0; i < ARRAY_SIZE(bcm_phy_hw_stats); i++) 526 ethtool_puts(&data, bcm_phy_hw_stats[i].string); 527 } 528 EXPORT_SYMBOL_GPL(bcm_phy_get_strings); 529 530 /* Caller is supposed to provide appropriate storage for the library code to 531 * access the shadow copy 532 */ 533 static u64 bcm_phy_get_stat(struct phy_device *phydev, u64 *shadow, 534 unsigned int i) 535 { 536 struct bcm_phy_hw_stat stat = bcm_phy_hw_stats[i]; 537 int val; 538 u64 ret; 539 540 if (stat.devad < 0) 541 val = phy_read(phydev, stat.reg); 542 else 543 val = phy_read_mmd(phydev, stat.devad, stat.reg); 544 if (val < 0) { 545 ret = U64_MAX; 546 } else { 547 val >>= stat.shift; 548 val = val & ((1 << stat.bits) - 1); 549 shadow[i] += val; 550 ret = shadow[i]; 551 } 552 553 return ret; 554 } 555 556 void bcm_phy_get_stats(struct phy_device *phydev, u64 *shadow, 557 struct ethtool_stats *stats, u64 *data) 558 { 559 unsigned int i; 560 561 for (i = 0; i < ARRAY_SIZE(bcm_phy_hw_stats); i++) 562 data[i] = bcm_phy_get_stat(phydev, shadow, i); 563 } 564 EXPORT_SYMBOL_GPL(bcm_phy_get_stats); 565 566 void bcm_phy_update_stats_shadow(struct phy_device *phydev, u64 *shadow) 567 { 568 unsigned int i; 569 570 for (i = 0; i < ARRAY_SIZE(bcm_phy_hw_stats); i++) 571 bcm_phy_get_stat(phydev, shadow, i); 572 } 573 EXPORT_SYMBOL_GPL(bcm_phy_update_stats_shadow); 574 575 void bcm_phy_r_rc_cal_reset(struct phy_device *phydev) 576 { 577 /* Reset R_CAL/RC_CAL Engine */ 578 bcm_phy_write_exp_sel(phydev, 0x00b0, 0x0010); 579 580 /* Disable Reset R_AL/RC_CAL Engine */ 581 bcm_phy_write_exp_sel(phydev, 0x00b0, 0x0000); 582 } 583 EXPORT_SYMBOL_GPL(bcm_phy_r_rc_cal_reset); 584 585 int bcm_phy_28nm_a0b0_afe_config_init(struct phy_device *phydev) 586 { 587 /* Increase VCO range to prevent unlocking problem of PLL at low 588 * temp 589 */ 590 bcm_phy_write_misc(phydev, PLL_PLLCTRL_1, 0x0048); 591 592 /* Change Ki to 011 */ 593 bcm_phy_write_misc(phydev, PLL_PLLCTRL_2, 0x021b); 594 595 /* Disable loading of TVCO buffer to bandgap, set bandgap trim 596 * to 111 597 */ 598 bcm_phy_write_misc(phydev, PLL_PLLCTRL_4, 0x0e20); 599 600 /* Adjust bias current trim by -3 */ 601 bcm_phy_write_misc(phydev, DSP_TAP10, 0x690b); 602 603 /* Switch to CORE_BASE1E */ 604 phy_write(phydev, MII_BRCM_CORE_BASE1E, 0xd); 605 606 bcm_phy_r_rc_cal_reset(phydev); 607 608 /* write AFE_RXCONFIG_0 */ 609 bcm_phy_write_misc(phydev, AFE_RXCONFIG_0, 0xeb19); 610 611 /* write AFE_RXCONFIG_1 */ 612 bcm_phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9a3f); 613 614 /* write AFE_RX_LP_COUNTER */ 615 bcm_phy_write_misc(phydev, AFE_RX_LP_COUNTER, 0x7fc0); 616 617 /* write AFE_HPF_TRIM_OTHERS */ 618 bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x000b); 619 620 /* write AFTE_TX_CONFIG */ 621 bcm_phy_write_misc(phydev, AFE_TX_CONFIG, 0x0800); 622 623 return 0; 624 } 625 EXPORT_SYMBOL_GPL(bcm_phy_28nm_a0b0_afe_config_init); 626 627 int bcm_phy_enable_jumbo(struct phy_device *phydev) 628 { 629 int ret; 630 631 ret = bcm54xx_auxctl_read(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL); 632 if (ret < 0) 633 return ret; 634 635 /* Enable extended length packet reception */ 636 ret = bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL, 637 ret | MII_BCM54XX_AUXCTL_ACTL_EXT_PKT_LEN); 638 if (ret < 0) 639 return ret; 640 641 /* Enable the elastic FIFO for raising the transmission limit from 642 * 4.5KB to 10KB, at the expense of an additional 16 ns in propagation 643 * latency. 644 */ 645 return phy_set_bits(phydev, MII_BCM54XX_ECR, MII_BCM54XX_ECR_FIFOE); 646 } 647 EXPORT_SYMBOL_GPL(bcm_phy_enable_jumbo); 648 649 static int __bcm_phy_enable_rdb_access(struct phy_device *phydev) 650 { 651 return __bcm_phy_write_exp(phydev, BCM54XX_EXP_REG7E, 0); 652 } 653 654 static int __bcm_phy_enable_legacy_access(struct phy_device *phydev) 655 { 656 return __bcm_phy_write_rdb(phydev, BCM54XX_RDB_REG0087, 657 BCM54XX_ACCESS_MODE_LEGACY_EN); 658 } 659 660 static int _bcm_phy_cable_test_start(struct phy_device *phydev, bool is_rdb) 661 { 662 u16 mask, set; 663 int ret; 664 665 /* Auto-negotiation must be enabled for cable diagnostics to work, but 666 * don't advertise any capabilities. 667 */ 668 phy_write(phydev, MII_BMCR, BMCR_ANENABLE); 669 phy_write(phydev, MII_ADVERTISE, ADVERTISE_CSMA); 670 phy_write(phydev, MII_CTRL1000, 0); 671 672 phy_lock_mdio_bus(phydev); 673 if (is_rdb) { 674 ret = __bcm_phy_enable_legacy_access(phydev); 675 if (ret) 676 goto out; 677 } 678 679 mask = BCM54XX_ECD_CTRL_CROSS_SHORT_DIS | BCM54XX_ECD_CTRL_UNIT_MASK; 680 set = BCM54XX_ECD_CTRL_RUN | BCM54XX_ECD_CTRL_BREAK_LINK | 681 FIELD_PREP(BCM54XX_ECD_CTRL_UNIT_MASK, 682 BCM54XX_ECD_CTRL_UNIT_CM); 683 684 ret = __bcm_phy_modify_exp(phydev, BCM54XX_EXP_ECD_CTRL, mask, set); 685 686 out: 687 /* re-enable the RDB access even if there was an error */ 688 if (is_rdb) 689 ret = __bcm_phy_enable_rdb_access(phydev) ? : ret; 690 691 phy_unlock_mdio_bus(phydev); 692 693 return ret; 694 } 695 696 static int bcm_phy_cable_test_report_trans(int result) 697 { 698 switch (result) { 699 case BCM54XX_ECD_FAULT_TYPE_OK: 700 return ETHTOOL_A_CABLE_RESULT_CODE_OK; 701 case BCM54XX_ECD_FAULT_TYPE_OPEN: 702 return ETHTOOL_A_CABLE_RESULT_CODE_OPEN; 703 case BCM54XX_ECD_FAULT_TYPE_SAME_SHORT: 704 return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT; 705 case BCM54XX_ECD_FAULT_TYPE_CROSS_SHORT: 706 return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT; 707 case BCM54XX_ECD_FAULT_TYPE_INVALID: 708 case BCM54XX_ECD_FAULT_TYPE_BUSY: 709 default: 710 return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC; 711 } 712 } 713 714 static bool bcm_phy_distance_valid(int result) 715 { 716 switch (result) { 717 case BCM54XX_ECD_FAULT_TYPE_OPEN: 718 case BCM54XX_ECD_FAULT_TYPE_SAME_SHORT: 719 case BCM54XX_ECD_FAULT_TYPE_CROSS_SHORT: 720 return true; 721 } 722 return false; 723 } 724 725 static int bcm_phy_report_length(struct phy_device *phydev, int pair) 726 { 727 int val; 728 729 val = __bcm_phy_read_exp(phydev, 730 BCM54XX_EXP_ECD_PAIR_A_LENGTH_RESULTS + pair); 731 if (val < 0) 732 return val; 733 734 if (val == BCM54XX_ECD_LENGTH_RESULTS_INVALID) 735 return 0; 736 737 ethnl_cable_test_fault_length(phydev, pair, val); 738 739 return 0; 740 } 741 742 static int _bcm_phy_cable_test_get_status(struct phy_device *phydev, 743 bool *finished, bool is_rdb) 744 { 745 int pair_a, pair_b, pair_c, pair_d, ret; 746 747 *finished = false; 748 749 phy_lock_mdio_bus(phydev); 750 751 if (is_rdb) { 752 ret = __bcm_phy_enable_legacy_access(phydev); 753 if (ret) 754 goto out; 755 } 756 757 ret = __bcm_phy_read_exp(phydev, BCM54XX_EXP_ECD_CTRL); 758 if (ret < 0) 759 goto out; 760 761 if (ret & BCM54XX_ECD_CTRL_IN_PROGRESS) { 762 ret = 0; 763 goto out; 764 } 765 766 ret = __bcm_phy_read_exp(phydev, BCM54XX_EXP_ECD_FAULT_TYPE); 767 if (ret < 0) 768 goto out; 769 770 pair_a = FIELD_GET(BCM54XX_ECD_FAULT_TYPE_PAIR_A_MASK, ret); 771 pair_b = FIELD_GET(BCM54XX_ECD_FAULT_TYPE_PAIR_B_MASK, ret); 772 pair_c = FIELD_GET(BCM54XX_ECD_FAULT_TYPE_PAIR_C_MASK, ret); 773 pair_d = FIELD_GET(BCM54XX_ECD_FAULT_TYPE_PAIR_D_MASK, ret); 774 775 ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, 776 bcm_phy_cable_test_report_trans(pair_a)); 777 ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_B, 778 bcm_phy_cable_test_report_trans(pair_b)); 779 ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_C, 780 bcm_phy_cable_test_report_trans(pair_c)); 781 ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_D, 782 bcm_phy_cable_test_report_trans(pair_d)); 783 784 if (bcm_phy_distance_valid(pair_a)) 785 bcm_phy_report_length(phydev, 0); 786 if (bcm_phy_distance_valid(pair_b)) 787 bcm_phy_report_length(phydev, 1); 788 if (bcm_phy_distance_valid(pair_c)) 789 bcm_phy_report_length(phydev, 2); 790 if (bcm_phy_distance_valid(pair_d)) 791 bcm_phy_report_length(phydev, 3); 792 793 ret = 0; 794 *finished = true; 795 out: 796 /* re-enable the RDB access even if there was an error */ 797 if (is_rdb) 798 ret = __bcm_phy_enable_rdb_access(phydev) ? : ret; 799 800 phy_unlock_mdio_bus(phydev); 801 802 return ret; 803 } 804 805 static int bcm_setup_lre_forced(struct phy_device *phydev) 806 { 807 u16 ctl = 0; 808 809 phydev->pause = 0; 810 phydev->asym_pause = 0; 811 812 if (phydev->speed == SPEED_100) 813 ctl |= LRECR_SPEED100; 814 815 if (phydev->duplex != DUPLEX_FULL) 816 return -EOPNOTSUPP; 817 818 return phy_modify(phydev, MII_BCM54XX_LRECR, LRECR_SPEED100, ctl); 819 } 820 821 /** 822 * bcm_linkmode_adv_to_lre_adv_t - translate linkmode advertisement to LDS 823 * @advertising: the linkmode advertisement settings 824 * Return: LDS Auto-Negotiation Advertised Ability register value 825 * 826 * A small helper function that translates linkmode advertisement 827 * settings to phy LDS autonegotiation advertisements for the 828 * MII_BCM54XX_LREANAA register of Broadcom PHYs capable of LDS 829 */ 830 static u32 bcm_linkmode_adv_to_lre_adv_t(unsigned long *advertising) 831 { 832 u32 result = 0; 833 834 if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT1BRR_Full_BIT, 835 advertising)) 836 result |= LREANAA_10_1PAIR; 837 if (linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT1_Full_BIT, 838 advertising)) 839 result |= LREANAA_100_1PAIR; 840 if (linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT, advertising)) 841 result |= LRELPA_PAUSE; 842 if (linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, advertising)) 843 result |= LRELPA_PAUSE_ASYM; 844 845 return result; 846 } 847 848 int bcm_phy_cable_test_start(struct phy_device *phydev) 849 { 850 return _bcm_phy_cable_test_start(phydev, false); 851 } 852 EXPORT_SYMBOL_GPL(bcm_phy_cable_test_start); 853 854 int bcm_phy_cable_test_get_status(struct phy_device *phydev, bool *finished) 855 { 856 return _bcm_phy_cable_test_get_status(phydev, finished, false); 857 } 858 EXPORT_SYMBOL_GPL(bcm_phy_cable_test_get_status); 859 860 /* We assume that all PHYs which support RDB access can be switched to legacy 861 * mode. If, in the future, this is not true anymore, we have to re-implement 862 * this with RDB access. 863 */ 864 int bcm_phy_cable_test_start_rdb(struct phy_device *phydev) 865 { 866 return _bcm_phy_cable_test_start(phydev, true); 867 } 868 EXPORT_SYMBOL_GPL(bcm_phy_cable_test_start_rdb); 869 870 int bcm_phy_cable_test_get_status_rdb(struct phy_device *phydev, 871 bool *finished) 872 { 873 return _bcm_phy_cable_test_get_status(phydev, finished, true); 874 } 875 EXPORT_SYMBOL_GPL(bcm_phy_cable_test_get_status_rdb); 876 877 #define BCM54XX_WOL_SUPPORTED_MASK (WAKE_UCAST | \ 878 WAKE_MCAST | \ 879 WAKE_BCAST | \ 880 WAKE_MAGIC | \ 881 WAKE_MAGICSECURE) 882 883 int bcm_phy_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol) 884 { 885 struct net_device *ndev = phydev->attached_dev; 886 u8 da[ETH_ALEN], mask[ETH_ALEN]; 887 unsigned int i; 888 u16 ctl; 889 int ret; 890 891 /* Allow a MAC driver to play through its own Wake-on-LAN 892 * implementation 893 */ 894 if (wol->wolopts & ~BCM54XX_WOL_SUPPORTED_MASK) 895 return -EOPNOTSUPP; 896 897 /* The PHY supports passwords of 4, 6 and 8 bytes in size, but Linux's 898 * ethtool only supports 6, for now. 899 */ 900 BUILD_BUG_ON(sizeof(wol->sopass) != ETH_ALEN); 901 902 /* Clear previous interrupts */ 903 ret = bcm_phy_read_exp(phydev, BCM54XX_WOL_INT_STATUS); 904 if (ret < 0) 905 return ret; 906 907 ret = bcm_phy_read_exp(phydev, BCM54XX_WOL_MAIN_CTL); 908 if (ret < 0) 909 return ret; 910 911 ctl = ret; 912 913 if (!wol->wolopts) { 914 if (phy_interrupt_is_valid(phydev)) 915 disable_irq_wake(phydev->irq); 916 917 /* Leave all interrupts disabled */ 918 ret = bcm_phy_write_exp(phydev, BCM54XX_WOL_INT_MASK, 919 BCM54XX_WOL_ALL_INTRS); 920 if (ret < 0) 921 return ret; 922 923 /* Disable the global Wake-on-LAN enable bit */ 924 ctl &= ~BCM54XX_WOL_EN; 925 926 return bcm_phy_write_exp(phydev, BCM54XX_WOL_MAIN_CTL, ctl); 927 } 928 929 /* Clear the previously configured mode and mask mode for Wake-on-LAN */ 930 ctl &= ~(BCM54XX_WOL_MODE_MASK << BCM54XX_WOL_MODE_SHIFT); 931 ctl &= ~(BCM54XX_WOL_MASK_MODE_MASK << BCM54XX_WOL_MASK_MODE_SHIFT); 932 ctl &= ~BCM54XX_WOL_DIR_PKT_EN; 933 ctl &= ~(BCM54XX_WOL_SECKEY_OPT_MASK << BCM54XX_WOL_SECKEY_OPT_SHIFT); 934 935 /* When using WAKE_MAGIC, we program the magic pattern filter to match 936 * the device's MAC address and we accept any MAC DA in the Ethernet 937 * frame. 938 * 939 * When using WAKE_UCAST, WAKE_BCAST or WAKE_MCAST, we program the 940 * following: 941 * - WAKE_UCAST -> MAC DA is the device's MAC with a perfect match 942 * - WAKE_MCAST -> MAC DA is X1:XX:XX:XX:XX:XX where XX is don't care 943 * - WAKE_BCAST -> MAC DA is FF:FF:FF:FF:FF:FF with a perfect match 944 * 945 * Note that the Broadcast MAC DA is inherently going to match the 946 * multicast pattern being matched. 947 */ 948 memset(mask, 0, sizeof(mask)); 949 950 if (wol->wolopts & WAKE_MCAST) { 951 memset(da, 0, sizeof(da)); 952 memset(mask, 0xff, sizeof(mask)); 953 da[0] = 0x01; 954 mask[0] = ~da[0]; 955 } else { 956 if (wol->wolopts & WAKE_UCAST) { 957 ether_addr_copy(da, ndev->dev_addr); 958 } else if (wol->wolopts & WAKE_BCAST) { 959 eth_broadcast_addr(da); 960 } else if (wol->wolopts & WAKE_MAGICSECURE) { 961 ether_addr_copy(da, wol->sopass); 962 } else if (wol->wolopts & WAKE_MAGIC) { 963 memset(da, 0, sizeof(da)); 964 memset(mask, 0xff, sizeof(mask)); 965 } 966 } 967 968 for (i = 0; i < ETH_ALEN / 2; i++) { 969 if (wol->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE)) { 970 ret = bcm_phy_write_exp(phydev, 971 BCM54XX_WOL_MPD_DATA1(2 - i), 972 ndev->dev_addr[i * 2] << 8 | 973 ndev->dev_addr[i * 2 + 1]); 974 if (ret < 0) 975 return ret; 976 } 977 978 ret = bcm_phy_write_exp(phydev, BCM54XX_WOL_MPD_DATA2(2 - i), 979 da[i * 2] << 8 | da[i * 2 + 1]); 980 if (ret < 0) 981 return ret; 982 983 ret = bcm_phy_write_exp(phydev, BCM54XX_WOL_MASK(2 - i), 984 mask[i * 2] << 8 | mask[i * 2 + 1]); 985 if (ret) 986 return ret; 987 } 988 989 if (wol->wolopts & WAKE_MAGICSECURE) { 990 ctl |= BCM54XX_WOL_SECKEY_OPT_6B << 991 BCM54XX_WOL_SECKEY_OPT_SHIFT; 992 ctl |= BCM54XX_WOL_MODE_SINGLE_MPDSEC << BCM54XX_WOL_MODE_SHIFT; 993 ctl |= BCM54XX_WOL_MASK_MODE_DA_FF << 994 BCM54XX_WOL_MASK_MODE_SHIFT; 995 } else { 996 if (wol->wolopts & WAKE_MAGIC) 997 ctl |= BCM54XX_WOL_MODE_SINGLE_MPD; 998 else 999 ctl |= BCM54XX_WOL_DIR_PKT_EN; 1000 ctl |= BCM54XX_WOL_MASK_MODE_DA_ONLY << 1001 BCM54XX_WOL_MASK_MODE_SHIFT; 1002 } 1003 1004 /* Globally enable Wake-on-LAN */ 1005 ctl |= BCM54XX_WOL_EN | BCM54XX_WOL_CRC_CHK; 1006 1007 ret = bcm_phy_write_exp(phydev, BCM54XX_WOL_MAIN_CTL, ctl); 1008 if (ret < 0) 1009 return ret; 1010 1011 /* Enable WOL interrupt on LED4 */ 1012 ret = bcm_phy_read_exp(phydev, BCM54XX_TOP_MISC_LED_CTL); 1013 if (ret < 0) 1014 return ret; 1015 1016 ret |= BCM54XX_LED4_SEL_INTR; 1017 ret = bcm_phy_write_exp(phydev, BCM54XX_TOP_MISC_LED_CTL, ret); 1018 if (ret < 0) 1019 return ret; 1020 1021 /* Enable all Wake-on-LAN interrupt sources */ 1022 ret = bcm_phy_write_exp(phydev, BCM54XX_WOL_INT_MASK, 0); 1023 if (ret < 0) 1024 return ret; 1025 1026 if (phy_interrupt_is_valid(phydev)) 1027 enable_irq_wake(phydev->irq); 1028 1029 return 0; 1030 } 1031 EXPORT_SYMBOL_GPL(bcm_phy_set_wol); 1032 1033 void bcm_phy_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol) 1034 { 1035 struct net_device *ndev = phydev->attached_dev; 1036 u8 da[ETH_ALEN]; 1037 unsigned int i; 1038 int ret; 1039 u16 ctl; 1040 1041 wol->supported = BCM54XX_WOL_SUPPORTED_MASK; 1042 wol->wolopts = 0; 1043 1044 ret = bcm_phy_read_exp(phydev, BCM54XX_WOL_MAIN_CTL); 1045 if (ret < 0) 1046 return; 1047 1048 ctl = ret; 1049 1050 if (!(ctl & BCM54XX_WOL_EN)) 1051 return; 1052 1053 for (i = 0; i < sizeof(da) / 2; i++) { 1054 ret = bcm_phy_read_exp(phydev, 1055 BCM54XX_WOL_MPD_DATA2(2 - i)); 1056 if (ret < 0) 1057 return; 1058 1059 da[i * 2] = ret >> 8; 1060 da[i * 2 + 1] = ret & 0xff; 1061 } 1062 1063 if (ctl & BCM54XX_WOL_DIR_PKT_EN) { 1064 if (is_broadcast_ether_addr(da)) 1065 wol->wolopts |= WAKE_BCAST; 1066 else if (is_multicast_ether_addr(da)) 1067 wol->wolopts |= WAKE_MCAST; 1068 else if (ether_addr_equal(da, ndev->dev_addr)) 1069 wol->wolopts |= WAKE_UCAST; 1070 } else { 1071 ctl = (ctl >> BCM54XX_WOL_MODE_SHIFT) & BCM54XX_WOL_MODE_MASK; 1072 switch (ctl) { 1073 case BCM54XX_WOL_MODE_SINGLE_MPD: 1074 wol->wolopts |= WAKE_MAGIC; 1075 break; 1076 case BCM54XX_WOL_MODE_SINGLE_MPDSEC: 1077 wol->wolopts |= WAKE_MAGICSECURE; 1078 memcpy(wol->sopass, da, sizeof(da)); 1079 break; 1080 default: 1081 break; 1082 } 1083 } 1084 } 1085 EXPORT_SYMBOL_GPL(bcm_phy_get_wol); 1086 1087 irqreturn_t bcm_phy_wol_isr(int irq, void *dev_id) 1088 { 1089 return IRQ_HANDLED; 1090 } 1091 EXPORT_SYMBOL_GPL(bcm_phy_wol_isr); 1092 1093 int bcm_phy_led_brightness_set(struct phy_device *phydev, 1094 u8 index, enum led_brightness value) 1095 { 1096 u8 led_num; 1097 int ret; 1098 u16 reg; 1099 1100 if (index >= 4) 1101 return -EINVAL; 1102 1103 /* Two LEDS per register */ 1104 led_num = index % 2; 1105 reg = index >= 2 ? BCM54XX_SHD_LEDS2 : BCM54XX_SHD_LEDS1; 1106 1107 ret = bcm_phy_read_shadow(phydev, reg); 1108 if (ret < 0) 1109 return ret; 1110 1111 ret &= ~(BCM_LED_SRC_MASK << BCM54XX_SHD_LEDS_SHIFT(led_num)); 1112 if (value == LED_OFF) 1113 ret |= BCM_LED_SRC_OFF << BCM54XX_SHD_LEDS_SHIFT(led_num); 1114 else 1115 ret |= BCM_LED_SRC_ON << BCM54XX_SHD_LEDS_SHIFT(led_num); 1116 return bcm_phy_write_shadow(phydev, reg, ret); 1117 } 1118 EXPORT_SYMBOL_GPL(bcm_phy_led_brightness_set); 1119 1120 int bcm_setup_lre_master_slave(struct phy_device *phydev) 1121 { 1122 u16 ctl = 0; 1123 1124 switch (phydev->master_slave_set) { 1125 case MASTER_SLAVE_CFG_MASTER_PREFERRED: 1126 case MASTER_SLAVE_CFG_MASTER_FORCE: 1127 ctl = LRECR_MASTER; 1128 break; 1129 case MASTER_SLAVE_CFG_SLAVE_PREFERRED: 1130 case MASTER_SLAVE_CFG_SLAVE_FORCE: 1131 break; 1132 case MASTER_SLAVE_CFG_UNKNOWN: 1133 case MASTER_SLAVE_CFG_UNSUPPORTED: 1134 return 0; 1135 default: 1136 phydev_warn(phydev, "Unsupported Master/Slave mode\n"); 1137 return -EOPNOTSUPP; 1138 } 1139 1140 return phy_modify_changed(phydev, MII_BCM54XX_LRECR, LRECR_MASTER, ctl); 1141 } 1142 EXPORT_SYMBOL_GPL(bcm_setup_lre_master_slave); 1143 1144 int bcm_config_lre_aneg(struct phy_device *phydev, bool changed) 1145 { 1146 int err; 1147 1148 if (genphy_c45_an_config_eee_aneg(phydev) > 0) 1149 changed = true; 1150 1151 err = bcm_setup_lre_master_slave(phydev); 1152 if (err < 0) 1153 return err; 1154 else if (err) 1155 changed = true; 1156 1157 if (phydev->autoneg != AUTONEG_ENABLE) 1158 return bcm_setup_lre_forced(phydev); 1159 1160 err = bcm_config_lre_advert(phydev); 1161 if (err < 0) 1162 return err; 1163 else if (err) 1164 changed = true; 1165 1166 return genphy_check_and_restart_aneg(phydev, changed); 1167 } 1168 EXPORT_SYMBOL_GPL(bcm_config_lre_aneg); 1169 1170 /** 1171 * bcm_config_lre_advert - sanitize and advertise Long-Distance Signaling 1172 * auto-negotiation parameters 1173 * @phydev: target phy_device struct 1174 * Return: 0 if the PHY's advertisement hasn't changed, < 0 on error, 1175 * > 0 if it has changed 1176 * 1177 * Writes MII_BCM54XX_LREANAA with the appropriate values. The values are to be 1178 * sanitized before, to make sure we only advertise what is supported. 1179 * The sanitization is done already in phy_ethtool_ksettings_set() 1180 */ 1181 int bcm_config_lre_advert(struct phy_device *phydev) 1182 { 1183 u32 adv = bcm_linkmode_adv_to_lre_adv_t(phydev->advertising); 1184 1185 /* Setup BroadR-Reach mode advertisement */ 1186 return phy_modify_changed(phydev, MII_BCM54XX_LREANAA, 1187 LRE_ADVERTISE_ALL | LREANAA_PAUSE | 1188 LREANAA_PAUSE_ASYM, adv); 1189 } 1190 EXPORT_SYMBOL_GPL(bcm_config_lre_advert); 1191 1192 MODULE_DESCRIPTION("Broadcom PHY Library"); 1193 MODULE_LICENSE("GPL v2"); 1194 MODULE_AUTHOR("Broadcom Corporation"); 1195