This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit ea65363d578ffb3b7ee33ae5039f46167ac49914
Author: Daniel P. Carvalho <[email protected]>
AuthorDate: Sat Oct 3 21:45:00 2026 -0300

    arch/mips/pic32mz: keep the PHY auto-negotiation enabled.
    
    After a successful auto-negotiation, pic32mz_phyinit() called
    pic32mz_phymode() with the negotiated speed and duplex.  That function
    clears MII_MCR_ANENABLE, so the PHY stayed in a forced mode.  The link
    keeps working until the cable is removed, but on reconnection the PHY
    no longer negotiates and, against an auto-negotiating partner, the link
    stays down (seen with a LAN8720A: MCR 0x2100, MSR without link status).
    
    Only force the mode when CONFIG_PIC32MZ_PHY_AUTONEG is not selected.
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Daniel P. Carvalho <[email protected]>
---
 arch/mips/src/pic32mz/pic32mz_ethernet.c | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/arch/mips/src/pic32mz/pic32mz_ethernet.c 
b/arch/mips/src/pic32mz/pic32mz_ethernet.c
index 130d71bc528..bcdc9f4b151 100644
--- a/arch/mips/src/pic32mz/pic32mz_ethernet.c
+++ b/arch/mips/src/pic32mz/pic32mz_ethernet.c
@@ -488,8 +488,9 @@ static uint16_t pic32mz_phyread(uint8_t phyaddr, uint8_t 
regaddr);
 static inline int pic32mz_phyreset(uint8_t phyaddr);
 #  ifdef CONFIG_PIC32MZ_PHY_AUTONEG
 static inline int pic32mz_phyautoneg(uint8_t phyaddr);
-#  endif
+#  else
 static int pic32mz_phymode(uint8_t phyaddr, uint8_t mode);
+#  endif
 static inline int pic32mz_phyinit(struct pic32mz_driver_s *priv);
 #else
 #  define pic32mz_phyinit(priv)
@@ -2829,7 +2830,7 @@ static inline int pic32mz_phyautoneg(uint8_t phyaddr)
  *
  ****************************************************************************/
 
-#ifdef PIC32MZ_HAVE_PHY
+#if defined(PIC32MZ_HAVE_PHY) && !defined(CONFIG_PIC32MZ_PHY_AUTONEG)
 static int pic32mz_phymode(uint8_t phyaddr, uint8_t mode)
 {
   int32_t timeout;
@@ -2914,7 +2915,7 @@ static inline int pic32mz_phyinit(struct pic32mz_driver_s 
*priv)
   unsigned int phyaddr;
   uint16_t phyreg;
   uint32_t regval;
-  int ret;
+  int ret = OK;
 
 #if CONFIG_PIC32MZ_FMIIEN == 0
   /* Set the RMII operation mode. This usually requires access to a vendor
@@ -3181,11 +3182,16 @@ static inline int pic32mz_phyinit(struct 
pic32mz_driver_s *priv)
         (priv->pd_mode & PIC32MZ_DUPLEX_MASK) ==
           PIC32MZ_DUPLEX_FULL ?"full" : "half");
 
-  /* Disable auto-configuration.  Set the fixed speed/duplex mode.
-   * (probably more than little redundant).
+#ifndef CONFIG_PIC32MZ_PHY_AUTONEG
+  /* Set the fixed speed/duplex mode (again).  With auto-negotiation, the
+   * negotiated mode is not forced: auto-negotiation stays enabled so that
+   * the PHY negotiates again when the cable is reconnected.  Forcing the
+   * mode would leave the link down against an auto-negotiating partner.
    */
 
   ret = pic32mz_phymode(phyaddr, priv->pd_mode);
+#endif
+
   pic32mz_showmii(phyaddr, "After final configuration");
   return ret;
 }

Reply via email to