On Tue, Apr 11, 2023 at 05:27:24PM +0800, Jiawen Wu wrote: > +static void txgbe_set_an37_ability(struct txgbe *txgbe) > +{ > + u16 val; > + > + pcs_write(txgbe, MDIO_MMD_PCS, TXGBE_PCS_DIG_CTRL1, > + TXGBE_PCS_DIG_CTRL1_EN_VSMMD1 | > + TXGBE_PCS_DIG_CTRL1_CLS7_BP | > + TXGBE_PCS_DIG_CTRL1_BYP_PWRUP); > + pcs_write(txgbe, MDIO_MMD_VEND2, TXGBE_MII_AN_CTRL, > + TXGBE_MII_AN_CTRL_MII | > + TXGBE_MII_AN_CTRL_TXCFG | > + TXGBE_MII_AN_CTRL_PCS_MODE(0) | > + TXGBE_MII_AN_CTRL_INTR_EN); > + pcs_write(txgbe, MDIO_MMD_VEND2, TXGBE_MII_DIG_CTRL1, > + TXGBE_MII_DIG_CTRL1_MAC_AUTOSW); > + val = pcs_read(txgbe, MDIO_MMD_VEND2, MDIO_CTRL1); > + val |= BMCR_ANRESTART | BMCR_ANENABLE; val |= BMCR_ANENABLE; > + pcs_write(txgbe, MDIO_MMD_VEND2, MDIO_CTRL1, val); > +} > +static void txgbe_setup_adv(struct txgbe *txgbe, phy_interface_t interface, > + const unsigned long *advertising) Please return an int. > +{ > + int adv; > + > + adv = phylink_mii_c22_pcs_encode_advertisement(interface, > + advertising); if (adv < 0) return adv; > + if (adv > 0) > + mdiodev_c45_modify(txgbe->mdiodev, MDIO_MMD_VEND2, MII_ADVERTISE, > + 0xffff, adv); return mdiodev_c45_modify_changed(txgbe->mdiodev, MDIO_MMD_VEND2, MII_ADVERTISE, 0xffff, adv); > +} > + > +static int txgbe_pcs_config(struct phylink_pcs *pcs, unsigned int mode, > + phy_interface_t interface, > + const unsigned long *advertising, > + bool permit_pause_to_mac) > +{ > + struct txgbe *txgbe = container_of(pcs, struct txgbe, pcs); > + struct wx *wx = txgbe->wx; > + int ret, val; > + > + if (interface == txgbe->interface) > + goto out; > + > + /* Wait xpcs power-up good */ > + ret = read_poll_timeout(pcs_read, val, > + (val & TXGBE_PCS_DIG_STS_PSEQ_ST) == > + TXGBE_PCS_DIG_STS_PSEQ_ST_GOOD, > + 10000, 1000000, false, > + txgbe, MDIO_MMD_PCS, TXGBE_PCS_DIG_STS); > + if (ret < 0) { > + wx_err(wx, "xpcs power-up timeout.\n"); > + return ret; > + } > + > + /* Disable xpcs AN-73 */ > + pcs_write(txgbe, MDIO_MMD_AN, MDIO_CTRL1, 0); > + > + /* Disable PHY MPLLA for eth mode change(after ECO) */ > + txgbe_ephy_write(txgbe, TXGBE_SUP_DIG_MPLLA_OVRD_IN_0, 0x243A); > + WX_WRITE_FLUSH(wx); > + usleep_range(1000, 2000); > + > + /* Set the eth change_mode bit first in mis_rst register > + * for corresponding LAN port > + */ > + wr32(wx, TXGBE_MIS_RST, TXGBE_MIS_RST_LAN_ETH_MODE(wx->bus.func)); > + > + switch (interface) { > + case PHY_INTERFACE_MODE_10GBASER: > + txgbe_pma_config_10gbaser(txgbe); > + break; > + case PHY_INTERFACE_MODE_1000BASEX: > + txgbe_pma_config_1000basex(txgbe); > + break; > + default: > + break; > + } > + > + pcs_write(txgbe, MDIO_MMD_PCS, TXGBE_PCS_DIG_CTRL1, > + TXGBE_PCS_DIG_CTRL1_VR_RST | TXGBE_PCS_DIG_CTRL1_EN_VSMMD1); > + /* wait phy initialization done */ > + ret = read_poll_timeout(pcs_read, val, > + !(val & TXGBE_PCS_DIG_CTRL1_VR_RST), > + 100000, 10000000, false, > + txgbe, MDIO_MMD_PCS, TXGBE_PCS_DIG_CTRL1); > + if (ret < 0) > + wx_err(wx, "PHY initialization timeout.\n"); > + > + txgbe->interface = interface; > + > +out: > + if (interface == PHY_INTERFACE_MODE_1000BASEX) { > + txgbe_setup_adv(txgbe, interface, advertising); ret = txgbe_setup_adv(txgbe, interface, advertising); if (ret < 0) return ret; > + txgbe_set_an37_ability(txgbe); > + } > + > + return ret; ... and then this will propagate whether the advertisement has changed, which will then cause... > +static void txgbe_pcs_an_restart(struct phylink_pcs *pcs) > +{ > + struct txgbe *txgbe = container_of(pcs, struct txgbe, pcs); > + > + mdiodev_c45_modify(txgbe->mdiodev, MDIO_MMD_VEND2, MDIO_CTRL1, > + BMCR_ANRESTART, BMCR_ANRESTART); > +} to be called whenever the advertisement changes (which is why you then don't need to do it in txgbe_set_an37_ability().) -- RMK's Patch system: https://www.armlinux.org.uk/developer/patches/ FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!