summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorhathach <[email protected]>2024-11-04 17:22:25 +0700
committerhathach <[email protected]>2024-11-04 17:22:25 +0700
commit29262f3e24326c1a7c06137824e44ffaa6301094 (patch)
tree47bd8f3782f7e660a76c56935db03129f8870f60 /src
parent80ad7c4e87b74b1bccc4f566a3cee8d1ff0fafc9 (diff)
improve port0_enable(), properly configure hcfg and hfir according to port speed. Enable low power UTMI+ phy mode for ls/fs device.
Diffstat (limited to 'src')
-rw-r--r--src/portable/synopsys/dwc2/dwc2_type.h4
-rw-r--r--src/portable/synopsys/dwc2/hcd_dwc2.c115
2 files changed, 63 insertions, 56 deletions
diff --git a/src/portable/synopsys/dwc2/dwc2_type.h b/src/portable/synopsys/dwc2/dwc2_type.h
index 89561a5e6..a88a2d389 100644
--- a/src/portable/synopsys/dwc2/dwc2_type.h
+++ b/src/portable/synopsys/dwc2/dwc2_type.h
@@ -730,6 +730,7 @@ TU_VERIFY_STATIC(offsetof(dwc2_regs_t, fifo ) == 0x1000, "incorrect size");
#define HCFG_FSLS_PHYCLK_SEL HCFG_FSLS_PHYCLK_SEL_Msk // FS/LS PHY clock select
#define HCFG_FSLS_PHYCLK_SEL_30_60MHZ (0x0UL << HCFG_FSLS_PHYCLK_SEL_Pos) // 0x00000000
#define HCFG_FSLS_PHYCLK_SEL_48MHZ (0x1UL << HCFG_FSLS_PHYCLK_SEL_Pos) // 0x00000001
+#define HCFG_FSLS_PHYCLK_SEL_6MHZ (0x2UL << HCFG_FSLS_PHYCLK_SEL_Pos) // 0x00000002
#define HCFG_FSLS_ONLY_Pos (2U)
#define HCFG_FSLS_ONLY_Msk (0x1UL << HCFG_FSLS_ONLY_Pos) // 0x00000004
@@ -848,6 +849,9 @@ TU_VERIFY_STATIC(offsetof(dwc2_regs_t, fifo ) == 0x1000, "incorrect size");
#define HFIR_FRIVL_Pos (0U)
#define HFIR_FRIVL_Msk (0xFFFFUL << HFIR_FRIVL_Pos) // 0x0000FFFF
#define HFIR_FRIVL HFIR_FRIVL_Msk // Frame interval
+#define HFIR_RELOAD_CTRL_Pos (16U) // available since v2.92a
+#define HFIR_RELOAD_CTRL_Msk (0x1UL << HFIR_RELOAD_CTRL_Pos)
+#define HFIR_RELOAD_CTRL HFIR_RELOAD_CTRL_Msk
/******************** Bit definition for HFNUM register ********************/
#define HFNUM_FRNUM_Pos (0U)
diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c
index 8bfba442b..b2ca86a36 100644
--- a/src/portable/synopsys/dwc2/hcd_dwc2.c
+++ b/src/portable/synopsys/dwc2/hcd_dwc2.c
@@ -45,7 +45,7 @@
TU_VERIFY_STATIC(CFG_TUH_DWC2_ENDPOINT_MAX <= 255, "currently only use 8-bit for index");
enum {
- HPRT_W1C_MASK = HPRT_CONN_DETECT | HPRT_ENABLE | HPRT_ENABLE_CHANGE | HPRT_OVER_CURRENT_CHANGE
+ HPRT_W1_MASK = HPRT_CONN_DETECT | HPRT_ENABLE | HPRT_ENABLE_CHANGE | HPRT_OVER_CURRENT_CHANGE | HPRT_SUSPEND
};
enum {
@@ -79,7 +79,7 @@ typedef struct {
typedef struct {
volatile bool allocated;
uint8_t ep_id;
- union TU_ATTR_PACKED {
+ struct TU_ATTR_PACKED {
uint8_t err_count : 6;
uint8_t do_ping : 1;
uint8_t sof_schedule : 1;
@@ -336,26 +336,13 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
//------------- 3.1 Host Initialization -------------//
- // FS/LS PHY Clock Select
- uint32_t hcfg = dwc2->hcfg;
- if (is_highspeed) {
- hcfg &= ~HCFG_FSLS_ONLY;
- } else {
- hcfg &= ~HCFG_FSLS_ONLY; // since we are using FS PHY
- hcfg &= ~HCFG_FSLS_PHYCLK_SEL;
-
- if (dwc2->ghwcfg2_bm.hs_phy_type == GHWCFG2_HSPHY_ULPI &&
- dwc2->ghwcfg2_bm.fs_phy_type == GHWCFG2_FSPHY_DEDICATED) {
- // dedicated FS PHY with 48 mhz
- hcfg |= HCFG_FSLS_PHYCLK_SEL_48MHZ;
- } else {
- // shared HS PHY running at full speed
- hcfg |= HCFG_FSLS_PHYCLK_SEL_30_60MHZ;
- }
- }
- dwc2->hcfg = hcfg;
+ // work at max supported speed
+ dwc2->hcfg &= ~HCFG_FSLS_ONLY;
// Enable HFIR reload
+ if (dwc2->gsnpsid >= DWC2_CORE_REV_2_92a) {
+ dwc2->hfir |= HFIR_RELOAD_CTRL;
+ }
// force host mode and wait for mode switch
dwc2->gusbcfg = (dwc2->gusbcfg & ~GUSBCFG_FDMOD) | GUSBCFG_FHMOD;
@@ -364,7 +351,7 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
// configure fixed-allocated fifo scheme
dfifo_host_init(rhport);
- dwc2->hprt = HPRT_W1C_MASK; // clear all write-1-clear bits
+ dwc2->hprt = HPRT_W1_MASK; // clear all write-1-clear bits
dwc2->hprt = HPRT_POWER; // turn on VBUS
// Enable required interrupts
@@ -408,7 +395,7 @@ bool hcd_port_connect_status(uint8_t rhport) {
// Some port would require hcd_port_reset_end() to be invoked after 10ms to complete the reset sequence.
void hcd_port_reset(uint8_t rhport) {
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
- uint32_t hprt = dwc2->hprt & ~HPRT_W1C_MASK;
+ uint32_t hprt = dwc2->hprt & ~HPRT_W1_MASK;
hprt |= HPRT_RESET;
dwc2->hprt = hprt;
}
@@ -416,7 +403,7 @@ void hcd_port_reset(uint8_t rhport) {
// Complete bus reset sequence, may be required by some controllers
void hcd_port_reset_end(uint8_t rhport) {
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
- uint32_t hprt = dwc2->hprt & ~HPRT_W1C_MASK; // skip w1c bits
+ uint32_t hprt = dwc2->hprt & ~HPRT_W1_MASK; // skip w1c bits
hprt &= ~HPRT_RESET;
dwc2->hprt = hprt;
}
@@ -1044,6 +1031,50 @@ static bool handle_sof_irq(uint8_t rhport, bool in_isr) {
return more_isr;
}
+// Config HCFG FS/LS clock and HFIR for SOF interval according to link speed (value is in PHY clock unit)
+static void port0_enable(dwc2_regs_t* dwc2, tusb_speed_t speed) {
+ uint32_t hcfg = dwc2->hcfg & ~HCFG_FSLS_PHYCLK_SEL;
+
+ const dwc2_gusbcfg_t gusbcfg_bm = dwc2->gusbcfg_bm;
+ uint32_t phy_clock;
+
+ if (gusbcfg_bm.phy_sel) {
+ phy_clock = 48; // dedicated FS is 48Mhz
+ if (speed == TUSB_SPEED_LOW) {
+ hcfg |= HCFG_FSLS_PHYCLK_SEL_6MHZ;
+ } else {
+ hcfg |= HCFG_FSLS_PHYCLK_SEL_48MHZ;
+ }
+ } else {
+ if (gusbcfg_bm.ulpi_utmi_sel) {
+ phy_clock = 60; // ULPI 8-bit is 60Mhz
+ } else {
+ // UTMI+ 16-bit is 30Mhz, 8-bit is 60Mhz
+ phy_clock = gusbcfg_bm.phy_if16 ? 30 : 60;
+
+ // Enable UTMI+ low power mode 48Mhz external clock if not highspeed
+ if (speed == TUSB_SPEED_HIGH) {
+ dwc2->gusbcfg &= ~GUSBCFG_PHYLPCS;
+ } else {
+ dwc2->gusbcfg |= GUSBCFG_PHYLPCS;
+ // may need to reset port
+ }
+ }
+ hcfg |= HCFG_FSLS_PHYCLK_SEL_30_60MHZ;
+ }
+
+ dwc2->hcfg = hcfg;
+
+ uint32_t hfir = dwc2->hfir & ~HFIR_FRIVL_Msk;
+ if (speed == TUSB_SPEED_HIGH) {
+ hfir |= 125*phy_clock;
+ } else {
+ hfir |= 1000*phy_clock;
+ }
+
+ dwc2->hfir = hfir;
+}
+
/* Handle Host Port interrupt, possible source are:
- Connection Detection
- Enable Change
@@ -1051,7 +1082,7 @@ static bool handle_sof_irq(uint8_t rhport, bool in_isr) {
*/
static void handle_hprt_irq(uint8_t rhport, bool in_isr) {
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
- uint32_t hprt = dwc2->hprt & ~HPRT_W1C_MASK;
+ uint32_t hprt = dwc2->hprt & ~HPRT_W1_MASK;
const dwc2_hprt_t hprt_bm = dwc2->hprt_bm;
if (dwc2->hprt & HPRT_CONN_DETECT) {
@@ -1071,38 +1102,10 @@ static void handle_hprt_irq(uint8_t rhport, bool in_isr) {
if (hprt_bm.enable) {
// Port enable
- // Config HCFG FS/LS clock and HFIR for SOF interval according to link speed (value is in PHY clock unit)
const tusb_speed_t speed = convert_hprt_speed(hprt_bm.speed);
- uint32_t hcfg = dwc2->hcfg & ~HCFG_FSLS_PHYCLK_SEL;
-
- const dwc2_gusbcfg_t gusbcfg_bm = dwc2->gusbcfg_bm;
- uint32_t clock = 60;
- if (gusbcfg_bm.phy_sel) {
- // dedicated FS is 48Mhz
- clock = 48;
- hcfg |= HCFG_FSLS_PHYCLK_SEL_48MHZ;
- } else {
- // UTMI+ or ULPI
- if (gusbcfg_bm.ulpi_utmi_sel) {
- clock = 60; // ULPI 8-bit is 60Mhz
- } else if (gusbcfg_bm.phy_if16) {
- clock = 30; // UTMI+ 16-bit is 30Mhz
- } else {
- clock = 60; // UTMI+ 8-bit is 60Mhz
- }
- hcfg |= HCFG_FSLS_PHYCLK_SEL_30_60MHZ;
- }
-
- dwc2->hcfg = hcfg;
-
- uint32_t hfir = dwc2->hfir & ~HFIR_FRIVL_Msk;
- if (speed == TUSB_SPEED_HIGH) {
- hfir |= 125*clock;
- } else {
- hfir |= 1000*clock;
- }
-
- dwc2->hfir = hfir;
+ port0_enable(dwc2, speed);
+ } else {
+ // TU_ASSERT(false, );
}
}
@@ -1121,7 +1124,7 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) {
const uint32_t gintmsk = dwc2->gintmsk;
const uint32_t gintsts = dwc2->gintsts & gintmsk;
- // TU_LOG1_HEX(int_status);
+ // TU_LOG1_HEX(gintsts);
if (gintsts & GINTSTS_CONIDSTSCHNG) {
// Connector ID status change