move gahbcfg/gintmsk with dma to dwc2 common
This commit is contained in:
@@ -68,22 +68,6 @@ static bool _sof_en;
|
||||
// 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) {
|
||||
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
|
||||
|
||||
@@ -103,16 +87,6 @@ static void dma_setup_prepare(uint8_t rhport) {
|
||||
// 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
|
||||
|
||||
@@ -215,7 +189,7 @@ static void dfifo_init(uint8_t rhport) {
|
||||
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
|
||||
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
|
||||
_dfifo_top = dma_cal_epfifo_base(rhport);
|
||||
}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_IN].max_size = 64;
|
||||
|
||||
if(dma_enabled(dwc2)) {
|
||||
if(dwc2_dma_enabled(dwc2, TUSB_ROLE_DEVICE)) {
|
||||
dma_setup_prepare(rhport);
|
||||
} else {
|
||||
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) |
|
||||
((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;
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
if(dma_enabled(dwc2)) {
|
||||
if(dwc2_dma_enabled(dwc2, TUSB_ROLE_DEVICE)) {
|
||||
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
|
||||
//--------------------------------------------------------------------
|
||||
bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
|
||||
(void) rh_init;
|
||||
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
|
||||
|
||||
// Core Initialization
|
||||
TU_ASSERT(dwc2_core_init(rhport, rh_init));
|
||||
|
||||
// Device Initialization
|
||||
@@ -500,9 +474,6 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
|
||||
}
|
||||
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
|
||||
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
|
||||
dwc2->dcfg |= DCFG_NZLSOHSK;
|
||||
|
||||
dfifo_flush_tx(dwc2, 0x10); // all tx fifo
|
||||
dfifo_flush_rx(dwc2);
|
||||
|
||||
// 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;
|
||||
// Enable required interrupts
|
||||
dwc2->gintmsk |= GINTMSK_OTGINT | GINTMSK_USBSUSPM | GINTMSK_USBRST | GINTMSK_ENUMDNEM | GINTMSK_WUIM;
|
||||
|
||||
// Configure TX FIFO empty level for interrupt. Default is complete empty
|
||||
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);
|
||||
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -866,7 +806,7 @@ static void handle_epout_irq(uint8_t rhport) {
|
||||
if (doepint & DOEPINT_SETUP) {
|
||||
epout->doepint = DOEPINT_SETUP;
|
||||
|
||||
if(dma_enabled(dwc2)) {
|
||||
if(dwc2_dma_enabled(dwc2, TUSB_ROLE_DEVICE)) {
|
||||
dma_setup_prepare(rhport);
|
||||
}
|
||||
|
||||
@@ -882,7 +822,7 @@ static void handle_epout_irq(uint8_t rhport) {
|
||||
if (!(doepint & (DOEPINT_SETUP | DOEPINT_STPKTRX | DOEPINT_STSPHSRX))) {
|
||||
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]) {
|
||||
// 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]);
|
||||
@@ -932,7 +872,7 @@ static void handle_epin_irq(uint8_t rhport) {
|
||||
// Schedule another packet to be transmitted.
|
||||
edpt_schedule_packets(rhport, n, TUSB_DIR_IN, 1, ep0_pending[TUSB_DIR_IN]);
|
||||
} else {
|
||||
if((n == 0) && dma_enabled(dwc2)) {
|
||||
if((n == 0) && dwc2_dma_enabled(dwc2, TUSB_ROLE_DEVICE)) {
|
||||
dma_setup_prepare(rhport);
|
||||
}
|
||||
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
|
||||
|
||||
DxEPMSK.XferComplMsk DxEPINTn.XferCompl
|
||||
DxEPINTn.XferCompl DxEPMSK.XferComplMsk
|
||||
| |
|
||||
+---------- AND --------+
|
||||
|
|
||||
|
@@ -63,7 +63,7 @@ bool dwc2_core_is_highspeed(dwc2_regs_t* dwc2, const tusb_rhport_init_t* rh_init
|
||||
}
|
||||
#endif
|
||||
#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;
|
||||
}
|
||||
#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
|
||||
* introduced by the PHY. This can be required, because the delay
|
||||
* 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);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
@@ -57,6 +57,8 @@ enum {
|
||||
DWC2_CONTROLLER_COUNT = TU_ARRAY_SIZE(_dwc2_controller)
|
||||
};
|
||||
|
||||
|
||||
//------------- Core -------------//
|
||||
TU_ATTR_ALWAYS_INLINE static inline dwc2_regs_t* DWC2_REG(uint8_t rhport) {
|
||||
if (rhport >= DWC2_CONTROLLER_COUNT) {
|
||||
// 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_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
|
||||
|
@@ -122,6 +122,12 @@ enum {
|
||||
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
|
||||
//--------------------------------------------------------------------
|
||||
@@ -301,6 +307,24 @@ typedef struct TU_ATTR_PACKED {
|
||||
}dwc2_ghwcfg4_t;
|
||||
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
|
||||
typedef struct {
|
||||
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
|
||||
|
||||
/******************** Bit definition for HPRT register ********************/
|
||||
#define HPRT_PCSTS_Pos (0U)
|
||||
#define HPRT_PCSTS_Msk (0x1UL << HPRT_PCSTS_Pos) // 0x00000001
|
||||
#define HPRT_PCSTS HPRT_PCSTS_Msk // Port connect status
|
||||
#define HPRT_PCDET_Pos (1U)
|
||||
#define HPRT_PCDET_Msk (0x1UL << HPRT_PCDET_Pos) // 0x00000002
|
||||
#define HPRT_PCDET HPRT_PCDET_Msk // Port connect detected
|
||||
#define HPRT_PENA_Pos (2U)
|
||||
#define HPRT_PENA_Msk (0x1UL << HPRT_PENA_Pos) // 0x00000004
|
||||
#define HPRT_PENA HPRT_PENA_Msk // Port enable
|
||||
#define HPRT_PENCHNG_Pos (3U)
|
||||
#define HPRT_PENCHNG_Msk (0x1UL << HPRT_PENCHNG_Pos) // 0x00000008
|
||||
#define HPRT_PENCHNG HPRT_PENCHNG_Msk // Port enable/disable change
|
||||
#define HPRT_POCA_Pos (4U)
|
||||
#define HPRT_POCA_Msk (0x1UL << HPRT_POCA_Pos) // 0x00000010
|
||||
#define HPRT_POCA HPRT_POCA_Msk // Port overcurrent active
|
||||
#define HPRT_POCCHNG_Pos (5U)
|
||||
#define HPRT_POCCHNG_Msk (0x1UL << HPRT_POCCHNG_Pos) // 0x00000020
|
||||
#define HPRT_POCCHNG HPRT_POCCHNG_Msk // Port overcurrent change
|
||||
#define HPRT_PRES_Pos (6U)
|
||||
#define HPRT_PRES_Msk (0x1UL << HPRT_PRES_Pos) // 0x00000040
|
||||
#define HPRT_PRES HPRT_PRES_Msk // Port resume
|
||||
#define HPRT_PSUSP_Pos (7U)
|
||||
#define HPRT_PSUSP_Msk (0x1UL << HPRT_PSUSP_Pos) // 0x00000080
|
||||
#define HPRT_PSUSP HPRT_PSUSP_Msk // Port suspend
|
||||
#define HPRT_PRST_Pos (8U)
|
||||
#define HPRT_PRST_Msk (0x1UL << HPRT_PRST_Pos) // 0x00000100
|
||||
#define HPRT_PRST HPRT_PRST_Msk // Port reset
|
||||
|
||||
#define HPRT_PLSTS_Pos (10U)
|
||||
#define HPRT_PLSTS_Msk (0x3UL << HPRT_PLSTS_Pos) // 0x00000C00
|
||||
#define HPRT_PLSTS HPRT_PLSTS_Msk // Port line status
|
||||
#define HPRT_PLSTS_0 (0x1UL << HPRT_PLSTS_Pos) // 0x00000400
|
||||
#define HPRT_PLSTS_1 (0x2UL << HPRT_PLSTS_Pos) // 0x00000800
|
||||
#define HPRT_PPWR_Pos (12U)
|
||||
#define HPRT_PPWR_Msk (0x1UL << HPRT_PPWR_Pos) // 0x00001000
|
||||
#define HPRT_PPWR HPRT_PPWR_Msk // Port power
|
||||
|
||||
#define HPRT_PTCTL_Pos (13U)
|
||||
#define HPRT_PTCTL_Msk (0xFUL << HPRT_PTCTL_Pos) // 0x0001E000
|
||||
#define HPRT_PTCTL HPRT_PTCTL_Msk // Port test control
|
||||
#define HPRT_PTCTL_0 (0x1UL << HPRT_PTCTL_Pos) // 0x00002000
|
||||
#define HPRT_PTCTL_1 (0x2UL << HPRT_PTCTL_Pos) // 0x00004000
|
||||
#define HPRT_PTCTL_2 (0x4UL << HPRT_PTCTL_Pos) // 0x00008000
|
||||
#define HPRT_PTCTL_3 (0x8UL << HPRT_PTCTL_Pos) // 0x00010000
|
||||
|
||||
#define HPRT_PSPD_Pos (17U)
|
||||
#define HPRT_PSPD_Msk (0x3UL << HPRT_PSPD_Pos) // 0x00060000
|
||||
#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
|
||||
#define HPRT_CONN_STATUS_Pos (0U)
|
||||
#define HPRT_CONN_STATUS_Msk (0x1UL << HPRT_CONN_STATUS_Pos) // 0x00000001
|
||||
#define HPRT_CONN_STATUS HPRT_CONN_STATUS_Msk // Port connect status
|
||||
#define HPRT_CONN_DETECTEDT_Pos (1U)
|
||||
#define HPRT_CONN_DETECTEDT_Msk (0x1UL << HPRT_CONN_DETECTEDT_Pos) // 0x00000002
|
||||
#define HPRT_CONN_DETECTEDT HPRT_CONN_DETECTEDT_Msk // Port connect detected
|
||||
#define HPRT_ENABLE_Pos (2U)
|
||||
#define HPRT_ENABLE_Msk (0x1UL << HPRT_ENABLE_Pos) // 0x00000004
|
||||
#define HPRT_ENABLE HPRT_ENABLE_Msk // Port enable
|
||||
#define HPRT_EN_CHANGE_Pos (3U)
|
||||
#define HPRT_EN_CHANGE_Msk (0x1UL << HPRT_EN_CHANGE_Pos) // 0x00000008
|
||||
#define HPRT_EN_CHANGE HPRT_EN_CHANGE_Msk // Port enable/disable change
|
||||
#define HPRT_OVER_CURRENT_ACTIVE_Pos (4U)
|
||||
#define HPRT_OVER_CURRENT_ACTIVE_Msk (0x1UL << HPRT_OVER_CURRENT_ACTIVE_Pos) // 0x00000010
|
||||
#define HPRT_OVER_CURRENT_ACTIVE HPRT_OVER_CURRENT_ACTIVE_Msk // Port overcurrent active
|
||||
#define HPRT_OVER_CURRENT_CHANGE_Pos (5U)
|
||||
#define HPRT_OVER_CURRENT_CHANGE_Msk (0x1UL << HPRT_OVER_CURRENT_CHANGE_Pos) // 0x00000020
|
||||
#define HPRT_OVER_CURRENT_CHANGE HPRT_OVER_CURRENT_CHANGE_Msk // Port overcurrent change
|
||||
#define HPRT_RESUME_Pos (6U)
|
||||
#define HPRT_RESUME_Msk (0x1UL << HPRT_RESUME_Pos) // 0x00000040
|
||||
#define HPRT_RESUME HPRT_RESUME_Msk // Port resume
|
||||
#define HPRT_SUSPEND_Pos (7U)
|
||||
#define HPRT_SUSPEND_Msk (0x1UL << HPRT_SUSPEND_Pos) // 0x00000080
|
||||
#define HPRT_SUSPEND HPRT_SUSPEND_Msk // Port suspend
|
||||
#define HPRT_RESET_Pos (8U)
|
||||
#define HPRT_RESET_Msk (0x1UL << HPRT_RESET_Pos) // 0x00000100
|
||||
#define HPRT_RESET HPRT_RESET_Msk // Port reset
|
||||
#define HPRT_LINE_STATUS_Pos (10U)
|
||||
#define HPRT_LINE_STATUS_Msk (0x3UL << HPRT_LINE_STATUS_Pos) // 0x00000C00
|
||||
#define HPRT_LINE_STATUS HPRT_LINE_STATUS_Msk // Port line status
|
||||
#define HPRT_LINE_STATUS_0 (0x1UL << HPRT_LINE_STATUS_Pos) // 0x00000400
|
||||
#define HPRT_LINE_STATUS_1 (0x2UL << HPRT_LINE_STATUS_Pos) // 0x00000800
|
||||
#define HPRT_POWER_Pos (12U)
|
||||
#define HPRT_POWER_Msk (0x1UL << HPRT_POWER_Pos) // 0x00001000
|
||||
#define HPRT_POWER HPRT_POWER_Msk // Port power
|
||||
#define HPRT_TEST_CONTROL_Pos (13U)
|
||||
#define HPRT_TEST_CONTROL_Msk (0xFUL << HPRT_TEST_CONTROL_Pos) // 0x0001E000
|
||||
#define HPRT_TEST_CONTROL HPRT_TEST_CONTROL_Msk // Port test control
|
||||
#define HPRT_TEST_CONTROL_0 (0x1UL << HPRT_TEST_CONTROL_Pos) // 0x00002000
|
||||
#define HPRT_TEST_CONTROL_1 (0x2UL << HPRT_TEST_CONTROL_Pos) // 0x00004000
|
||||
#define HPRT_TEST_CONTROL_2 (0x4UL << HPRT_TEST_CONTROL_Pos) // 0x00008000
|
||||
#define HPRT_TEST_CONTROL_3 (0x8UL << HPRT_TEST_CONTROL_Pos) // 0x00010000
|
||||
#define HPRT_SPEED_Pos (17U)
|
||||
#define HPRT_SPEED_Msk (0x3UL << HPRT_SPEED_Pos) // 0x00060000
|
||||
#define HPRT_SPEED HPRT_SPEED_Msk // Port speed
|
||||
#define HPRT_SPEED_0 (0x1UL << HPRT_SPEED_Pos) // 0x00020000
|
||||
#define HPRT_SPEED_1 (0x2UL << HPRT_SPEED_Pos) // 0x00040000
|
||||
|
||||
/******************** Bit definition for DOEPEACHMSK1 register ********************/
|
||||
#define DOEPEACHMSK1_XFRCM_Pos (0U)
|
||||
|
@@ -49,15 +49,29 @@ bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) {
|
||||
|
||||
// Initialize controller to host mode
|
||||
bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
|
||||
(void) rhport;
|
||||
(void) rh_init;
|
||||
return false;
|
||||
}
|
||||
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
|
||||
|
||||
// Interrupt Handler
|
||||
void hcd_int_handler(uint8_t rhport, bool in_isr) {
|
||||
(void) rhport;
|
||||
(void) in_isr;
|
||||
// Core Initialization
|
||||
TU_ASSERT(dwc2_core_init(rhport, rh_init));
|
||||
|
||||
// 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
|
||||
@@ -164,4 +178,38 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
|
||||
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
|
||||
|
@@ -254,6 +254,10 @@
|
||||
#define CFG_TUD_DWC2_DMA 0
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUH_DWC2_DMA
|
||||
#define CFG_TUH_DWC2_DMA 0
|
||||
#endif
|
||||
|
||||
// Enable PIO-USB software host controller
|
||||
#ifndef CFG_TUH_RPI_PIO_USB
|
||||
#define CFG_TUH_RPI_PIO_USB 0
|
||||
|
Reference in New Issue
Block a user