diff options
| author | hathach <[email protected]> | 2025-09-15 15:47:06 +0700 |
|---|---|---|
| committer | hathach <[email protected]> | 2025-09-15 15:47:06 +0700 |
| commit | cc19c02f860f96299ceccdfcaf1befb308c9fab8 (patch) | |
| tree | 2640691000e20c1f80d7849a8d91b36871aca885 /src/portable | |
| parent | f674561696220825d111c90954d4cd88ae3278dd (diff) | |
dwc2: wait for ahb idle before core reset
Diffstat (limited to 'src/portable')
| -rw-r--r-- | src/portable/synopsys/dwc2/dwc2_common.c | 16 |
1 files changed, 11 insertions, 5 deletions
diff --git a/src/portable/synopsys/dwc2/dwc2_common.c b/src/portable/synopsys/dwc2/dwc2_common.c index d7d157149..5ff18ab94 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.c +++ b/src/portable/synopsys/dwc2/dwc2_common.c @@ -45,20 +45,26 @@ // //-------------------------------------------------------------------- static void reset_core(dwc2_regs_t* dwc2) { + // The software must check that bit 31 in this register is set to 1 (AHB Master is Idle) before starting any operation + while (!(dwc2->grstctl & GRSTCTL_AHBIDL)) { + } + // load gsnpsid (it is not readable after reset is asserted) - uint32_t gsnpsid = dwc2->gsnpsid; + const uint32_t gsnpsid = dwc2->gsnpsid; // reset core dwc2->grstctl |= GRSTCTL_CSRST; if ((gsnpsid & DWC2_CORE_REV_MASK) < (DWC2_CORE_REV_4_20a & DWC2_CORE_REV_MASK)) { - // prior v4.20a CSRST is self-clearing + // prior v4.20a: CSRST is self-clearing and the core clears this bit after all the necessary logic is reset in + // the core, which can take several clocks, depending on the current state of the core. Once this bit has been + // cleared, the software must wait at least 3 PHY clocks before accessing the PHY domain (synchronization delay). while (dwc2->grstctl & GRSTCTL_CSRST) {} } else { - // From v4.20a CSRST bit is write only, CSRT_DONE (w1c) is introduced for checking. - // CSRST must also be explicitly cleared + // From v4.20a: CSRST bit is write only. The application must clear this bit after checking the bit 29 of this + // register i.e Core Soft Reset Done CSRT_DONE (w1c) while (!(dwc2->grstctl & GRSTCTL_CSRST_DONE)) {} - dwc2->grstctl = (dwc2->grstctl & ~GRSTCTL_CSRST) | GRSTCTL_CSRST_DONE; + dwc2->grstctl = (dwc2->grstctl & ~GRSTCTL_CSRST) | GRSTCTL_CSRST_DONE; } while (!(dwc2->grstctl & GRSTCTL_AHBIDL)) {} // wait for AHB master IDLE |
