mirror of
https://github.com/hathach/tinyusb.git
synced 2025-01-17 05:32:55 +08:00
improve port0_enable(), properly configure hcfg and hfir according to port speed. Enable low power UTMI+ phy mode for ls/fs device.
This commit is contained in:
parent
80ad7c4e87
commit
29262f3e24
@ -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 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_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_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_Pos (2U)
|
||||||
#define HCFG_FSLS_ONLY_Msk (0x1UL << HCFG_FSLS_ONLY_Pos) // 0x00000004
|
#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_Pos (0U)
|
||||||
#define HFIR_FRIVL_Msk (0xFFFFUL << HFIR_FRIVL_Pos) // 0x0000FFFF
|
#define HFIR_FRIVL_Msk (0xFFFFUL << HFIR_FRIVL_Pos) // 0x0000FFFF
|
||||||
#define HFIR_FRIVL HFIR_FRIVL_Msk // Frame interval
|
#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 ********************/
|
/******************** Bit definition for HFNUM register ********************/
|
||||||
#define HFNUM_FRNUM_Pos (0U)
|
#define HFNUM_FRNUM_Pos (0U)
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
TU_VERIFY_STATIC(CFG_TUH_DWC2_ENDPOINT_MAX <= 255, "currently only use 8-bit for index");
|
TU_VERIFY_STATIC(CFG_TUH_DWC2_ENDPOINT_MAX <= 255, "currently only use 8-bit for index");
|
||||||
|
|
||||||
enum {
|
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 {
|
enum {
|
||||||
@ -79,7 +79,7 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
volatile bool allocated;
|
volatile bool allocated;
|
||||||
uint8_t ep_id;
|
uint8_t ep_id;
|
||||||
union TU_ATTR_PACKED {
|
struct TU_ATTR_PACKED {
|
||||||
uint8_t err_count : 6;
|
uint8_t err_count : 6;
|
||||||
uint8_t do_ping : 1;
|
uint8_t do_ping : 1;
|
||||||
uint8_t sof_schedule : 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 -------------//
|
//------------- 3.1 Host Initialization -------------//
|
||||||
|
|
||||||
// FS/LS PHY Clock Select
|
// work at max supported speed
|
||||||
uint32_t hcfg = dwc2->hcfg;
|
dwc2->hcfg &= ~HCFG_FSLS_ONLY;
|
||||||
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;
|
|
||||||
|
|
||||||
// Enable HFIR reload
|
// Enable HFIR reload
|
||||||
|
if (dwc2->gsnpsid >= DWC2_CORE_REV_2_92a) {
|
||||||
|
dwc2->hfir |= HFIR_RELOAD_CTRL;
|
||||||
|
}
|
||||||
|
|
||||||
// force host mode and wait for mode switch
|
// force host mode and wait for mode switch
|
||||||
dwc2->gusbcfg = (dwc2->gusbcfg & ~GUSBCFG_FDMOD) | GUSBCFG_FHMOD;
|
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
|
// configure fixed-allocated fifo scheme
|
||||||
dfifo_host_init(rhport);
|
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
|
dwc2->hprt = HPRT_POWER; // turn on VBUS
|
||||||
|
|
||||||
// Enable required interrupts
|
// 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.
|
// 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) {
|
void hcd_port_reset(uint8_t rhport) {
|
||||||
dwc2_regs_t* dwc2 = DWC2_REG(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;
|
hprt |= HPRT_RESET;
|
||||||
dwc2->hprt = hprt;
|
dwc2->hprt = hprt;
|
||||||
}
|
}
|
||||||
@ -416,7 +403,7 @@ void hcd_port_reset(uint8_t rhport) {
|
|||||||
// Complete bus reset sequence, may be required by some controllers
|
// Complete bus reset sequence, may be required by some controllers
|
||||||
void hcd_port_reset_end(uint8_t rhport) {
|
void hcd_port_reset_end(uint8_t rhport) {
|
||||||
dwc2_regs_t* dwc2 = DWC2_REG(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;
|
hprt &= ~HPRT_RESET;
|
||||||
dwc2->hprt = hprt;
|
dwc2->hprt = hprt;
|
||||||
}
|
}
|
||||||
@ -1044,6 +1031,50 @@ static bool handle_sof_irq(uint8_t rhport, bool in_isr) {
|
|||||||
return more_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:
|
/* Handle Host Port interrupt, possible source are:
|
||||||
- Connection Detection
|
- Connection Detection
|
||||||
- Enable Change
|
- 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) {
|
static void handle_hprt_irq(uint8_t rhport, bool in_isr) {
|
||||||
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
|
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;
|
const dwc2_hprt_t hprt_bm = dwc2->hprt_bm;
|
||||||
|
|
||||||
if (dwc2->hprt & HPRT_CONN_DETECT) {
|
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) {
|
if (hprt_bm.enable) {
|
||||||
// Port 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);
|
const tusb_speed_t speed = convert_hprt_speed(hprt_bm.speed);
|
||||||
uint32_t hcfg = dwc2->hcfg & ~HCFG_FSLS_PHYCLK_SEL;
|
port0_enable(dwc2, speed);
|
||||||
|
} else {
|
||||||
const dwc2_gusbcfg_t gusbcfg_bm = dwc2->gusbcfg_bm;
|
// TU_ASSERT(false, );
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1121,7 +1124,7 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) {
|
|||||||
const uint32_t gintmsk = dwc2->gintmsk;
|
const uint32_t gintmsk = dwc2->gintmsk;
|
||||||
const uint32_t gintsts = dwc2->gintsts & gintmsk;
|
const uint32_t gintsts = dwc2->gintsts & gintmsk;
|
||||||
|
|
||||||
// TU_LOG1_HEX(int_status);
|
// TU_LOG1_HEX(gintsts);
|
||||||
|
|
||||||
if (gintsts & GINTSTS_CONIDSTSCHNG) {
|
if (gintsts & GINTSTS_CONIDSTSCHNG) {
|
||||||
// Connector ID status change
|
// Connector ID status change
|
||||||
|
Loading…
x
Reference in New Issue
Block a user