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

xiaoxiang781216 pushed a commit to branch releases/13.1
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 34d29702a0443e7dad17bce1e1ecc81e2ab0a3e3
Author: Daniel P. Carvalho <[email protected]>
AuthorDate: Sun Oct 4 00:54:54 2026 -0300

    arch/mips/pic32mz: wait for the MII management busy flag to be set.
    
    After starting an MII management command, the driver executed 16 NOPs
    before waiting for the busy flag to clear.  The flag is set a few clock
    cycles after the command, and when the code runs from the I-Cache the
    NOPs end before that: the wait returned at once and phyread() returned
    the previous read data.  With the L1 cache enabled the PHY was not found
    (ID1 read as 0x3000) and the interface never came up.
    
    Poll until the busy flag is set, bounded in case the command has
    already completed, before waiting for it to clear.  A management frame
    lasts 64 MDC cycles, so the flag cannot be missed.
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Daniel P. Carvalho <[email protected]>
---
 arch/mips/src/pic32mz/pic32mz_ethernet.c | 60 +++++++++++++++++++++++---------
 1 file changed, 44 insertions(+), 16 deletions(-)

diff --git a/arch/mips/src/pic32mz/pic32mz_ethernet.c 
b/arch/mips/src/pic32mz/pic32mz_ethernet.c
index ec70b44c4de..b9c6c0e3201 100644
--- a/arch/mips/src/pic32mz/pic32mz_ethernet.c
+++ b/arch/mips/src/pic32mz/pic32mz_ethernet.c
@@ -203,6 +203,10 @@
 
 #define PIC32MZ_MIITIMEOUT     (666666)
 
+/* Busy flag polls after an MII management command */
+
+#define PIC32MZ_MIIBUSY_POLLS  (1000)
+
 /* Ethernet MII clocking.
  *
  * The clock divider used to create the MII Management Clock (MDC).  The MIIM
@@ -2757,6 +2761,42 @@ static void pic32mz_phybusywait(void)
   while ((pic32mz_getreg(PIC32MZ_EMAC1_MIND) & EMAC1_MIND_MIIMBUSY) != 0);
 }
 
+/****************************************************************************
+ * Function: pic32mz_phystartwait
+ *
+ * Description:
+ *   Wait until the MII management command just issued sets the busy flag.
+ *   The flag is set a few clock cycles after the command; a fixed number of
+ *   NOPs is not enough when the code runs from the I-Cache, and the
+ *   following busy wait would then return before the command has even
+ *   started.  A management frame lasts 64 MDC cycles, so the flag cannot
+ *   be missed.  The wait is bounded in case the command already finished.
+ *
+ * Input Parameters:
+ *  None
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+#ifdef PIC32MZ_HAVE_PHY
+static void pic32mz_phystartwait(void)
+{
+  int i;
+
+  for (i = 0; i < PIC32MZ_MIIBUSY_POLLS; i++)
+    {
+      if ((pic32mz_getreg(PIC32MZ_EMAC1_MIND) & EMAC1_MIND_MIIMBUSY) != 0)
+        {
+          break;
+        }
+    }
+}
+#endif
+
 /****************************************************************************
  * Function: pic32mz_phywrite
  *
@@ -2795,15 +2835,9 @@ static void pic32mz_phywrite(uint8_t phyaddr, uint8_t 
regaddr,
 
   pic32mz_putreg((uint32_t)phydata, PIC32MZ_EMAC1_MWTD);
 
-  /* Sixteen clock cycles until busy is set from the write operation */
+  /* Wait until the command has started */
 
-  __asm__ __volatile__
-    (
-      "nop; nop; nop; nop;"
-      "nop; nop; nop; nop;"
-      "nop; nop; nop; nop;"
-      "nop; nop; nop; nop;"
-    );
+  pic32mz_phystartwait();
 }
 #endif
 
@@ -2843,15 +2877,9 @@ static uint16_t pic32mz_phyread(uint8_t phyaddr, uint8_t 
regaddr)
 
   pic32mz_putreg(EMAC1_MCMD_READ, PIC32MZ_EMAC1_MCMDSET);
 
-  /* Sixteen clock cycles until busy is set from the write operation */
+  /* Wait until the command has started */
 
-  __asm__ __volatile__
-    (
-      "nop; nop; nop; nop;"
-      "nop; nop; nop; nop;"
-      "nop; nop; nop; nop;"
-      "nop; nop; nop; nop;"
-    );
+  pic32mz_phystartwait();
 
   /* Wait for the PHY command to complete */
 

Reply via email to