On some hardware using the DesignWare XPCS IP (e.g., RK3568 MAC side SGMII), the PCS does not automatically restart auto-negotiation when the link goes down and comes back up. Without an explicit ANRESTART, the link stays down forever. Add BMCR_ANRESTART in two places: 1. In xpcs_config_aneg_c37_sgmii(), when starting AN, set ANRESTART alongside ANENABLE to initiate a fresh negotiation. 2. In xpcs_get_state_c37_sgmii(), when link is down and AN completion is detected, clear the interrupt and trigger ANRESTART to restart the negotiation process. Tested-by: Jiawen Wu Tested-by: Maxime Chevallier Signed-off-by: Coia Prant --- drivers/net/pcs/pcs-xpcs.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c index 0337e2bcc0125..50b9cdf94fdaa 100644 --- a/drivers/net/pcs/pcs-xpcs.c +++ b/drivers/net/pcs/pcs-xpcs.c @@ -816,9 +816,14 @@ static int xpcs_config_aneg_c37_sgmii(struct dw_xpcs *xpcs, if (ret < 0) return ret; + /* Clear CL37 AN complete status */ + ret = xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_INTR_STS, 0); + if (ret < 0) + return ret; + if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) ret = xpcs_write(xpcs, MDIO_MMD_VEND2, MII_BMCR, - mdio_ctrl | BMCR_ANENABLE); + mdio_ctrl | BMCR_ANENABLE | BMCR_ANRESTART); return ret; } @@ -1093,10 +1098,15 @@ static int xpcs_get_state_c37_sgmii(struct dw_xpcs *xpcs, return 0; } - /* Clear AN complete status or interrupt */ - if (state->an_complete) + if (state->an_complete) { + /* Clear AN complete status or interrupt */ xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_INTR_STS, 0); + /* Initiate the next round of AN */ + xpcs_modify(xpcs, MDIO_MMD_VEND2, MII_BMCR, BMCR_ANRESTART, + BMCR_ANRESTART); + } + return 0; } -- 2.47.3