Skip to content

Commit 217b953

Browse files
committed
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/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents d944c27 + 03ab6c2 commit 217b953

File tree

8 files changed

+596
-29
lines changed

8 files changed

+596
-29
lines changed

Documentation/devicetree/bindings/net/ethernet-phy.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,14 @@ properties:
9393
the turn around line low at end of the control phase of the
9494
MDIO transaction.
9595

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+
96104
clocks:
97105
maxItems: 1
98106
description:

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)