move gahbcfg/gintmsk with dma to dwc2 common

This commit is contained in:
hathach
2024-10-16 13:19:28 +07:00
parent 4012e15075
commit 8d9d3d9a2a
6 changed files with 212 additions and 133 deletions

View File

@@ -68,22 +68,6 @@ static bool _sof_en;
// DMA // DMA
//-------------------------------------------------------------------- //--------------------------------------------------------------------
TU_ATTR_ALWAYS_INLINE static inline bool dma_enabled(const dwc2_regs_t* dwc2) {
#if !CFG_TUD_DWC2_DMA
(void) dwc2;
return false;
#else
// Internal DMA only
return (dwc2->ghwcfg2_bm.arch == GHWCFG2_ARCH_INTERNAL_DMA);
#endif
}
TU_ATTR_ALWAYS_INLINE static inline uint16_t dma_cal_epfifo_base(uint8_t rhport) {
// Scatter/Gather DMA mode is not yet supported. Buffer DMA only need 1 words per endpoint direction
const dwc2_controller_t* dwc2_controller = &_dwc2_controller[rhport];
return dwc2_controller->ep_fifo_size/4 - 2*dwc2_controller->ep_count;
}
static void dma_setup_prepare(uint8_t rhport) { static void dma_setup_prepare(uint8_t rhport) {
dwc2_regs_t* dwc2 = DWC2_REG(rhport); dwc2_regs_t* dwc2 = DWC2_REG(rhport);
@@ -103,16 +87,6 @@ static void dma_setup_prepare(uint8_t rhport) {
// Data FIFO // Data FIFO
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
TU_ATTR_ALWAYS_INLINE static inline void dfifo_flush_tx(dwc2_regs_t* dwc2, uint8_t epnum) {
// flush TX fifo and wait for it cleared
dwc2->grstctl = GRSTCTL_TXFFLSH | (epnum << GRSTCTL_TXFNUM_Pos);
while (dwc2->grstctl & GRSTCTL_TXFFLSH_Msk) {}
}
TU_ATTR_ALWAYS_INLINE static inline void dfifo_flush_rx(dwc2_regs_t* dwc2) {
// flush RX fifo and wait for it cleared
dwc2->grstctl = GRSTCTL_RXFFLSH;
while (dwc2->grstctl & GRSTCTL_RXFFLSH_Msk) {}
}
/* USB Data FIFO Layout /* USB Data FIFO Layout
@@ -215,7 +189,7 @@ static void dfifo_init(uint8_t rhport) {
dwc2_regs_t* dwc2 = DWC2_REG(rhport); dwc2_regs_t* dwc2 = DWC2_REG(rhport);
dwc2->grxfsiz = calc_grxfsiz(CFG_TUD_ENDPOINT0_SIZE, dwc2_controller->ep_count); dwc2->grxfsiz = calc_grxfsiz(CFG_TUD_ENDPOINT0_SIZE, dwc2_controller->ep_count);
if(dma_enabled(dwc2)) { if(dwc2_dma_enabled(dwc2, TUSB_ROLE_DEVICE)) {
// DMA use last DFIFO to store metadata // DMA use last DFIFO to store metadata
_dfifo_top = dma_cal_epfifo_base(rhport); _dfifo_top = dma_cal_epfifo_base(rhport);
}else { }else {
@@ -395,7 +369,7 @@ static void bus_reset(uint8_t rhport) {
xfer_status[0][TUSB_DIR_OUT].max_size = 64; xfer_status[0][TUSB_DIR_OUT].max_size = 64;
xfer_status[0][TUSB_DIR_IN].max_size = 64; xfer_status[0][TUSB_DIR_IN].max_size = 64;
if(dma_enabled(dwc2)) { if(dwc2_dma_enabled(dwc2, TUSB_ROLE_DEVICE)) {
dma_setup_prepare(rhport); dma_setup_prepare(rhport);
} else { } else {
dwc2->epout[0].doeptsiz |= (3 << DOEPTSIZ_STUPCNT_Pos); dwc2->epout[0].doeptsiz |= (3 << DOEPTSIZ_STUPCNT_Pos);
@@ -427,7 +401,7 @@ static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t c
dep->dieptsiz = (num_packets << DIEPTSIZ_PKTCNT_Pos) | dep->dieptsiz = (num_packets << DIEPTSIZ_PKTCNT_Pos) |
((total_bytes << DIEPTSIZ_XFRSIZ_Pos) & DIEPTSIZ_XFRSIZ_Msk); ((total_bytes << DIEPTSIZ_XFRSIZ_Pos) & DIEPTSIZ_XFRSIZ_Msk);
if(dma_enabled(dwc2)) { if(dwc2_dma_enabled(dwc2, TUSB_ROLE_DEVICE)) {
dep->diepdma = (uintptr_t)xfer->buffer; dep->diepdma = (uintptr_t)xfer->buffer;
// For ISO endpoint set correct odd/even bit for next frame. // For ISO endpoint set correct odd/even bit for next frame.
@@ -465,7 +439,7 @@ static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t c
dep->doepctl |= (odd_frame_now ? DOEPCTL_SD0PID_SEVNFRM_Msk : DOEPCTL_SODDFRM_Msk); dep->doepctl |= (odd_frame_now ? DOEPCTL_SD0PID_SEVNFRM_Msk : DOEPCTL_SODDFRM_Msk);
} }
if(dma_enabled(dwc2)) { if(dwc2_dma_enabled(dwc2, TUSB_ROLE_DEVICE)) {
dep->doepdma = (uintptr_t)xfer->buffer; dep->doepdma = (uintptr_t)xfer->buffer;
} }
@@ -477,9 +451,9 @@ static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t c
// Controller API // Controller API
//-------------------------------------------------------------------- //--------------------------------------------------------------------
bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
(void) rh_init;
dwc2_regs_t* dwc2 = DWC2_REG(rhport); dwc2_regs_t* dwc2 = DWC2_REG(rhport);
// Core Initialization
TU_ASSERT(dwc2_core_init(rhport, rh_init)); TU_ASSERT(dwc2_core_init(rhport, rh_init));
// Device Initialization // Device Initialization
@@ -500,9 +474,6 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
} }
dwc2->dcfg = dcfg; dwc2->dcfg = dcfg;
// Enable PHY clock TODO stop/gate clock when suspended mode
dwc2->pcgcctl &= ~(PCGCCTL_STOPPCLK | PCGCCTL_GATEHCLK | PCGCCTL_PWRCLMP | PCGCCTL_RSTPDWNMODULE);
// Force device mode // Force device mode
dwc2->gusbcfg = (dwc2->gusbcfg & ~GUSBCFG_FHMOD) | GUSBCFG_FDMOD; dwc2->gusbcfg = (dwc2->gusbcfg & ~GUSBCFG_FHMOD) | GUSBCFG_FDMOD;
@@ -512,44 +483,13 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
// If USB host misbehaves during status portion of control xfer (non zero-length packet), send STALL back and discard // If USB host misbehaves during status portion of control xfer (non zero-length packet), send STALL back and discard
dwc2->dcfg |= DCFG_NZLSOHSK; dwc2->dcfg |= DCFG_NZLSOHSK;
dfifo_flush_tx(dwc2, 0x10); // all tx fifo // Enable required interrupts
dfifo_flush_rx(dwc2); dwc2->gintmsk |= GINTMSK_OTGINT | GINTMSK_USBSUSPM | GINTMSK_USBRST | GINTMSK_ENUMDNEM | GINTMSK_WUIM;
// Clear all interrupts
uint32_t int_mask = dwc2->gintsts;
dwc2->gintsts |= int_mask;
int_mask = dwc2->gotgint;
dwc2->gotgint |= int_mask;
// Required as part of core initialization.
dwc2->gintmsk = GINTMSK_OTGINT | GINTMSK_USBSUSPM | GINTMSK_USBRST | GINTMSK_ENUMDNEM | GINTMSK_WUIM;
// Configure TX FIFO empty level for interrupt. Default is complete empty // Configure TX FIFO empty level for interrupt. Default is complete empty
dwc2->gahbcfg |= GAHBCFG_TXFELVL; dwc2->gahbcfg |= GAHBCFG_TXFELVL;
if (dma_enabled(dwc2)) {
const uint16_t epinfo_base = dma_cal_epfifo_base(rhport);
dwc2->gdfifocfg = (epinfo_base << GDFIFOCFG_EPINFOBASE_SHIFT) | epinfo_base;
// DMA seems to be only settable after a core reset
dwc2->gahbcfg |= GAHBCFG_DMAEN | GAHBCFG_HBSTLEN_2;
}else {
dwc2->gintmsk |= GINTMSK_RXFLVLM;
}
// Enable global interrupt
dwc2->gahbcfg |= GAHBCFG_GINT;
// make sure we are in device mode
// TU_ASSERT(!(dwc2->gintsts & GINTSTS_CMOD), );
// TU_LOG_HEX(DWC2_DEBUG, dwc2->gotgctl);
// TU_LOG_HEX(DWC2_DEBUG, dwc2->gusbcfg);
// TU_LOG_HEX(DWC2_DEBUG, dwc2->dcfg);
// TU_LOG_HEX(DWC2_DEBUG, dwc2->gahbcfg);
dcd_connect(rhport); dcd_connect(rhport);
return true; return true;
} }
@@ -749,7 +689,7 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) {
void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) {
edpt_disable(rhport, ep_addr, true); edpt_disable(rhport, ep_addr, true);
if((tu_edpt_number(ep_addr) == 0) && dma_enabled(DWC2_REG(rhport))) { if((tu_edpt_number(ep_addr) == 0) && dwc2_dma_enabled(DWC2_REG(rhport), TUSB_ROLE_DEVICE)) {
dma_setup_prepare(rhport); dma_setup_prepare(rhport);
} }
} }
@@ -866,7 +806,7 @@ static void handle_epout_irq(uint8_t rhport) {
if (doepint & DOEPINT_SETUP) { if (doepint & DOEPINT_SETUP) {
epout->doepint = DOEPINT_SETUP; epout->doepint = DOEPINT_SETUP;
if(dma_enabled(dwc2)) { if(dwc2_dma_enabled(dwc2, TUSB_ROLE_DEVICE)) {
dma_setup_prepare(rhport); dma_setup_prepare(rhport);
} }
@@ -882,7 +822,7 @@ static void handle_epout_irq(uint8_t rhport) {
if (!(doepint & (DOEPINT_SETUP | DOEPINT_STPKTRX | DOEPINT_STSPHSRX))) { if (!(doepint & (DOEPINT_SETUP | DOEPINT_STPKTRX | DOEPINT_STSPHSRX))) {
xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT);
if(dma_enabled(dwc2)) { if(dwc2_dma_enabled(dwc2, TUSB_ROLE_DEVICE)) {
if ((epnum == 0) && ep0_pending[TUSB_DIR_OUT]) { if ((epnum == 0) && ep0_pending[TUSB_DIR_OUT]) {
// EP0 can only handle one packet Schedule another packet to be received. // EP0 can only handle one packet Schedule another packet to be received.
edpt_schedule_packets(rhport, epnum, TUSB_DIR_OUT, 1, ep0_pending[TUSB_DIR_OUT]); edpt_schedule_packets(rhport, epnum, TUSB_DIR_OUT, 1, ep0_pending[TUSB_DIR_OUT]);
@@ -932,7 +872,7 @@ static void handle_epin_irq(uint8_t rhport) {
// Schedule another packet to be transmitted. // Schedule another packet to be transmitted.
edpt_schedule_packets(rhport, n, TUSB_DIR_IN, 1, ep0_pending[TUSB_DIR_IN]); edpt_schedule_packets(rhport, n, TUSB_DIR_IN, 1, ep0_pending[TUSB_DIR_IN]);
} else { } else {
if((n == 0) && dma_enabled(dwc2)) { if((n == 0) && dwc2_dma_enabled(dwc2, TUSB_ROLE_DEVICE)) {
dma_setup_prepare(rhport); dma_setup_prepare(rhport);
} }
dcd_event_xfer_complete(rhport, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); dcd_event_xfer_complete(rhport, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true);
@@ -982,7 +922,7 @@ static void handle_epin_irq(uint8_t rhport) {
/* Interrupt Hierarchy /* Interrupt Hierarchy
DxEPMSK.XferComplMsk DxEPINTn.XferCompl DxEPINTn.XferCompl DxEPMSK.XferComplMsk
| | | |
+---------- AND --------+ +---------- AND --------+
| |

View File

@@ -63,7 +63,7 @@ bool dwc2_core_is_highspeed(dwc2_regs_t* dwc2, const tusb_rhport_init_t* rh_init
} }
#endif #endif
#if CFG_TUH_ENABLED #if CFG_TUH_ENABLED
if (rh_init->role == TUSB_ROLE_DEVICE && !TUH_OPT_HIGH_SPEED) { if (rh_init->role == TUSB_ROLE_HOST && !TUH_OPT_HIGH_SPEED) {
return false; return false;
} }
#endif #endif
@@ -193,10 +193,39 @@ bool dwc2_core_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
* duration in the core to account for any additional delays * duration in the core to account for any additional delays
* introduced by the PHY. This can be required, because the delay * introduced by the PHY. This can be required, because the delay
* introduced by the PHY in generating the linestate condition * introduced by the PHY in generating the linestate condition
* can vary from one PHY to another. * can vary from one PHY to another. */
*/
dwc2->gusbcfg |= (7ul << GUSBCFG_TOCAL_Pos); dwc2->gusbcfg |= (7ul << GUSBCFG_TOCAL_Pos);
// Enable PHY clock TODO stop/gate clock when suspended mode
dwc2->pcgcctl &= ~(PCGCCTL_STOPPCLK | PCGCCTL_GATEHCLK | PCGCCTL_PWRCLMP | PCGCCTL_RSTPDWNMODULE);
dfifo_flush_tx(dwc2, 0x10); // all tx fifo
dfifo_flush_rx(dwc2);
// Clear all pending interrupts
uint32_t int_mask;
int_mask = dwc2->gintsts;
dwc2->gintsts |= int_mask;
int_mask = dwc2->gotgint;
dwc2->gotgint |= int_mask;
dwc2->gintmsk = GINTMSK_OTGINT;
if (dwc2_dma_enabled(dwc2, TUSB_ROLE_DEVICE)) {
const uint16_t epinfo_base = dma_cal_epfifo_base(rhport);
dwc2->gdfifocfg = (epinfo_base << GDFIFOCFG_EPINFOBASE_SHIFT) | epinfo_base;
// DMA seems to be only settable after a core reset, and not possible to switch on-the-fly
dwc2->gahbcfg |= GAHBCFG_DMAEN | GAHBCFG_HBSTLEN_2;
}else {
dwc2->gintmsk |= GINTMSK_RXFLVLM;
}
// Enable global interrupt
dwc2->gahbcfg |= GAHBCFG_GINT;
return true; return true;
} }

View File

@@ -57,6 +57,8 @@ enum {
DWC2_CONTROLLER_COUNT = TU_ARRAY_SIZE(_dwc2_controller) DWC2_CONTROLLER_COUNT = TU_ARRAY_SIZE(_dwc2_controller)
}; };
//------------- Core -------------//
TU_ATTR_ALWAYS_INLINE static inline dwc2_regs_t* DWC2_REG(uint8_t rhport) { TU_ATTR_ALWAYS_INLINE static inline dwc2_regs_t* DWC2_REG(uint8_t rhport) {
if (rhport >= DWC2_CONTROLLER_COUNT) { if (rhport >= DWC2_CONTROLLER_COUNT) {
// user mis-configured, ignore and use first controller // user mis-configured, ignore and use first controller
@@ -68,4 +70,39 @@ TU_ATTR_ALWAYS_INLINE static inline dwc2_regs_t* DWC2_REG(uint8_t rhport) {
bool dwc2_core_is_highspeed(dwc2_regs_t* dwc2, const tusb_rhport_init_t* rh_init); bool dwc2_core_is_highspeed(dwc2_regs_t* dwc2, const tusb_rhport_init_t* rh_init);
bool dwc2_core_init(uint8_t rhport, const tusb_rhport_init_t* rh_init); bool dwc2_core_init(uint8_t rhport, const tusb_rhport_init_t* rh_init);
//------------- DFIFO -------------//
TU_ATTR_ALWAYS_INLINE static inline void dfifo_flush_tx(dwc2_regs_t* dwc2, uint8_t fnum) {
// flush TX fifo and wait for it cleared
dwc2->grstctl = GRSTCTL_TXFFLSH | (fnum << GRSTCTL_TXFNUM_Pos);
while (dwc2->grstctl & GRSTCTL_TXFFLSH_Msk) {}
}
TU_ATTR_ALWAYS_INLINE static inline void dfifo_flush_rx(dwc2_regs_t* dwc2) {
// flush RX fifo and wait for it cleared
dwc2->grstctl = GRSTCTL_RXFFLSH;
while (dwc2->grstctl & GRSTCTL_RXFFLSH_Msk) {}
}
//------------- DMA -------------//
TU_ATTR_ALWAYS_INLINE static inline bool dwc2_dma_enabled(const dwc2_regs_t* dwc2, tusb_role_t role) {
(void) dwc2;
if (CFG_TUD_DWC2_DMA == 0 && role == TUSB_ROLE_DEVICE) {
return false;
}
if (CFG_TUH_DWC2_DMA == 0 && role == TUSB_ROLE_HOST) {
return false;
}
// Internal DMA only
return dwc2->ghwcfg2_bm.arch == GHWCFG2_ARCH_INTERNAL_DMA;
}
TU_ATTR_ALWAYS_INLINE static inline uint16_t dma_cal_epfifo_base(uint8_t rhport) {
// Scatter/Gather DMA mode is not yet supported. Buffer DMA only need 1 words per endpoint direction
const dwc2_controller_t* dwc2_controller = &_dwc2_controller[rhport];
return dwc2_controller->ep_fifo_size/4 - 2*dwc2_controller->ep_count;
}
#endif #endif

View File

@@ -122,6 +122,12 @@ enum {
GHWCFFG4_PHY_DATA_WIDTH_8_16 = 2, // software selectable GHWCFFG4_PHY_DATA_WIDTH_8_16 = 2, // software selectable
}; };
enum {
HPRT_SPEED_HIGH = 0,
HPRT_SPEED_FULL = 1,
HPRT_SPEED_LOW = 2
};
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Register bitfield definitions // Register bitfield definitions
//-------------------------------------------------------------------- //--------------------------------------------------------------------
@@ -301,6 +307,24 @@ typedef struct TU_ATTR_PACKED {
}dwc2_ghwcfg4_t; }dwc2_ghwcfg4_t;
TU_VERIFY_STATIC(sizeof(dwc2_ghwcfg4_t) == 4, "incorrect size"); TU_VERIFY_STATIC(sizeof(dwc2_ghwcfg4_t) == 4, "incorrect size");
typedef struct TU_ATTR_PACKED {
uint32_t conn_status : 1; // 0 Port connect status
uint32_t conn_detected : 1; // 1 Port connect detected
uint32_t enable : 1; // 2 Port enable status
uint32_t enable_change : 1; // 3 Port enable change
uint32_t over_current_active : 1; // 4 Port Over-current active
uint32_t over_current_change : 1; // 5 Port Over-current change
uint32_t resume : 1; // 6 Port resume
uint32_t suspend : 1; // 7 Port suspend
uint32_t reset : 1; // 8 Port reset
uint32_t rsv9 : 1; // 9 Reserved
uint32_t line_status : 2; // 10..11 Line status
uint32_t power : 1; // 12 Port power
uint32_t test_control : 4; // 13..16 Port Test control
uint32_t speed : 2; // 17..18 Port speed
uint32_t rsv19_31 :13; // 19..31 Reserved
}dwc2_hprt_t;
// Host Channel // Host Channel
typedef struct { typedef struct {
volatile uint32_t hcchar; // 500 + 20*ch Host Channel Characteristics volatile uint32_t hcchar; // 500 + 20*ch Host Channel Characteristics
@@ -1448,56 +1472,53 @@ TU_VERIFY_STATIC(offsetof(dwc2_regs_t, fifo ) == 0x1000, "incorrect size");
#define DIEPEACHMSK1_NAKM DIEPEACHMSK1_NAKM_Msk // NAK interrupt mask #define DIEPEACHMSK1_NAKM DIEPEACHMSK1_NAKM_Msk // NAK interrupt mask
/******************** Bit definition for HPRT register ********************/ /******************** Bit definition for HPRT register ********************/
#define HPRT_PCSTS_Pos (0U) #define HPRT_CONN_STATUS_Pos (0U)
#define HPRT_PCSTS_Msk (0x1UL << HPRT_PCSTS_Pos) // 0x00000001 #define HPRT_CONN_STATUS_Msk (0x1UL << HPRT_CONN_STATUS_Pos) // 0x00000001
#define HPRT_PCSTS HPRT_PCSTS_Msk // Port connect status #define HPRT_CONN_STATUS HPRT_CONN_STATUS_Msk // Port connect status
#define HPRT_PCDET_Pos (1U) #define HPRT_CONN_DETECTEDT_Pos (1U)
#define HPRT_PCDET_Msk (0x1UL << HPRT_PCDET_Pos) // 0x00000002 #define HPRT_CONN_DETECTEDT_Msk (0x1UL << HPRT_CONN_DETECTEDT_Pos) // 0x00000002
#define HPRT_PCDET HPRT_PCDET_Msk // Port connect detected #define HPRT_CONN_DETECTEDT HPRT_CONN_DETECTEDT_Msk // Port connect detected
#define HPRT_PENA_Pos (2U) #define HPRT_ENABLE_Pos (2U)
#define HPRT_PENA_Msk (0x1UL << HPRT_PENA_Pos) // 0x00000004 #define HPRT_ENABLE_Msk (0x1UL << HPRT_ENABLE_Pos) // 0x00000004
#define HPRT_PENA HPRT_PENA_Msk // Port enable #define HPRT_ENABLE HPRT_ENABLE_Msk // Port enable
#define HPRT_PENCHNG_Pos (3U) #define HPRT_EN_CHANGE_Pos (3U)
#define HPRT_PENCHNG_Msk (0x1UL << HPRT_PENCHNG_Pos) // 0x00000008 #define HPRT_EN_CHANGE_Msk (0x1UL << HPRT_EN_CHANGE_Pos) // 0x00000008
#define HPRT_PENCHNG HPRT_PENCHNG_Msk // Port enable/disable change #define HPRT_EN_CHANGE HPRT_EN_CHANGE_Msk // Port enable/disable change
#define HPRT_POCA_Pos (4U) #define HPRT_OVER_CURRENT_ACTIVE_Pos (4U)
#define HPRT_POCA_Msk (0x1UL << HPRT_POCA_Pos) // 0x00000010 #define HPRT_OVER_CURRENT_ACTIVE_Msk (0x1UL << HPRT_OVER_CURRENT_ACTIVE_Pos) // 0x00000010
#define HPRT_POCA HPRT_POCA_Msk // Port overcurrent active #define HPRT_OVER_CURRENT_ACTIVE HPRT_OVER_CURRENT_ACTIVE_Msk // Port overcurrent active
#define HPRT_POCCHNG_Pos (5U) #define HPRT_OVER_CURRENT_CHANGE_Pos (5U)
#define HPRT_POCCHNG_Msk (0x1UL << HPRT_POCCHNG_Pos) // 0x00000020 #define HPRT_OVER_CURRENT_CHANGE_Msk (0x1UL << HPRT_OVER_CURRENT_CHANGE_Pos) // 0x00000020
#define HPRT_POCCHNG HPRT_POCCHNG_Msk // Port overcurrent change #define HPRT_OVER_CURRENT_CHANGE HPRT_OVER_CURRENT_CHANGE_Msk // Port overcurrent change
#define HPRT_PRES_Pos (6U) #define HPRT_RESUME_Pos (6U)
#define HPRT_PRES_Msk (0x1UL << HPRT_PRES_Pos) // 0x00000040 #define HPRT_RESUME_Msk (0x1UL << HPRT_RESUME_Pos) // 0x00000040
#define HPRT_PRES HPRT_PRES_Msk // Port resume #define HPRT_RESUME HPRT_RESUME_Msk // Port resume
#define HPRT_PSUSP_Pos (7U) #define HPRT_SUSPEND_Pos (7U)
#define HPRT_PSUSP_Msk (0x1UL << HPRT_PSUSP_Pos) // 0x00000080 #define HPRT_SUSPEND_Msk (0x1UL << HPRT_SUSPEND_Pos) // 0x00000080
#define HPRT_PSUSP HPRT_PSUSP_Msk // Port suspend #define HPRT_SUSPEND HPRT_SUSPEND_Msk // Port suspend
#define HPRT_PRST_Pos (8U) #define HPRT_RESET_Pos (8U)
#define HPRT_PRST_Msk (0x1UL << HPRT_PRST_Pos) // 0x00000100 #define HPRT_RESET_Msk (0x1UL << HPRT_RESET_Pos) // 0x00000100
#define HPRT_PRST HPRT_PRST_Msk // Port reset #define HPRT_RESET HPRT_RESET_Msk // Port reset
#define HPRT_LINE_STATUS_Pos (10U)
#define HPRT_PLSTS_Pos (10U) #define HPRT_LINE_STATUS_Msk (0x3UL << HPRT_LINE_STATUS_Pos) // 0x00000C00
#define HPRT_PLSTS_Msk (0x3UL << HPRT_PLSTS_Pos) // 0x00000C00 #define HPRT_LINE_STATUS HPRT_LINE_STATUS_Msk // Port line status
#define HPRT_PLSTS HPRT_PLSTS_Msk // Port line status #define HPRT_LINE_STATUS_0 (0x1UL << HPRT_LINE_STATUS_Pos) // 0x00000400
#define HPRT_PLSTS_0 (0x1UL << HPRT_PLSTS_Pos) // 0x00000400 #define HPRT_LINE_STATUS_1 (0x2UL << HPRT_LINE_STATUS_Pos) // 0x00000800
#define HPRT_PLSTS_1 (0x2UL << HPRT_PLSTS_Pos) // 0x00000800 #define HPRT_POWER_Pos (12U)
#define HPRT_PPWR_Pos (12U) #define HPRT_POWER_Msk (0x1UL << HPRT_POWER_Pos) // 0x00001000
#define HPRT_PPWR_Msk (0x1UL << HPRT_PPWR_Pos) // 0x00001000 #define HPRT_POWER HPRT_POWER_Msk // Port power
#define HPRT_PPWR HPRT_PPWR_Msk // Port power #define HPRT_TEST_CONTROL_Pos (13U)
#define HPRT_TEST_CONTROL_Msk (0xFUL << HPRT_TEST_CONTROL_Pos) // 0x0001E000
#define HPRT_PTCTL_Pos (13U) #define HPRT_TEST_CONTROL HPRT_TEST_CONTROL_Msk // Port test control
#define HPRT_PTCTL_Msk (0xFUL << HPRT_PTCTL_Pos) // 0x0001E000 #define HPRT_TEST_CONTROL_0 (0x1UL << HPRT_TEST_CONTROL_Pos) // 0x00002000
#define HPRT_PTCTL HPRT_PTCTL_Msk // Port test control #define HPRT_TEST_CONTROL_1 (0x2UL << HPRT_TEST_CONTROL_Pos) // 0x00004000
#define HPRT_PTCTL_0 (0x1UL << HPRT_PTCTL_Pos) // 0x00002000 #define HPRT_TEST_CONTROL_2 (0x4UL << HPRT_TEST_CONTROL_Pos) // 0x00008000
#define HPRT_PTCTL_1 (0x2UL << HPRT_PTCTL_Pos) // 0x00004000 #define HPRT_TEST_CONTROL_3 (0x8UL << HPRT_TEST_CONTROL_Pos) // 0x00010000
#define HPRT_PTCTL_2 (0x4UL << HPRT_PTCTL_Pos) // 0x00008000 #define HPRT_SPEED_Pos (17U)
#define HPRT_PTCTL_3 (0x8UL << HPRT_PTCTL_Pos) // 0x00010000 #define HPRT_SPEED_Msk (0x3UL << HPRT_SPEED_Pos) // 0x00060000
#define HPRT_SPEED HPRT_SPEED_Msk // Port speed
#define HPRT_PSPD_Pos (17U) #define HPRT_SPEED_0 (0x1UL << HPRT_SPEED_Pos) // 0x00020000
#define HPRT_PSPD_Msk (0x3UL << HPRT_PSPD_Pos) // 0x00060000 #define HPRT_SPEED_1 (0x2UL << HPRT_SPEED_Pos) // 0x00040000
#define HPRT_PSPD HPRT_PSPD_Msk // Port speed
#define HPRT_PSPD_0 (0x1UL << HPRT_PSPD_Pos) // 0x00020000
#define HPRT_PSPD_1 (0x2UL << HPRT_PSPD_Pos) // 0x00040000
/******************** Bit definition for DOEPEACHMSK1 register ********************/ /******************** Bit definition for DOEPEACHMSK1 register ********************/
#define DOEPEACHMSK1_XFRCM_Pos (0U) #define DOEPEACHMSK1_XFRCM_Pos (0U)

View File

@@ -49,15 +49,29 @@ bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) {
// Initialize controller to host mode // Initialize controller to host mode
bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
(void) rhport; dwc2_regs_t* dwc2 = DWC2_REG(rhport);
(void) rh_init;
return false;
}
// Interrupt Handler // Core Initialization
void hcd_int_handler(uint8_t rhport, bool in_isr) { TU_ASSERT(dwc2_core_init(rhport, rh_init));
(void) rhport;
(void) in_isr; // force host mode
dwc2->gusbcfg = (dwc2->gusbcfg & ~GUSBCFG_FDMOD) | GUSBCFG_FHMOD;
//------------- 3.1 Host Initialization -------------//
// Enable required interrupts
dwc2->gintmsk |= GINTMSK_OTGINT | GINTMSK_PRTIM | GINTMSK_WUIM;
// max speed
if (dwc2_core_is_highspeed(dwc2, rh_init)) {
dwc2->hcfg &= ~HCFG_FSLSS;
} else {
dwc2->hcfg |= HCFG_FSLSS;
}
// port power on -> drive VBUS
dwc2->hprt = HPRT_POWER;
return true;
} }
// Enable USB interrupt // Enable USB interrupt
@@ -164,4 +178,38 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
return false; return false;
} }
//--------------------------------------------------------------------
// HCD Event Handler
//--------------------------------------------------------------------
/* Interrupt Hierarchy
HCINTn.XferCompl HCINTMSKn.XferComplMsk
| |
+---------- AND --------+
|
HAINT.CHn HAINTMSK.CHn
| |
+---------- AND --------+
|
GINTSTS.PrtInt GINTMSK.PrtInt
| |
+---------- AND --------+
|
GAHBCFG.GblIntrMsk
|
IRQn
*/
void hcd_int_handler(uint8_t rhport, bool in_isr) {
(void) in_isr;
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
const uint32_t int_mask = dwc2->gintmsk;
const uint32_t int_status = dwc2->gintsts & int_mask;
if (int_status & GINTSTS_HPRTINT) {
TU_LOG1_HEX(dwc2->hprt);
}
}
#endif #endif

View File

@@ -254,6 +254,10 @@
#define CFG_TUD_DWC2_DMA 0 #define CFG_TUD_DWC2_DMA 0
#endif #endif
#ifndef CFG_TUH_DWC2_DMA
#define CFG_TUH_DWC2_DMA 0
#endif
// Enable PIO-USB software host controller // Enable PIO-USB software host controller
#ifndef CFG_TUH_RPI_PIO_USB #ifndef CFG_TUH_RPI_PIO_USB
#define CFG_TUH_RPI_PIO_USB 0 #define CFG_TUH_RPI_PIO_USB 0