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 74eafb0354b8a149273a8c1cdd7a860478ff5a7a
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 24f2c509184..7d5b7004d0b 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
@@ -2751,6 +2755,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
  *
@@ -2789,15 +2829,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
 
@@ -2837,15 +2871,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