Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'net-phy-bcm5481x-add-support-for-broadr-reach-mode'

Kamil Horák says:

====================
net: phy: bcm5481x: add support for BroadR-Reach mode

PATCH 1 - Add the 10baseT1BRR_Full link mode

PATCH 2 - Add the definitions of LRE registers, necessary to use
BroadR-Reach modes on the BCM5481x PHY

PATCH 3 - Add brr-mode flag to switch between IEEE802.3 and BroadR-Reach

PATCH 4 - Implementation of the BroadR-Reach modes for the Broadcom
PHYs
====================

Link: https://patch.msgid.link/20240712150709.3134474-1-kamilh@axis.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+603 -36
+8
Documentation/devicetree/bindings/net/ethernet-phy.yaml
··· 93 93 the turn around line low at end of the control phase of the 94 94 MDIO transaction. 95 95 96 + brr-mode: 97 + $ref: /schemas/types.yaml#/definitions/flag 98 + description: 99 + If set, indicates the network cable interface is an alternative one as 100 + defined in the BroadR-Reach link mode specification under 1BR-100 and 101 + 1BR-10 names. The PHY must be configured to operate in BroadR-Reach mode 102 + by software. 103 + 96 104 clocks: 97 105 maxItems: 1 98 106 description:
+115
drivers/net/phy/bcm-phy-lib.c
··· 794 794 return ret; 795 795 } 796 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 + 797 840 int bcm_phy_cable_test_start(struct phy_device *phydev) 798 841 { 799 842 return _bcm_phy_cable_test_start(phydev, false); ··· 1108 1065 return bcm_phy_write_shadow(phydev, reg, ret); 1109 1066 } 1110 1067 EXPORT_SYMBOL_GPL(bcm_phy_led_brightness_set); 1068 + 1069 + int bcm_setup_lre_master_slave(struct phy_device *phydev) 1070 + { 1071 + u16 ctl = 0; 1072 + 1073 + switch (phydev->master_slave_set) { 1074 + case MASTER_SLAVE_CFG_MASTER_PREFERRED: 1075 + case MASTER_SLAVE_CFG_MASTER_FORCE: 1076 + ctl = LRECR_MASTER; 1077 + break; 1078 + case MASTER_SLAVE_CFG_SLAVE_PREFERRED: 1079 + case MASTER_SLAVE_CFG_SLAVE_FORCE: 1080 + break; 1081 + case MASTER_SLAVE_CFG_UNKNOWN: 1082 + case MASTER_SLAVE_CFG_UNSUPPORTED: 1083 + return 0; 1084 + default: 1085 + phydev_warn(phydev, "Unsupported Master/Slave mode\n"); 1086 + return -EOPNOTSUPP; 1087 + } 1088 + 1089 + return phy_modify_changed(phydev, MII_BCM54XX_LRECR, LRECR_MASTER, ctl); 1090 + } 1091 + EXPORT_SYMBOL_GPL(bcm_setup_lre_master_slave); 1092 + 1093 + int bcm_config_lre_aneg(struct phy_device *phydev, bool changed) 1094 + { 1095 + int err; 1096 + 1097 + if (genphy_config_eee_advert(phydev)) 1098 + changed = true; 1099 + 1100 + err = bcm_setup_lre_master_slave(phydev); 1101 + if (err < 0) 1102 + return err; 1103 + else if (err) 1104 + changed = true; 1105 + 1106 + if (phydev->autoneg != AUTONEG_ENABLE) 1107 + return bcm_setup_lre_forced(phydev); 1108 + 1109 + err = bcm_config_lre_advert(phydev); 1110 + if (err < 0) 1111 + return err; 1112 + else if (err) 1113 + changed = true; 1114 + 1115 + return genphy_check_and_restart_aneg(phydev, changed); 1116 + } 1117 + EXPORT_SYMBOL_GPL(bcm_config_lre_aneg); 1118 + 1119 + /** 1120 + * bcm_config_lre_advert - sanitize and advertise Long-Distance Signaling 1121 + * auto-negotiation parameters 1122 + * @phydev: target phy_device struct 1123 + * Return: 0 if the PHY's advertisement hasn't changed, < 0 on error, 1124 + * > 0 if it has changed 1125 + * 1126 + * Writes MII_BCM54XX_LREANAA with the appropriate values. The values are to be 1127 + * sanitized before, to make sure we only advertise what is supported. 1128 + * The sanitization is done already in phy_ethtool_ksettings_set() 1129 + */ 1130 + int bcm_config_lre_advert(struct phy_device *phydev) 1131 + { 1132 + u32 adv = bcm_linkmode_adv_to_lre_adv_t(phydev->advertising); 1133 + 1134 + /* Setup BroadR-Reach mode advertisement */ 1135 + return phy_modify_changed(phydev, MII_BCM54XX_LREANAA, 1136 + LRE_ADVERTISE_ALL | LREANAA_PAUSE | 1137 + LREANAA_PAUSE_ASYM, adv); 1138 + } 1139 + EXPORT_SYMBOL_GPL(bcm_config_lre_advert); 1111 1140 1112 1141 MODULE_DESCRIPTION("Broadcom PHY Library"); 1113 1142 MODULE_LICENSE("GPL v2");
+4
drivers/net/phy/bcm-phy-lib.h
··· 121 121 int bcm_phy_led_brightness_set(struct phy_device *phydev, 122 122 u8 index, enum led_brightness value); 123 123 124 + int bcm_setup_lre_master_slave(struct phy_device *phydev); 125 + int bcm_config_lre_aneg(struct phy_device *phydev, bool changed); 126 + int bcm_config_lre_advert(struct phy_device *phydev); 127 + 124 128 #endif /* _LINUX_BCM_PHY_LIB_H */
+382 -35
drivers/net/phy/broadcom.c
··· 5 5 * Broadcom BCM5411, BCM5421 and BCM5461 Gigabit Ethernet 6 6 * transceivers. 7 7 * 8 + * Broadcom BCM54810, BCM54811 BroadR-Reach transceivers. 9 + * 8 10 * Copyright (c) 2006 Maciej W. Rozycki 9 11 * 10 12 * Inspired by code written by Amy Fong. ··· 38 36 struct bcm_ptp_private *ptp; 39 37 int wake_irq; 40 38 bool wake_irq_enabled; 39 + bool brr_mode; 40 + }; 41 + 42 + /* Link modes for BCM58411 PHY */ 43 + static const int bcm54811_linkmodes[] = { 44 + ETHTOOL_LINK_MODE_100baseT1_Full_BIT, 45 + ETHTOOL_LINK_MODE_10baseT1BRR_Full_BIT, 46 + ETHTOOL_LINK_MODE_1000baseT_Full_BIT, 47 + ETHTOOL_LINK_MODE_1000baseX_Full_BIT, 48 + ETHTOOL_LINK_MODE_1000baseT_Half_BIT, 49 + ETHTOOL_LINK_MODE_100baseT_Full_BIT, 50 + ETHTOOL_LINK_MODE_100baseT_Half_BIT, 51 + ETHTOOL_LINK_MODE_10baseT_Full_BIT, 52 + ETHTOOL_LINK_MODE_10baseT_Half_BIT 53 + }; 54 + 55 + /* Long-Distance Signaling (BroadR-Reach mode aneg) relevant linkmode bits */ 56 + static const int lds_br_bits[] = { 57 + ETHTOOL_LINK_MODE_Autoneg_BIT, 58 + ETHTOOL_LINK_MODE_Pause_BIT, 59 + ETHTOOL_LINK_MODE_Asym_Pause_BIT, 60 + ETHTOOL_LINK_MODE_10baseT1BRR_Full_BIT, 61 + ETHTOOL_LINK_MODE_100baseT1_Full_BIT 41 62 }; 42 63 43 64 static bool bcm54xx_phy_can_wakeup(struct phy_device *phydev) ··· 372 347 bcm_ptp_config_init(phydev); 373 348 } 374 349 350 + static int bcm5481x_set_brrmode(struct phy_device *phydev, bool on) 351 + { 352 + int reg; 353 + int err; 354 + u16 val; 355 + 356 + reg = bcm_phy_read_exp(phydev, BCM54810_EXP_BROADREACH_LRE_MISC_CTL); 357 + 358 + if (reg < 0) 359 + return reg; 360 + 361 + if (on) 362 + reg |= BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN; 363 + else 364 + reg &= ~BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN; 365 + 366 + err = bcm_phy_write_exp(phydev, 367 + BCM54810_EXP_BROADREACH_LRE_MISC_CTL, reg); 368 + if (err) 369 + return err; 370 + 371 + /* Ensure LRE or IEEE register set is accessed according to the brr 372 + * on/off, thus set the override 373 + */ 374 + val = BCM54811_EXP_BROADREACH_LRE_OVERLAY_CTL_EN; 375 + if (!on) 376 + val |= BCM54811_EXP_BROADREACH_LRE_OVERLAY_CTL_OVERRIDE_VAL; 377 + 378 + return bcm_phy_write_exp(phydev, 379 + BCM54811_EXP_BROADREACH_LRE_OVERLAY_CTL, val); 380 + } 381 + 382 + static int bcm54811_config_init(struct phy_device *phydev) 383 + { 384 + struct bcm54xx_phy_priv *priv = phydev->priv; 385 + int err, reg; 386 + 387 + /* Enable CLK125 MUX on LED4 if ref clock is enabled. */ 388 + if (!(phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED)) { 389 + reg = bcm_phy_read_exp(phydev, BCM54612E_EXP_SPARE0); 390 + if (reg < 0) 391 + return reg; 392 + err = bcm_phy_write_exp(phydev, BCM54612E_EXP_SPARE0, 393 + BCM54612E_LED4_CLK125OUT_EN | reg); 394 + if (err < 0) 395 + return err; 396 + } 397 + 398 + /* With BCM54811, BroadR-Reach implies no autoneg */ 399 + if (priv->brr_mode) 400 + phydev->autoneg = 0; 401 + 402 + return bcm5481x_set_brrmode(phydev, priv->brr_mode); 403 + } 404 + 375 405 static int bcm54xx_config_init(struct phy_device *phydev) 376 406 { 377 407 int reg, err, val; ··· 478 398 err = bcm_phy_write_exp(phydev, 479 399 BCM54810_EXP_BROADREACH_LRE_MISC_CTL, 480 400 val); 401 + break; 402 + case PHY_ID_BCM54811: 403 + err = bcm54811_config_init(phydev); 481 404 break; 482 405 } 483 406 if (err) ··· 636 553 return -EOPNOTSUPP; 637 554 } 638 555 639 - static int bcm54811_config_init(struct phy_device *phydev) 640 - { 641 - int err, reg; 642 556 643 - /* Disable BroadR-Reach function. */ 644 - reg = bcm_phy_read_exp(phydev, BCM54810_EXP_BROADREACH_LRE_MISC_CTL); 645 - reg &= ~BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN; 646 - err = bcm_phy_write_exp(phydev, BCM54810_EXP_BROADREACH_LRE_MISC_CTL, 647 - reg); 648 - if (err < 0) 649 - return err; 650 - 651 - err = bcm54xx_config_init(phydev); 652 - 653 - /* Enable CLK125 MUX on LED4 if ref clock is enabled. */ 654 - if (!(phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED)) { 655 - reg = bcm_phy_read_exp(phydev, BCM54612E_EXP_SPARE0); 656 - err = bcm_phy_write_exp(phydev, BCM54612E_EXP_SPARE0, 657 - BCM54612E_LED4_CLK125OUT_EN | reg); 658 - if (err < 0) 659 - return err; 660 - } 661 - 662 - return err; 663 - } 664 - 665 - static int bcm5481_config_aneg(struct phy_device *phydev) 557 + /** 558 + * bcm5481x_read_abilities - read PHY abilities from LRESR or Clause 22 559 + * (BMSR) registers, based on whether the PHY is in BroadR-Reach or IEEE mode 560 + * @phydev: target phy_device struct 561 + * 562 + * Description: Reads the PHY's abilities and populates phydev->supported 563 + * accordingly. The register to read the abilities from is determined by 564 + * the brr mode setting of the PHY as read from the device tree. 565 + * Note that the LRE and IEEE sets of abilities are disjunct, in other words, 566 + * not only the link modes differ, but also the auto-negotiation and 567 + * master-slave setup is controlled differently. 568 + * 569 + * Returns: 0 on success, < 0 on failure 570 + */ 571 + static int bcm5481x_read_abilities(struct phy_device *phydev) 666 572 { 667 573 struct device_node *np = phydev->mdio.dev.of_node; 668 - int ret; 574 + struct bcm54xx_phy_priv *priv = phydev->priv; 575 + int i, val, err; 669 576 670 - /* Aneg firstly. */ 671 - ret = genphy_config_aneg(phydev); 577 + for (i = 0; i < ARRAY_SIZE(bcm54811_linkmodes); i++) 578 + linkmode_clear_bit(bcm54811_linkmodes[i], phydev->supported); 672 579 673 - /* Then we can set up the delay. */ 580 + priv->brr_mode = of_property_read_bool(np, "brr-mode"); 581 + 582 + /* Set BroadR-Reach mode as configured in the DT. */ 583 + err = bcm5481x_set_brrmode(phydev, priv->brr_mode); 584 + if (err) 585 + return err; 586 + 587 + if (priv->brr_mode) { 588 + linkmode_set_bit_array(phy_basic_ports_array, 589 + ARRAY_SIZE(phy_basic_ports_array), 590 + phydev->supported); 591 + 592 + val = phy_read(phydev, MII_BCM54XX_LRESR); 593 + if (val < 0) 594 + return val; 595 + 596 + linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, 597 + phydev->supported, 598 + val & LRESR_LDSABILITY); 599 + linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT1_Full_BIT, 600 + phydev->supported, 601 + val & LRESR_100_1PAIR); 602 + linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT1BRR_Full_BIT, 603 + phydev->supported, 604 + val & LRESR_10_1PAIR); 605 + return 0; 606 + } 607 + 608 + return genphy_read_abilities(phydev); 609 + } 610 + 611 + static int bcm5481x_config_delay_swap(struct phy_device *phydev) 612 + { 613 + struct device_node *np = phydev->mdio.dev.of_node; 614 + 615 + /* Set up the delay. */ 674 616 bcm54xx_config_clock_delay(phydev); 675 617 676 618 if (of_property_read_bool(np, "enet-phy-lane-swap")) { 677 619 /* Lane Swap - Undocumented register...magic! */ 678 - ret = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_SEL_ER + 0x9, 679 - 0x11B); 620 + int ret = bcm_phy_write_exp(phydev, 621 + MII_BCM54XX_EXP_SEL_ER + 0x9, 622 + 0x11B); 680 623 if (ret < 0) 681 624 return ret; 682 625 } 683 626 684 - return ret; 627 + return 0; 628 + } 629 + 630 + static int bcm5481_config_aneg(struct phy_device *phydev) 631 + { 632 + struct bcm54xx_phy_priv *priv = phydev->priv; 633 + int ret; 634 + 635 + /* Aneg firstly. */ 636 + if (priv->brr_mode) 637 + ret = bcm_config_lre_aneg(phydev, false); 638 + else 639 + ret = genphy_config_aneg(phydev); 640 + 641 + if (ret) 642 + return ret; 643 + 644 + /* Then we can set up the delay and swap. */ 645 + return bcm5481x_config_delay_swap(phydev); 646 + } 647 + 648 + static int bcm54811_config_aneg(struct phy_device *phydev) 649 + { 650 + struct bcm54xx_phy_priv *priv = phydev->priv; 651 + int ret; 652 + 653 + /* Aneg firstly. */ 654 + if (priv->brr_mode) { 655 + /* BCM54811 is only capable of autonegotiation in IEEE mode */ 656 + phydev->autoneg = 0; 657 + ret = bcm_config_lre_aneg(phydev, false); 658 + } else { 659 + ret = genphy_config_aneg(phydev); 660 + } 661 + 662 + if (ret) 663 + return ret; 664 + 665 + /* Then we can set up the delay and swap. */ 666 + return bcm5481x_config_delay_swap(phydev); 685 667 } 686 668 687 669 struct bcm54616s_phy_priv { ··· 1210 1062 bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP08, ret); 1211 1063 } 1212 1064 1065 + static int lre_read_master_slave(struct phy_device *phydev) 1066 + { 1067 + int cfg = MASTER_SLAVE_CFG_UNKNOWN, state; 1068 + int val; 1069 + 1070 + /* In BroadR-Reach mode we are always capable of master-slave 1071 + * and there is no preferred master or slave configuration 1072 + */ 1073 + phydev->master_slave_get = MASTER_SLAVE_CFG_UNKNOWN; 1074 + phydev->master_slave_state = MASTER_SLAVE_STATE_UNKNOWN; 1075 + 1076 + val = phy_read(phydev, MII_BCM54XX_LRECR); 1077 + if (val < 0) 1078 + return val; 1079 + 1080 + if ((val & LRECR_LDSEN) == 0) { 1081 + if (val & LRECR_MASTER) 1082 + cfg = MASTER_SLAVE_CFG_MASTER_FORCE; 1083 + else 1084 + cfg = MASTER_SLAVE_CFG_SLAVE_FORCE; 1085 + } 1086 + 1087 + val = phy_read(phydev, MII_BCM54XX_LRELDSE); 1088 + if (val < 0) 1089 + return val; 1090 + 1091 + if (val & LDSE_MASTER) 1092 + state = MASTER_SLAVE_STATE_MASTER; 1093 + else 1094 + state = MASTER_SLAVE_STATE_SLAVE; 1095 + 1096 + phydev->master_slave_get = cfg; 1097 + phydev->master_slave_state = state; 1098 + 1099 + return 0; 1100 + } 1101 + 1102 + /* Read LDS Link Partner Ability in BroadR-Reach mode */ 1103 + static int lre_read_lpa(struct phy_device *phydev) 1104 + { 1105 + int i, lrelpa; 1106 + 1107 + if (phydev->autoneg != AUTONEG_ENABLE) { 1108 + if (!phydev->autoneg_complete) { 1109 + /* aneg not yet done, reset all relevant bits */ 1110 + for (i = 0; i < ARRAY_SIZE(lds_br_bits); i++) 1111 + linkmode_clear_bit(lds_br_bits[i], 1112 + phydev->lp_advertising); 1113 + 1114 + return 0; 1115 + } 1116 + 1117 + /* Long-Distance Signaling Link Partner Ability */ 1118 + lrelpa = phy_read(phydev, MII_BCM54XX_LRELPA); 1119 + if (lrelpa < 0) 1120 + return lrelpa; 1121 + 1122 + linkmode_mod_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, 1123 + phydev->lp_advertising, 1124 + lrelpa & LRELPA_PAUSE_ASYM); 1125 + linkmode_mod_bit(ETHTOOL_LINK_MODE_Pause_BIT, 1126 + phydev->lp_advertising, 1127 + lrelpa & LRELPA_PAUSE); 1128 + linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT1_Full_BIT, 1129 + phydev->lp_advertising, 1130 + lrelpa & LRELPA_100_1PAIR); 1131 + linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT1BRR_Full_BIT, 1132 + phydev->lp_advertising, 1133 + lrelpa & LRELPA_10_1PAIR); 1134 + } else { 1135 + linkmode_zero(phydev->lp_advertising); 1136 + } 1137 + 1138 + return 0; 1139 + } 1140 + 1141 + static int lre_read_status_fixed(struct phy_device *phydev) 1142 + { 1143 + int lrecr = phy_read(phydev, MII_BCM54XX_LRECR); 1144 + 1145 + if (lrecr < 0) 1146 + return lrecr; 1147 + 1148 + phydev->duplex = DUPLEX_FULL; 1149 + 1150 + if (lrecr & LRECR_SPEED100) 1151 + phydev->speed = SPEED_100; 1152 + else 1153 + phydev->speed = SPEED_10; 1154 + 1155 + return 0; 1156 + } 1157 + 1158 + /** 1159 + * lre_update_link - update link status in @phydev 1160 + * @phydev: target phy_device struct 1161 + * Return: 0 on success, < 0 on error 1162 + * 1163 + * Description: Update the value in phydev->link to reflect the 1164 + * current link value. In order to do this, we need to read 1165 + * the status register twice, keeping the second value. 1166 + * This is a genphy_update_link modified to work on LRE registers 1167 + * of BroadR-Reach PHY 1168 + */ 1169 + static int lre_update_link(struct phy_device *phydev) 1170 + { 1171 + int status = 0, lrecr; 1172 + 1173 + lrecr = phy_read(phydev, MII_BCM54XX_LRECR); 1174 + if (lrecr < 0) 1175 + return lrecr; 1176 + 1177 + /* Autoneg is being started, therefore disregard BMSR value and 1178 + * report link as down. 1179 + */ 1180 + if (lrecr & BMCR_ANRESTART) 1181 + goto done; 1182 + 1183 + /* The link state is latched low so that momentary link 1184 + * drops can be detected. Do not double-read the status 1185 + * in polling mode to detect such short link drops except 1186 + * the link was already down. 1187 + */ 1188 + if (!phy_polling_mode(phydev) || !phydev->link) { 1189 + status = phy_read(phydev, MII_BCM54XX_LRESR); 1190 + if (status < 0) 1191 + return status; 1192 + else if (status & LRESR_LSTATUS) 1193 + goto done; 1194 + } 1195 + 1196 + /* Read link and autonegotiation status */ 1197 + status = phy_read(phydev, MII_BCM54XX_LRESR); 1198 + if (status < 0) 1199 + return status; 1200 + done: 1201 + phydev->link = status & LRESR_LSTATUS ? 1 : 0; 1202 + phydev->autoneg_complete = status & LRESR_LDSCOMPLETE ? 1 : 0; 1203 + 1204 + /* Consider the case that autoneg was started and "aneg complete" 1205 + * bit has been reset, but "link up" bit not yet. 1206 + */ 1207 + if (phydev->autoneg == AUTONEG_ENABLE && !phydev->autoneg_complete) 1208 + phydev->link = 0; 1209 + 1210 + return 0; 1211 + } 1212 + 1213 + /* Get the status in BroadRReach mode just like genphy_read_status does 1214 + * in normal mode 1215 + */ 1216 + static int bcm54811_lre_read_status(struct phy_device *phydev) 1217 + { 1218 + int err, old_link = phydev->link; 1219 + 1220 + /* Update the link, but return if there was an error */ 1221 + err = lre_update_link(phydev); 1222 + if (err) 1223 + return err; 1224 + 1225 + /* why bother the PHY if nothing can have changed */ 1226 + if (phydev->autoneg == 1227 + AUTONEG_ENABLE && old_link && phydev->link) 1228 + return 0; 1229 + 1230 + phydev->speed = SPEED_UNKNOWN; 1231 + phydev->duplex = DUPLEX_UNKNOWN; 1232 + phydev->pause = 0; 1233 + phydev->asym_pause = 0; 1234 + 1235 + err = lre_read_master_slave(phydev); 1236 + if (err < 0) 1237 + return err; 1238 + 1239 + /* Read LDS Link Partner Ability */ 1240 + err = lre_read_lpa(phydev); 1241 + if (err < 0) 1242 + return err; 1243 + 1244 + if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete) 1245 + phy_resolve_aneg_linkmode(phydev); 1246 + else if (phydev->autoneg == AUTONEG_DISABLE) 1247 + err = lre_read_status_fixed(phydev); 1248 + 1249 + return err; 1250 + } 1251 + 1252 + static int bcm54811_read_status(struct phy_device *phydev) 1253 + { 1254 + struct bcm54xx_phy_priv *priv = phydev->priv; 1255 + 1256 + if (priv->brr_mode) 1257 + return bcm54811_lre_read_status(phydev); 1258 + 1259 + return genphy_read_status(phydev); 1260 + } 1261 + 1213 1262 static struct phy_driver broadcom_drivers[] = { 1214 1263 { 1215 1264 .phy_id = PHY_ID_BCM5411, ··· 1556 1211 .get_strings = bcm_phy_get_strings, 1557 1212 .get_stats = bcm54xx_get_stats, 1558 1213 .probe = bcm54xx_phy_probe, 1559 - .config_init = bcm54811_config_init, 1560 - .config_aneg = bcm5481_config_aneg, 1214 + .config_init = bcm54xx_config_init, 1215 + .config_aneg = bcm54811_config_aneg, 1561 1216 .config_intr = bcm_phy_config_intr, 1562 1217 .handle_interrupt = bcm_phy_handle_interrupt, 1218 + .read_status = bcm54811_read_status, 1219 + .get_features = bcm5481x_read_abilities, 1563 1220 .suspend = bcm54xx_suspend, 1564 1221 .resume = bcm54xx_resume, 1565 1222 .link_change_notify = bcm54xx_link_change_notify,
+2 -1
drivers/net/phy/phy-core.c
··· 13 13 */ 14 14 const char *phy_speed_to_str(int speed) 15 15 { 16 - BUILD_BUG_ON_MSG(__ETHTOOL_LINK_MODE_MASK_NBITS != 102, 16 + BUILD_BUG_ON_MSG(__ETHTOOL_LINK_MODE_MASK_NBITS != 103, 17 17 "Enum ethtool_link_mode_bit_indices and phylib are out of sync. " 18 18 "If a speed or mode has been added please update phy_speed_to_str " 19 19 "and the PHY settings array.\n"); ··· 266 266 PHY_SETTING( 10, FULL, 10baseT1S_Full ), 267 267 PHY_SETTING( 10, HALF, 10baseT1S_Half ), 268 268 PHY_SETTING( 10, HALF, 10baseT1S_P2MP_Half ), 269 + PHY_SETTING( 10, FULL, 10baseT1BRR_Full ), 269 270 }; 270 271 #undef PHY_SETTING 271 272
+88
include/linux/brcmphy.h
··· 271 271 #define BCM5482_SSD_SGMII_SLAVE_EN 0x0002 /* Slave mode enable */ 272 272 #define BCM5482_SSD_SGMII_SLAVE_AD 0x0001 /* Slave auto-detection */ 273 273 274 + /* BroadR-Reach LRE Registers. */ 275 + #define MII_BCM54XX_LRECR 0x00 /* LRE Control Register */ 276 + #define MII_BCM54XX_LRESR 0x01 /* LRE Status Register */ 277 + #define MII_BCM54XX_LREPHYSID1 0x02 /* LRE PHYS ID 1 */ 278 + #define MII_BCM54XX_LREPHYSID2 0x03 /* LRE PHYS ID 2 */ 279 + #define MII_BCM54XX_LREANAA 0x04 /* LDS Auto-Negotiation Advertised Ability */ 280 + #define MII_BCM54XX_LREANAC 0x05 /* LDS Auto-Negotiation Advertised Control */ 281 + #define MII_BCM54XX_LREANPT 0x06 /* LDS Ability Next Page Transmit */ 282 + #define MII_BCM54XX_LRELPA 0x07 /* LDS Link Partner Ability */ 283 + #define MII_BCM54XX_LRELPNPM 0x08 /* LDS Link Partner Next Page Message */ 284 + #define MII_BCM54XX_LRELPNPC 0x09 /* LDS Link Partner Next Page Control */ 285 + #define MII_BCM54XX_LRELDSE 0x0a /* LDS Expansion Register */ 286 + #define MII_BCM54XX_LREES 0x0f /* LRE Extended Status */ 287 + 288 + /* LRE control register. */ 289 + #define LRECR_RESET 0x8000 /* Reset to default state */ 290 + #define LRECR_LOOPBACK 0x4000 /* Internal Loopback */ 291 + #define LRECR_LDSRES 0x2000 /* Restart LDS Process */ 292 + #define LRECR_LDSEN 0x1000 /* LDS Enable */ 293 + #define LRECR_PDOWN 0x0800 /* Enable low power state */ 294 + #define LRECR_ISOLATE 0x0400 /* Isolate data paths from MII */ 295 + #define LRECR_SPEED100 0x0200 /* Select 100 Mbps */ 296 + #define LRECR_SPEED10 0x0000 /* Select 10 Mbps */ 297 + #define LRECR_4PAIRS 0x0020 /* Select 4 Pairs */ 298 + #define LRECR_2PAIRS 0x0010 /* Select 2 Pairs */ 299 + #define LRECR_1PAIR 0x0000 /* Select 1 Pair */ 300 + #define LRECR_MASTER 0x0008 /* Force Master when LDS disabled */ 301 + #define LRECR_SLAVE 0x0000 /* Force Slave when LDS disabled */ 302 + 303 + /* LRE status register. */ 304 + #define LRESR_100_1PAIR 0x2000 /* Can do 100Mbps 1 Pair */ 305 + #define LRESR_100_4PAIR 0x1000 /* Can do 100Mbps 4 Pairs */ 306 + #define LRESR_100_2PAIR 0x0800 /* Can do 100Mbps 2 Pairs */ 307 + #define LRESR_10_2PAIR 0x0400 /* Can do 10Mbps 2 Pairs */ 308 + #define LRESR_10_1PAIR 0x0200 /* Can do 10Mbps 1 Pair */ 309 + #define LRESR_ESTATEN 0x0100 /* Extended Status in R15 */ 310 + #define LRESR_RESV 0x0080 /* Unused... */ 311 + #define LRESR_MFPS 0x0040 /* Can suppress Management Frames Preamble */ 312 + #define LRESR_LDSCOMPLETE 0x0020 /* LDS Auto-negotiation complete */ 313 + #define LRESR_8023 0x0010 /* Has IEEE 802.3 Support */ 314 + #define LRESR_LDSABILITY 0x0008 /* LDS auto-negotiation capable */ 315 + #define LRESR_LSTATUS 0x0004 /* Link status */ 316 + #define LRESR_JCD 0x0002 /* Jabber detected */ 317 + #define LRESR_ERCAP 0x0001 /* Ext-reg capability */ 318 + 319 + /* LDS Auto-Negotiation Advertised Ability. */ 320 + #define LREANAA_PAUSE_ASYM 0x8000 /* Can pause asymmetrically */ 321 + #define LREANAA_PAUSE 0x4000 /* Can pause */ 322 + #define LREANAA_100_1PAIR 0x0020 /* Can do 100Mbps 1 Pair */ 323 + #define LREANAA_100_4PAIR 0x0010 /* Can do 100Mbps 4 Pair */ 324 + #define LREANAA_100_2PAIR 0x0008 /* Can do 100Mbps 2 Pair */ 325 + #define LREANAA_10_2PAIR 0x0004 /* Can do 10Mbps 2 Pair */ 326 + #define LREANAA_10_1PAIR 0x0002 /* Can do 10Mbps 1 Pair */ 327 + 328 + #define LRE_ADVERTISE_FULL (LREANAA_100_1PAIR | LREANAA_100_4PAIR | \ 329 + LREANAA_100_2PAIR | LREANAA_10_2PAIR | \ 330 + LREANAA_10_1PAIR) 331 + 332 + #define LRE_ADVERTISE_ALL LRE_ADVERTISE_FULL 333 + 334 + /* LDS Link Partner Ability. */ 335 + #define LRELPA_PAUSE_ASYM 0x8000 /* Supports asymmetric pause */ 336 + #define LRELPA_PAUSE 0x4000 /* Supports pause capability */ 337 + #define LRELPA_100_1PAIR 0x0020 /* 100Mbps 1 Pair capable */ 338 + #define LRELPA_100_4PAIR 0x0010 /* 100Mbps 4 Pair capable */ 339 + #define LRELPA_100_2PAIR 0x0008 /* 100Mbps 2 Pair capable */ 340 + #define LRELPA_10_2PAIR 0x0004 /* 10Mbps 2 Pair capable */ 341 + #define LRELPA_10_1PAIR 0x0002 /* 10Mbps 1 Pair capable */ 342 + 343 + /* LDS Expansion register. */ 344 + #define LDSE_DOWNGRADE 0x8000 /* Can do LDS Speed Downgrade */ 345 + #define LDSE_MASTER 0x4000 /* Master / Slave */ 346 + #define LDSE_PAIRS_MASK 0x3000 /* Pair Count Mask */ 347 + #define LDSE_PAIRS_SHIFT 12 348 + #define LDSE_4PAIRS (2 << LDSE_PAIRS_SHIFT) /* 4 Pairs Connection */ 349 + #define LDSE_2PAIRS (1 << LDSE_PAIRS_SHIFT) /* 2 Pairs Connection */ 350 + #define LDSE_1PAIR (0 << LDSE_PAIRS_SHIFT) /* 1 Pair Connection */ 351 + #define LDSE_CABLEN_MASK 0x0FFF /* Cable Length Mask */ 352 + 274 353 /* BCM54810 Registers */ 275 354 #define BCM54810_EXP_BROADREACH_LRE_MISC_CTL (MII_BCM54XX_EXP_SEL_ER + 0x90) 276 355 #define BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN (1 << 0) 277 356 #define BCM54810_SHD_CLK_CTL 0x3 278 357 #define BCM54810_SHD_CLK_CTL_GTXCLK_EN (1 << 9) 358 + 359 + /* BCM54811 Registers */ 360 + #define BCM54811_EXP_BROADREACH_LRE_OVERLAY_CTL (MII_BCM54XX_EXP_SEL_ER + 0x9A) 361 + /* Access Control Override Enable */ 362 + #define BCM54811_EXP_BROADREACH_LRE_OVERLAY_CTL_EN BIT(15) 363 + /* Access Control Override Value */ 364 + #define BCM54811_EXP_BROADREACH_LRE_OVERLAY_CTL_OVERRIDE_VAL BIT(14) 365 + /* Access Control Value */ 366 + #define BCM54811_EXP_BROADREACH_LRE_OVERLAY_CTL_VAL BIT(13) 279 367 280 368 /* BCM54612E Registers */ 281 369 #define BCM54612E_EXP_SPARE0 (MII_BCM54XX_EXP_SEL_ETC + 0x34)
+1
include/uapi/linux/ethtool.h
··· 2054 2054 ETHTOOL_LINK_MODE_10baseT1S_Full_BIT = 99, 2055 2055 ETHTOOL_LINK_MODE_10baseT1S_Half_BIT = 100, 2056 2056 ETHTOOL_LINK_MODE_10baseT1S_P2MP_Half_BIT = 101, 2057 + ETHTOOL_LINK_MODE_10baseT1BRR_Full_BIT = 102, 2057 2058 2058 2059 /* must be last entry */ 2059 2060 __ETHTOOL_LINK_MODE_MASK_NBITS
+3
net/ethtool/common.c
··· 211 211 __DEFINE_LINK_MODE_NAME(10, T1S, Full), 212 212 __DEFINE_LINK_MODE_NAME(10, T1S, Half), 213 213 __DEFINE_LINK_MODE_NAME(10, T1S_P2MP, Half), 214 + __DEFINE_LINK_MODE_NAME(10, T1BRR, Full), 214 215 }; 215 216 static_assert(ARRAY_SIZE(link_mode_names) == __ETHTOOL_LINK_MODE_MASK_NBITS); 216 217 ··· 252 251 #define __LINK_MODE_LANES_T1S_P2MP 1 253 252 #define __LINK_MODE_LANES_VR8 8 254 253 #define __LINK_MODE_LANES_DR8_2 8 254 + #define __LINK_MODE_LANES_T1BRR 1 255 255 256 256 #define __DEFINE_LINK_MODE_PARAMS(_speed, _type, _duplex) \ 257 257 [ETHTOOL_LINK_MODE(_speed, _type, _duplex)] = { \ ··· 376 374 __DEFINE_LINK_MODE_PARAMS(10, T1S, Full), 377 375 __DEFINE_LINK_MODE_PARAMS(10, T1S, Half), 378 376 __DEFINE_LINK_MODE_PARAMS(10, T1S_P2MP, Half), 377 + __DEFINE_LINK_MODE_PARAMS(10, T1BRR, Full), 379 378 }; 380 379 static_assert(ARRAY_SIZE(link_mode_params) == __ETHTOOL_LINK_MODE_MASK_NBITS); 381 380