mirror of
https://github.com/hathach/tinyusb.git
synced 2026-03-05 15:17:14 +00:00
Merge pull request #3506 from Precidata/fs-host-with-hs-phy-v3
Supports full-speed host with an high-speed PHY (DWC2, v3)
This commit is contained in:
@ -96,6 +96,7 @@ enum {
|
||||
TUH_CFGID_RPI_PIO_USB_CONFIGURATION = 100, // cfg_param: pio_usb_configuration_t
|
||||
TUH_CFGID_MAX3421 = 200,
|
||||
TUH_CFGID_FSDEV = 300,
|
||||
TUH_CFGID_DWC2 = 400
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
@ -108,10 +109,15 @@ typedef struct {
|
||||
uint8_t max_nak; // max NAK per endpoint per frame to save CPU usage (0=unlimited)
|
||||
} tuh_configure_fsdev_t;
|
||||
|
||||
typedef struct {
|
||||
bool use_hs_phy; // Always use high-speed ULPI/UTMI phy even when working at full-speed
|
||||
} tuh_configure_dwc2_t;
|
||||
|
||||
typedef union {
|
||||
// For TUH_CFGID_RPI_PIO_USB_CONFIGURATION use pio_usb_configuration_t
|
||||
tuh_configure_max3421_t max3421;
|
||||
tuh_configure_fsdev_t fsdev;
|
||||
tuh_configure_dwc2_t dwc2;
|
||||
} tuh_configure_param_t;
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
@ -442,14 +442,14 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
|
||||
tu_memclr(&_dcd_data, sizeof(_dcd_data));
|
||||
|
||||
// Core Initialization
|
||||
const bool is_highspeed = dwc2_core_is_highspeed(dwc2, TUSB_ROLE_DEVICE);
|
||||
const bool highspeed_phy = dwc2_core_is_highspeed_phy(dwc2, TUD_OPT_HIGH_SPEED);
|
||||
const bool is_dma = dma_device_enabled(dwc2);
|
||||
TU_ASSERT(dwc2_core_init(rhport, is_highspeed, is_dma));
|
||||
TU_ASSERT(dwc2_core_init(rhport, highspeed_phy, is_dma));
|
||||
|
||||
//------------- 7.1 Device Initialization -------------//
|
||||
// Set device max speed
|
||||
uint32_t dcfg = dwc2->dcfg & ~DCFG_DSPD_Msk;
|
||||
if (is_highspeed) {
|
||||
if (highspeed_phy) {
|
||||
// dcfg Highspeed's mask is 0
|
||||
|
||||
// XCVRDLY: transceiver delay between xcvr_sel and txvalid during device chirp is required
|
||||
|
||||
@ -179,18 +179,17 @@ static bool check_dwc2(dwc2_regs_t* dwc2) {
|
||||
//--------------------------------------------------------------------
|
||||
//
|
||||
//--------------------------------------------------------------------
|
||||
bool dwc2_core_is_highspeed(dwc2_regs_t* dwc2, tusb_role_t role) {
|
||||
(void)dwc2;
|
||||
#if CFG_TUD_ENABLED
|
||||
if (role == TUSB_ROLE_DEVICE && !TUD_OPT_HIGH_SPEED) {
|
||||
return false;
|
||||
bool dwc2_core_is_highspeed_phy(dwc2_regs_t* dwc2, bool prefer_hs_phy) {
|
||||
#ifdef TUP_USBIP_DWC2_STM32
|
||||
if (dwc2->guid >= 0x5000) {
|
||||
// femtoPHY UTMI+ PHY
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#if CFG_TUH_ENABLED
|
||||
if (role == TUSB_ROLE_HOST && !TUH_OPT_HIGH_SPEED) {
|
||||
|
||||
if (!prefer_hs_phy) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2};
|
||||
return ghwcfg2.hs_phy_type != GHWCFG2_HSPHY_NOT_SUPPORTED;
|
||||
@ -204,7 +203,7 @@ bool dwc2_core_is_highspeed(dwc2_regs_t* dwc2, tusb_role_t role) {
|
||||
* In addition, UTMI+/ULPI can be shared to run at fullspeed mode with 48Mhz
|
||||
*
|
||||
*/
|
||||
bool dwc2_core_init(uint8_t rhport, bool is_highspeed, bool is_dma) {
|
||||
bool dwc2_core_init(uint8_t rhport, bool highspeed_phy, bool is_dma) {
|
||||
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
|
||||
|
||||
// Check Synopsys ID register, failed if controller clock/power is not enabled
|
||||
@ -213,7 +212,7 @@ bool dwc2_core_init(uint8_t rhport, bool is_highspeed, bool is_dma) {
|
||||
// disable global interrupt
|
||||
dwc2->gahbcfg &= ~GAHBCFG_GINT;
|
||||
|
||||
if (is_highspeed) {
|
||||
if (highspeed_phy) {
|
||||
phy_hs_init(dwc2);
|
||||
} else {
|
||||
phy_fs_init(dwc2);
|
||||
|
||||
@ -84,8 +84,8 @@ TU_ATTR_ALWAYS_INLINE static inline dwc2_regs_t* DWC2_REG(uint8_t rhport) {
|
||||
return (dwc2_regs_t*)_dwc2_controller[rhport].reg_base;
|
||||
}
|
||||
|
||||
bool dwc2_core_is_highspeed(dwc2_regs_t* dwc2, tusb_role_t role);
|
||||
bool dwc2_core_init(uint8_t rhport, bool is_highspeed, bool is_dma);
|
||||
bool dwc2_core_is_highspeed_phy(dwc2_regs_t* dwc2, bool prefer_hs_phy);
|
||||
bool dwc2_core_init(uint8_t rhport, bool highspeed_phy, bool is_dma);
|
||||
void dwc2_core_handle_common_irq(uint8_t rhport, bool in_isr);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
@ -111,7 +111,9 @@ typedef struct {
|
||||
hcd_endpoint_t edpt[CFG_TUH_DWC2_ENDPOINT_MAX];
|
||||
} hcd_data_t;
|
||||
|
||||
hcd_data_t _hcd_data;
|
||||
static hcd_data_t _hcd_data;
|
||||
|
||||
static tuh_configure_dwc2_t _tuh_cfg = {.use_hs_phy = TUH_OPT_HIGH_SPEED};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
//
|
||||
@ -364,9 +366,9 @@ static void dfifo_host_init(uint8_t rhport) {
|
||||
|
||||
// fixed allocation for now, improve later:
|
||||
// - ptx_largest is limited to 256 for FS since most FS core only has 1024 bytes total
|
||||
bool is_highspeed = dwc2_core_is_highspeed(dwc2, TUSB_ROLE_HOST);
|
||||
uint32_t nptx_largest = is_highspeed ? TUSB_EPSIZE_BULK_HS/4 : TUSB_EPSIZE_BULK_FS/4;
|
||||
uint32_t ptx_largest = is_highspeed ? TUSB_EPSIZE_ISO_HS_MAX/4 : 256/4;
|
||||
bool highspeed_phy = dwc2_core_is_highspeed_phy(dwc2, _tuh_cfg.use_hs_phy);
|
||||
uint32_t nptx_largest = highspeed_phy ? TUSB_EPSIZE_BULK_HS/4 : TUSB_EPSIZE_BULK_FS/4;
|
||||
uint32_t ptx_largest = highspeed_phy ? TUSB_EPSIZE_ISO_HS_MAX/4 : 256/4;
|
||||
|
||||
uint16_t nptxfsiz = 2 * nptx_largest;
|
||||
uint16_t rxfsiz = 2 * (ptx_largest + 2) + ghwcfg2.num_host_ch;
|
||||
@ -392,29 +394,25 @@ static void dfifo_host_init(uint8_t rhport) {
|
||||
// optional hcd configuration, called by tuh_configure()
|
||||
bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) {
|
||||
(void) rhport;
|
||||
(void) cfg_id;
|
||||
(void) cfg_param;
|
||||
|
||||
TU_VERIFY(cfg_id == TUH_CFGID_DWC2 && cfg_param != NULL);
|
||||
tuh_configure_param_t const* cfg = (tuh_configure_param_t const*) cfg_param;
|
||||
_tuh_cfg = cfg->dwc2;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Initialize controller to host mode
|
||||
bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
|
||||
(void) rh_init;
|
||||
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
|
||||
|
||||
tu_memclr(&_hcd_data, sizeof(_hcd_data));
|
||||
|
||||
// Core Initialization
|
||||
const bool is_highspeed = dwc2_core_is_highspeed(dwc2, TUSB_ROLE_HOST);
|
||||
const bool highspeed_phy = dwc2_core_is_highspeed_phy(dwc2, _tuh_cfg.use_hs_phy);
|
||||
const bool is_dma = dma_host_enabled(dwc2);
|
||||
TU_ASSERT(dwc2_core_init(rhport, is_highspeed, is_dma));
|
||||
TU_ASSERT(dwc2_core_init(rhport, highspeed_phy, is_dma));
|
||||
|
||||
//------------- 3.1 Host Initialization -------------//
|
||||
|
||||
// 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;
|
||||
@ -432,6 +430,17 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
|
||||
dwc2_stm32_gccfg_cfg(dwc2, false, true);
|
||||
#endif
|
||||
|
||||
if (rh_init->speed < TUSB_SPEED_HIGH || !TUH_OPT_HIGH_SPEED) {
|
||||
// disable high speed mode
|
||||
dwc2->hcfg |= HCFG_FSLS_ONLY;
|
||||
}
|
||||
#if TUH_OPT_HIGH_SPEED
|
||||
else {
|
||||
// work at max supported speed
|
||||
dwc2->hcfg &= ~HCFG_FSLS_ONLY;
|
||||
}
|
||||
#endif
|
||||
|
||||
// configure fixed-allocated fifo scheme
|
||||
dfifo_host_init(rhport);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user