Commit 217b953a authored by Jakub Kicinski's avatar Jakub Kicinski

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.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents d944c27a 03ab6c24
......@@ -93,6 +93,14 @@ properties:
the turn around line low at end of the control phase of the
MDIO transaction.
brr-mode:
$ref: /schemas/types.yaml#/definitions/flag
description:
If set, indicates the network cable interface is an alternative one as
defined in the BroadR-Reach link mode specification under 1BR-100 and
1BR-10 names. The PHY must be configured to operate in BroadR-Reach mode
by software.
clocks:
maxItems: 1
description:
......
......@@ -794,6 +794,49 @@ static int _bcm_phy_cable_test_get_status(struct phy_device *phydev,
return ret;
}
static int bcm_setup_lre_forced(struct phy_device *phydev)
{
u16 ctl = 0;
phydev->pause = 0;
phydev->asym_pause = 0;
if (phydev->speed == SPEED_100)
ctl |= LRECR_SPEED100;
if (phydev->duplex != DUPLEX_FULL)
return -EOPNOTSUPP;
return phy_modify(phydev, MII_BCM54XX_LRECR, LRECR_SPEED100, ctl);
}
/**
* bcm_linkmode_adv_to_lre_adv_t - translate linkmode advertisement to LDS
* @advertising: the linkmode advertisement settings
* Return: LDS Auto-Negotiation Advertised Ability register value
*
* A small helper function that translates linkmode advertisement
* settings to phy LDS autonegotiation advertisements for the
* MII_BCM54XX_LREANAA register of Broadcom PHYs capable of LDS
*/
static u32 bcm_linkmode_adv_to_lre_adv_t(unsigned long *advertising)
{
u32 result = 0;
if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT1BRR_Full_BIT,
advertising))
result |= LREANAA_10_1PAIR;
if (linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT1_Full_BIT,
advertising))
result |= LREANAA_100_1PAIR;
if (linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT, advertising))
result |= LRELPA_PAUSE;
if (linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, advertising))
result |= LRELPA_PAUSE_ASYM;
return result;
}
int bcm_phy_cable_test_start(struct phy_device *phydev)
{
return _bcm_phy_cable_test_start(phydev, false);
......@@ -1066,6 +1109,78 @@ int bcm_phy_led_brightness_set(struct phy_device *phydev,
}
EXPORT_SYMBOL_GPL(bcm_phy_led_brightness_set);
int bcm_setup_lre_master_slave(struct phy_device *phydev)
{
u16 ctl = 0;
switch (phydev->master_slave_set) {
case MASTER_SLAVE_CFG_MASTER_PREFERRED:
case MASTER_SLAVE_CFG_MASTER_FORCE:
ctl = LRECR_MASTER;
break;
case MASTER_SLAVE_CFG_SLAVE_PREFERRED:
case MASTER_SLAVE_CFG_SLAVE_FORCE:
break;
case MASTER_SLAVE_CFG_UNKNOWN:
case MASTER_SLAVE_CFG_UNSUPPORTED:
return 0;
default:
phydev_warn(phydev, "Unsupported Master/Slave mode\n");
return -EOPNOTSUPP;
}
return phy_modify_changed(phydev, MII_BCM54XX_LRECR, LRECR_MASTER, ctl);
}
EXPORT_SYMBOL_GPL(bcm_setup_lre_master_slave);
int bcm_config_lre_aneg(struct phy_device *phydev, bool changed)
{
int err;
if (genphy_config_eee_advert(phydev))
changed = true;
err = bcm_setup_lre_master_slave(phydev);
if (err < 0)
return err;
else if (err)
changed = true;
if (phydev->autoneg != AUTONEG_ENABLE)
return bcm_setup_lre_forced(phydev);
err = bcm_config_lre_advert(phydev);
if (err < 0)
return err;
else if (err)
changed = true;
return genphy_check_and_restart_aneg(phydev, changed);
}
EXPORT_SYMBOL_GPL(bcm_config_lre_aneg);
/**
* bcm_config_lre_advert - sanitize and advertise Long-Distance Signaling
* auto-negotiation parameters
* @phydev: target phy_device struct
* Return: 0 if the PHY's advertisement hasn't changed, < 0 on error,
* > 0 if it has changed
*
* Writes MII_BCM54XX_LREANAA with the appropriate values. The values are to be
* sanitized before, to make sure we only advertise what is supported.
* The sanitization is done already in phy_ethtool_ksettings_set()
*/
int bcm_config_lre_advert(struct phy_device *phydev)
{
u32 adv = bcm_linkmode_adv_to_lre_adv_t(phydev->advertising);
/* Setup BroadR-Reach mode advertisement */
return phy_modify_changed(phydev, MII_BCM54XX_LREANAA,
LRE_ADVERTISE_ALL | LREANAA_PAUSE |
LREANAA_PAUSE_ASYM, adv);
}
EXPORT_SYMBOL_GPL(bcm_config_lre_advert);
MODULE_DESCRIPTION("Broadcom PHY Library");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Broadcom Corporation");
......@@ -121,4 +121,8 @@ irqreturn_t bcm_phy_wol_isr(int irq, void *dev_id);
int bcm_phy_led_brightness_set(struct phy_device *phydev,
u8 index, enum led_brightness value);
int bcm_setup_lre_master_slave(struct phy_device *phydev);
int bcm_config_lre_aneg(struct phy_device *phydev, bool changed);
int bcm_config_lre_advert(struct phy_device *phydev);
#endif /* _LINUX_BCM_PHY_LIB_H */
This diff is collapsed.
......@@ -13,7 +13,7 @@
*/
const char *phy_speed_to_str(int speed)
{
BUILD_BUG_ON_MSG(__ETHTOOL_LINK_MODE_MASK_NBITS != 102,
BUILD_BUG_ON_MSG(__ETHTOOL_LINK_MODE_MASK_NBITS != 103,
"Enum ethtool_link_mode_bit_indices and phylib are out of sync. "
"If a speed or mode has been added please update phy_speed_to_str "
"and the PHY settings array.\n");
......@@ -266,6 +266,7 @@ static const struct phy_setting settings[] = {
PHY_SETTING( 10, FULL, 10baseT1S_Full ),
PHY_SETTING( 10, HALF, 10baseT1S_Half ),
PHY_SETTING( 10, HALF, 10baseT1S_P2MP_Half ),
PHY_SETTING( 10, FULL, 10baseT1BRR_Full ),
};
#undef PHY_SETTING
......
......@@ -271,12 +271,100 @@
#define BCM5482_SSD_SGMII_SLAVE_EN 0x0002 /* Slave mode enable */
#define BCM5482_SSD_SGMII_SLAVE_AD 0x0001 /* Slave auto-detection */
/* BroadR-Reach LRE Registers. */
#define MII_BCM54XX_LRECR 0x00 /* LRE Control Register */
#define MII_BCM54XX_LRESR 0x01 /* LRE Status Register */
#define MII_BCM54XX_LREPHYSID1 0x02 /* LRE PHYS ID 1 */
#define MII_BCM54XX_LREPHYSID2 0x03 /* LRE PHYS ID 2 */
#define MII_BCM54XX_LREANAA 0x04 /* LDS Auto-Negotiation Advertised Ability */
#define MII_BCM54XX_LREANAC 0x05 /* LDS Auto-Negotiation Advertised Control */
#define MII_BCM54XX_LREANPT 0x06 /* LDS Ability Next Page Transmit */
#define MII_BCM54XX_LRELPA 0x07 /* LDS Link Partner Ability */
#define MII_BCM54XX_LRELPNPM 0x08 /* LDS Link Partner Next Page Message */
#define MII_BCM54XX_LRELPNPC 0x09 /* LDS Link Partner Next Page Control */
#define MII_BCM54XX_LRELDSE 0x0a /* LDS Expansion Register */
#define MII_BCM54XX_LREES 0x0f /* LRE Extended Status */
/* LRE control register. */
#define LRECR_RESET 0x8000 /* Reset to default state */
#define LRECR_LOOPBACK 0x4000 /* Internal Loopback */
#define LRECR_LDSRES 0x2000 /* Restart LDS Process */
#define LRECR_LDSEN 0x1000 /* LDS Enable */
#define LRECR_PDOWN 0x0800 /* Enable low power state */
#define LRECR_ISOLATE 0x0400 /* Isolate data paths from MII */
#define LRECR_SPEED100 0x0200 /* Select 100 Mbps */
#define LRECR_SPEED10 0x0000 /* Select 10 Mbps */
#define LRECR_4PAIRS 0x0020 /* Select 4 Pairs */
#define LRECR_2PAIRS 0x0010 /* Select 2 Pairs */
#define LRECR_1PAIR 0x0000 /* Select 1 Pair */
#define LRECR_MASTER 0x0008 /* Force Master when LDS disabled */
#define LRECR_SLAVE 0x0000 /* Force Slave when LDS disabled */
/* LRE status register. */
#define LRESR_100_1PAIR 0x2000 /* Can do 100Mbps 1 Pair */
#define LRESR_100_4PAIR 0x1000 /* Can do 100Mbps 4 Pairs */
#define LRESR_100_2PAIR 0x0800 /* Can do 100Mbps 2 Pairs */
#define LRESR_10_2PAIR 0x0400 /* Can do 10Mbps 2 Pairs */
#define LRESR_10_1PAIR 0x0200 /* Can do 10Mbps 1 Pair */
#define LRESR_ESTATEN 0x0100 /* Extended Status in R15 */
#define LRESR_RESV 0x0080 /* Unused... */
#define LRESR_MFPS 0x0040 /* Can suppress Management Frames Preamble */
#define LRESR_LDSCOMPLETE 0x0020 /* LDS Auto-negotiation complete */
#define LRESR_8023 0x0010 /* Has IEEE 802.3 Support */
#define LRESR_LDSABILITY 0x0008 /* LDS auto-negotiation capable */
#define LRESR_LSTATUS 0x0004 /* Link status */
#define LRESR_JCD 0x0002 /* Jabber detected */
#define LRESR_ERCAP 0x0001 /* Ext-reg capability */
/* LDS Auto-Negotiation Advertised Ability. */
#define LREANAA_PAUSE_ASYM 0x8000 /* Can pause asymmetrically */
#define LREANAA_PAUSE 0x4000 /* Can pause */
#define LREANAA_100_1PAIR 0x0020 /* Can do 100Mbps 1 Pair */
#define LREANAA_100_4PAIR 0x0010 /* Can do 100Mbps 4 Pair */
#define LREANAA_100_2PAIR 0x0008 /* Can do 100Mbps 2 Pair */
#define LREANAA_10_2PAIR 0x0004 /* Can do 10Mbps 2 Pair */
#define LREANAA_10_1PAIR 0x0002 /* Can do 10Mbps 1 Pair */
#define LRE_ADVERTISE_FULL (LREANAA_100_1PAIR | LREANAA_100_4PAIR | \
LREANAA_100_2PAIR | LREANAA_10_2PAIR | \
LREANAA_10_1PAIR)
#define LRE_ADVERTISE_ALL LRE_ADVERTISE_FULL
/* LDS Link Partner Ability. */
#define LRELPA_PAUSE_ASYM 0x8000 /* Supports asymmetric pause */
#define LRELPA_PAUSE 0x4000 /* Supports pause capability */
#define LRELPA_100_1PAIR 0x0020 /* 100Mbps 1 Pair capable */
#define LRELPA_100_4PAIR 0x0010 /* 100Mbps 4 Pair capable */
#define LRELPA_100_2PAIR 0x0008 /* 100Mbps 2 Pair capable */
#define LRELPA_10_2PAIR 0x0004 /* 10Mbps 2 Pair capable */
#define LRELPA_10_1PAIR 0x0002 /* 10Mbps 1 Pair capable */
/* LDS Expansion register. */
#define LDSE_DOWNGRADE 0x8000 /* Can do LDS Speed Downgrade */
#define LDSE_MASTER 0x4000 /* Master / Slave */
#define LDSE_PAIRS_MASK 0x3000 /* Pair Count Mask */
#define LDSE_PAIRS_SHIFT 12
#define LDSE_4PAIRS (2 << LDSE_PAIRS_SHIFT) /* 4 Pairs Connection */
#define LDSE_2PAIRS (1 << LDSE_PAIRS_SHIFT) /* 2 Pairs Connection */
#define LDSE_1PAIR (0 << LDSE_PAIRS_SHIFT) /* 1 Pair Connection */
#define LDSE_CABLEN_MASK 0x0FFF /* Cable Length Mask */
/* BCM54810 Registers */
#define BCM54810_EXP_BROADREACH_LRE_MISC_CTL (MII_BCM54XX_EXP_SEL_ER + 0x90)
#define BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN (1 << 0)
#define BCM54810_SHD_CLK_CTL 0x3
#define BCM54810_SHD_CLK_CTL_GTXCLK_EN (1 << 9)
/* BCM54811 Registers */
#define BCM54811_EXP_BROADREACH_LRE_OVERLAY_CTL (MII_BCM54XX_EXP_SEL_ER + 0x9A)
/* Access Control Override Enable */
#define BCM54811_EXP_BROADREACH_LRE_OVERLAY_CTL_EN BIT(15)
/* Access Control Override Value */
#define BCM54811_EXP_BROADREACH_LRE_OVERLAY_CTL_OVERRIDE_VAL BIT(14)
/* Access Control Value */
#define BCM54811_EXP_BROADREACH_LRE_OVERLAY_CTL_VAL BIT(13)
/* BCM54612E Registers */
#define BCM54612E_EXP_SPARE0 (MII_BCM54XX_EXP_SEL_ETC + 0x34)
#define BCM54612E_LED4_CLK125OUT_EN (1 << 1)
......
......@@ -2054,6 +2054,7 @@ enum ethtool_link_mode_bit_indices {
ETHTOOL_LINK_MODE_10baseT1S_Full_BIT = 99,
ETHTOOL_LINK_MODE_10baseT1S_Half_BIT = 100,
ETHTOOL_LINK_MODE_10baseT1S_P2MP_Half_BIT = 101,
ETHTOOL_LINK_MODE_10baseT1BRR_Full_BIT = 102,
/* must be last entry */
__ETHTOOL_LINK_MODE_MASK_NBITS
......
......@@ -211,6 +211,7 @@ const char link_mode_names[][ETH_GSTRING_LEN] = {
__DEFINE_LINK_MODE_NAME(10, T1S, Full),
__DEFINE_LINK_MODE_NAME(10, T1S, Half),
__DEFINE_LINK_MODE_NAME(10, T1S_P2MP, Half),
__DEFINE_LINK_MODE_NAME(10, T1BRR, Full),
};
static_assert(ARRAY_SIZE(link_mode_names) == __ETHTOOL_LINK_MODE_MASK_NBITS);
......@@ -251,6 +252,7 @@ static_assert(ARRAY_SIZE(link_mode_names) == __ETHTOOL_LINK_MODE_MASK_NBITS);
#define __LINK_MODE_LANES_T1S_P2MP 1
#define __LINK_MODE_LANES_VR8 8
#define __LINK_MODE_LANES_DR8_2 8
#define __LINK_MODE_LANES_T1BRR 1
#define __DEFINE_LINK_MODE_PARAMS(_speed, _type, _duplex) \
[ETHTOOL_LINK_MODE(_speed, _type, _duplex)] = { \
......@@ -374,6 +376,7 @@ const struct link_mode_info link_mode_params[] = {
__DEFINE_LINK_MODE_PARAMS(10, T1S, Full),
__DEFINE_LINK_MODE_PARAMS(10, T1S, Half),
__DEFINE_LINK_MODE_PARAMS(10, T1S_P2MP, Half),
__DEFINE_LINK_MODE_PARAMS(10, T1BRR, Full),
};
static_assert(ARRAY_SIZE(link_mode_params) == __ETHTOOL_LINK_MODE_MASK_NBITS);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment