From 3592794393997f839163c0d095ddca1773c77535 Mon Sep 17 00:00:00 2001 From: sakumisu <1203593632@qq.com> Date: Sun, 14 Apr 2024 19:35:48 +0800 Subject: [PATCH] import bouffalo dcd --- SConscript | 14 +- cherryusb.cmake | 2 + port/bouffalolab/README.md | 7 +- port/bouffalolab/usb_dc_bl.c | 1103 ++++++++++++++++++++++++++++++++++ 4 files changed, 1111 insertions(+), 15 deletions(-) create mode 100644 port/bouffalolab/usb_dc_bl.c diff --git a/SConscript b/SConscript index 3990cc0e..31689d5e 100644 --- a/SConscript +++ b/SConscript @@ -27,7 +27,7 @@ if GetDepend(['PKG_CHERRYUSB_DEVICE']): CPPDEFINES+=['CONFIG_USB_HS'] if GetDepend(['PKG_CHERRYUSB_DEVICE_BL']): - CPPDEFINES += ['CONFIG_CHERRYUSB'] + src += Glob('port/bouffalolab/usb_dc_bl.c') if GetDepend(['PKG_CHERRYUSB_DEVICE_CH32']): if GetDepend(['PKG_CHERRYUSB_DEVICE_HS']): src += Glob('port/ch32/usb_dc_usbhs.c') @@ -44,9 +44,6 @@ if GetDepend(['PKG_CHERRYUSB_DEVICE']): if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_AT']): src += Glob('port/dwc2/usb_dc_dwc2.c') src += Glob('port/dwc2/usb_glue_at.c') - if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_AIC']): - src += Glob('port/dwc2/usb_dc_dwc2.c') - src += Glob('port/dwc2/usb_glue_aic.c') if GetDepend(['PKG_CHERRYUSB_DEVICE_DWC2_CUSTOM']): src += Glob('port/dwc2/usb_dc_dwc2.c') if GetDepend(['PKG_CHERRYUSB_DEVICE_MUSB_STANDARD']): @@ -158,15 +155,6 @@ if GetDepend(['PKG_CHERRYUSB_HOST']): CPPDEFINES += ['CONFIG_USB_MUSB_SUNXI'] if GetDepend(['PKG_CHERRYUSB_HOST_MUSB_CUSTOM']): src += Glob('port/musb/usb_hc_musb.c') - if GetDepend(['PKG_CHERRYUSB_HOST_XHCI']): - src += Glob('port/xhci/usb_hc_xhci.c') - src += Glob('port/xhci/xhci_dbg.c') - src += Glob('port/xhci/xhci.c') - if GetDepend(['PKG_CHERRYUSB_HOST_PUSB2']): - path += [cwd + '/port/pusb2/common'] - path += [cwd + '/port/pusb2/fpusb2'] - src += Glob('port/pusb2/fpusb2' + '/*.c') - src += Glob('port/pusb2/usb_hc_pusb2.c') if GetDepend(['PKG_CHERRYUSB_HOST_CDC_ACM']): src += Glob('class/cdc/usbh_cdc_acm.c') diff --git a/cherryusb.cmake b/cherryusb.cmake index 439df433..1bc02d14 100644 --- a/cherryusb.cmake +++ b/cherryusb.cmake @@ -87,6 +87,8 @@ if(CONFIG_CHERRYUSB_DEVICE) list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/fsdev/usb_dc_fsdev.c) elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "hpm") list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/hpm/usb_dc_hpm.c) + elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "bl") + list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/bouffalolab/usb_dc_bl.c) elseif("${CONFIG_CHERRYUSB_DEVICE_DCD}" STREQUAL "musb") list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/musb/usb_dc_musb.c) endif() diff --git a/port/bouffalolab/README.md b/port/bouffalolab/README.md index dd500e82..7779b2bb 100644 --- a/port/bouffalolab/README.md +++ b/port/bouffalolab/README.md @@ -1,2 +1,5 @@ -[BL702](https://github.com/bouffalolab/bl_mcu_sdk/blob/master/drivers/lhal/src/bflb_usb_v1.c) -[BL616/BL808](https://github.com/bouffalolab/bl_mcu_sdk/blob/master/drivers/lhal/src/bflb_usb_v2.c) +# Note + +## Support Chip List + +- BL616/BL808 diff --git a/port/bouffalolab/usb_dc_bl.c b/port/bouffalolab/usb_dc_bl.c new file mode 100644 index 00000000..9f61f1cb --- /dev/null +++ b/port/bouffalolab/usb_dc_bl.c @@ -0,0 +1,1103 @@ +#include "bflb_core.h" +#include "usbd_core.h" +#include "hardware/usb_v2_reg.h" + +/* select only one mode */ +// #define CONFIG_USB_PINGPONG_ENABLE +// #define CONFIG_USB_TRIPLE_ENABLE + +#define BFLB_USB_BASE ((uint32_t)0x20072000) +#define BFLB_PDS_BASE ((uint32_t)0x2000e000) + +#define PDS_USB_CTL_OFFSET (0x500) /* usb_ctl */ +#define PDS_USB_PHY_CTRL_OFFSET (0x504) /* usb_phy_ctrl */ + +/* 0x500 : usb_ctl */ +#define PDS_REG_USB_SW_RST_N (1 << 0U) +#define PDS_REG_USB_EXT_SUSP_N (1 << 1U) +#define PDS_REG_USB_WAKEUP (1 << 2U) +#define PDS_REG_USB_L1_WAKEUP (1 << 3U) +#define PDS_REG_USB_DRVBUS_POL (1 << 4U) +#define PDS_REG_USB_IDDIG (1 << 5U) + +/* 0x504 : usb_phy_ctrl */ +#define PDS_REG_USB_PHY_PONRST (1 << 0U) +#define PDS_REG_USB_PHY_OSCOUTEN (1 << 1U) +#define PDS_REG_USB_PHY_XTLSEL_SHIFT (2U) +#define PDS_REG_USB_PHY_XTLSEL_MASK (0x3 << PDS_REG_USB_PHY_XTLSEL_SHIFT) +#define PDS_REG_USB_PHY_OUTCLKSEL (1 << 4U) +#define PDS_REG_USB_PHY_PLLALIV (1 << 5U) +#define PDS_REG_PU_USB20_PSW (1 << 6U) + +#define USB_SOF_TIMER_MASK_AFTER_RESET_HS (0x44C) +#define USB_SOF_TIMER_MASK_AFTER_RESET_FS (0x2710) + +extern void USBD_IRQHandler(uint8_t busid); + +void USBD_IRQ(int irq, void *arg) +{ + USBD_IRQHandler(0); +} + +static void bflb_usb_phy_init(void) +{ + uint32_t regval; + + /* USB_PHY_CTRL[3:2] reg_usb_phy_xtlsel=0 */ + /* 2000e504 = 0x40; #100; USB_PHY_CTRL[6] reg_pu_usb20_psw=1 (VCC33A) */ + /* 2000e504 = 0x41; #500; USB_PHY_CTRL[0] reg_usb_phy_ponrst=1 */ + /* 2000e500 = 0x20; #100; USB_CTL[0] reg_usb_sw_rst_n=0 */ + /* 2000e500 = 0x22; #500; USB_CTL[1] reg_usb_ext_susp_n=1 */ + /* 2000e500 = 0x23; #100; USB_CTL[0] reg_usb_sw_rst_n=1 */ + /* #1.2ms; wait UCLK */ + /* wait(soc616_b0.usb_uclk); */ + + regval = getreg32(BFLB_PDS_BASE + PDS_USB_PHY_CTRL_OFFSET); + regval &= ~PDS_REG_USB_PHY_XTLSEL_MASK; + putreg32(regval, BFLB_PDS_BASE + PDS_USB_PHY_CTRL_OFFSET); + + regval = getreg32(BFLB_PDS_BASE + PDS_USB_PHY_CTRL_OFFSET); + regval |= PDS_REG_PU_USB20_PSW; + putreg32(regval, BFLB_PDS_BASE + PDS_USB_PHY_CTRL_OFFSET); + + regval = getreg32(BFLB_PDS_BASE + PDS_USB_PHY_CTRL_OFFSET); + regval |= PDS_REG_USB_PHY_PONRST; + putreg32(regval, BFLB_PDS_BASE + PDS_USB_PHY_CTRL_OFFSET); + + /* greater than 5T */ + bflb_mtimer_delay_us(1); + + regval = getreg32(BFLB_PDS_BASE + PDS_USB_CTL_OFFSET); + regval &= ~PDS_REG_USB_SW_RST_N; + putreg32(regval, BFLB_PDS_BASE + PDS_USB_CTL_OFFSET); + + /* greater than 5T */ + bflb_mtimer_delay_us(1); + + regval = getreg32(BFLB_PDS_BASE + PDS_USB_CTL_OFFSET); + regval |= PDS_REG_USB_EXT_SUSP_N; + putreg32(regval, BFLB_PDS_BASE + PDS_USB_CTL_OFFSET); + + /* wait UCLK 1.2ms */ + bflb_mtimer_delay_ms(3); + + regval = getreg32(BFLB_PDS_BASE + PDS_USB_CTL_OFFSET); + regval |= PDS_REG_USB_SW_RST_N; + putreg32(regval, BFLB_PDS_BASE + PDS_USB_CTL_OFFSET); + + bflb_mtimer_delay_ms(2); +} + +#define USB_FIFO_F0 0 +#define USB_FIFO_F1 1 +#define USB_FIFO_F2 2 +#define USB_FIFO_F3 3 +#define USB_FIFO_CXF 0xff + +#define USB_FIFO_DIR_OUT 0 +#define USB_FIFO_DIR_IN 1 +#define USB_FIFO_DIR_BID 2 + +#define USB_VDMA_DIR_FIFO2MEM 0 +#define USB_VDMA_DIR_MEM2FIFO 1 + +#define USB_NUM_BIDIR_ENDPOINTS 5 + +/* Endpoint state */ +struct bl_ep_state { + uint16_t ep_mps; /* Endpoint max packet size */ + uint8_t ep_type; /* Endpoint type */ + uint8_t ep_stalled; /* Endpoint stall flag */ + uint8_t ep_enable; /* Endpoint enable */ + bool ep_active; + uint8_t *xfer_buf; + uint32_t xfer_len; + uint32_t actual_xfer_len; +}; + +struct bl_udc { + struct bl_ep_state in_ep[USB_NUM_BIDIR_ENDPOINTS]; /*!< IN endpoint parameters */ + struct bl_ep_state out_ep[USB_NUM_BIDIR_ENDPOINTS]; /*!< OUT endpoint parameters */ +} g_bl_udc; + +static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_setup_buffer[8]; + +static void bflb_usb_reset_fifo(uint8_t fifo) +{ + uint32_t regval; + + if (fifo == USB_FIFO_CXF) { + regval = getreg32(BFLB_USB_BASE + USB_DEV_CXCFE_OFFSET); + regval |= USB_CX_CLR; + putreg32(regval, BFLB_USB_BASE + USB_DEV_CXCFE_OFFSET); + } else { + regval = getreg32(BFLB_USB_BASE + USB_DEV_FIBC0_OFFSET + 4 * fifo); + regval |= USB_FFRST0_HOV; + putreg32(regval, BFLB_USB_BASE + USB_DEV_FIBC0_OFFSET + 4 * fifo); + } +} + +void bflb_usb_get_setup_packet(uint32_t setup[2]) +{ + uint32_t regval; + + regval = getreg32(BFLB_USB_BASE + USB_DMA_TFN_OFFSET); + regval |= USB_ACC_CXF_HOV; + putreg32(regval, BFLB_USB_BASE + USB_DMA_TFN_OFFSET); + + setup[0] = getreg32(BFLB_USB_BASE + USB_DMA_CPS3_OFFSET); + setup[1] = getreg32(BFLB_USB_BASE + USB_DMA_CPS3_OFFSET); + + regval = getreg32(BFLB_USB_BASE + USB_DMA_TFN_OFFSET); + regval &= ~USB_ACC_CXF_HOV; + putreg32(regval, BFLB_USB_BASE + USB_DMA_TFN_OFFSET); +} + +static void bflb_usb_set_ep_fifomap(uint8_t ep_idx, uint8_t fifo) +{ + uint32_t regval; + + if (ep_idx < 5) { + regval = getreg32(BFLB_USB_BASE + USB_DEV_EPMAP0_OFFSET); + regval &= ~(0xff << ((ep_idx - 1) * 8)); + regval |= (fifo << ((ep_idx - 1) * 8)); + regval |= (fifo << ((ep_idx - 1) * 8 + 4)); + putreg32(regval, BFLB_USB_BASE + USB_DEV_EPMAP0_OFFSET); + } else { + regval = getreg32(BFLB_USB_BASE + USB_DEV_EPMAP1_OFFSET); + regval &= ~(0xff << ((ep_idx - 4 - 1) * 8)); + regval |= (fifo << ((ep_idx - 4 - 1) * 8)); + regval |= (fifo << ((ep_idx - 4 - 1) * 8 + 4)); + putreg32(regval, BFLB_USB_BASE + USB_DEV_EPMAP1_OFFSET); + } +} + +static void bflb_usb_set_fifo_epmap(uint8_t fifo, uint8_t ep_idx, uint8_t dir) +{ + uint32_t regval; + + regval = getreg32(BFLB_USB_BASE + USB_DEV_FMAP_OFFSET); + regval &= ~(0x3f << (fifo * 8)); + regval |= (ep_idx << (fifo * 8)); + regval |= (dir << (fifo * 8 + 4)); + putreg32(regval, BFLB_USB_BASE + USB_DEV_FMAP_OFFSET); +} + +static void bflb_usb_set_outep_mps(uint8_t ep_idx, uint16_t ep_mps) +{ + uint32_t regval; + + regval = getreg32(BFLB_USB_BASE + USB_DEV_OUTMPS1_OFFSET + (ep_idx - 1) * 4); + regval &= ~USB_MAXPS_OEP1_MASK; + regval |= ep_mps; + putreg32(regval, BFLB_USB_BASE + USB_DEV_OUTMPS1_OFFSET + (ep_idx - 1) * 4); +} + +static void bflb_usb_set_inep_mps(uint8_t ep_idx, uint16_t ep_mps) +{ + uint32_t regval; + + regval = getreg32(BFLB_USB_BASE + USB_DEV_INMPS1_OFFSET + (ep_idx - 1) * 4); + regval &= ~USB_MAXPS_IEP1_MASK; + regval |= ep_mps; + putreg32(regval, BFLB_USB_BASE + USB_DEV_INMPS1_OFFSET + (ep_idx - 1) * 4); +} + +static uint8_t bflb_usb_get_fifo_ep(uint8_t fifo) +{ + uint32_t regval; + + regval = (getreg32(BFLB_USB_BASE + USB_DEV_FMAP_OFFSET) & (0xf << (fifo * 8))); + regval >>= (fifo * 8); + return regval; +} + +static void bflb_usb_fifo_config(uint8_t fifo, uint8_t ep_type, uint16_t block_size, uint8_t block_num, bool fifo_en) +{ + uint32_t regval; + + if (fifo < 4) { + regval = getreg32(BFLB_USB_BASE + USB_DEV_FCFG_OFFSET); + regval &= ~(0x3f << (fifo * 8)); + regval |= (ep_type << (fifo * 8 + 0)); + regval |= ((block_num - 1) << (fifo * 8 + 2)); + if (block_size == 1024) { + regval |= (1 << (fifo * 8 + 4)); + } + + if (fifo_en) { + regval |= (1 << (fifo * 8 + 5)); + } + putreg32(regval, BFLB_USB_BASE + USB_DEV_FCFG_OFFSET); + } +} + +static void bflb_usb_vdma_start_write(uint8_t fifo, const uint8_t *data, uint32_t len) +{ + uint32_t regval; + + if (fifo == USB_FIFO_CXF) { + regval = getreg32(BFLB_USB_BASE + USB_VDMA_CXFPS1_OFFSET); + regval &= ~USB_VDMA_LEN_CXF_MASK; + regval &= ~USB_VDMA_IO_CXF; + regval |= USB_VDMA_TYPE_CXF; + regval |= (len << USB_VDMA_LEN_CXF_SHIFT); + putreg32(regval, BFLB_USB_BASE + USB_VDMA_CXFPS1_OFFSET); + + putreg32((uint32_t)data, BFLB_USB_BASE + USB_VDMA_CXFPS2_OFFSET); + + regval = getreg32(BFLB_USB_BASE + USB_VDMA_CXFPS1_OFFSET); + regval |= USB_VDMA_START_CXF; + putreg32(regval, BFLB_USB_BASE + USB_VDMA_CXFPS1_OFFSET); + } else { + regval = getreg32(BFLB_USB_BASE + USB_VDMA_F0PS1_OFFSET + fifo * 8); + regval &= ~USB_VDMA_LEN_CXF_MASK; + regval &= ~USB_VDMA_IO_CXF; + regval |= USB_VDMA_TYPE_CXF; + regval |= (len << USB_VDMA_LEN_CXF_SHIFT); + putreg32(regval, BFLB_USB_BASE + USB_VDMA_F0PS1_OFFSET + fifo * 8); + + putreg32((uint32_t)data, BFLB_USB_BASE + USB_VDMA_F0PS2_OFFSET + fifo * 8); + + regval = getreg32(BFLB_USB_BASE + USB_VDMA_F0PS1_OFFSET + fifo * 8); + regval |= USB_VDMA_START_CXF; + putreg32(regval, BFLB_USB_BASE + USB_VDMA_F0PS1_OFFSET + fifo * 8); + } +} + +static void bflb_usb_vdma_start_read(uint8_t fifo, uint8_t *data, uint32_t len) +{ + uint32_t regval; + + if (fifo == USB_FIFO_CXF) { + regval = getreg32(BFLB_USB_BASE + USB_VDMA_CXFPS1_OFFSET); + regval &= ~USB_VDMA_LEN_CXF_MASK; + regval &= ~USB_VDMA_IO_CXF; + regval &= ~USB_VDMA_TYPE_CXF; + regval |= (len << USB_VDMA_LEN_CXF_SHIFT); + putreg32(regval, BFLB_USB_BASE + USB_VDMA_CXFPS1_OFFSET); + + putreg32((uint32_t)data, BFLB_USB_BASE + USB_VDMA_CXFPS2_OFFSET); + + regval = getreg32(BFLB_USB_BASE + USB_VDMA_CXFPS1_OFFSET); + regval |= USB_VDMA_START_CXF; + putreg32(regval, BFLB_USB_BASE + USB_VDMA_CXFPS1_OFFSET); + } else { + regval = getreg32(BFLB_USB_BASE + USB_VDMA_F0PS1_OFFSET + fifo * 8); + regval &= ~USB_VDMA_LEN_CXF_MASK; + regval &= ~USB_VDMA_IO_CXF; + regval &= ~USB_VDMA_TYPE_CXF; + regval |= (len << USB_VDMA_LEN_CXF_SHIFT); + putreg32(regval, BFLB_USB_BASE + USB_VDMA_F0PS1_OFFSET + fifo * 8); + + putreg32((uint32_t)data, BFLB_USB_BASE + USB_VDMA_F0PS2_OFFSET + fifo * 8); + + regval = getreg32(BFLB_USB_BASE + USB_VDMA_F0PS1_OFFSET + fifo * 8); + regval |= USB_VDMA_START_CXF; + putreg32(regval, BFLB_USB_BASE + USB_VDMA_F0PS1_OFFSET + fifo * 8); + } +} + +static uint32_t bflb_usb_vdma_get_remain_size(uint8_t fifo) +{ + uint32_t regval; + + if (fifo == USB_FIFO_CXF) { + regval = (getreg32(BFLB_USB_BASE + USB_VDMA_CXFPS1_OFFSET) & USB_VDMA_LEN_CXF_MASK); + regval >>= USB_VDMA_LEN_CXF_SHIFT; + + } else { + regval = (getreg32(BFLB_USB_BASE + USB_VDMA_F0PS1_OFFSET + fifo * 8) & USB_VDMA_LEN_CXF_MASK); + regval >>= USB_VDMA_LEN_CXF_SHIFT; + } + + return regval; +} + +static inline void bflb_usb_control_transfer_done(void) +{ + uint32_t regval; + + regval = getreg32(BFLB_USB_BASE + USB_DEV_CXCFE_OFFSET); + regval |= USB_CX_DONE; + putreg32(regval, BFLB_USB_BASE + USB_DEV_CXCFE_OFFSET); +} + +static inline void bflb_usb_set_mult(uint8_t ep_idx, uint8_t mult) +{ + uint32_t regval; + + regval = getreg32(BFLB_USB_BASE + USB_DEV_INMPS1_OFFSET + (ep_idx - 1) * 4); + regval &= ~USB_TX_NUM_HBW_IEP1_MASK; + regval |= (mult << USB_TX_NUM_HBW_IEP1_SHIFT); + putreg32(regval, BFLB_USB_BASE + USB_DEV_INMPS1_OFFSET + (ep_idx - 1) * 4); +} + +static inline void bflb_usb_send_zlp(uint8_t ep_idx) +{ + uint32_t regval; + + regval = getreg32(BFLB_USB_BASE + USB_DEV_INMPS1_OFFSET + (ep_idx - 1) * 4); + regval |= USB_TX0BYTE_IEP1; + putreg32(regval, BFLB_USB_BASE + USB_DEV_INMPS1_OFFSET + (ep_idx - 1) * 4); +} + +static inline uint32_t bflb_usb_get_tx_zlp_intstatus(void) +{ + return getreg32(BFLB_USB_BASE + USB_DEV_TXZ_OFFSET); +} + +static inline uint32_t bflb_usb_get_rx_zlp_intstatus(void) +{ + return getreg32(BFLB_USB_BASE + USB_DEV_RXZ_OFFSET); +} + +static inline void bflb_usb_clear_tx_zlp_intstatus(uint8_t ep_idx) +{ + putreg32((1 << (ep_idx - 1)), BFLB_USB_BASE + USB_DEV_TXZ_OFFSET); +} + +static inline void bflb_usb_clear_rx_zlp_intstatus(uint8_t ep_idx) +{ + putreg32((1 << (ep_idx - 1)), BFLB_USB_BASE + USB_DEV_RXZ_OFFSET); +} + +static uint32_t bflb_usb_get_source_group_intstatus(uint8_t group) +{ + switch (group) { + case 0: + return (getreg32(BFLB_USB_BASE + USB_DEV_ISG0_OFFSET) & ~getreg32(BFLB_USB_BASE + USB_DEV_MISG0_OFFSET)); + case 1: + return (getreg32(BFLB_USB_BASE + USB_DEV_ISG1_OFFSET) & ~getreg32(BFLB_USB_BASE + USB_DEV_MISG1_OFFSET)); + case 2: + return (getreg32(BFLB_USB_BASE + USB_DEV_ISG2_OFFSET) & ~getreg32(BFLB_USB_BASE + USB_DEV_MISG2_OFFSET)); + case 3: + return (getreg32(BFLB_USB_BASE + USB_DEV_ISG3_OFFSET) & ~getreg32(BFLB_USB_BASE + USB_DEV_MISG3_OFFSET)); + case 4: + return (getreg32(BFLB_USB_BASE + USB_DEV_ISG4_OFFSET) & ~getreg32(BFLB_USB_BASE + USB_DEV_MISG4_OFFSET)); + default: + break; + } + return 0; +} + +static void bflb_usb_source_group_int_clear(uint8_t group, uint32_t int_clear) +{ + switch (group) { + case 0: + putreg32(int_clear, BFLB_USB_BASE + USB_DEV_ISG0_OFFSET); + break; + case 1: + putreg32(int_clear, BFLB_USB_BASE + USB_DEV_ISG1_OFFSET); + break; + case 2: + putreg32(int_clear, BFLB_USB_BASE + USB_DEV_ISG2_OFFSET); + break; + case 3: + putreg32(int_clear, BFLB_USB_BASE + USB_DEV_ISG3_OFFSET); + break; + case 4: + putreg32(int_clear, BFLB_USB_BASE + USB_DEV_ISG4_OFFSET); + break; + + default: + break; + } +} + +static uint8_t usb_get_transfer_fifo(uint8_t ep_idx) +{ + uint8_t target_fifo_id; + + if ((g_bl_udc.out_ep[ep_idx].ep_mps > 512) || (g_bl_udc.in_ep[ep_idx].ep_mps > 512)) { +#if defined(CONFIG_USB_PINGPONG_ENABLE) + target_fifo_id = USB_FIFO_F0; +#elif defined(CONFIG_USB_TRIPLE_ENABLE) + while (1) { + } +#else + if (ep_idx == 1) { + target_fifo_id = USB_FIFO_F0; + } else { + target_fifo_id = USB_FIFO_F2; + } +#endif + } else { +#if defined(CONFIG_USB_PINGPONG_ENABLE) + if (ep_idx == 1) { + target_fifo_id = USB_FIFO_F0; + } else { + target_fifo_id = USB_FIFO_F2; + } +#elif defined(CONFIG_USB_TRIPLE_ENABLE) + if (ep_idx == 1) { + target_fifo_id = USB_FIFO_F0; + } else { + target_fifo_id = USB_FIFO_F3; + } +#else + target_fifo_id = (ep_idx - 1); +#endif + } + + return target_fifo_id; +} + +int usb_dc_init(uint8_t busid) +{ + uint32_t regval; + + bflb_usb_phy_init(); + + bflb_irq_attach(37, USBD_IRQ, NULL); + bflb_irq_enable(37); + + /* disable global irq */ + regval = getreg32(BFLB_USB_BASE + USB_DEV_CTL_OFFSET); + regval &= ~USB_GLINT_EN_HOV; + putreg32(regval, BFLB_USB_BASE + USB_DEV_CTL_OFFSET); + + regval = getreg32(BFLB_USB_BASE + USB_PHY_TST_OFFSET); + regval |= USB_UNPLUG; + putreg32(regval, BFLB_USB_BASE + USB_PHY_TST_OFFSET); + + regval = getreg32(BFLB_USB_BASE + USB_DEV_CTL_OFFSET); + regval &= ~USB_CAP_RMWAKUP; + regval |= USB_CHIP_EN_HOV; + putreg32(regval, BFLB_USB_BASE + USB_DEV_CTL_OFFSET); + + regval = getreg32(BFLB_USB_BASE + USB_DEV_CTL_OFFSET); + regval |= USB_SFRST_HOV; + putreg32(regval, BFLB_USB_BASE + USB_DEV_CTL_OFFSET); + + while (getreg32(BFLB_USB_BASE + USB_DEV_CTL_OFFSET) & USB_SFRST_HOV) { + } + + regval = getreg32(BFLB_USB_BASE + USB_DEV_ADR_OFFSET); + regval &= ~USB_AFT_CONF; + putreg32(regval, BFLB_USB_BASE + USB_DEV_ADR_OFFSET); + + regval = getreg32(BFLB_USB_BASE + USB_DEV_SMT_OFFSET); + regval &= ~USB_SOFMT_MASK; +#ifdef CONFIG_USB_HS + regval |= USB_SOF_TIMER_MASK_AFTER_RESET_HS; +#else + regval |= USB_SOF_TIMER_MASK_AFTER_RESET_FS; +#endif + putreg32(regval, BFLB_USB_BASE + USB_DEV_SMT_OFFSET); + + /* enable setup irq in source group0 */ + regval = getreg32(BFLB_USB_BASE + USB_DEV_MISG0_OFFSET); + regval &= ~USB_MCX_SETUP_INT; + regval |= USB_MCX_IN_INT; + regval |= (1 << 3); + regval |= USB_MCX_OUT_INT; + regval |= USB_MCX_IN_INT; + regval |= USB_MCX_COMFAIL_INT; + regval |= USB_MCX_COMABORT_INT; + putreg32(regval, BFLB_USB_BASE + USB_DEV_MISG0_OFFSET); + + /* disable all fifo irq in source group1 */ + putreg32(0xffffffff, BFLB_USB_BASE + USB_DEV_MISG1_OFFSET); + + /* enable rst/tx0/rx0 irq in source group2 */ + regval = 0xffffffff; + regval &= ~USB_MUSBRST_INT; + regval &= ~USB_MSUSP_INT; + regval &= ~USB_MRESM_INT; + regval &= ~USB_MTX0BYTE_INT; + regval &= ~USB_MRX0BYTE_INT; + putreg32(regval, BFLB_USB_BASE + USB_DEV_MISG2_OFFSET); + + /* enable vdma cmplt and error irq in source group3 */ + regval = 0xffffffff; + regval &= ~(USB_MVDMA_CMPLT_CXF | + USB_MVDMA_CMPLT_F0 | + USB_MVDMA_CMPLT_F1 | + USB_MVDMA_CMPLT_F2 | + USB_MVDMA_CMPLT_F3); + // regval &= ~(USB_MVDMA_ERROR_CXF | + // USB_MVDMA_ERROR_F0 | + // USB_MVDMA_ERROR_F1 | + // USB_MVDMA_ERROR_F2 | + // USB_MVDMA_ERROR_F3); + putreg32(regval, BFLB_USB_BASE + USB_DEV_MISG3_OFFSET); + + /* enable group irq */ + regval = getreg32(BFLB_USB_BASE + USB_DEV_MIGR_OFFSET); + regval &= ~USB_MINT_G0; + regval &= ~USB_MINT_G1; + regval &= ~USB_MINT_G2; + regval &= ~USB_MINT_G3; + regval &= ~USB_MINT_G4; + putreg32(regval, BFLB_USB_BASE + USB_DEV_MIGR_OFFSET); + + /* enable device irq */ + regval = getreg32(BFLB_USB_BASE + USB_GLB_INT_OFFSET); + regval |= USB_MHC_INT; + regval |= USB_MOTG_INT; + regval &= ~USB_MDEV_INT; + putreg32(regval, BFLB_USB_BASE + USB_GLB_INT_OFFSET); + + bflb_usb_source_group_int_clear(2, 0x3ff); + bflb_usb_source_group_int_clear(3, 0xffffffff); + + for (uint8_t i = 1; i < 9; i++) { + bflb_usb_set_ep_fifomap(i, 15); + bflb_usb_set_fifo_epmap(i, 15, 0); + } + + /* enable vdma */ + regval = getreg32(BFLB_USB_BASE + USB_VDMA_CTRL_OFFSET); + regval |= USB_VDMA_EN; + putreg32(regval, BFLB_USB_BASE + USB_VDMA_CTRL_OFFSET); + + regval = getreg32(BFLB_USB_BASE + USB_PHY_TST_OFFSET); + regval &= ~USB_UNPLUG; + putreg32(regval, BFLB_USB_BASE + USB_PHY_TST_OFFSET); + + /* enable global irq */ + regval = getreg32(BFLB_USB_BASE + USB_DEV_CTL_OFFSET); + regval |= USB_GLINT_EN_HOV; + putreg32(regval, BFLB_USB_BASE + USB_DEV_CTL_OFFSET); + + return 0; +} + +int usb_dc_deinit(uint8_t busid) +{ + uint32_t regval; + + /* disable global irq */ + regval = getreg32(BFLB_USB_BASE + USB_DEV_CTL_OFFSET); + regval &= ~USB_GLINT_EN_HOV; + putreg32(regval, BFLB_USB_BASE + USB_DEV_CTL_OFFSET); + + regval = getreg32(BFLB_USB_BASE + USB_PHY_TST_OFFSET); + regval |= USB_UNPLUG; + putreg32(regval, BFLB_USB_BASE + USB_PHY_TST_OFFSET); + + regval = getreg32(BFLB_PDS_BASE + PDS_USB_PHY_CTRL_OFFSET); + regval &= ~PDS_REG_USB_PHY_XTLSEL_MASK; + putreg32(regval, BFLB_PDS_BASE + PDS_USB_PHY_CTRL_OFFSET); + + regval = getreg32(BFLB_PDS_BASE + PDS_USB_PHY_CTRL_OFFSET); + regval &= ~PDS_REG_PU_USB20_PSW; + putreg32(regval, BFLB_PDS_BASE + PDS_USB_PHY_CTRL_OFFSET); + + regval = getreg32(BFLB_PDS_BASE + PDS_USB_PHY_CTRL_OFFSET); + regval &= ~PDS_REG_USB_PHY_PONRST; + putreg32(regval, BFLB_PDS_BASE + PDS_USB_PHY_CTRL_OFFSET); + + regval = getreg32(BFLB_PDS_BASE + PDS_USB_CTL_OFFSET); + regval &= ~PDS_REG_USB_EXT_SUSP_N; + putreg32(regval, BFLB_PDS_BASE + PDS_USB_CTL_OFFSET); + + return 0; +} + +int usbd_set_address(uint8_t busid, const uint8_t addr) +{ + uint32_t regval; + + regval = getreg32(BFLB_USB_BASE + USB_DEV_ADR_OFFSET); + regval &= ~USB_DEVADR_MASK; + regval |= addr; + putreg32(regval, BFLB_USB_BASE + USB_DEV_ADR_OFFSET); + + return 0; +} + +uint8_t usbd_get_port_speed(uint8_t busid, const uint8_t port) +{ + uint8_t speed = 3; + + speed = (getreg32(BFLB_USB_BASE + USB_OTG_CSR_OFFSET) & USB_SPD_TYP_HOV_POV_MASK) >> USB_SPD_TYP_HOV_POV_SHIFT; + + if (speed == 0) { + return USB_SPEED_FULL; + } else if (speed == 1) { + return USB_SPEED_LOW; + } else if (speed == 2) { + return USB_SPEED_HIGH; + } + return USB_SPEED_HIGH; +} + +int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep) +{ + uint8_t ep_addr; + uint32_t regval; + + ep_addr = ep->bEndpointAddress; + + uint8_t ep_idx = USB_EP_GET_IDX(ep_addr); + + if ((ep_idx > 4) && (ep_idx < 9)) { + return 0; + } + + if (USB_EP_DIR_IS_OUT(ep_addr)) { + g_bl_udc.out_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize); + g_bl_udc.out_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes); + g_bl_udc.out_ep[ep_idx].ep_enable = 1U; + bflb_usb_set_outep_mps(ep_idx, USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize)); + } else { + g_bl_udc.in_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize); + g_bl_udc.in_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes); + g_bl_udc.in_ep[ep_idx].ep_enable = 1U; + bflb_usb_set_inep_mps(ep_idx, USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize)); + bflb_usb_set_mult(ep_idx, 0); + } + + if (ep_idx != 0) { +#if !defined(CONFIG_USB_PINGPONG_ENABLE) && !defined(CONFIG_USB_TRIPLE_ENABLE) + if (USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize) > 512) { + bflb_usb_set_ep_fifomap(1, USB_FIFO_F0); + bflb_usb_set_ep_fifomap(2, USB_FIFO_F2); + + bflb_usb_set_fifo_epmap(USB_FIFO_F0, 1, USB_FIFO_DIR_BID); + bflb_usb_set_fifo_epmap(USB_FIFO_F1, 1, USB_FIFO_DIR_BID); + bflb_usb_set_fifo_epmap(USB_FIFO_F2, 2, USB_FIFO_DIR_BID); + bflb_usb_set_fifo_epmap(USB_FIFO_F3, 2, USB_FIFO_DIR_BID); + + if (ep_idx == 1) { + bflb_usb_fifo_config(USB_FIFO_F0, USB_GET_ENDPOINT_TYPE(ep->bmAttributes), 1024, 1, true); + bflb_usb_fifo_config(USB_FIFO_F1, USB_GET_ENDPOINT_TYPE(ep->bmAttributes), 1024, 1, false); + } else if (ep_idx == 2) { + bflb_usb_fifo_config(USB_FIFO_F2, USB_GET_ENDPOINT_TYPE(ep->bmAttributes), 1024, 1, true); + bflb_usb_fifo_config(USB_FIFO_F3, USB_GET_ENDPOINT_TYPE(ep->bmAttributes), 1024, 1, false); + } else { + return -1; + } + } else { + bflb_usb_set_ep_fifomap(1, USB_FIFO_F0); + bflb_usb_set_ep_fifomap(2, USB_FIFO_F1); + bflb_usb_set_ep_fifomap(3, USB_FIFO_F2); + bflb_usb_set_ep_fifomap(4, USB_FIFO_F3); + + bflb_usb_set_fifo_epmap(USB_FIFO_F0, 1, USB_FIFO_DIR_BID); + bflb_usb_set_fifo_epmap(USB_FIFO_F1, 2, USB_FIFO_DIR_BID); + bflb_usb_set_fifo_epmap(USB_FIFO_F2, 3, USB_FIFO_DIR_BID); + bflb_usb_set_fifo_epmap(USB_FIFO_F3, 4, USB_FIFO_DIR_BID); + + if (ep_idx == 1) { + bflb_usb_fifo_config(USB_FIFO_F0, USB_GET_ENDPOINT_TYPE(ep->bmAttributes), 512, 1, true); + } else if (ep_idx == 2) { + bflb_usb_fifo_config(USB_FIFO_F1, USB_GET_ENDPOINT_TYPE(ep->bmAttributes), 512, 1, true); + } else if (ep_idx == 3) { + bflb_usb_fifo_config(USB_FIFO_F2, USB_GET_ENDPOINT_TYPE(ep->bmAttributes), 512, 1, true); + } else if (ep_idx == 4) { + bflb_usb_fifo_config(USB_FIFO_F3, USB_GET_ENDPOINT_TYPE(ep->bmAttributes), 512, 1, true); + } else { + return -1; + } + } +#elif defined(CONFIG_USB_PINGPONG_ENABLE) + if (USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize) > 512) { + bflb_usb_set_ep_fifomap(1, USB_FIFO_F0); + + bflb_usb_set_fifo_epmap(USB_FIFO_F0, 1, USB_FIFO_DIR_BID); + bflb_usb_set_fifo_epmap(USB_FIFO_F1, 1, USB_FIFO_DIR_BID); + bflb_usb_set_fifo_epmap(USB_FIFO_F2, 1, USB_FIFO_DIR_BID); + bflb_usb_set_fifo_epmap(USB_FIFO_F3, 1, USB_FIFO_DIR_BID); + + if (ep_idx == 1) { + bflb_usb_fifo_config(USB_FIFO_F0, USB_GET_ENDPOINT_TYPE(ep->bmAttributes), 1024, 2, true); + bflb_usb_fifo_config(USB_FIFO_F1, USB_GET_ENDPOINT_TYPE(ep->bmAttributes), 1024, 2, false); + bflb_usb_fifo_config(USB_FIFO_F2, USB_GET_ENDPOINT_TYPE(ep->bmAttributes), 1024, 2, false); + bflb_usb_fifo_config(USB_FIFO_F3, USB_GET_ENDPOINT_TYPE(ep->bmAttributes), 1024, 2, false); + } else { + return -1; + } + } else { + bflb_usb_set_ep_fifomap(1, USB_FIFO_F0); + bflb_usb_set_ep_fifomap(2, USB_FIFO_F2); + + bflb_usb_set_fifo_epmap(USB_FIFO_F0, 1, USB_FIFO_DIR_BID); + bflb_usb_set_fifo_epmap(USB_FIFO_F1, 1, USB_FIFO_DIR_BID); + bflb_usb_set_fifo_epmap(USB_FIFO_F2, 2, USB_FIFO_DIR_BID); + bflb_usb_set_fifo_epmap(USB_FIFO_F3, 2, USB_FIFO_DIR_BID); + + if (ep_idx == 1) { + bflb_usb_fifo_config(USB_FIFO_F0, USB_GET_ENDPOINT_TYPE(ep->bmAttributes), 512, 2, true); + bflb_usb_fifo_config(USB_FIFO_F1, USB_GET_ENDPOINT_TYPE(ep->bmAttributes), 512, 2, false); + } else if (ep_idx == 2) { + bflb_usb_fifo_config(USB_FIFO_F2, USB_GET_ENDPOINT_TYPE(ep->bmAttributes), 512, 2, true); + bflb_usb_fifo_config(USB_FIFO_F3, USB_GET_ENDPOINT_TYPE(ep->bmAttributes), 512, 2, false); + } else { + return -1; + } + } +#elif defined(CONFIG_USB_TRIPLE_ENABLE) + if (USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize) > 512) { + return -1; + } else { + bflb_usb_set_ep_fifomap(1, USB_FIFO_F0); + bflb_usb_set_ep_fifomap(2, USB_FIFO_F3); + + bflb_usb_set_fifo_epmap(USB_FIFO_F0, 1, USB_FIFO_DIR_BID); + bflb_usb_set_fifo_epmap(USB_FIFO_F1, 1, USB_FIFO_DIR_BID); + bflb_usb_set_fifo_epmap(USB_FIFO_F2, 1, USB_FIFO_DIR_BID); + bflb_usb_set_fifo_epmap(USB_FIFO_F3, 2, USB_FIFO_DIR_BID); + + if (ep_idx == 1) { + bflb_usb_fifo_config(USB_FIFO_F0, USB_GET_ENDPOINT_TYPE(ep->bmAttributes), 512, 3, true); + bflb_usb_fifo_config(USB_FIFO_F1, USB_GET_ENDPOINT_TYPE(ep->bmAttributes), 512, 3, false); + bflb_usb_fifo_config(USB_FIFO_F2, USB_GET_ENDPOINT_TYPE(ep->bmAttributes), 512, 3, false); + } else if (ep_idx == 2) { + bflb_usb_fifo_config(USB_FIFO_F3, USB_GET_ENDPOINT_TYPE(ep->bmAttributes), 512, 1, true); + } else { + return -1; + } + } +#endif + regval = getreg32(BFLB_USB_BASE + USB_DEV_ADR_OFFSET); + regval |= USB_AFT_CONF; + putreg32(regval, BFLB_USB_BASE + USB_DEV_ADR_OFFSET); + } + return 0; +} + +int usbd_ep_close(uint8_t busid, const uint8_t ep) +{ + return 0; +} + +int usbd_ep_set_stall(uint8_t busid, const uint8_t ep) +{ + uint32_t regval; + + uint8_t ep_idx = USB_EP_GET_IDX(ep); + + if (ep_idx == 0) { + regval = getreg32(BFLB_USB_BASE + USB_DEV_CXCFE_OFFSET); + regval |= USB_CX_STL; + putreg32(regval, BFLB_USB_BASE + USB_DEV_CXCFE_OFFSET); + } else { + if (USB_EP_DIR_IS_OUT(ep)) { + regval = getreg32(BFLB_USB_BASE + USB_DEV_OUTMPS1_OFFSET + (ep_idx - 1) * 4); + regval |= USB_STL_OEP1; + //regval |= USB_RSTG_OEP1; + putreg32(regval, BFLB_USB_BASE + USB_DEV_OUTMPS1_OFFSET + (ep_idx - 1) * 4); + } else { + regval = getreg32(BFLB_USB_BASE + USB_DEV_INMPS1_OFFSET + (ep_idx - 1) * 4); + regval |= USB_STL_IEP1; + //regval |= USB_RSTG_IEP1; + putreg32(regval, BFLB_USB_BASE + USB_DEV_INMPS1_OFFSET + (ep_idx - 1) * 4); + } + } + + return 0; +} + +int usbd_ep_clear_stall(uint8_t busid, const uint8_t ep) +{ + uint32_t regval; + + uint8_t ep_idx = USB_EP_GET_IDX(ep); + + if (ep_idx == 0) { + } else { + if (USB_EP_DIR_IS_OUT(ep)) { + regval = getreg32(BFLB_USB_BASE + USB_DEV_OUTMPS1_OFFSET + (ep_idx - 1) * 4); + //regval &= ~USB_RSTG_OEP1; + regval &= ~USB_STL_OEP1; + putreg32(regval, BFLB_USB_BASE + USB_DEV_OUTMPS1_OFFSET + (ep_idx - 1) * 4); + } else { + regval = getreg32(BFLB_USB_BASE + USB_DEV_INMPS1_OFFSET + (ep_idx - 1) * 4); + //regval &= ~USB_RSTG_IEP1; + regval &= ~USB_STL_IEP1; + putreg32(regval, BFLB_USB_BASE + USB_DEV_INMPS1_OFFSET + (ep_idx - 1) * 4); + } + } + + return 0; +} + +int usbd_ep_is_stalled(uint8_t busid, const uint8_t ep, uint8_t *stalled) +{ + return 0; +} + +int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, uint32_t data_len) +{ + uint8_t ep_idx = USB_EP_GET_IDX(ep); + + if (!data && data_len) { + return -1; + } + + if (!g_bl_udc.in_ep[ep_idx].ep_enable) { + return -2; + } + + g_bl_udc.in_ep[ep_idx].xfer_buf = (uint8_t *)data; + g_bl_udc.in_ep[ep_idx].xfer_len = data_len; + g_bl_udc.in_ep[ep_idx].actual_xfer_len = 0; + g_bl_udc.in_ep[ep_idx].ep_active = true; + + if (ep_idx == 0) { + if (data_len == 0) { + g_bl_udc.in_ep[ep_idx].ep_active = false; + bflb_usb_control_transfer_done(); + } else { + data_len = MIN(data_len, g_bl_udc.in_ep[ep_idx].ep_mps); + g_bl_udc.in_ep[ep_idx].xfer_len = data_len; + bflb_usb_vdma_start_write(USB_FIFO_CXF, data, data_len); + } + } else { + if (data_len == 0) { + bflb_usb_send_zlp(ep_idx); + } else { + bflb_usb_vdma_start_write(usb_get_transfer_fifo(ep_idx), data, data_len); + } + } + + return 0; +} + +int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t data_len) +{ + uint8_t ep_idx = USB_EP_GET_IDX(ep); + + if (!data && data_len) { + return -1; + } + + if (!g_bl_udc.out_ep[ep_idx].ep_enable) { + return -2; + } + + if (data_len == 0) { + return 0; + } + + g_bl_udc.out_ep[ep_idx].xfer_buf = (uint8_t *)data; + g_bl_udc.out_ep[ep_idx].xfer_len = data_len; + g_bl_udc.out_ep[ep_idx].actual_xfer_len = 0; + g_bl_udc.out_ep[ep_idx].ep_active = true; + + if (ep_idx == 0) { + data_len = MIN(data_len, g_bl_udc.out_ep[ep_idx].ep_mps); + g_bl_udc.out_ep[ep_idx].xfer_len = data_len; + bflb_usb_vdma_start_read(USB_FIFO_CXF, data, data_len); + } else { + bflb_usb_vdma_start_read(usb_get_transfer_fifo(ep_idx), data, data_len); + } + return 0; +} + +void USBD_IRQHandler(uint8_t busid) +{ + uint32_t glb_intstatus; + uint32_t dev_intstatus; + uint32_t subgroup_intstatus; + uint32_t regval; + uint8_t ep_idx; + + glb_intstatus = getreg32(BFLB_USB_BASE + USB_GLB_ISR_OFFSET); + + if (glb_intstatus & USB_DEV_INT) { + dev_intstatus = getreg32(BFLB_USB_BASE + USB_DEV_IGR_OFFSET); + if (dev_intstatus & USB_INT_G0) { + subgroup_intstatus = bflb_usb_get_source_group_intstatus(0); + + if (subgroup_intstatus & USB_CX_SETUP_INT) { + bflb_usb_vdma_start_read(USB_FIFO_CXF, g_setup_buffer, 8); + while (getreg32(BFLB_USB_BASE + USB_VDMA_CXFPS1_OFFSET) & USB_VDMA_START_CXF) { + } + + bflb_usb_source_group_int_clear(3, USB_VDMA_CMPLT_CXF); + + usbd_event_ep0_setup_complete_handler(0, g_setup_buffer); + } + } + if (dev_intstatus & USB_INT_G1) { + } + if (dev_intstatus & USB_INT_G2) { + subgroup_intstatus = bflb_usb_get_source_group_intstatus(2); + + if (subgroup_intstatus & USB_SUSP_INT) { + bflb_usb_source_group_int_clear(2, USB_SUSP_INT); + + bflb_usb_reset_fifo(USB_FIFO_F0); + bflb_usb_reset_fifo(USB_FIFO_F1); + bflb_usb_reset_fifo(USB_FIFO_F2); + bflb_usb_reset_fifo(USB_FIFO_F3); + bflb_usb_reset_fifo(USB_FIFO_CXF); + + usbd_event_suspend_handler(0); + } + if (subgroup_intstatus & USB_RESM_INT) { + bflb_usb_source_group_int_clear(2, USB_RESM_INT); + usbd_event_resume_handler(0); + } + if (subgroup_intstatus & USB_TX0BYTE_INT) { + for (uint8_t i = 1; i < 5; i++) { + if (bflb_usb_get_tx_zlp_intstatus() & (1 << (i - 1))) { + bflb_usb_clear_tx_zlp_intstatus(i); + usbd_event_ep_in_complete_handler(0, i | 0x80, 0); + } + } + bflb_usb_source_group_int_clear(2, USB_TX0BYTE_INT); + } + if (subgroup_intstatus & USB_RX0BYTE_INT) { + for (uint8_t i = 1; i < 5; i++) { + if (bflb_usb_get_rx_zlp_intstatus() & (1 << (i - 1))) { + bflb_usb_clear_rx_zlp_intstatus(i); + usbd_event_ep_out_complete_handler(0, i, 0); + } + } + + bflb_usb_source_group_int_clear(2, USB_RX0BYTE_INT); + } + if (subgroup_intstatus & USBRST_INT) { + bflb_usb_source_group_int_clear(2, USBRST_INT); + + bflb_usb_reset_fifo(USB_FIFO_F0); + bflb_usb_reset_fifo(USB_FIFO_F1); + bflb_usb_reset_fifo(USB_FIFO_F2); + bflb_usb_reset_fifo(USB_FIFO_F3); + bflb_usb_reset_fifo(USB_FIFO_CXF); + + regval = getreg32(BFLB_USB_BASE + USB_DEV_SMT_OFFSET); + regval &= ~USB_SOFMT_MASK; +#ifdef CONFIG_USB_HS + regval |= USB_SOF_TIMER_MASK_AFTER_RESET_HS; +#else + regval |= USB_SOF_TIMER_MASK_AFTER_RESET_FS; +#endif + putreg32(regval, BFLB_USB_BASE + USB_DEV_SMT_OFFSET); + + memset(&g_bl_udc, 0, sizeof(g_bl_udc)); + + usbd_event_reset_handler(0); + } + } + if (dev_intstatus & USB_INT_G3) { + subgroup_intstatus = bflb_usb_get_source_group_intstatus(3); + bflb_usb_source_group_int_clear(3, subgroup_intstatus); + if (subgroup_intstatus & USB_VDMA_CMPLT_CXF) { + if (g_bl_udc.in_ep[0].ep_active) { + g_bl_udc.in_ep[0].ep_active = false; + g_bl_udc.in_ep[0].actual_xfer_len = g_bl_udc.in_ep[0].xfer_len - bflb_usb_vdma_get_remain_size(USB_FIFO_CXF); + if (g_bl_udc.in_ep[0].actual_xfer_len < g_bl_udc.in_ep[0].ep_mps) { + bflb_usb_control_transfer_done(); + } + usbd_event_ep_in_complete_handler(0, 0x80, g_bl_udc.in_ep[0].actual_xfer_len); + } else { + g_bl_udc.out_ep[0].ep_active = false; + g_bl_udc.out_ep[0].actual_xfer_len = g_bl_udc.out_ep[0].xfer_len - bflb_usb_vdma_get_remain_size(USB_FIFO_CXF); + usbd_event_ep_out_complete_handler(0, 0x00, g_bl_udc.out_ep[0].actual_xfer_len); + } + } + + for (uint8_t i = 0; i < 4; i++) { + if (subgroup_intstatus & (1 << (i + 1))) { + ep_idx = bflb_usb_get_fifo_ep(i); + if (g_bl_udc.in_ep[ep_idx].ep_active) { + g_bl_udc.in_ep[ep_idx].ep_active = 0; + g_bl_udc.in_ep[ep_idx].actual_xfer_len = g_bl_udc.in_ep[ep_idx].xfer_len - bflb_usb_vdma_get_remain_size(i); + usbd_event_ep_in_complete_handler(0, ep_idx | 0x80, g_bl_udc.in_ep[ep_idx].actual_xfer_len); + } else if (g_bl_udc.out_ep[ep_idx].ep_active) { + g_bl_udc.out_ep[ep_idx].ep_active = 0; + g_bl_udc.out_ep[ep_idx].actual_xfer_len = g_bl_udc.out_ep[ep_idx].xfer_len - bflb_usb_vdma_get_remain_size(i); + usbd_event_ep_out_complete_handler(0, ep_idx & 0x7f, g_bl_udc.out_ep[ep_idx].actual_xfer_len); + } + } + } + } + if (dev_intstatus & USB_INT_G4) { + } + } +} + +#ifdef CONFIG_USBDEV_TEST_MODE +void usbd_execute_test_mode(struct usb_setup_packet *setup) +{ + uint32_t regval; + uint8_t index = setup->wIndex >> 8; + + switch (index) { + case 1: // Test_J + { + regval = getreg32(BFLB_USB_BASE + USB_PHY_TST_OFFSET); + regval |= USB_TST_JSTA; + putreg32(regval, BFLB_USB_BASE + USB_PHY_TST_OFFSET); + bflb_usb_control_transfer_done(); + } break; + case 2: // Test_K + { + regval = getreg32(BFLB_USB_BASE + USB_PHY_TST_OFFSET); + regval |= USB_TST_KSTA; + putreg32(regval, BFLB_USB_BASE + USB_PHY_TST_OFFSET); + + bflb_usb_control_transfer_done(); + } break; + case 3: // TEST_SE0_NAK + { + regval = getreg32(BFLB_USB_BASE + USB_PHY_TST_OFFSET); + regval |= USB_TST_SE0NAK; + putreg32(regval, BFLB_USB_BASE + USB_PHY_TST_OFFSET); + + bflb_usb_control_transfer_done(); + } break; + case 4: // Test_Packet + { + bflb_usb_control_transfer_done(); + regval = getreg32(BFLB_USB_BASE + USB_PHY_TST_OFFSET); + regval |= USB_TST_PKT; + putreg32(regval, BFLB_USB_BASE + USB_PHY_TST_OFFSET); + + __attribute__((aligned(32))) uint8_t temp[53]; + uint8_t *pp; + uint8_t i; + pp = temp; + + for (i = 0; i < 9; i++) /*JKJKJKJK x 9*/ + *pp++ = 0x00; + + for (i = 0; i < 8; i++) /* 8*AA */ + *pp++ = 0xAA; + + for (i = 0; i < 8; i++) /* 8*EE */ + *pp++ = 0xEE; + + *pp++ = 0xFE; + + for (i = 0; i < 11; i++) /* 11*FF */ + *pp++ = 0xFF; + + *pp++ = 0x7F; + *pp++ = 0xBF; + *pp++ = 0xDF; + *pp++ = 0xEF; + *pp++ = 0xF7; + *pp++ = 0xFB; + *pp++ = 0xFD; + *pp++ = 0xFC; + *pp++ = 0x7E; + *pp++ = 0xBF; + *pp++ = 0xDF; + *pp++ = 0xEF; + *pp++ = 0xF7; + *pp++ = 0xFB; + *pp++ = 0xFD; + *pp++ = 0x7E; + + bflb_usb_vdma_start_write(USB_FIFO_CXF, temp, 53); + + regval = getreg32(BFLB_USB_BASE + USB_DEV_CXCFE_OFFSET); + regval |= USB_TST_PKDONE; + putreg32(regval, BFLB_USB_BASE + USB_DEV_CXCFE_OFFSET); + + } break; + case 5: // Test_Force_Enable + break; + + default: + break; + } +} +#endif \ No newline at end of file