]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net: dpaa: fman_memac: complete phylink support with 2500base-x
authorVladimir Oltean <vladimir.oltean@nxp.com>
Sat, 22 Nov 2025 11:55:23 +0000 (13:55 +0200)
committerJakub Kicinski <kuba@kernel.org>
Thu, 27 Nov 2025 02:06:10 +0000 (18:06 -0800)
The DPAA phylink conversion in the following commits partially developed
code for handling the 2500base-x host interface mode (called "2.5G
SGMII" in LS1043A/LS1046A reference manuals).

0fc83bd79589 ("net: fman: memac: Add serdes support")
5d93cfcf7360 ("net: dpaa: Convert to phylink")

In principle, having phy-interface-mode = "2500base-x" and a pcsphy-handle
(unnamed or with pcs-handle-names = "sgmii") in the MAC device tree node
results in PHY_INTERFACE_MODE_2500BASEX being set in phylink_config ::
supported_interfaces, but this isn't sufficient.

Because memac_select_pcs() returns no PCS for PHY_INTERFACE_MODE_2500BASEX,
the Lynx PCS code never engages. There's a chance the PCS driver doesn't
have any configuration to change for 2500base-x fixed-link (based on
bootloader pre-initialization), but there's an even higher chance that
this is not the case, and the PCS remains misconfigured.

More importantly, memac_if_mode() does not handle
PHY_INTERFACE_MODE_2500BASEX, and it should be telling the mEMAC to
configure itself in GMII mode (which is upclocked by the PCS). Currently
it prints a WARN_ON() and returns zero, aka IF_MODE_10G (incorrect).

The additional case statement in memac_prepare() for calling
phy_set_mode_ext() does not make any difference, because there is no
generic PHY driver for the Lynx 10G SerDes from LS1043A/LS1046A. But we
add it nonetheless, for consistency.

Regarding the question "did 2500base-x ever work with the FMan mEMAC
mainline code prior to the phylink conversion?" - the answer is more
nuanced.

For context, the previous phylib-based implementation was unable to
describe the fixed-link speed as 2500, because the software PHY
implementation is limited to 1G. However, improperly describing the link
as an sgmii fixed-link with speed = <1000> would have resulted in a
functional 2.5G speed, because there is no other difference than the
SerDes lane clock net frequency (3.125 GHz for 2500base-x) - all the
other higher-level settings are the same, and the SerDes lane frequency
is currently handled by the RCW.

But this hack cannot be extended towards a phylib PHY such as Aquantia
operating in OCSGMII, because the latter requires phy-mode = "2500base-x",
which the mEMAC driver did not support prior to the phylink conversion.
So I do not really consider this a regression, just completing support
for a missing feature.

The FMan mEMAC driver sets phylink's "default_an_inband" property to
true, making it as if the device tree node had the managed =
"in-band-status" property anyway. This default made sense for SGMII,
where it was added to avoid regressions, but for 2500base-x we learned
only recently how to enable in-band autoneg:
https://lore.kernel.org/netdev/20251122113433.141930-1-vladimir.oltean@nxp.com/

so the driver needs to opt out of this default in-band enabled
behaviour, and only enable in-band based on the device tree property.

Suggested-by: Russell King (Oracle) <linux@armlinux.org.uk>
Link: https://lore.kernel.org/netdev/aIyx0OLWGw5zKarX@shell.armlinux.org.uk/#t
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Link: https://patch.msgid.link/20251122115523.150260-1-vladimir.oltean@nxp.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/freescale/fman/fman_memac.c

index 0291093f2e4e45b277bab2b9da2977c9e1a5468e..d32ffd6be7b1e0552f6608f1eb92b0c6d7b727ac 100644 (file)
@@ -649,6 +649,7 @@ static u32 memac_if_mode(phy_interface_t interface)
                return IF_MODE_GMII | IF_MODE_RGMII;
        case PHY_INTERFACE_MODE_SGMII:
        case PHY_INTERFACE_MODE_1000BASEX:
+       case PHY_INTERFACE_MODE_2500BASEX:
        case PHY_INTERFACE_MODE_QSGMII:
                return IF_MODE_GMII;
        case PHY_INTERFACE_MODE_10GBASER:
@@ -667,6 +668,7 @@ static struct phylink_pcs *memac_select_pcs(struct phylink_config *config,
        switch (iface) {
        case PHY_INTERFACE_MODE_SGMII:
        case PHY_INTERFACE_MODE_1000BASEX:
+       case PHY_INTERFACE_MODE_2500BASEX:
                return memac->sgmii_pcs;
        case PHY_INTERFACE_MODE_QSGMII:
                return memac->qsgmii_pcs;
@@ -685,6 +687,7 @@ static int memac_prepare(struct phylink_config *config, unsigned int mode,
        switch (iface) {
        case PHY_INTERFACE_MODE_SGMII:
        case PHY_INTERFACE_MODE_1000BASEX:
+       case PHY_INTERFACE_MODE_2500BASEX:
        case PHY_INTERFACE_MODE_QSGMII:
        case PHY_INTERFACE_MODE_10GBASER:
                return phy_set_mode_ext(memac->serdes, PHY_MODE_ETHERNET,
@@ -1226,6 +1229,7 @@ int memac_initialization(struct mac_device *mac_dev,
         * those configurations modes don't use in-band autonegotiation.
         */
        if (!of_property_present(mac_node, "managed") &&
+           mac_dev->phy_if != PHY_INTERFACE_MODE_2500BASEX &&
            mac_dev->phy_if != PHY_INTERFACE_MODE_MII &&
            !phy_interface_mode_is_rgmii(mac_dev->phy_if))
                mac_dev->phylink_config.default_an_inband = true;