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 */
