net: pcs: xpcs: Add support for 25G, 50G, and 100G interfaces

With this change we are adding support for 25G, 50G, and 100G interface
types to the XPCS driver. This had supposedly been enabled with the
addition of XLGMII but I don't see any capability for configuration there
so I suspect it may need to be refactored in the future.

With this change we can enable the XPCS driver with the selected interface
and it should be able to detect link, speed, and report the link status to
the phylink interface.

Signed-off-by: Alexander Duyck <alexanderduyck@fb.com>
Link: https://patch.msgid.link/176374320248.959489.11649590675011158859.stgit@ahduyck-xeon-server.home.arpa
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
Alexander Duyck 2025-11-21 08:40:02 -08:00 committed by Paolo Abeni
parent e6c43c9500
commit 7622d55276
2 changed files with 107 additions and 4 deletions

View File

@ -37,6 +37,16 @@ static const int xpcs_10gkr_features[] = {
__ETHTOOL_LINK_MODE_MASK_NBITS,
};
static const int xpcs_25gbaser_features[] = {
ETHTOOL_LINK_MODE_MII_BIT,
ETHTOOL_LINK_MODE_Pause_BIT,
ETHTOOL_LINK_MODE_Asym_Pause_BIT,
ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
__ETHTOOL_LINK_MODE_MASK_NBITS,
};
static const int xpcs_xlgmii_features[] = {
ETHTOOL_LINK_MODE_Pause_BIT,
ETHTOOL_LINK_MODE_Asym_Pause_BIT,
@ -67,6 +77,40 @@ static const int xpcs_xlgmii_features[] = {
__ETHTOOL_LINK_MODE_MASK_NBITS,
};
static const int xpcs_50gbaser_features[] = {
ETHTOOL_LINK_MODE_MII_BIT,
ETHTOOL_LINK_MODE_Pause_BIT,
ETHTOOL_LINK_MODE_Asym_Pause_BIT,
ETHTOOL_LINK_MODE_50000baseKR_Full_BIT,
ETHTOOL_LINK_MODE_50000baseSR_Full_BIT,
ETHTOOL_LINK_MODE_50000baseCR_Full_BIT,
ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT,
ETHTOOL_LINK_MODE_50000baseDR_Full_BIT,
__ETHTOOL_LINK_MODE_MASK_NBITS,
};
static const int xpcs_50gbaser2_features[] = {
ETHTOOL_LINK_MODE_MII_BIT,
ETHTOOL_LINK_MODE_Pause_BIT,
ETHTOOL_LINK_MODE_Asym_Pause_BIT,
ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT,
ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
__ETHTOOL_LINK_MODE_MASK_NBITS,
};
static const int xpcs_100gbasep_features[] = {
ETHTOOL_LINK_MODE_MII_BIT,
ETHTOOL_LINK_MODE_Pause_BIT,
ETHTOOL_LINK_MODE_Asym_Pause_BIT,
ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT,
ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT,
ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT,
ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT,
ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT,
__ETHTOOL_LINK_MODE_MASK_NBITS,
};
static const int xpcs_10gbaser_features[] = {
ETHTOOL_LINK_MODE_Pause_BIT,
ETHTOOL_LINK_MODE_Asym_Pause_BIT,
@ -523,9 +567,38 @@ static int xpcs_get_max_xlgmii_speed(struct dw_xpcs *xpcs,
return speed;
}
static void xpcs_resolve_pma(struct dw_xpcs *xpcs,
struct phylink_link_state *state)
static int xpcs_c45_read_pcs_speed(struct dw_xpcs *xpcs,
struct phylink_link_state *state)
{
int pcs_ctrl1;
pcs_ctrl1 = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_CTRL1);
if (pcs_ctrl1 < 0)
return pcs_ctrl1;
switch (pcs_ctrl1 & MDIO_CTRL1_SPEEDSEL) {
case MDIO_PCS_CTRL1_SPEED25G:
state->speed = SPEED_25000;
break;
case MDIO_PCS_CTRL1_SPEED50G:
state->speed = SPEED_50000;
break;
case MDIO_PCS_CTRL1_SPEED100G:
state->speed = SPEED_100000;
break;
default:
state->speed = SPEED_UNKNOWN;
break;
}
return 0;
}
static int xpcs_resolve_pma(struct dw_xpcs *xpcs,
struct phylink_link_state *state)
{
int err = 0;
state->pause = MLO_PAUSE_TX | MLO_PAUSE_RX;
state->duplex = DUPLEX_FULL;
@ -536,10 +609,18 @@ static void xpcs_resolve_pma(struct dw_xpcs *xpcs,
case PHY_INTERFACE_MODE_XLGMII:
state->speed = xpcs_get_max_xlgmii_speed(xpcs, state);
break;
case PHY_INTERFACE_MODE_100GBASEP:
case PHY_INTERFACE_MODE_LAUI:
case PHY_INTERFACE_MODE_50GBASER:
case PHY_INTERFACE_MODE_25GBASER:
err = xpcs_c45_read_pcs_speed(xpcs, state);
break;
default:
state->speed = SPEED_UNKNOWN;
break;
}
return err;
}
static int xpcs_validate(struct phylink_pcs *pcs, unsigned long *supported,
@ -945,10 +1026,10 @@ static int xpcs_get_state_c73(struct dw_xpcs *xpcs,
phylink_resolve_c73(state);
} else {
xpcs_resolve_pma(xpcs, state);
ret = xpcs_resolve_pma(xpcs, state);
}
return 0;
return ret;
}
static int xpcs_get_state_c37_sgmii(struct dw_xpcs *xpcs,
@ -1312,10 +1393,26 @@ static const struct dw_xpcs_compat synopsys_xpcs_compat[] = {
.interface = PHY_INTERFACE_MODE_10GKR,
.supported = xpcs_10gkr_features,
.an_mode = DW_AN_C73,
}, {
.interface = PHY_INTERFACE_MODE_25GBASER,
.supported = xpcs_25gbaser_features,
.an_mode = DW_AN_C73,
}, {
.interface = PHY_INTERFACE_MODE_XLGMII,
.supported = xpcs_xlgmii_features,
.an_mode = DW_AN_C73,
}, {
.interface = PHY_INTERFACE_MODE_50GBASER,
.supported = xpcs_50gbaser_features,
.an_mode = DW_AN_C73,
}, {
.interface = PHY_INTERFACE_MODE_LAUI,
.supported = xpcs_50gbaser2_features,
.an_mode = DW_AN_C73,
}, {
.interface = PHY_INTERFACE_MODE_100GBASEP,
.supported = xpcs_100gbasep_features,
.an_mode = DW_AN_C73,
}, {
.interface = PHY_INTERFACE_MODE_10GBASER,
.supported = xpcs_10gbaser_features,

View File

@ -123,6 +123,12 @@
*/
#define MDIO_CTRL1_SPEED2_5G MDIO_PMA_CTRL1_SPEED2_5G
#define MDIO_CTRL1_SPEED5G MDIO_PMA_CTRL1_SPEED5G
/* 100 Gb/s */
#define MDIO_PCS_CTRL1_SPEED100G (MDIO_CTRL1_SPEEDSELEXT | 0x10)
/* 25 Gb/s */
#define MDIO_PCS_CTRL1_SPEED25G (MDIO_CTRL1_SPEEDSELEXT | 0x14)
/* 50 Gb/s */
#define MDIO_PCS_CTRL1_SPEED50G (MDIO_CTRL1_SPEEDSELEXT | 0x18)
/* 2.5 Gb/s */
#define MDIO_PMA_CTRL1_SPEED2_5G (MDIO_CTRL1_SPEEDSELEXT | 0x18)
/* 5 Gb/s */