refactor(port/dwc2): support custom config for each dwc2 usb port

Signed-off-by: sakumisu <1203593632@qq.com>
This commit is contained in:
sakumisu
2025-07-03 20:55:44 +08:00
parent 8e0ff856fe
commit 22e150a8e6
9 changed files with 1381 additions and 514 deletions

View File

@@ -5,6 +5,7 @@
*/
#include "usbd_core.h"
#include "usb_dwc2_reg.h"
#include "usb_dwc2_param.h"
// clang-format off
#if defined ( __CC_ARM )
@@ -51,46 +52,6 @@
#endif
// clang-format on
#ifndef CONFIG_USB_DWC2_RXALL_FIFO_SIZE
#define CONFIG_USB_DWC2_RXALL_FIFO_SIZE (1024 / 4)
#endif
#ifndef CONFIG_USB_DWC2_TX0_FIFO_SIZE
#define CONFIG_USB_DWC2_TX0_FIFO_SIZE (64 / 4)
#endif
#ifndef CONFIG_USB_DWC2_TX1_FIFO_SIZE
#define CONFIG_USB_DWC2_TX1_FIFO_SIZE (1024 / 4)
#endif
#ifndef CONFIG_USB_DWC2_TX2_FIFO_SIZE
#define CONFIG_USB_DWC2_TX2_FIFO_SIZE (64 / 4)
#endif
#ifndef CONFIG_USB_DWC2_TX3_FIFO_SIZE
#define CONFIG_USB_DWC2_TX3_FIFO_SIZE (64 / 4)
#endif
#ifndef CONFIG_USB_DWC2_TX4_FIFO_SIZE
#define CONFIG_USB_DWC2_TX4_FIFO_SIZE (64 / 4)
#endif
#ifndef CONFIG_USB_DWC2_TX5_FIFO_SIZE
#define CONFIG_USB_DWC2_TX5_FIFO_SIZE (64 / 4)
#endif
#ifndef CONFIG_USB_DWC2_TX6_FIFO_SIZE
#define CONFIG_USB_DWC2_TX6_FIFO_SIZE (0 / 4)
#endif
#ifndef CONFIG_USB_DWC2_TX7_FIFO_SIZE
#define CONFIG_USB_DWC2_TX7_FIFO_SIZE (0 / 4)
#endif
#ifndef CONFIG_USB_DWC2_TX8_FIFO_SIZE
#define CONFIG_USB_DWC2_TX8_FIFO_SIZE (0 / 4)
#endif
#define USBD_BASE (g_usbdev_bus[busid].reg_base)
#define USB_OTG_GLB ((DWC2_GlobalTypeDef *)(USBD_BASE))
@@ -115,9 +76,11 @@ struct dwc2_ep_state {
/* Driver state */
USB_NOCACHE_RAM_SECTION struct dwc2_udc {
USB_MEM_ALIGNX struct usb_setup_packet setup;
USB_MEM_ALIGNX uint32_t GSNPSID;
struct dwc2_ep_state in_ep[CONFIG_USBDEV_EP_NUM]; /*!< IN endpoint parameters*/
struct dwc2_ep_state out_ep[CONFIG_USBDEV_EP_NUM]; /*!< OUT endpoint parameters */
uint8_t pad[24]; /* Pad to 32 bytes */
struct dwc2_hw_params hw_params;
struct dwc2_user_params user_params;
struct dwc2_ep_state in_ep[16]; /*!< IN endpoint parameters*/
struct dwc2_ep_state out_ep[16]; /*!< OUT endpoint parameters */
} g_dwc2_udc[CONFIG_USBDEV_MAX_BUS];
static inline int dwc2_reset(uint8_t busid)
@@ -135,7 +98,7 @@ static inline int dwc2_reset(uint8_t busid)
count = 0U;
USB_OTG_GLB->GRSTCTL |= USB_OTG_GRSTCTL_CSRST;
if (g_dwc2_udc[busid].GSNPSID < 0x4F54420AU) {
if (g_dwc2_udc[busid].hw_params.snpsid < 0x4F54420AU) {
do {
if (++count > 200000U) {
USB_LOG_ERR("DWC2 reset timeout\r\n");
@@ -160,22 +123,42 @@ static inline int dwc2_reset(uint8_t busid)
static inline int dwc2_core_init(uint8_t busid)
{
int ret;
#if defined(CONFIG_USB_HS)
/* Init The ULPI Interface */
USB_OTG_GLB->GUSBCFG &= ~(USB_OTG_GUSBCFG_TSDPS | USB_OTG_GUSBCFG_ULPIFSLS | USB_OTG_GUSBCFG_PHYSEL);
uint32_t regval;
/* Select vbus source */
USB_OTG_GLB->GUSBCFG &= ~(USB_OTG_GUSBCFG_ULPIEVBUSD | USB_OTG_GUSBCFG_ULPIEVBUSI);
if (g_dwc2_udc[busid].user_params.phy_type == DWC2_PHY_TYPE_PARAM_FS) {
/* Select FS Embedded PHY */
USB_OTG_GLB->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL;
} else {
regval = USB_OTG_GLB->GUSBCFG;
regval &= ~USB_OTG_GUSBCFG_PHYSEL;
/* disable external vbus source */
regval &= ~(USB_OTG_GUSBCFG_ULPIEVBUSD | USB_OTG_GUSBCFG_ULPIEVBUSI);
/* disable ULPI FS/LS */
regval &= ~(USB_OTG_GUSBCFG_ULPIFSLS | USB_OTG_GUSBCFG_ULPICSM);
switch (g_dwc2_udc[busid].user_params.phy_type) {
case DWC2_PHY_TYPE_PARAM_ULPI:
regval |= USB_OTG_GUSBCFG_ULPI_UTMI_SEL;
regval &= ~USB_OTG_GUSBCFG_PHYIF16;
regval &= ~USB_OTG_GUSBCFG_DDR_SEL;
if (g_dwc2_udc[busid].user_params.phy_utmi_width == 16) {
regval |= USB_OTG_GUSBCFG_PHYIF16;
}
break;
case DWC2_PHY_TYPE_PARAM_UTMI:
regval &= ~USB_OTG_GUSBCFG_ULPI_UTMI_SEL;
regval &= ~USB_OTG_GUSBCFG_PHYIF16;
break;
default:
break;
}
USB_OTG_GLB->GUSBCFG = regval;
}
/* Reset after a PHY select */
ret = dwc2_reset(busid);
#else
/* Select FS Embedded PHY */
USB_OTG_GLB->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL;
/* Reset after a PHY select */
ret = dwc2_reset(busid);
#endif
return ret;
}
@@ -285,8 +268,6 @@ static void dwc2_set_turnaroundtime(uint8_t busid, uint32_t hclk, uint8_t speed)
UsbTrd = USBD_DEFAULT_TRDT_VALUE;
}
USB_OTG_GLB->GUSBCFG |= USB_OTG_GUSBCFG_TOCAL;
USB_OTG_GLB->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT;
USB_OTG_GLB->GUSBCFG |= (uint32_t)((UsbTrd << USB_OTG_GUSBCFG_TRDT_Pos) & USB_OTG_GUSBCFG_TRDT);
}
@@ -347,11 +328,11 @@ static void dwc2_ep0_start_read_setup(uint8_t busid, uint8_t *psetup)
USB_OTG_OUTEP(0U)->DOEPTSIZ |= (3U * 8U);
USB_OTG_OUTEP(0U)->DOEPTSIZ |= USB_OTG_DOEPTSIZ_STUPCNT;
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
USB_OTG_OUTEP(0U)->DOEPDMA = (uint32_t)psetup;
/* EP enable */
USB_OTG_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_USBAEP;
#endif
if (g_dwc2_udc[busid].user_params.device_dma_enable) {
USB_OTG_OUTEP(0U)->DOEPDMA = (uint32_t)psetup;
/* EP enable */
USB_OTG_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_USBAEP;
}
}
void dwc2_ep_write(uint8_t busid, uint8_t ep_idx, uint8_t *src, uint16_t len)
@@ -504,41 +485,13 @@ static inline uint32_t dwc2_get_inep_intstatus(uint8_t busid, uint8_t epnum)
int usb_dc_init(uint8_t busid)
{
int ret;
uint8_t fsphy_type;
uint8_t hsphy_type;
uint8_t dma_support;
uint8_t endpoints;
uint32_t fifo_num;
memset(&g_dwc2_udc[busid], 0, sizeof(struct dwc2_udc));
usb_dc_low_level_init(busid);
/*
Full-Speed PHY Interface Type (FSPhyType)
2'b00: Full-speed interface not supported
2'b01: Dedicated full-speed interface
2'b10: FS pins shared with UTMI+ pins
2'b11: FS pins shared with ULPI pins
High-Speed PHY Interface Type (HSPhyType)
2'b00: High-Speed interface not supported
2'b01: UTMI+
2'b10: ULPI
2'b11: UTMI+ and ULPI
Architecture (OtgArch)
2'b00: Slave-Only
2'b01: External DMA
2'b10: Internal DMA
Others: Reserved
*/
fsphy_type = ((USB_OTG_GLB->GHWCFG2 & (0x03 << 8)) >> 8);
hsphy_type = ((USB_OTG_GLB->GHWCFG2 & (0x03 << 6)) >> 6);
dma_support = ((USB_OTG_GLB->GHWCFG2 & (0x03 << 3)) >> 3);
endpoints = ((USB_OTG_GLB->GHWCFG2 & (0x0f << 10)) >> 10) + 1;
USB_LOG_INFO("========== dwc2 udc params ==========\r\n");
USB_LOG_INFO("========== dwc2 dcd params ==========\r\n");
USB_LOG_INFO("CID:%08x\r\n", (unsigned int)USB_OTG_GLB->CID);
USB_LOG_INFO("GSNPSID:%08x\r\n", (unsigned int)USB_OTG_GLB->GSNPSID);
USB_LOG_INFO("GHWCFG1:%08x\r\n", (unsigned int)USB_OTG_GLB->GHWCFG1);
@@ -546,26 +499,40 @@ int usb_dc_init(uint8_t busid)
USB_LOG_INFO("GHWCFG3:%08x\r\n", (unsigned int)USB_OTG_GLB->GHWCFG3);
USB_LOG_INFO("GHWCFG4:%08x\r\n", (unsigned int)USB_OTG_GLB->GHWCFG4);
USB_LOG_INFO("dwc2 fsphy type:%d, hsphy type:%d, dma support:%d\r\n", fsphy_type, hsphy_type, dma_support);
USB_LOG_INFO("dwc2 has %d endpoints and dfifo depth(32-bit words) is %d, default config: %d endpoints\r\n", endpoints, (USB_OTG_GLB->GHWCFG3 >> 16), CONFIG_USBDEV_EP_NUM);
USB_LOG_INFO("=================================\r\n");
dwc2_get_hwparams(USBD_BASE, &g_dwc2_udc[busid].hw_params);
dwc2_get_user_params(USBD_BASE, &g_dwc2_udc[busid].user_params);
USB_ASSERT_MSG(endpoints >= CONFIG_USBDEV_EP_NUM, "dwc2 has less endpoints than config, please check");
if (g_dwc2_udc[busid].user_params.phy_utmi_width == 0) {
g_dwc2_udc[busid].user_params.phy_utmi_width = 8;
}
if (g_dwc2_udc[busid].user_params.total_fifo_size == 0) {
g_dwc2_udc[busid].user_params.total_fifo_size = g_dwc2_udc[busid].hw_params.total_fifo_size;
}
g_dwc2_udc[busid].GSNPSID = USB_OTG_GLB->GSNPSID;
USB_OTG_DEV->DCTL |= USB_OTG_DCTL_SDIS;
USB_LOG_INFO("dwc2 has %d endpoints and dfifo depth(32-bit words) is %d\r\n",
g_dwc2_udc[busid].hw_params.num_dev_ep + 1,
g_dwc2_udc[busid].user_params.total_fifo_size);
USB_OTG_GLB->GAHBCFG &= ~USB_OTG_GAHBCFG_GINT;
USB_OTG_DEV->DCTL |= USB_OTG_DCTL_SDIS;
/* This is vendor register */
USB_OTG_GLB->GCCFG = usbd_get_dwc2_gccfg_conf(USBD_BASE);
USB_OTG_GLB->GCCFG = g_dwc2_udc[busid].user_params.device_gccfg;
ret = dwc2_core_init(busid);
/* Force Device Mode*/
dwc2_set_mode(busid, USB_OTG_MODE_DEVICE);
if (g_dwc2_udc[busid].user_params.b_session_valid_override) {
/* B-peripheral session valid override enable */
USB_OTG_GLB->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN;
USB_OTG_GLB->GOTGCTL |= USB_OTG_GOTGCTL_BVALOVAL;
}
USB_OTG_GLB->GUSBCFG |= USB_OTG_GUSBCFG_TOCAL;
for (uint8_t i = 0U; i < 15U; i++) {
USB_OTG_GLB->DIEPTXF[i] = 0U;
}
@@ -575,15 +542,17 @@ int usb_dc_init(uint8_t busid)
/* Device speed configuration */
USB_OTG_DEV->DCFG &= ~USB_OTG_DCFG_DSPD;
#if defined(CONFIG_USB_HS)
USB_OTG_DEV->DCFG |= USB_OTG_SPEED_HIGH;
#else
if (hsphy_type == 0) {
USB_OTG_DEV->DCFG |= USB_OTG_SPEED_FULL;
if (g_dwc2_udc[busid].user_params.phy_type != DWC2_PHY_TYPE_PARAM_FS) {
USB_ASSERT_MSG(g_dwc2_udc[busid].hw_params.hs_phy_type != 0, "This dwc2 version does not support hs, so stop working");
USB_OTG_DEV->DCFG |= USB_OTG_SPEED_HIGH;
} else {
USB_OTG_DEV->DCFG |= USB_OTG_SPEED_HIGH_IN_FULL;
if (g_dwc2_udc[busid].hw_params.hs_phy_type == 0) {
USB_OTG_DEV->DCFG |= USB_OTG_SPEED_FULL;
} else {
USB_OTG_DEV->DCFG |= USB_OTG_SPEED_HIGH_IN_FULL;
}
}
#endif
/* Clear all pending Device Interrupts */
USB_OTG_DEV->DIEPMSK = 0U;
@@ -600,58 +569,35 @@ int usb_dc_init(uint8_t busid)
USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT |
USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_WUIM;
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
USB_ASSERT_MSG(((USB_OTG_GLB->GHWCFG2 & (0x3U << 3)) >> 3) == 2, "This dwc2 version does not support dma mode, so stop working");
if (g_dwc2_udc[busid].user_params.device_dma_enable) {
USB_ASSERT_MSG(g_dwc2_udc[busid].hw_params.arch == GHWCFG2_INT_DMA_ARCH, "This dwc2 version does not support dma mode, so stop working");
USB_OTG_DEV->DCFG &= ~USB_OTG_DCFG_DESCDMA;
USB_OTG_GLB->GAHBCFG &= ~USB_OTG_GAHBCFG_HBSTLEN;
USB_OTG_GLB->GAHBCFG |= (USB_OTG_GAHBCFG_DMAEN | USB_OTG_GAHBCFG_HBSTLEN_4);
} else {
USB_OTG_GLB->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM;
}
USB_OTG_DEV->DCFG &= ~USB_OTG_DCFG_DESCDMA;
USB_OTG_GLB->GAHBCFG &= ~USB_OTG_GAHBCFG_HBSTLEN;
USB_OTG_GLB->GAHBCFG |= (USB_OTG_GAHBCFG_DMAEN | USB_OTG_GAHBCFG_HBSTLEN_4);
#else
USB_OTG_GLB->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM;
#endif
#if CONFIG_DWC2_VBUS_SENSING
USB_OTG_GLB->GINTMSK |= (USB_OTG_GINTMSK_OTGINT | USB_OTG_GINTMSK_SRQIM);
#endif
#ifdef CONFIG_USBDEV_SOF_ENABLE
USB_OTG_GLB->GINTMSK |= USB_OTG_GINTMSK_SOFM;
#endif
USB_OTG_GLB->GRXFSIZ = (CONFIG_USB_DWC2_RXALL_FIFO_SIZE);
USB_OTG_GLB->GRXFSIZ = g_dwc2_udc[busid].user_params.device_rx_fifo_size;
dwc2_set_txfifo(busid, 0, CONFIG_USB_DWC2_TX0_FIFO_SIZE);
dwc2_set_txfifo(busid, 1, CONFIG_USB_DWC2_TX1_FIFO_SIZE);
dwc2_set_txfifo(busid, 2, CONFIG_USB_DWC2_TX2_FIFO_SIZE);
dwc2_set_txfifo(busid, 3, CONFIG_USB_DWC2_TX3_FIFO_SIZE);
fifo_num = g_dwc2_udc[busid].user_params.device_rx_fifo_size;
for (uint8_t i = 0; i < (g_dwc2_udc[busid].hw_params.num_dev_ep + 1); i++) {
dwc2_set_txfifo(busid, i, g_dwc2_udc[busid].user_params.device_tx_fifo_size[i]);
fifo_num += g_dwc2_udc[busid].user_params.device_tx_fifo_size[i];
fifo_num = CONFIG_USB_DWC2_RXALL_FIFO_SIZE;
fifo_num += CONFIG_USB_DWC2_TX0_FIFO_SIZE;
fifo_num += CONFIG_USB_DWC2_TX1_FIFO_SIZE;
fifo_num += CONFIG_USB_DWC2_TX2_FIFO_SIZE;
fifo_num += CONFIG_USB_DWC2_TX3_FIFO_SIZE;
#if CONFIG_USBDEV_EP_NUM > 4
dwc2_set_txfifo(busid, 4, CONFIG_USB_DWC2_TX4_FIFO_SIZE);
fifo_num += CONFIG_USB_DWC2_TX4_FIFO_SIZE;
#endif
#if CONFIG_USBDEV_EP_NUM > 5
dwc2_set_txfifo(busid, 5, CONFIG_USB_DWC2_TX5_FIFO_SIZE);
fifo_num += CONFIG_USB_DWC2_TX5_FIFO_SIZE;
#endif
#if CONFIG_USBDEV_EP_NUM > 6
dwc2_set_txfifo(busid, 6, CONFIG_USB_DWC2_TX6_FIFO_SIZE);
fifo_num += CONFIG_USB_DWC2_TX6_FIFO_SIZE;
#endif
#if CONFIG_USBDEV_EP_NUM > 7
dwc2_set_txfifo(busid, 7, CONFIG_USB_DWC2_TX7_FIFO_SIZE);
fifo_num += CONFIG_USB_DWC2_TX7_FIFO_SIZE;
#endif
#if CONFIG_USBDEV_EP_NUM > 8
dwc2_set_txfifo(busid, 8, CONFIG_USB_DWC2_TX8_FIFO_SIZE);
fifo_num += CONFIG_USB_DWC2_TX8_FIFO_SIZE;
#endif
USB_ASSERT_MSG(fifo_num <= g_dwc2_udc[busid].user_params.total_fifo_size, "Your fifo config is overflow, please check");
}
USB_ASSERT_MSG(fifo_num <= (USB_OTG_GLB->GHWCFG3 >> 16), "Your fifo config is overflow, please check");
/* xxx32 chips do not follow (USB_OTG_GLB->GHWCFG3 >> 16) if hsphy_type is zero, they use 1.25KB(320 DWORD) */
USB_ASSERT_MSG(!((hsphy_type == 0) && (fifo_num > 320)), "Your fifo config is larger than 320 , please check");
if (g_dwc2_udc[busid].user_params.phy_type != DWC2_PHY_TYPE_PARAM_FS) {
USB_ASSERT_MSG(g_dwc2_udc[busid].user_params.device_rx_fifo_size >= (5 + 8 + 512 / 4 + 1 + 2 * 8 + 1), "Your rx fifo size config is invalid, please check");
} else {
USB_ASSERT_MSG(g_dwc2_udc[busid].user_params.device_rx_fifo_size >= (5 + 8 + 64 / 4 + 1 + 2 * 8 + 1), "Your rx fifo size config is invalid, please check");
}
ret = dwc2_flush_txfifo(busid, 0x10U);
ret = dwc2_flush_rxfifo(busid);
@@ -725,7 +671,7 @@ int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep)
{
uint8_t ep_idx = USB_EP_GET_IDX(ep->bEndpointAddress);
USB_ASSERT_MSG(ep_idx < CONFIG_USBDEV_EP_NUM, "Ep addr %02x overflow", ep->bEndpointAddress);
USB_ASSERT_MSG(ep_idx < (g_dwc2_udc[busid].hw_params.num_dev_ep + 1), "Ep addr %02x overflow", ep->bEndpointAddress);
if (USB_EP_DIR_IS_OUT(ep->bEndpointAddress)) {
g_dwc2_udc[busid].out_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize);
@@ -829,11 +775,11 @@ int usbd_ep_set_stall(uint8_t busid, const uint8_t ep)
}
USB_OTG_INEP(ep_idx)->DIEPCTL |= USB_OTG_DIEPCTL_STALL;
}
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
if (ep_idx == 0) {
if ((ep_idx == 0) && g_dwc2_udc[busid].user_params.device_dma_enable) {
dwc2_ep0_start_read_setup(busid, (uint8_t *)&g_dwc2_udc[busid].setup);
}
#endif
return 0;
}
@@ -884,9 +830,9 @@ int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, ui
USB_ASSERT_MSG(!((uint32_t)data % 0x04), "dwc2 data must be 4-byte aligned");
#ifdef CONFIG_USB_DCACHE_ENABLE
USB_ASSERT_MSG(!((uint32_t)data % CONFIG_USB_ALIGN_SIZE), "dwc2 data must be %d-byte aligned", CONFIG_USB_ALIGN_SIZE);
#endif
if (g_dwc2_udc[busid].user_params.device_dma_enable) {
USB_ASSERT_MSG(!((uint32_t)data % CONFIG_USB_ALIGN_SIZE), "dwc2 data must be %d-byte aligned", CONFIG_USB_ALIGN_SIZE);
}
if (!data && data_len) {
return -1;
@@ -935,18 +881,18 @@ int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, ui
USB_OTG_INEP(ep_idx)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_MULCNT & (1U << 29));
}
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
usb_dcache_clean((uintptr_t)data, USB_ALIGN_UP(data_len, CONFIG_USB_ALIGN_SIZE));
USB_OTG_INEP(ep_idx)->DIEPDMA = (uint32_t)data;
if (g_dwc2_udc[busid].user_params.device_dma_enable) {
usb_dcache_clean((uintptr_t)data, USB_ALIGN_UP(data_len, CONFIG_USB_ALIGN_SIZE));
USB_OTG_INEP(ep_idx)->DIEPDMA = (uint32_t)data;
USB_OTG_INEP(ep_idx)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
#else
USB_OTG_INEP(ep_idx)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
/* Enable the Tx FIFO Empty Interrupt for this EP */
if (data_len > 0U) {
USB_OTG_DEV->DIEPEMPMSK |= 1UL << (ep_idx & 0x0f);
USB_OTG_INEP(ep_idx)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
} else {
USB_OTG_INEP(ep_idx)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
/* Enable the Tx FIFO Empty Interrupt for this EP */
if (data_len > 0U) {
USB_OTG_DEV->DIEPEMPMSK |= 1UL << (ep_idx & 0x0f);
}
}
#endif
return 0;
}
@@ -957,9 +903,9 @@ int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t
USB_ASSERT_MSG(!((uint32_t)data % 0x04), "dwc2 data must be 4-byte aligned");
#ifdef CONFIG_USB_DCACHE_ENABLE
USB_ASSERT_MSG(!((uint32_t)data % CONFIG_USB_ALIGN_SIZE), "dwc2 data must be %d-byte aligned", CONFIG_USB_ALIGN_SIZE);
#endif
if (g_dwc2_udc[busid].user_params.device_dma_enable) {
USB_ASSERT_MSG(!((uint32_t)data % CONFIG_USB_ALIGN_SIZE), "dwc2 data must be %d-byte aligned", CONFIG_USB_ALIGN_SIZE);
}
if (!data && data_len) {
return -1;
@@ -996,9 +942,9 @@ int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t
USB_OTG_OUTEP(ep_idx)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_XFRSIZ & data_len);
}
#ifdef CONFIG_USB_DWC2_DMA_ENABLE
USB_OTG_OUTEP(ep_idx)->DOEPDMA = (uint32_t)data;
#endif
if (g_dwc2_udc[busid].user_params.device_dma_enable) {
USB_OTG_OUTEP(ep_idx)->DOEPDMA = (uint32_t)data;
}
if (g_dwc2_udc[busid].out_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS) {
if ((USB_OTG_DEV->DSTS & (1U << 8)) == 0U) {
USB_OTG_OUTEP(ep_idx)->DOEPCTL &= ~USB_OTG_DOEPCTL_SD0PID_SEVNFRM;
@@ -1025,29 +971,30 @@ void USBD_IRQHandler(uint8_t busid)
return;
}
#ifndef CONFIG_USB_DWC2_DMA_ENABLE
/* Handle RxQLevel Interrupt */
if (gint_status & USB_OTG_GINTSTS_RXFLVL) {
USB_MASK_INTERRUPT(USB_OTG_GLB, USB_OTG_GINTSTS_RXFLVL);
if (!g_dwc2_udc[busid].user_params.device_dma_enable) {
/* Handle RxQLevel Interrupt */
if (gint_status & USB_OTG_GINTSTS_RXFLVL) {
USB_MASK_INTERRUPT(USB_OTG_GLB, USB_OTG_GINTSTS_RXFLVL);
temp = USB_OTG_GLB->GRXSTSP;
ep_idx = temp & USB_OTG_GRXSTSP_EPNUM;
temp = USB_OTG_GLB->GRXSTSP;
ep_idx = temp & USB_OTG_GRXSTSP_EPNUM;
if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> USB_OTG_GRXSTSP_PKTSTS_Pos) == STS_DATA_UPDT) {
read_count = (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
if (read_count != 0) {
dwc2_ep_read(busid, g_dwc2_udc[busid].out_ep[ep_idx].xfer_buf, read_count);
g_dwc2_udc[busid].out_ep[ep_idx].xfer_buf += read_count;
if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> USB_OTG_GRXSTSP_PKTSTS_Pos) == STS_DATA_UPDT) {
read_count = (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
if (read_count != 0) {
dwc2_ep_read(busid, g_dwc2_udc[busid].out_ep[ep_idx].xfer_buf, read_count);
g_dwc2_udc[busid].out_ep[ep_idx].xfer_buf += read_count;
}
} else if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> USB_OTG_GRXSTSP_PKTSTS_Pos) == STS_SETUP_UPDT) {
read_count = (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
dwc2_ep_read(busid, (uint8_t *)&g_dwc2_udc[busid].setup, read_count);
} else {
/* ... */
}
} else if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> USB_OTG_GRXSTSP_PKTSTS_Pos) == STS_SETUP_UPDT) {
read_count = (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
dwc2_ep_read(busid, (uint8_t *)&g_dwc2_udc[busid].setup, read_count);
} else {
/* ... */
USB_UNMASK_INTERRUPT(USB_OTG_GLB, USB_OTG_GINTSTS_RXFLVL);
}
USB_UNMASK_INTERRUPT(USB_OTG_GLB, USB_OTG_GINTSTS_RXFLVL);
}
#endif
if (gint_status & USB_OTG_GINTSTS_OEPINT) {
ep_idx = 0;
ep_intr = dwc2_get_outeps_intstatus(busid);
@@ -1109,8 +1056,10 @@ void USBD_IRQHandler(uint8_t busid)
usbd_event_ep_in_complete_handler(busid, ep_idx | 0x80, g_dwc2_udc[busid].in_ep[ep_idx].actual_xfer_len);
}
}
if ((epint & USB_OTG_DIEPINT_TXFE) == USB_OTG_DIEPINT_TXFE) {
dwc2_tx_fifo_empty_procecss(busid, ep_idx);
if (!g_dwc2_udc[busid].user_params.device_dma_enable) {
if ((epint & USB_OTG_DIEPINT_TXFE) == USB_OTG_DIEPINT_TXFE) {
dwc2_tx_fifo_empty_procecss(busid, ep_idx);
}
}
}
ep_intr >>= 1U;
@@ -1124,7 +1073,7 @@ void USBD_IRQHandler(uint8_t busid)
dwc2_flush_txfifo(busid, 0x10U);
dwc2_flush_rxfifo(busid);
for (uint8_t i = 0U; i < CONFIG_USBDEV_EP_NUM; i++) {
for (uint8_t i = 0U; i < (g_dwc2_udc[busid].hw_params.num_dev_ep + 1); i++) {
if (i == 0U) {
USB_OTG_INEP(i)->DIEPCTL = USB_OTG_DIEPCTL_SNAK;
USB_OTG_OUTEP(i)->DOEPCTL = USB_OTG_DOEPCTL_SNAK;
@@ -1153,7 +1102,8 @@ void USBD_IRQHandler(uint8_t busid)
USB_OTG_DEV->DIEPMSK = USB_OTG_DIEPMSK_XFRCM;
memset(&g_dwc2_udc[busid], 0, sizeof(struct dwc2_udc));
memset(g_dwc2_udc[busid].in_ep, 0, sizeof(struct dwc2_ep_state) * 16);
memset(g_dwc2_udc[busid].out_ep, 0, sizeof(struct dwc2_ep_state) * 16);
usbd_event_reset_handler(busid);
/* Start reading setup */
dwc2_ep0_start_read_setup(busid, (uint8_t *)&g_dwc2_udc[busid].setup);