Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'support-phys-that-have-inband-autoneg-disabled-with-gem'

Charles Perry says:

====================
Support PHYs that have inband autoneg disabled with GEM

I'm testing SGMII with a VSC8574 PHY [1] and microchip HPSC SoC [2].

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 autoneg is always enabled (in the ->mac_config()
phylink_mac_ops). More precisely, the PHY driver (mscc_main.c) has
phylink's ->config_inband() implemented while the MAC ->pcs_config() ops
has an empty body.

This is based on code written by Sean Anderson [3]. Let me know if I
should add a From: or Co-developed-by: tag.

Logs with inband autoneg (managed = "in-band-status"):

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=03 phy=03
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
macb_pcs_config: PCSANADV=0x1 PCSCNTRL=0x1040
macb_pcs_get_state: PCSSTS=0x109 PCSANLPBASE=0x1
macb_pcs_get_state: PCSSTS=0x12d PCSANLPBASE=0x1801
macb 40004184000.ethernet eth1: phy link down sgmii/Unknown/Unknown/none/off/nolpi
macb_pcs_get_state: PCSSTS=0x12d PCSANLPBASE=0x1801
macb_pcs_get_state: PCSSTS=0x12d PCSANLPBASE=0x1801
macb 40004184000.ethernet eth1: phy link up sgmii/1Gbps/Full/none/tx/nolpi
macb_pcs_get_state: PCSSTS=0x129 PCSANLPBASE=0x9801
macb_pcs_get_state: PCSSTS=0x12d PCSANLPBASE=0x9801
macb 40004184000.ethernet eth1: Link is Up - 1Gbps/Full - flow control tx

Logs without inband autoneg:

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 phy/sgmii link mode
macb 40004184000.ethernet eth1: major config, requested phy/sgmii
macb 40004184000.ethernet eth1: interface sgmii inband modes: pcs=03 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
macb_pcs_config: 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

The above logs are generated with an additional printk() in macb_psc_config()
and macb_pcs_get_state() and "#define DEBUG" in phylink.c.

[1]: https://www.microchip.com/en-us/product/vsc8574
[2]: https://www.microchip.com/en-us/products/microprocessors/64-bit-mpus/pic64-hpsc
[3]: https://lore.kernel.org/all/20250610233547.3588356-1-sean.anderson@linux.dev/
====================

Link: https://patch.msgid.link/20260224202854.112813-1-charles.perry@microchip.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+33 -17
+33 -17
drivers/net/ethernet/cadence/macb_main.c
··· 557 557 return 0; 558 558 } 559 559 560 + static unsigned int macb_pcs_inband_caps(struct phylink_pcs *pcs, 561 + phy_interface_t interface) 562 + { 563 + return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; 564 + } 565 + 560 566 static void macb_pcs_get_state(struct phylink_pcs *pcs, unsigned int neg_mode, 561 567 struct phylink_link_state *state) 562 568 { 563 - state->link = 0; 569 + struct macb *bp = container_of(pcs, struct macb, phylink_sgmii_pcs); 570 + u16 bmsr, lpa; 571 + 572 + bmsr = gem_readl(bp, PCSSTS); 573 + lpa = gem_readl(bp, PCSANLPBASE); 574 + phylink_mii_c22_pcs_decode_state(state, neg_mode, bmsr, lpa); 564 575 } 565 576 566 577 static void macb_pcs_an_restart(struct phylink_pcs *pcs) ··· 585 574 const unsigned long *advertising, 586 575 bool permit_pause_to_mac) 587 576 { 577 + struct macb *bp = container_of(pcs, struct macb, phylink_sgmii_pcs); 578 + u32 old, new; 579 + 580 + old = gem_readl(bp, PCSANADV); 581 + new = phylink_mii_c22_pcs_encode_advertisement(interface, advertising); 582 + if (new != -EINVAL && old != new) 583 + gem_writel(bp, PCSANADV, new); 584 + 585 + /* Disable AN if it's not to be used, enable otherwise. 586 + * Must be written after PCSSEL is set in NCFGR which is done in 587 + * macb_mac_config(), otherwise writes will not take effect. 588 + */ 589 + old = gem_readl(bp, PCSCNTRL); 590 + if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) 591 + new = old | BMCR_ANENABLE; 592 + else 593 + new = old & ~BMCR_ANENABLE; 594 + if (old != new) 595 + gem_writel(bp, PCSCNTRL, new); 596 + 588 597 return 0; 589 598 } 590 599 ··· 615 584 }; 616 585 617 586 static const struct phylink_pcs_ops macb_phylink_pcs_ops = { 587 + .pcs_inband_caps = macb_pcs_inband_caps, 618 588 .pcs_get_state = macb_pcs_get_state, 619 589 .pcs_an_restart = macb_pcs_an_restart, 620 590 .pcs_config = macb_pcs_config, ··· 659 627 660 628 if (old_ncr ^ ncr) 661 629 macb_or_gem_writel(bp, NCR, ncr); 662 - 663 - /* Disable AN for SGMII fixed link configuration, enable otherwise. 664 - * Must be written after PCSSEL is set in NCFGR, 665 - * otherwise writes will not take effect. 666 - */ 667 - if (macb_is_gem(bp) && state->interface == PHY_INTERFACE_MODE_SGMII) { 668 - u32 pcsctrl, old_pcsctrl; 669 - 670 - old_pcsctrl = gem_readl(bp, PCSCNTRL); 671 - if (mode == MLO_AN_FIXED) 672 - pcsctrl = old_pcsctrl & ~GEM_BIT(PCSAUTONEG); 673 - else 674 - pcsctrl = old_pcsctrl | GEM_BIT(PCSAUTONEG); 675 - if (old_pcsctrl != pcsctrl) 676 - gem_writel(bp, PCSCNTRL, pcsctrl); 677 - } 678 630 679 631 spin_unlock_irqrestore(&bp->lock, flags); 680 632 }