summaryrefslogtreecommitdiff
path: root/src/portable
diff options
context:
space:
mode:
authorhathach <[email protected]>2025-09-15 15:47:06 +0700
committerhathach <[email protected]>2025-09-15 15:47:06 +0700
commitcc19c02f860f96299ceccdfcaf1befb308c9fab8 (patch)
tree2640691000e20c1f80d7849a8d91b36871aca885 /src/portable
parentf674561696220825d111c90954d4cd88ae3278dd (diff)
dwc2: wait for ahb idle before core reset
Diffstat (limited to 'src/portable')
-rw-r--r--src/portable/synopsys/dwc2/dwc2_common.c16
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