move gahbcfg/gintmsk with dma to dwc2 common
This commit is contained in:
@@ -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 --------+
|
||||||
|
|
|
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
@@ -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)
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
Reference in New Issue
Block a user