Make it possible to connect a PHY which does not use inband autoneg to a gem MAC using phylink's information. The previous implementation relied on whether or not the link was a fixed-link to disable SGMII autoneg. This commit extend this to all link which are not configured for inband autonegotiation. Signed-off-by: Charles Perry --- Notes: I'm testing with a VSC8574 PHY which phylink can configure in outband mode or in inband,an-enabled mode if I add a managed = "in-band-status" property in the device tree. The link can work with or without autoneg, as long as the MAC and the PHY are configured the same way. This doesn't work with the current MAC driver because the MAC inband autoned is always enabled. This is based on code written by Sean Anderson [1]. Let me know if I should add a From: or Co-developed-by: tag. [1]: https://lore.kernel.org/all/20250610233547.3588356-1-sean.anderson@linux.dev/ drivers/net/ethernet/cadence/macb_main.c | 35 +++++++++++++----------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index f72270a39d25..5002087cda09 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -574,6 +574,25 @@ static int macb_pcs_config(struct phylink_pcs *pcs, const unsigned long *advertising, bool permit_pause_to_mac) { + struct macb *bp = container_of(pcs, struct macb, phylink_sgmii_pcs); + unsigned long flags; + u32 old, new; + + spin_lock_irqsave(&bp->lock, flags); + old = gem_readl(bp, PCSANADV); + new = phylink_mii_c22_pcs_encode_advertisement(interface, advertising); + if (new != -EINVAL && old != new) + gem_writel(bp, PCSANADV, new); + + old = gem_readl(bp, PCSCNTRL); + if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) + new = old | BMCR_ANENABLE; + else + new = old & ~BMCR_ANENABLE; + if (old != new) + gem_writel(bp, PCSCNTRL, new); + + spin_unlock_irqrestore(&bp->lock, flags); return 0; } @@ -628,22 +647,6 @@ static void macb_mac_config(struct phylink_config *config, unsigned int mode, if (old_ncr ^ ncr) macb_or_gem_writel(bp, NCR, ncr); - /* Disable AN for SGMII fixed link configuration, enable otherwise. - * Must be written after PCSSEL is set in NCFGR, - * otherwise writes will not take effect. - */ - if (macb_is_gem(bp) && state->interface == PHY_INTERFACE_MODE_SGMII) { - u32 pcsctrl, old_pcsctrl; - - old_pcsctrl = gem_readl(bp, PCSCNTRL); - if (mode == MLO_AN_FIXED) - pcsctrl = old_pcsctrl & ~GEM_BIT(PCSAUTONEG); - else - pcsctrl = old_pcsctrl | GEM_BIT(PCSAUTONEG); - if (old_pcsctrl != pcsctrl) - gem_writel(bp, PCSCNTRL, pcsctrl); - } - spin_unlock_irqrestore(&bp->lock, flags); } -- 2.47.3 This makes it possible to use in-band autonegotiation with SGMII. If using a device tree, this can be done by adding the managed = "in-band-status" property to the gem node. Signed-off-by: Charles Perry --- Notes: Logs with inband aneg: root@p64h:~# ifconfig eth1 up 10.180.59.33 macb 40004184000.ethernet eth1: PHY 4000c21e000.mdio-mdio:02 doesn't supply possible interfaces macb 40004184000.ethernet eth1: PHY [4000c21e000.mdio-mdio:02] driver [Microsemi GE VSC8574 SyncE] (irq=POLL) macb 40004184000.ethernet eth1: phy: sgmii setting supported 00000000,00000000,00000000,000042ff advertising 00000000,00000000,00000000,000042ff macb 40004184000.ethernet eth1: configuring for inband/sgmii link mode macb 40004184000.ethernet eth1: major config, requested inband/sgmii macb 40004184000.ethernet eth1: interface sgmii inband modes: pcs=00 phy=03 pcs_ib_caps=0x0 phy_ib_caps=0x3 macb 40004184000.ethernet eth1: major config, active inband/inband,an-enabled/sgmii macb 40004184000.ethernet eth1: phylink_mac_config: mode=inband/sgmii/none adv=00000000,00000000,00000000,000042ff pause=00 PCSANADV=0x1 PCSCNTRL=0x1040 PCSSTS=0x109 PCSANLPBASE=0x1801 PCSSTS=0x12d PCSANLPBASE=0x1801 macb 40004184000.ethernet eth1: phy link down sgmii/Unknown/Unknown/none/off/nolpi PCSSTS=0x12d PCSANLPBASE=0x1801 PCSSTS=0x12d PCSANLPBASE=0x1801 macb 40004184000.ethernet eth1: phy link up sgmii/1Gbps/Full/none/tx/nolpi PCSSTS=0x129 PCSANLPBASE=0x9801 PCSSTS=0x12d PCSANLPBASE=0x9801 macb 40004184000.ethernet eth1: Link is Up - 1Gbps/Full - flow control tx Logs without inband aneg: macb 40004184000.ethernet eth1: PHY 4000c21e000.mdio-mdio:02 doesn't supply possible interfaces macb 40004184000.ethernet eth1: PHY [4000c21e000.mdio-mdio:02] driver [Microsemi GE VSC8574 SyncE] (irq=POLL) macb 40004184000.ethernet eth1: phy: sgmii setting supported 00000000,00000000,00000000,000042ff advertising 00000000,00000000,00000000,000042ff macb 40004184000.ethernet eth1: configuring for phy/sgmii link mode macb 40004184000.ethernet eth1: major config, requested phy/sgmii macb 40004184000.ethernet eth1: interface sgmii inband modes: pcs=00 phy=03 macb 40004184000.ethernet eth1: major config, active phy/outband/sgmii macb 40004184000.ethernet eth1: phylink_mac_config: mode=phy/sgmii/none adv=00000000,00000000,00000000,00000000 pause=00 PCSANADV=0x1 PCSCNTRL=0x40 macb 40004184000.ethernet eth1: phy link down sgmii/Unknown/Unknown/none/off/nolpi macb 40004184000.ethernet eth1: phy link up sgmii/1Gbps/Full/none/tx/nolpi macb 40004184000.ethernet eth1: Link is Up - 1Gbps/Full - flow control tx drivers/net/ethernet/cadence/macb_main.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 5002087cda09..a7a2d7fcb18c 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -560,7 +560,12 @@ static int macb_usx_pcs_config(struct phylink_pcs *pcs, static void macb_pcs_get_state(struct phylink_pcs *pcs, unsigned int neg_mode, struct phylink_link_state *state) { - state->link = 0; + struct macb *bp = container_of(pcs, struct macb, phylink_sgmii_pcs); + u16 bmsr, lpa; + + bmsr = gem_readl(bp, PCSSTS); + lpa = gem_readl(bp, PCSANLPBASE); + phylink_mii_c22_pcs_decode_state(state, neg_mode, bmsr, lpa); } static void macb_pcs_an_restart(struct phylink_pcs *pcs) -- 2.47.3