Skip to content

Commit 03ab6c2

Browse files
Kamil Horák (2N)kuba-moo
authored andcommitted
net: phy: bcm-phy-lib: Implement BroadR-Reach link modes
Implement single-pair BroadR-Reach modes on bcm5481x PHY by Broadcom. Create set of functions alternative to IEEE 802.3 to handle configuration of these modes on compatible Broadcom PHYs. There is only subset of capabilities supported because of limited collection of hardware available for the development. For BroadR-Reach capable PHYs, the LRE (Long Reach Ethernet) alternative register set is handled. Only bcm54811 PHY is verified, for bcm54810, there is some support possible but untested. There is no auto-negotiation of the link parameters (called LDS in the Broadcom terminology, Long-Distance Signaling) for bcm54811. It should be possible to enable LDS for bcm54810. Signed-off-by: Kamil Horák (2N) <[email protected]> Reviewed-by: Andrew Lunn <[email protected]> Reviewed-by: Florian Fainelli <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 775631d commit 03ab6c2

File tree

3 files changed

+494
-28
lines changed

3 files changed

+494
-28
lines changed

drivers/net/phy/bcm-phy-lib.c

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,49 @@ static int _bcm_phy_cable_test_get_status(struct phy_device *phydev,
794794
return ret;
795795
}
796796

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+
797840
int bcm_phy_cable_test_start(struct phy_device *phydev)
798841
{
799842
return _bcm_phy_cable_test_start(phydev, false);
@@ -1066,6 +1109,78 @@ int bcm_phy_led_brightness_set(struct phy_device *phydev,
10661109
}
10671110
EXPORT_SYMBOL_GPL(bcm_phy_led_brightness_set);
10681111

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+
10691184
MODULE_DESCRIPTION("Broadcom PHY Library");
10701185
MODULE_LICENSE("GPL v2");
10711186
MODULE_AUTHOR("Broadcom Corporation");

drivers/net/phy/bcm-phy-lib.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,4 +121,8 @@ irqreturn_t bcm_phy_wol_isr(int irq, void *dev_id);
121121
int bcm_phy_led_brightness_set(struct phy_device *phydev,
122122
u8 index, enum led_brightness value);
123123

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+
124128
#endif /* _LINUX_BCM_PHY_LIB_H */

0 commit comments

Comments
 (0)