--- /dev/null
+--- a/include/linux/phylink.h
++++ b/include/linux/phylink.h
+@@ -584,10 +584,37 @@ int phylink_speed_up(struct phylink *pl)
+ #define phylink_test(bm, mode) __phylink_do_bit(test_bit, bm, mode)
+
+ void phylink_set_port_modes(unsigned long *bits);
++
++/**
++ * phylink_get_link_timer_ns - return the PCS link timer value
++ * @interface: link &typedef phy_interface_t mode
++ *
++ * Return the PCS link timer setting in nanoseconds for the PHY @interface
++ * mode, or -EINVAL if not appropriate.
++ */
++static inline int phylink_get_link_timer_ns(phy_interface_t interface)
++{
++ switch (interface) {
++ case PHY_INTERFACE_MODE_SGMII:
++ return 1600000;
++
++ case PHY_INTERFACE_MODE_1000BASEX:
++ case PHY_INTERFACE_MODE_2500BASEX:
++ return 10000000;
++
++ default:
++ return -EINVAL;
++ }
++}
++
+ void phylink_helper_basex_speed(struct phylink_link_state *state);
+
++void phylink_mii_c22_pcs_decode_state(struct phylink_link_state *state,
++ u16 bmsr, u16 lpa);
+ void phylink_mii_c22_pcs_get_state(struct mdio_device *pcs,
+ struct phylink_link_state *state);
++int phylink_mii_c22_pcs_encode_advertisement(phy_interface_t interface,
++ const unsigned long *advertising);
+ int phylink_mii_c22_pcs_set_advertisement(struct mdio_device *pcs,
+ phy_interface_t interface,
+ const unsigned long *advertising);
+--- a/drivers/net/phy/phylink.c
++++ b/drivers/net/phy/phylink.c
+@@ -885,7 +885,6 @@ static int phylink_change_inband_advert(
+
+ return 0;
+ }
+-
+ static void phylink_mac_pcs_get_state(struct phylink *pl,
+ struct phylink_link_state *state)
+ {
+@@ -2966,6 +2965,52 @@ void phylink_mii_c22_pcs_get_state(struc
+ EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_get_state);
+
+ /**
++ * phylink_mii_c22_pcs_decode_state() - Decode MAC PCS state from MII registers
++ * @state: a pointer to a &struct phylink_link_state.
++ * @bmsr: The value of the %MII_BMSR register
++ * @lpa: The value of the %MII_LPA register
++ *
++ * Helper for MAC PCS supporting the 802.3 clause 22 register set for
++ * clause 37 negotiation and/or SGMII control.
++ *
++ * Parse the Clause 37 or Cisco SGMII link partner negotiation word into
++ * the phylink @state structure. This is suitable to be used for implementing
++ * the mac_pcs_get_state() member of the struct phylink_mac_ops structure if
++ * accessing @bmsr and @lpa cannot be done with MDIO directly.
++ */
++void phylink_mii_c22_pcs_decode_state(struct phylink_link_state *state,
++ u16 bmsr, u16 lpa)
++{
++ state->link = !!(bmsr & BMSR_LSTATUS);
++ state->an_complete = !!(bmsr & BMSR_ANEGCOMPLETE);
++ /* If there is no link or autonegotiation is disabled, the LP advertisement
++ * data is not meaningful, so don't go any further.
++ */
++ if (!state->link || !state->an_enabled)
++ return;
++
++ switch (state->interface) {
++ case PHY_INTERFACE_MODE_1000BASEX:
++ phylink_decode_c37_word(state, lpa, SPEED_1000);
++ break;
++
++ case PHY_INTERFACE_MODE_2500BASEX:
++ phylink_decode_c37_word(state, lpa, SPEED_2500);
++ break;
++
++ case PHY_INTERFACE_MODE_SGMII:
++ case PHY_INTERFACE_MODE_QSGMII:
++ phylink_decode_sgmii_word(state, lpa);
++ break;
++
++ default:
++ state->link = false;
++ break;
++ }
++}
++EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_decode_state);
++
++/**
+ * phylink_mii_c22_pcs_set_advertisement() - configure the clause 37 PCS
+ * advertisement
+ * @pcs: a pointer to a &struct mdio_device.
+@@ -3037,6 +3082,46 @@ int phylink_mii_c22_pcs_set_advertisemen
+ EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_set_advertisement);
+
+ /**
++ * phylink_mii_c22_pcs_encode_advertisement() - configure the clause 37 PCS
++ * advertisement
++ * @interface: the PHY interface mode being configured
++ * @advertising: the ethtool advertisement mask
++ *
++ * Helper for MAC PCS supporting the 802.3 clause 22 register set for
++ * clause 37 negotiation and/or SGMII control.
++ *
++ * Encode the clause 37 PCS advertisement as specified by @interface and
++ * @advertising.
++ *
++ * Return: The new value for @adv, or ``-EINVAL`` if it should not be changed.
++ */
++int phylink_mii_c22_pcs_encode_advertisement(phy_interface_t interface,
++ const unsigned long *advertising)
++{
++ u16 adv;
++
++ switch (interface) {
++ case PHY_INTERFACE_MODE_1000BASEX:
++ case PHY_INTERFACE_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;
++ return adv;
++ case PHY_INTERFACE_MODE_SGMII:
++ case PHY_INTERFACE_MODE_QSGMII:
++ return 0x0001;
++ default:
++ /* Nothing to do for other modes */
++ return -EINVAL;
++ }
++}
++EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_encode_advertisement);
++
++/**
+ * phylink_mii_c22_pcs_config() - configure clause 22 PCS
+ * @pcs: a pointer to a &struct mdio_device.
+ * @mode: link autonegotiation mode