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_r_rc_cal_reset(struct phy_device *phydev) 567 { 568 /* Reset R_CAL/RC_CAL Engine */ 569 bcm_phy_write_exp_sel(phydev, 0x00b0, 0x0010); 570 571 /* Disable Reset R_AL/RC_CAL Engine */ 572 bcm_phy_write_exp_sel(phydev, 0x00b0, 0x0000); 573 } 574 EXPORT_SYMBOL_GPL(bcm_phy_r_rc_cal_reset); 575 576 int bcm_phy_28nm_a0b0_afe_config_init(struct phy_device *phydev) 577 { 578 /* Increase VCO range to prevent unlocking problem of PLL at low 579 * temp 580 */ 581 bcm_phy_write_misc(phydev, PLL_PLLCTRL_1, 0x0048); 582 583 /* Change Ki to 011 */ 584 bcm_phy_write_misc(phydev, PLL_PLLCTRL_2, 0x021b); 585 586 /* Disable loading of TVCO buffer to bandgap, set bandgap trim 587 * to 111 588 */ 589 bcm_phy_write_misc(phydev, PLL_PLLCTRL_4, 0x0e20); 590 591 /* Adjust bias current trim by -3 */ 592 bcm_phy_write_misc(phydev, DSP_TAP10, 0x690b); 593 594 /* Switch to CORE_BASE1E */ 595 phy_write(phydev, MII_BRCM_CORE_BASE1E, 0xd); 596 597 bcm_phy_r_rc_cal_reset(phydev); 598 599 /* write AFE_RXCONFIG_0 */ 600 bcm_phy_write_misc(phydev, AFE_RXCONFIG_0, 0xeb19); 601 602 /* write AFE_RXCONFIG_1 */ 603 bcm_phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9a3f); 604 605 /* write AFE_RX_LP_COUNTER */ 606 bcm_phy_write_misc(phydev, AFE_RX_LP_COUNTER, 0x7fc0); 607 608 /* write AFE_HPF_TRIM_OTHERS */ 609 bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x000b); 610 611 /* write AFTE_TX_CONFIG */ 612 bcm_phy_write_misc(phydev, AFE_TX_CONFIG, 0x0800); 613 614 return 0; 615 } 616 EXPORT_SYMBOL_GPL(bcm_phy_28nm_a0b0_afe_config_init); 617 618 int bcm_phy_enable_jumbo(struct phy_device *phydev) 619 { 620 int ret; 621 622 ret = bcm54xx_auxctl_read(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL); 623 if (ret < 0) 624 return ret; 625 626 /* Enable extended length packet reception */ 627 ret = bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL, 628 ret | MII_BCM54XX_AUXCTL_ACTL_EXT_PKT_LEN); 629 if (ret < 0) 630 return ret; 631 632 /* Enable the elastic FIFO for raising the transmission limit from 633 * 4.5KB to 10KB, at the expense of an additional 16 ns in propagation 634 * latency. 635 */ 636 return phy_set_bits(phydev, MII_BCM54XX_ECR, MII_BCM54XX_ECR_FIFOE); 637 } 638 EXPORT_SYMBOL_GPL(bcm_phy_enable_jumbo); 639 640 static int __bcm_phy_enable_rdb_access(struct phy_device *phydev) 641 { 642 return __bcm_phy_write_exp(phydev, BCM54XX_EXP_REG7E, 0); 643 } 644 645 static int __bcm_phy_enable_legacy_access(struct phy_device *phydev) 646 { 647 return __bcm_phy_write_rdb(phydev, BCM54XX_RDB_REG0087, 648 BCM54XX_ACCESS_MODE_LEGACY_EN); 649 } 650 651 static int _bcm_phy_cable_test_start(struct phy_device *phydev, bool is_rdb) 652 { 653 u16 mask, set; 654 int ret; 655 656 /* Auto-negotiation must be enabled for cable diagnostics to work, but 657 * don't advertise any capabilities. 658 */ 659 phy_write(phydev, MII_BMCR, BMCR_ANENABLE); 660 phy_write(phydev, MII_ADVERTISE, ADVERTISE_CSMA); 661 phy_write(phydev, MII_CTRL1000, 0); 662 663 phy_lock_mdio_bus(phydev); 664 if (is_rdb) { 665 ret = __bcm_phy_enable_legacy_access(phydev); 666 if (ret) 667 goto out; 668 } 669 670 mask = BCM54XX_ECD_CTRL_CROSS_SHORT_DIS | BCM54XX_ECD_CTRL_UNIT_MASK; 671 set = BCM54XX_ECD_CTRL_RUN | BCM54XX_ECD_CTRL_BREAK_LINK | 672 FIELD_PREP(BCM54XX_ECD_CTRL_UNIT_MASK, 673 BCM54XX_ECD_CTRL_UNIT_CM); 674 675 ret = __bcm_phy_modify_exp(phydev, BCM54XX_EXP_ECD_CTRL, mask, set); 676 677 out: 678 /* re-enable the RDB access even if there was an error */ 679 if (is_rdb) 680 ret = __bcm_phy_enable_rdb_access(phydev) ? : ret; 681 682 phy_unlock_mdio_bus(phydev); 683 684 return ret; 685 } 686 687 static int bcm_phy_cable_test_report_trans(int result) 688 { 689 switch (result) { 690 case BCM54XX_ECD_FAULT_TYPE_OK: 691 return ETHTOOL_A_CABLE_RESULT_CODE_OK; 692 case BCM54XX_ECD_FAULT_TYPE_OPEN: 693 return ETHTOOL_A_CABLE_RESULT_CODE_OPEN; 694 case BCM54XX_ECD_FAULT_TYPE_SAME_SHORT: 695 return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT; 696 case BCM54XX_ECD_FAULT_TYPE_CROSS_SHORT: 697 return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT; 698 case BCM54XX_ECD_FAULT_TYPE_INVALID: 699 case BCM54XX_ECD_FAULT_TYPE_BUSY: 700 default: 701 return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC; 702 } 703 } 704 705 static bool bcm_phy_distance_valid(int result) 706 { 707 switch (result) { 708 case BCM54XX_ECD_FAULT_TYPE_OPEN: 709 case BCM54XX_ECD_FAULT_TYPE_SAME_SHORT: 710 case BCM54XX_ECD_FAULT_TYPE_CROSS_SHORT: 711 return true; 712 } 713 return false; 714 } 715 716 static int bcm_phy_report_length(struct phy_device *phydev, int pair) 717 { 718 int val; 719 720 val = __bcm_phy_read_exp(phydev, 721 BCM54XX_EXP_ECD_PAIR_A_LENGTH_RESULTS + pair); 722 if (val < 0) 723 return val; 724 725 if (val == BCM54XX_ECD_LENGTH_RESULTS_INVALID) 726 return 0; 727 728 ethnl_cable_test_fault_length(phydev, pair, val); 729 730 return 0; 731 } 732 733 static int _bcm_phy_cable_test_get_status(struct phy_device *phydev, 734 bool *finished, bool is_rdb) 735 { 736 int pair_a, pair_b, pair_c, pair_d, ret; 737 738 *finished = false; 739 740 phy_lock_mdio_bus(phydev); 741 742 if (is_rdb) { 743 ret = __bcm_phy_enable_legacy_access(phydev); 744 if (ret) 745 goto out; 746 } 747 748 ret = __bcm_phy_read_exp(phydev, BCM54XX_EXP_ECD_CTRL); 749 if (ret < 0) 750 goto out; 751 752 if (ret & BCM54XX_ECD_CTRL_IN_PROGRESS) { 753 ret = 0; 754 goto out; 755 } 756 757 ret = __bcm_phy_read_exp(phydev, BCM54XX_EXP_ECD_FAULT_TYPE); 758 if (ret < 0) 759 goto out; 760 761 pair_a = FIELD_GET(BCM54XX_ECD_FAULT_TYPE_PAIR_A_MASK, ret); 762 pair_b = FIELD_GET(BCM54XX_ECD_FAULT_TYPE_PAIR_B_MASK, ret); 763 pair_c = FIELD_GET(BCM54XX_ECD_FAULT_TYPE_PAIR_C_MASK, ret); 764 pair_d = FIELD_GET(BCM54XX_ECD_FAULT_TYPE_PAIR_D_MASK, ret); 765 766 ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A, 767 bcm_phy_cable_test_report_trans(pair_a)); 768 ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_B, 769 bcm_phy_cable_test_report_trans(pair_b)); 770 ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_C, 771 bcm_phy_cable_test_report_trans(pair_c)); 772 ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_D, 773 bcm_phy_cable_test_report_trans(pair_d)); 774 775 if (bcm_phy_distance_valid(pair_a)) 776 bcm_phy_report_length(phydev, 0); 777 if (bcm_phy_distance_valid(pair_b)) 778 bcm_phy_report_length(phydev, 1); 779 if (bcm_phy_distance_valid(pair_c)) 780 bcm_phy_report_length(phydev, 2); 781 if (bcm_phy_distance_valid(pair_d)) 782 bcm_phy_report_length(phydev, 3); 783 784 ret = 0; 785 *finished = true; 786 out: 787 /* re-enable the RDB access even if there was an error */ 788 if (is_rdb) 789 ret = __bcm_phy_enable_rdb_access(phydev) ? : ret; 790 791 phy_unlock_mdio_bus(phydev); 792 793 return ret; 794 } 795 796 static int bcm_setup_lre_forced(struct phy_device *phydev) 797 { 798 u16 ctl = 0; 799 800 phydev->pause = 0; 801 phydev->asym_pause = 0; 802 803 if (phydev->speed == SPEED_100) 804 ctl |= LRECR_SPEED100; 805 806 if (phydev->duplex != DUPLEX_FULL) 807 return -EOPNOTSUPP; 808 809 return phy_modify(phydev, MII_BCM54XX_LRECR, LRECR_SPEED100, ctl); 810 } 811 812 /** 813 * bcm_linkmode_adv_to_lre_adv_t - translate linkmode advertisement to LDS 814 * @advertising: the linkmode advertisement settings 815 * Return: LDS Auto-Negotiation Advertised Ability register value 816 * 817 * A small helper function that translates linkmode advertisement 818 * settings to phy LDS autonegotiation advertisements for the 819 * MII_BCM54XX_LREANAA register of Broadcom PHYs capable of LDS 820 */ 821 static u32 bcm_linkmode_adv_to_lre_adv_t(unsigned long *advertising) 822 { 823 u32 result = 0; 824 825 if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT1BRR_Full_BIT, 826 advertising)) 827 result |= LREANAA_10_1PAIR; 828 if (linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT1_Full_BIT, 829 advertising)) 830 result |= LREANAA_100_1PAIR; 831 if (linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT, advertising)) 832 result |= LRELPA_PAUSE; 833 if (linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, advertising)) 834 result |= LRELPA_PAUSE_ASYM; 835 836 return result; 837 } 838 839 int bcm_phy_cable_test_start(struct phy_device *phydev) 840 { 841 return _bcm_phy_cable_test_start(phydev, false); 842 } 843 EXPORT_SYMBOL_GPL(bcm_phy_cable_test_start); 844 845 int bcm_phy_cable_test_get_status(struct phy_device *phydev, bool *finished) 846 { 847 return _bcm_phy_cable_test_get_status(phydev, finished, false); 848 } 849 EXPORT_SYMBOL_GPL(bcm_phy_cable_test_get_status); 850 851 /* We assume that all PHYs which support RDB access can be switched to legacy 852 * mode. If, in the future, this is not true anymore, we have to re-implement 853 * this with RDB access. 854 */ 855 int bcm_phy_cable_test_start_rdb(struct phy_device *phydev) 856 { 857 return _bcm_phy_cable_test_start(phydev, true); 858 } 859 EXPORT_SYMBOL_GPL(bcm_phy_cable_test_start_rdb); 860 861 int bcm_phy_cable_test_get_status_rdb(struct phy_device *phydev, 862 bool *finished) 863 { 864 return _bcm_phy_cable_test_get_status(phydev, finished, true); 865 } 866 EXPORT_SYMBOL_GPL(bcm_phy_cable_test_get_status_rdb); 867 868 #define BCM54XX_WOL_SUPPORTED_MASK (WAKE_UCAST | \ 869 WAKE_MCAST | \ 870 WAKE_BCAST | \ 871 WAKE_MAGIC | \ 872 WAKE_MAGICSECURE) 873 874 int bcm_phy_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol) 875 { 876 struct net_device *ndev = phydev->attached_dev; 877 u8 da[ETH_ALEN], mask[ETH_ALEN]; 878 unsigned int i; 879 u16 ctl; 880 int ret; 881 882 /* Allow a MAC driver to play through its own Wake-on-LAN 883 * implementation 884 */ 885 if (wol->wolopts & ~BCM54XX_WOL_SUPPORTED_MASK) 886 return -EOPNOTSUPP; 887 888 /* The PHY supports passwords of 4, 6 and 8 bytes in size, but Linux's 889 * ethtool only supports 6, for now. 890 */ 891 BUILD_BUG_ON(sizeof(wol->sopass) != ETH_ALEN); 892 893 /* Clear previous interrupts */ 894 ret = bcm_phy_read_exp(phydev, BCM54XX_WOL_INT_STATUS); 895 if (ret < 0) 896 return ret; 897 898 ret = bcm_phy_read_exp(phydev, BCM54XX_WOL_MAIN_CTL); 899 if (ret < 0) 900 return ret; 901 902 ctl = ret; 903 904 if (!wol->wolopts) { 905 if (phy_interrupt_is_valid(phydev)) 906 disable_irq_wake(phydev->irq); 907 908 /* Leave all interrupts disabled */ 909 ret = bcm_phy_write_exp(phydev, BCM54XX_WOL_INT_MASK, 910 BCM54XX_WOL_ALL_INTRS); 911 if (ret < 0) 912 return ret; 913 914 /* Disable the global Wake-on-LAN enable bit */ 915 ctl &= ~BCM54XX_WOL_EN; 916 917 return bcm_phy_write_exp(phydev, BCM54XX_WOL_MAIN_CTL, ctl); 918 } 919 920 /* Clear the previously configured mode and mask mode for Wake-on-LAN */ 921 ctl &= ~(BCM54XX_WOL_MODE_MASK << BCM54XX_WOL_MODE_SHIFT); 922 ctl &= ~(BCM54XX_WOL_MASK_MODE_MASK << BCM54XX_WOL_MASK_MODE_SHIFT); 923 ctl &= ~BCM54XX_WOL_DIR_PKT_EN; 924 ctl &= ~(BCM54XX_WOL_SECKEY_OPT_MASK << BCM54XX_WOL_SECKEY_OPT_SHIFT); 925 926 /* When using WAKE_MAGIC, we program the magic pattern filter to match 927 * the device's MAC address and we accept any MAC DA in the Ethernet 928 * frame. 929 * 930 * When using WAKE_UCAST, WAKE_BCAST or WAKE_MCAST, we program the 931 * following: 932 * - WAKE_UCAST -> MAC DA is the device's MAC with a perfect match 933 * - WAKE_MCAST -> MAC DA is X1:XX:XX:XX:XX:XX where XX is don't care 934 * - WAKE_BCAST -> MAC DA is FF:FF:FF:FF:FF:FF with a perfect match 935 * 936 * Note that the Broadcast MAC DA is inherently going to match the 937 * multicast pattern being matched. 938 */ 939 memset(mask, 0, sizeof(mask)); 940 941 if (wol->wolopts & WAKE_MCAST) { 942 memset(da, 0, sizeof(da)); 943 memset(mask, 0xff, sizeof(mask)); 944 da[0] = 0x01; 945 mask[0] = ~da[0]; 946 } else { 947 if (wol->wolopts & WAKE_UCAST) { 948 ether_addr_copy(da, ndev->dev_addr); 949 } else if (wol->wolopts & WAKE_BCAST) { 950 eth_broadcast_addr(da); 951 } else if (wol->wolopts & WAKE_MAGICSECURE) { 952 ether_addr_copy(da, wol->sopass); 953 } else if (wol->wolopts & WAKE_MAGIC) { 954 memset(da, 0, sizeof(da)); 955 memset(mask, 0xff, sizeof(mask)); 956 } 957 } 958 959 for (i = 0; i < ETH_ALEN / 2; i++) { 960 if (wol->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE)) { 961 ret = bcm_phy_write_exp(phydev, 962 BCM54XX_WOL_MPD_DATA1(2 - i), 963 ndev->dev_addr[i * 2] << 8 | 964 ndev->dev_addr[i * 2 + 1]); 965 if (ret < 0) 966 return ret; 967 } 968 969 ret = bcm_phy_write_exp(phydev, BCM54XX_WOL_MPD_DATA2(2 - i), 970 da[i * 2] << 8 | da[i * 2 + 1]); 971 if (ret < 0) 972 return ret; 973 974 ret = bcm_phy_write_exp(phydev, BCM54XX_WOL_MASK(2 - i), 975 mask[i * 2] << 8 | mask[i * 2 + 1]); 976 if (ret) 977 return ret; 978 } 979 980 if (wol->wolopts & WAKE_MAGICSECURE) { 981 ctl |= BCM54XX_WOL_SECKEY_OPT_6B << 982 BCM54XX_WOL_SECKEY_OPT_SHIFT; 983 ctl |= BCM54XX_WOL_MODE_SINGLE_MPDSEC << BCM54XX_WOL_MODE_SHIFT; 984 ctl |= BCM54XX_WOL_MASK_MODE_DA_FF << 985 BCM54XX_WOL_MASK_MODE_SHIFT; 986 } else { 987 if (wol->wolopts & WAKE_MAGIC) 988 ctl |= BCM54XX_WOL_MODE_SINGLE_MPD; 989 else 990 ctl |= BCM54XX_WOL_DIR_PKT_EN; 991 ctl |= BCM54XX_WOL_MASK_MODE_DA_ONLY << 992 BCM54XX_WOL_MASK_MODE_SHIFT; 993 } 994 995 /* Globally enable Wake-on-LAN */ 996 ctl |= BCM54XX_WOL_EN | BCM54XX_WOL_CRC_CHK; 997 998 ret = bcm_phy_write_exp(phydev, BCM54XX_WOL_MAIN_CTL, ctl); 999 if (ret < 0) 1000 return ret; 1001 1002 /* Enable WOL interrupt on LED4 */ 1003 ret = bcm_phy_read_exp(phydev, BCM54XX_TOP_MISC_LED_CTL); 1004 if (ret < 0) 1005 return ret; 1006 1007 ret |= BCM54XX_LED4_SEL_INTR; 1008 ret = bcm_phy_write_exp(phydev, BCM54XX_TOP_MISC_LED_CTL, ret); 1009 if (ret < 0) 1010 return ret; 1011 1012 /* Enable all Wake-on-LAN interrupt sources */ 1013 ret = bcm_phy_write_exp(phydev, BCM54XX_WOL_INT_MASK, 0); 1014 if (ret < 0) 1015 return ret; 1016 1017 if (phy_interrupt_is_valid(phydev)) 1018 enable_irq_wake(phydev->irq); 1019 1020 return 0; 1021 } 1022 EXPORT_SYMBOL_GPL(bcm_phy_set_wol); 1023 1024 void bcm_phy_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol) 1025 { 1026 struct net_device *ndev = phydev->attached_dev; 1027 u8 da[ETH_ALEN]; 1028 unsigned int i; 1029 int ret; 1030 u16 ctl; 1031 1032 wol->supported = BCM54XX_WOL_SUPPORTED_MASK; 1033 wol->wolopts = 0; 1034 1035 ret = bcm_phy_read_exp(phydev, BCM54XX_WOL_MAIN_CTL); 1036 if (ret < 0) 1037 return; 1038 1039 ctl = ret; 1040 1041 if (!(ctl & BCM54XX_WOL_EN)) 1042 return; 1043 1044 for (i = 0; i < sizeof(da) / 2; i++) { 1045 ret = bcm_phy_read_exp(phydev, 1046 BCM54XX_WOL_MPD_DATA2(2 - i)); 1047 if (ret < 0) 1048 return; 1049 1050 da[i * 2] = ret >> 8; 1051 da[i * 2 + 1] = ret & 0xff; 1052 } 1053 1054 if (ctl & BCM54XX_WOL_DIR_PKT_EN) { 1055 if (is_broadcast_ether_addr(da)) 1056 wol->wolopts |= WAKE_BCAST; 1057 else if (is_multicast_ether_addr(da)) 1058 wol->wolopts |= WAKE_MCAST; 1059 else if (ether_addr_equal(da, ndev->dev_addr)) 1060 wol->wolopts |= WAKE_UCAST; 1061 } else { 1062 ctl = (ctl >> BCM54XX_WOL_MODE_SHIFT) & BCM54XX_WOL_MODE_MASK; 1063 switch (ctl) { 1064 case BCM54XX_WOL_MODE_SINGLE_MPD: 1065 wol->wolopts |= WAKE_MAGIC; 1066 break; 1067 case BCM54XX_WOL_MODE_SINGLE_MPDSEC: 1068 wol->wolopts |= WAKE_MAGICSECURE; 1069 memcpy(wol->sopass, da, sizeof(da)); 1070 break; 1071 default: 1072 break; 1073 } 1074 } 1075 } 1076 EXPORT_SYMBOL_GPL(bcm_phy_get_wol); 1077 1078 irqreturn_t bcm_phy_wol_isr(int irq, void *dev_id) 1079 { 1080 return IRQ_HANDLED; 1081 } 1082 EXPORT_SYMBOL_GPL(bcm_phy_wol_isr); 1083 1084 int bcm_phy_led_brightness_set(struct phy_device *phydev, 1085 u8 index, enum led_brightness value) 1086 { 1087 u8 led_num; 1088 int ret; 1089 u16 reg; 1090 1091 if (index >= 4) 1092 return -EINVAL; 1093 1094 /* Two LEDS per register */ 1095 led_num = index % 2; 1096 reg = index >= 2 ? BCM54XX_SHD_LEDS2 : BCM54XX_SHD_LEDS1; 1097 1098 ret = bcm_phy_read_shadow(phydev, reg); 1099 if (ret < 0) 1100 return ret; 1101 1102 ret &= ~(BCM_LED_SRC_MASK << BCM54XX_SHD_LEDS_SHIFT(led_num)); 1103 if (value == LED_OFF) 1104 ret |= BCM_LED_SRC_OFF << BCM54XX_SHD_LEDS_SHIFT(led_num); 1105 else 1106 ret |= BCM_LED_SRC_ON << BCM54XX_SHD_LEDS_SHIFT(led_num); 1107 return bcm_phy_write_shadow(phydev, reg, ret); 1108 } 1109 EXPORT_SYMBOL_GPL(bcm_phy_led_brightness_set); 1110 1111 int bcm_setup_lre_master_slave(struct phy_device *phydev) 1112 { 1113 u16 ctl = 0; 1114 1115 switch (phydev->master_slave_set) { 1116 case MASTER_SLAVE_CFG_MASTER_PREFERRED: 1117 case MASTER_SLAVE_CFG_MASTER_FORCE: 1118 ctl = LRECR_MASTER; 1119 break; 1120 case MASTER_SLAVE_CFG_SLAVE_PREFERRED: 1121 case MASTER_SLAVE_CFG_SLAVE_FORCE: 1122 break; 1123 case MASTER_SLAVE_CFG_UNKNOWN: 1124 case MASTER_SLAVE_CFG_UNSUPPORTED: 1125 return 0; 1126 default: 1127 phydev_warn(phydev, "Unsupported Master/Slave mode\n"); 1128 return -EOPNOTSUPP; 1129 } 1130 1131 return phy_modify_changed(phydev, MII_BCM54XX_LRECR, LRECR_MASTER, ctl); 1132 } 1133 EXPORT_SYMBOL_GPL(bcm_setup_lre_master_slave); 1134 1135 int bcm_config_lre_aneg(struct phy_device *phydev, bool changed) 1136 { 1137 int err; 1138 1139 if (genphy_c45_an_config_eee_aneg(phydev) > 0) 1140 changed = true; 1141 1142 err = bcm_setup_lre_master_slave(phydev); 1143 if (err < 0) 1144 return err; 1145 else if (err) 1146 changed = true; 1147 1148 if (phydev->autoneg != AUTONEG_ENABLE) 1149 return bcm_setup_lre_forced(phydev); 1150 1151 err = bcm_config_lre_advert(phydev); 1152 if (err < 0) 1153 return err; 1154 else if (err) 1155 changed = true; 1156 1157 return genphy_check_and_restart_aneg(phydev, changed); 1158 } 1159 EXPORT_SYMBOL_GPL(bcm_config_lre_aneg); 1160 1161 /** 1162 * bcm_config_lre_advert - sanitize and advertise Long-Distance Signaling 1163 * auto-negotiation parameters 1164 * @phydev: target phy_device struct 1165 * Return: 0 if the PHY's advertisement hasn't changed, < 0 on error, 1166 * > 0 if it has changed 1167 * 1168 * Writes MII_BCM54XX_LREANAA with the appropriate values. The values are to be 1169 * sanitized before, to make sure we only advertise what is supported. 1170 * The sanitization is done already in phy_ethtool_ksettings_set() 1171 */ 1172 int bcm_config_lre_advert(struct phy_device *phydev) 1173 { 1174 u32 adv = bcm_linkmode_adv_to_lre_adv_t(phydev->advertising); 1175 1176 /* Setup BroadR-Reach mode advertisement */ 1177 return phy_modify_changed(phydev, MII_BCM54XX_LREANAA, 1178 LRE_ADVERTISE_ALL | LREANAA_PAUSE | 1179 LREANAA_PAUSE_ASYM, adv); 1180 } 1181 EXPORT_SYMBOL_GPL(bcm_config_lre_advert); 1182 1183 MODULE_DESCRIPTION("Broadcom PHY Library"); 1184 MODULE_LICENSE("GPL v2"); 1185 MODULE_AUTHOR("Broadcom Corporation"); 1186