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