From: Jan Hoffmann Date: Sun, 8 Feb 2026 17:10:01 +0000 (+0100) Subject: realtek: pcs: configure auto-negotiation on all SoCs X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a517d94c9f5993a1847a2c9a8bc01e2744b83b3c;p=thirdparty%2Fopenwrt.git realtek: pcs: configure auto-negotiation on all SoCs RTL83xx uses the BMCR and ADVERTISE registers like RTL93xx to configure in-band auto-negotiation. Split out the common parts as a new generic implementation and use it for RTL83xx. RTL93xx retains its own variant of set_autoneg to support XSGMII, but calls into the generic version for all other modes. Tested 1000Base-X auto-negotiation on HPE 1920-8G (RTL8380). Also tested HPE 1920-24G (RTL8382) and HPE-1920-48G (RTL8393) to make sure this does not affect PHY ports. Signed-off-by: Jan Hoffmann Link: https://github.com/openwrt/openwrt/pull/21934 Signed-off-by: Hauke Mehrtens --- diff --git a/target/linux/realtek/files-6.12/drivers/net/pcs/pcs-rtl-otto.c b/target/linux/realtek/files-6.12/drivers/net/pcs/pcs-rtl-otto.c index e7efe048889..72379c1d7f1 100644 --- a/target/linux/realtek/files-6.12/drivers/net/pcs/pcs-rtl-otto.c +++ b/target/linux/realtek/files-6.12/drivers/net/pcs/pcs-rtl-otto.c @@ -444,6 +444,46 @@ static int rtpcs_sds_determine_hw_mode(struct rtpcs_serdes *sds, return 0; } +/* Generic auto-negotiation config */ + +static int rtpcs_generic_sds_set_autoneg(struct rtpcs_serdes *sds, unsigned int neg_mode, + const unsigned long *advertising) +{ + u16 bmcr, adv; + bool changed = 0; + int ret; + + if ((sds->hw_mode == RTPCS_SDS_MODE_1000BASEX) || + (sds->hw_mode == RTPCS_SDS_MODE_2500BASEX)) { + adv = ADVERTISE_1000XFULL; + if (linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT, + advertising)) + adv |= ADVERTISE_1000XPAUSE; + if (linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, + advertising)) + adv |= ADVERTISE_1000XPSE_ASYM; + + ret = rtpcs_sds_modify_changed(sds, 0x2, MII_ADVERTISE, + 0xffff, adv); + if (ret < 0) + return ret; + changed = ret; + } + + bmcr = neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED ? BMCR_ANENABLE : 0; + + ret = rtpcs_sds_modify(sds, 0x2, MII_BMCR, BMCR_ANENABLE, bmcr); + if (ret < 0) + return ret; + + return changed; +} + +static void rtpcs_generic_sds_restart_autoneg(struct rtpcs_serdes *sds) +{ + rtpcs_sds_modify(sds, 0x2, MII_BMCR, BMCR_ANRESTART, BMCR_ANRESTART); +} + /* Variant-specific functions */ /* RTL838X */ @@ -968,9 +1008,7 @@ static int rtpcs_839x_setup_serdes(struct rtpcs_serdes *sds, static int rtpcs_93xx_sds_set_autoneg(struct rtpcs_serdes *sds, unsigned int neg_mode, const unsigned long *advertising) { - u16 bmcr, adv, en_val; - bool changed = 0; - int ret; + u16 en_val; switch (sds->hw_mode) { case RTPCS_SDS_MODE_XSGMII: /* XSG N-way state */ @@ -978,38 +1016,10 @@ static int rtpcs_93xx_sds_set_autoneg(struct rtpcs_serdes *sds, unsigned int neg return rtpcs_sds_xsg_write_bits(sds, 0x0, 0x2, 9, 8, en_val); default: - if ((sds->hw_mode == RTPCS_SDS_MODE_1000BASEX) || - (sds->hw_mode == RTPCS_SDS_MODE_2500BASEX)) { - adv = ADVERTISE_1000XFULL; - if (linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT, - advertising)) - adv |= ADVERTISE_1000XPAUSE; - if (linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, - advertising)) - adv |= ADVERTISE_1000XPSE_ASYM; - - ret = rtpcs_sds_modify_changed(sds, 0x2, MII_ADVERTISE, - 0xffff, adv); - if (ret < 0) - return ret; - changed = ret; - } - - bmcr = neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED ? BMCR_ANENABLE : 0; - - ret = rtpcs_sds_modify(sds, 0x2, MII_BMCR, BMCR_ANENABLE, bmcr); - if (ret < 0) - return ret; - - return changed; + return rtpcs_generic_sds_set_autoneg(sds, neg_mode, advertising); } } -static void rtpcs_93xx_sds_restart_autoneg(struct rtpcs_serdes *sds) -{ - rtpcs_sds_modify(sds, 0x2, MII_BMCR, BMCR_ANRESTART, BMCR_ANRESTART); -} - static int rtpcs_93xx_init_serdes_common(struct rtpcs_ctrl *ctrl) { u32 model_info = 0; @@ -3980,6 +3990,8 @@ static const struct phylink_pcs_ops rtpcs_838x_pcs_ops = { static const struct rtpcs_serdes_ops rtpcs_838x_sds_ops = { .read = rtpcs_generic_sds_op_read, .write = rtpcs_generic_sds_op_write, + .set_autoneg = rtpcs_generic_sds_set_autoneg, + .restart_autoneg = rtpcs_generic_sds_restart_autoneg, }; static const struct rtpcs_config rtpcs_838x_cfg = { @@ -4006,6 +4018,8 @@ static const struct phylink_pcs_ops rtpcs_839x_pcs_ops = { static const struct rtpcs_serdes_ops rtpcs_839x_sds_ops = { .read = rtpcs_generic_sds_op_read, .write = rtpcs_generic_sds_op_write, + .set_autoneg = rtpcs_generic_sds_set_autoneg, + .restart_autoneg = rtpcs_generic_sds_restart_autoneg, }; static const struct rtpcs_config rtpcs_839x_cfg = { @@ -4034,7 +4048,7 @@ static const struct rtpcs_serdes_ops rtpcs_930x_sds_ops = { .write = rtpcs_930x_sds_op_write, .xsg_write = rtpcs_930x_sds_op_xsg_write, .set_autoneg = rtpcs_93xx_sds_set_autoneg, - .restart_autoneg = rtpcs_93xx_sds_restart_autoneg, + .restart_autoneg = rtpcs_generic_sds_restart_autoneg, }; static const struct rtpcs_config rtpcs_930x_cfg = { @@ -4063,7 +4077,7 @@ static const struct rtpcs_serdes_ops rtpcs_931x_sds_ops = { .write = rtpcs_generic_sds_op_write, .xsg_write = rtpcs_931x_sds_op_xsg_write, .set_autoneg = rtpcs_93xx_sds_set_autoneg, - .restart_autoneg = rtpcs_93xx_sds_restart_autoneg, + .restart_autoneg = rtpcs_generic_sds_restart_autoneg, }; static const struct rtpcs_config rtpcs_931x_cfg = {