[PATCH net-next v2 2/2] net: macb: add support for 1000BASE-X autonegotiation to PCS
From: Nathan Whitehorn <hidden>
Date: 2026-07-21 18:02:19
Subsystem:
atmel macb ethernet driver, networking drivers, the rest · Maintainers:
Théo Lebrun, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
The current PCS code unconditionally uses SGMII autonegotiation, though the hardware supports both SGMII and 1000BASE-X modes. Decouple the choice of PCS enablement from use of the SGMII mode when running at gigabit rates and announce to phylink that 1000BASE-X is a supported operating mode. This enables direct attachment of the PCS to e.g. an SFP. The 1000BASE-X code in phylink also sometimes calls the autonegotiation restart method, so add an implementation of autonegotiation restart. Signed-off-by: Nathan Whitehorn <redacted> --- drivers/net/ethernet/cadence/macb_main.c | 26 ++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index c15a9c7e69d3..310ad8eac21f 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c@@ -583,7 +583,12 @@ static void macb_pcs_get_state(struct phylink_pcs *pcs, unsigned int neg_mode, static void macb_pcs_an_restart(struct phylink_pcs *pcs) { - /* Not supported */ + struct macb *bp = container_of(pcs, struct macb, phylink_sgmii_pcs); + u32 old, new; + + old = gem_readl(bp, PCSCNTRL); + new = old | BMCR_ANRESTART; + gem_writel(bp, PCSCNTRL, new); } static int macb_pcs_config(struct phylink_pcs *pcs,
@@ -750,7 +755,9 @@ static void macb_mac_config(struct phylink_config *config, unsigned int mode, ctrl &= ~(GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL)); ncr &= ~GEM_BIT(ENABLE_HS_MAC); - if (state->interface == PHY_INTERFACE_MODE_SGMII) { + if (state->interface == PHY_INTERFACE_MODE_1000BASEX) { + ctrl |= GEM_BIT(PCSSEL); + } else if (state->interface == PHY_INTERFACE_MODE_SGMII) { ctrl |= GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL); } else if (state->interface == PHY_INTERFACE_MODE_10GBASER) { ctrl |= GEM_BIT(PCSSEL);
@@ -957,7 +964,8 @@ static struct phylink_pcs *macb_mac_select_pcs(struct phylink_config *config, if (interface == PHY_INTERFACE_MODE_10GBASER) return &bp->phylink_usx_pcs; - else if (interface == PHY_INTERFACE_MODE_SGMII) + else if (interface == PHY_INTERFACE_MODE_1000BASEX || + interface == PHY_INTERFACE_MODE_SGMII) return &bp->phylink_sgmii_pcs; else return NULL;
@@ -1032,7 +1040,8 @@ static int macb_mii_probe(struct net_device *dev) bp->phylink_config.type = PHYLINK_NETDEV; bp->phylink_config.mac_managed_pm = true; - if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII) { + if (bp->phy_interface == PHY_INTERFACE_MODE_1000BASEX || + bp->phy_interface == PHY_INTERFACE_MODE_SGMII) { bp->phylink_config.poll_fixed_state = true; bp->phylink_config.get_fixed_state = macb_get_pcs_fixed_state; /* The PCSAUTONEG bit in PCSCNTRL is on out of reset. Setting
@@ -1061,9 +1070,12 @@ static int macb_mii_probe(struct net_device *dev) bp->phylink_config.supported_interfaces); phy_interface_set_rgmii(bp->phylink_config.supported_interfaces); - if (bp->caps & MACB_CAPS_PCS) + if (bp->caps & MACB_CAPS_PCS) { + __set_bit(PHY_INTERFACE_MODE_1000BASEX, + bp->phylink_config.supported_interfaces); __set_bit(PHY_INTERFACE_MODE_SGMII, bp->phylink_config.supported_interfaces); + } if (bp->caps & MACB_CAPS_HIGH_SPEED) { __set_bit(PHY_INTERFACE_MODE_10GBASER,
@@ -4932,7 +4944,9 @@ static int macb_init_dflt(struct platform_device *pdev) /* Set MII management clock divider */ val = macb_mdc_clk_div(bp); val |= macb_dbw(bp); - if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII) + if (bp->phy_interface == PHY_INTERFACE_MODE_1000BASEX) + val |= GEM_BIT(PCSSEL); + else if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII) val |= GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL); macb_writel(bp, NCFGR, val);
--
2.54.0