From: Mike Marciniszyn (Meta) The DW PCS IP data sheet calls out the need to populate these vendor registers when operating at speeds above 10Gbps. This change enables the correct FEC settings to enable RS-FEC encoding on the link which is the standard used for most links at these higher speeds. Signed-off-by: Mike Marciniszyn (Meta) Signed-off-by: Alexander Duyck --- drivers/net/pcs/pcs-xpcs.c | 67 ++++++++++++++++++++++++++++++++++++++++++++ drivers/net/pcs/pcs-xpcs.h | 6 ++++ include/uapi/linux/mdio.h | 3 ++ 3 files changed, 76 insertions(+) diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c index 2e236ff1ad85..c252f8ba6517 100644 --- a/drivers/net/pcs/pcs-xpcs.c +++ b/drivers/net/pcs/pcs-xpcs.c @@ -1412,6 +1412,69 @@ static int xpcs_read_ids(struct dw_xpcs *xpcs) return 0; } +struct pma_pcs_values { + int channels; + u16 rsfec_ctrl; +}; + +static int +xpcs_config_rsfec_pma(struct dw_xpcs *xpcs, const struct pma_pcs_values *v) +{ + /* fbnic's DW IP exposes the RS-FEC PMA at SEP_PMA1, so use it + * directly. Scanning DEVS1 for the correct PMA MMD is left as future + * work for enabling a non-fbnic device on this PCS. + */ + int pma_mmd = MDIO_MMD_SEP_PMA1; + int ret = 0, i; + + for (i = 0; ret >= 0 && i < v->channels; i++) { + ret = xpcs_mdev_write_ch(xpcs, i, pma_mmd, + MDIO_PMA_RSFEC_CTRL, v->rsfec_ctrl); + } + + return ret; +} + +static int xpcs_25gbaser_pma_config(struct dw_xpcs *xpcs) +{ + const struct pma_pcs_values v = { + .rsfec_ctrl = 0, + .channels = 1, + }; + + return xpcs_config_rsfec_pma(xpcs, &v); +} + +static int xpcs_50gbaser_pma_config(struct dw_xpcs *xpcs) +{ + const struct pma_pcs_values v = { + .rsfec_ctrl = DW_VR_RSFEC_CTRL_TC_PAD_ALTER, + .channels = 1, + }; + + return xpcs_config_rsfec_pma(xpcs, &v); +} + +static int xpcs_50gbaser2_pma_config(struct dw_xpcs *xpcs) +{ + const struct pma_pcs_values v = { + .rsfec_ctrl = DW_VR_RSFEC_CTRL_TC_PAD_ALTER, + .channels = 2, + }; + + return xpcs_config_rsfec_pma(xpcs, &v); +} + +static int xpcs_100gbasep_pma_config(struct dw_xpcs *xpcs) +{ + const struct pma_pcs_values v = { + .rsfec_ctrl = MDIO_PMA_RSFEC_CTRL_4LANE_PMD, + .channels = 2, + }; + + return xpcs_config_rsfec_pma(xpcs, &v); +} + static const struct dw_xpcs_compat synopsys_xpcs_compat[] = { { .interface = PHY_INTERFACE_MODE_USXGMII, @@ -1425,6 +1488,7 @@ static const struct dw_xpcs_compat synopsys_xpcs_compat[] = { .interface = PHY_INTERFACE_MODE_25GBASER, .supported = xpcs_25gbaser_features, .an_mode = DW_AN_C73, + .pma_config = xpcs_25gbaser_pma_config, }, { .interface = PHY_INTERFACE_MODE_XLGMII, .supported = xpcs_xlgmii_features, @@ -1433,14 +1497,17 @@ static const struct dw_xpcs_compat synopsys_xpcs_compat[] = { .interface = PHY_INTERFACE_MODE_50GBASER, .supported = xpcs_50gbaser_features, .an_mode = DW_AN_C73, + .pma_config = xpcs_50gbaser_pma_config, }, { .interface = PHY_INTERFACE_MODE_LAUI, .supported = xpcs_50gbaser2_features, .an_mode = DW_AN_C73, + .pma_config = xpcs_50gbaser2_pma_config, }, { .interface = PHY_INTERFACE_MODE_100GBASEP, .supported = xpcs_100gbasep_features, .an_mode = DW_AN_C73, + .pma_config = xpcs_100gbasep_pma_config, }, { .interface = PHY_INTERFACE_MODE_10GBASER, .supported = xpcs_10gbaser_features, diff --git a/drivers/net/pcs/pcs-xpcs.h b/drivers/net/pcs/pcs-xpcs.h index 36f4906e689a..ab47d6dd050c 100644 --- a/drivers/net/pcs/pcs-xpcs.h +++ b/drivers/net/pcs/pcs-xpcs.h @@ -94,6 +94,12 @@ #define DW_VR_MII_DIG_CTRL2_TX_POL_INV BIT(4) #define DW_VR_MII_DIG_CTRL2_RX_POL_INV BIT(0) +/* Clause 133 defines */ +/* RSFEC transcode pad alter + * DW vendor extension in RS-FEC control + */ +#define DW_VR_RSFEC_CTRL_TC_PAD_ALTER BIT(10) + #define DW_XPCS_INFO_DECLARE(_name, _pcs, _pma) \ static const struct dw_xpcs_info _name = { .pcs = _pcs, .pma = _pma } diff --git a/include/uapi/linux/mdio.h b/include/uapi/linux/mdio.h index b2541c948fc1..5219c877b2cf 100644 --- a/include/uapi/linux/mdio.h +++ b/include/uapi/linux/mdio.h @@ -317,6 +317,9 @@ #define MDIO_PMA_10GBR_FECABLE_ABLE 0x0001 /* FEC ability */ #define MDIO_PMA_10GBR_FECABLE_ERRABLE 0x0002 /* FEC error indic. ability */ +/* RSFEC PMA Control register */ +#define MDIO_PMA_RSFEC_CTRL_4LANE_PMD BIT(3) + /* PMA 10GBASE-R Fast Retrain status and control register. */ #define MDIO_PMA_10GBR_FSRT_ENABLE 0x0001 /* Fast retrain enable */