/* * Copyright (c) 2022, Artinchip Technology Co., Ltd * * SPDX-License-Identifier: Apache-2.0 */ #include #include "usbd_core.h" #include "usb_dc_aic_reg.h" #define FS_PORT 0 #define HS_PORT 1 #ifndef CONFIG_USB_AIC_DC_PORT #error "please select CONFIG_USB_AIC_DC_PORT with FS_PORT or HS_PORT" #endif #ifdef CONFIG_USB_AIC_DC_BASE #define USB_BASE CONFIG_USB_AIC_DC_BASE #endif #ifndef USB_NUM_BIDIR_ENDPOINTS #define USB_NUM_BIDIR_ENDPOINTS 6 /* define with minimum value*/ #endif #define AIC_UDC_REG ((AIC_UDC_RegDef *)(USB_BASE)) #define AIC_EP_FIFO(i) *(__IO uint32_t *)(USB_BASE + AIC_EP_FIFO_BASE + ((i)*AIC_EP_FIFO_SIZE)) extern uint32_t SystemCoreClock; /* Endpoint state */ struct aic_ep_state { /** Endpoint max packet size */ uint16_t ep_mps; /** Endpoint Transfer Type. * May be Bulk, Interrupt, Control or Isochronous */ uint8_t ep_type; uint8_t ep_stalled; /** Endpoint stall flag */ }; /* Driver state */ struct aic_udc { volatile uint32_t read_len; struct aic_ep_state in_ep[USB_NUM_BIDIR_ENDPOINTS]; /*!< IN endpoint parameters*/ struct aic_ep_state out_ep[USB_NUM_BIDIR_ENDPOINTS]; /*!< OUT endpoint parameters */ uint32_t tx_fifo_map; uint32_t rst_allow; } g_aic_udc; static void aic_set_dma_nextep(void) { uint32_t i; /* dma to set the next-endpoint pointer. */ for (i = 0; i < USB_NUM_BIDIR_ENDPOINTS; i++) { uint32_t next = ((i + 1) % USB_NUM_BIDIR_ENDPOINTS) << DEPCTL_NEXT_EP_BIT; AIC_UDC_REG->inepcfg[i] &= ~DEPCTL_NEXT_EP_MASK; AIC_UDC_REG->inepcfg[i] |= next; } } static inline int aic_reset(void) { uint32_t count = 0U; /* Wait for AHB master IDLE state. */ do { if (++count > 200000U) { return -1; } } while ((AIC_UDC_REG->ahbbasic & AHBBASIC_AHBIDLE) == 0U); /* Core Soft Reset */ count = 0U; AIC_UDC_REG->usbdevinit |= USBDEVINIT_CSFTRST; do { if (++count > 200000U) { return -1; } } while ((AIC_UDC_REG->usbdevinit & USBDEVINIT_CSFTRST) == USBDEVINIT_CSFTRST); return 0; } static inline int aic_core_init(void) { int ret; uint32_t usb_gusbcfg = 0 << 19 /* ULPI Clock SuspendM */ | 0 << 18 /* ULPI Phy Auto Resume */ | 0 << 15 /* PHY Low Power Clock sel */ | 0x5 << 10 /* USB Turnaround time (0x5 for HS phy) */ | 0 << 7 /* ULPI DDR sel 0:single 8bit, 1:double 4bit */ /*| 0 << 6 0: high speed utmi+, 1: full speed serial*/ #ifdef FPGA_BOARD_ARTINCHIP | 1 << 4 /* 0: utmi+, 1:ulpi*/ #else | 0 << 4 /* 0: utmi+, 1:ulpi*/ #endif | 0 << 3 /* UTMI+ PHY 0:8bit, 1:16bit (ULPI PHY set 8bit) */ | 0x7 << 0; /* HS/FS timeout calibration**/ /* Reset after a PHY select */ ret = aic_reset(); /* Activate the USB Transceiver */ AIC_UDC_REG->usbphyif = usb_gusbcfg; aic_set_dma_nextep(); return ret; } static inline int aic_flush_rxfifo(void) { uint32_t count = 0; AIC_UDC_REG->usbdevinit |= USBDEVINIT_RXFFLSH; do { if (++count > 200000U) { return -1; } } while ((AIC_UDC_REG->usbdevinit & USBDEVINIT_RXFFLSH) == USBDEVINIT_RXFFLSH); return 0; } static inline int aic_flush_txfifo(uint32_t num) { uint32_t count = 0U; AIC_UDC_REG->usbdevinit |= USBDEVINIT_TXFNUM(num & USBDEVINIT_TXFNUM_LIMIT); do { if (++count > 200000U) { return -1; } } while ((AIC_UDC_REG->usbdevinit & USBDEVINIT_TXFFLSH) == USBDEVINIT_TXFFLSH); return 0; } #if 0 static uint8_t aic_get_devspeed(void) { return ((AIC_UDC_REG->usblinests & USB_ENUM_SPEED_MASK) >> USB_ENUM_SPEED_SHIFT); } #endif /** * @brief aic_get_glb_intstatus: return the global USB interrupt status * @retval status */ static inline uint32_t aic_get_glb_intstatus(void) { uint32_t tmpreg; tmpreg = AIC_UDC_REG->usbintsts; tmpreg &= AIC_UDC_REG->usbintmsk; return tmpreg; } /** * @brief aic_get_outeps_intstatus: return the USB device OUT endpoints interrupt status * @retval status */ static inline uint32_t aic_get_outeps_intstatus(void) { uint32_t tmpreg; tmpreg = AIC_UDC_REG->usbepint; tmpreg &= AIC_UDC_REG->usbepintmsk; return ((tmpreg & 0xffff0000U) >> 16); } /** * @brief aic_get_ineps_intstatus: return the USB device IN endpoints interrupt status * @retval status */ static inline uint32_t aic_get_ineps_intstatus(void) { uint32_t tmpreg; tmpreg = AIC_UDC_REG->usbepint; tmpreg &= AIC_UDC_REG->usbepintmsk; return ((tmpreg & 0xFFFFU)); } /** * @brief Returns Device OUT EP Interrupt register * @param epnum endpoint number * This parameter can be a value from 0 to 15 * @retval Device OUT EP Interrupt register */ static inline uint32_t aic_get_outep_intstatus(uint8_t epnum) { uint32_t tmpreg; tmpreg = AIC_UDC_REG->outepint[epnum]; tmpreg &= AIC_UDC_REG->outepintmsk; return tmpreg; } /** * @brief Returns Device IN EP Interrupt register * @param epnum endpoint number * This parameter can be a value from 0 to 15 * @retval Device IN EP Interrupt register */ static inline uint32_t aic_get_inep_intstatus(uint8_t epnum) { uint32_t tmpreg; tmpreg = AIC_UDC_REG->inepint[epnum]; tmpreg &= AIC_UDC_REG->inepintmsk; return tmpreg; } __WEAK void usb_dc_low_level_init(void) { } __WEAK void usb_dc_low_level_deinit(void) { } int usb_dc_rst(void) { int ret; uint32_t base = 0; memset(&g_aic_udc, 0, sizeof(struct aic_udc)); /* USB dc global reset */ ret = aic_core_init(); /* Disable Interrupt, Disable connect */ AIC_UDC_REG->usbdevfunc |= USBDEVFUNC_SFTDISCON; AIC_UDC_REG->usbdevinit &= ~USBDEVINIT_GLBL_INTR_EN; /* Device mode configuration */ AIC_UDC_REG->usbdevconf |= PERIOD_FRAME_INTERVAL_80; #if defined(CONFIG_USB_HS) /* Set Core speed to High speed mode */ AIC_UDC_REG->usbdevconf |= DEV_SPEED_HIGH_SPEED_20; #else AIC_UDC_REG->usbdevconf |= DEV_SPEED_FULL_SPEED_11; #endif ret = aic_flush_txfifo(0x10U); ret = aic_flush_rxfifo(); /* Disable all EPs */ for (uint8_t i = 0U; i < USB_NUM_BIDIR_ENDPOINTS; i++) { if ((AIC_UDC_REG->inepcfg[i] & DEPCTL_EPENA) == DEPCTL_EPENA) { if (i == 0U) { AIC_UDC_REG->inepcfg[i] = DEPCTL_SNAK; } else { AIC_UDC_REG->inepcfg[i] = DEPCTL_EPDIS | DEPCTL_SNAK; } } else { AIC_UDC_REG->inepcfg[i] = 0U; } AIC_UDC_REG->ineptsfsiz[i] = 0U; AIC_UDC_REG->inepint[i] = 0xFB7FU; } for (uint8_t i = 0U; i < USB_NUM_BIDIR_ENDPOINTS; i++) { if ((AIC_UDC_REG->outepcfg[i] & DEPCTL_EPENA) == DEPCTL_EPENA) { if (i == 0U) { AIC_UDC_REG->outepcfg[i] = DEPCTL_SNAK; } else { AIC_UDC_REG->outepcfg[i] = DEPCTL_EPDIS | DEPCTL_SNAK; } } else { AIC_UDC_REG->outepcfg[i] = 0U; } AIC_UDC_REG->outeptsfsiz[i] = 0U; AIC_UDC_REG->outepint[i] = 0xFB7FU; } /* Clear all pending Device Interrupts */ AIC_UDC_REG->inepintmsk = 0U; AIC_UDC_REG->outepintmsk = 0U; AIC_UDC_REG->usbepintmsk = 0U; /* Disable all interrupts. */ AIC_UDC_REG->usbintmsk = 0U; /* Clear any pending interrupts */ AIC_UDC_REG->usbintsts = 0xBFFFFFFFU; /* Enable interrupts matching to the Device mode ONLY */ AIC_UDC_REG->usbintmsk = INT_SUSPEND | INT_RESET | INT_ENUMDONE | INT_OUT_EP | INT_IN_EP | INT_RX_FIFO_NOT_EMPTY | INT_RESUME; AIC_UDC_REG->outepintmsk = CTRL_OUT_EP_SETUP_PHASE_DONE | TRANSFER_DONE; AIC_UDC_REG->inepintmsk = TRANSFER_DONE; /* Assign FIFO */ base = 0; AIC_UDC_REG->rxfifosiz = AIC_RX_FIFO_SIZE; base += AIC_RX_FIFO_SIZE; AIC_UDC_REG->nptxfifosiz = (AIC_NP_TX_FIFO_SIZE << 16) | base; base += AIC_NP_TX_FIFO_SIZE; AIC_UDC_REG->txfifosiz[0] = (AIC_PERIOD_TX_FIFO1_SIZE << 16) | base; base += AIC_PERIOD_TX_FIFO1_SIZE; AIC_UDC_REG->txfifosiz[1] = (AIC_PERIOD_TX_FIFO2_SIZE << 16) | base; /* Enable EP0 */ usbd_event_notify_handler(USBD_EVENT_RESET, NULL); /* Enable Interrupt, Enable connect */ AIC_UDC_REG->usbdevinit |= USBDEVINIT_GLBL_INTR_EN; AIC_UDC_REG->usbdevfunc &= ~USBDEVFUNC_SFTDISCON; return ret; } int usb_dc_init(void) { int ret; usb_dc_low_level_init(); ret = usb_dc_rst(); return ret; } int usb_dc_deinit(void) { usb_dc_low_level_deinit(); /* Clear Pending interrupt */ for (uint8_t i = 0U; i < USB_NUM_BIDIR_ENDPOINTS; i++) { AIC_UDC_REG->outepint[i] = 0xFB7FU; AIC_UDC_REG->inepint[i] = 0xFB7FU; } /* Clear interrupt masks */ AIC_UDC_REG->inepintmsk = 0U; AIC_UDC_REG->outepintmsk = 0U; AIC_UDC_REG->usbepintmsk = 0U; /* Flush the FIFO */ aic_flush_txfifo(0x10U); aic_flush_rxfifo(); AIC_UDC_REG->usbdevfunc |= USBDEVFUNC_SFTDISCON; return 0; } int usbd_set_address(const uint8_t addr) { AIC_UDC_REG->usbdevconf &= ~(DEVICE_ADDRESS_MASK); AIC_UDC_REG->usbdevconf |= ((uint32_t)addr << 4) & DEVICE_ADDRESS_MASK; return 0; } int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg) { uint8_t ep_idx; uint16_t ep_mps; uint8_t tx_fifo_num = 0; uint32_t i; if (!ep_cfg) { return -1; } ep_idx = USB_EP_GET_IDX(ep_cfg->ep_addr); if (USB_EP_DIR_IS_OUT(ep_cfg->ep_addr)) { g_aic_udc.out_ep[ep_idx].ep_mps = ep_cfg->ep_mps; g_aic_udc.out_ep[ep_idx].ep_type = ep_cfg->ep_type; AIC_UDC_REG->usbepintmsk |= DAINT_OUT_MASK & (uint32_t)(1UL << (16 + ep_idx)); ep_mps = ep_cfg->ep_mps; if (ep_idx == 0) { switch (ep_cfg->ep_mps) { case 8: ep_mps = DEPCTL0_MPS_8; break; case 16: ep_mps = DEPCTL0_MPS_16; break; case 32: ep_mps = DEPCTL0_MPS_32; break; case 64: ep_mps = DEPCTL0_MPS_64; break; } } AIC_UDC_REG->outepcfg[ep_idx] |= (ep_mps & DEPCTL_MPS_MASK) | ((uint32_t)ep_cfg->ep_type << 18) | DEPCTL_SETD0PID | DEPCTL_USBACTEP; /* EP enable */ AIC_UDC_REG->outepcfg[ep_idx] |= (DEPCTL_CNAK | DEPCTL_EPENA); } else { g_aic_udc.in_ep[ep_idx].ep_mps = ep_cfg->ep_mps; g_aic_udc.in_ep[ep_idx].ep_type = ep_cfg->ep_type; AIC_UDC_REG->usbepintmsk |= DAINT_IN_MASK & (uint32_t)(1UL << ep_idx); /* Period IN EP alloc fifo num */ if ((ep_cfg->ep_type == USB_ENDPOINT_TYPE_INTERRUPT) || (ep_cfg->ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS)){ for (i=1; i<=2; i++){ if (g_aic_udc.tx_fifo_map & (1<inepcfg[ep_idx] |= (ep_cfg->ep_mps & DEPCTL_MPS_MASK) | ((uint32_t)ep_cfg->ep_type << 18) | (tx_fifo_num << 22) | DEPCTL_SETD0PID | DEPCTL_USBACTEP; } return 0; } int usbd_ep_close(const uint8_t ep) { return 0; } int usbd_ep_set_stall(const uint8_t ep) { uint8_t ep_idx = USB_EP_GET_IDX(ep); if (USB_EP_DIR_IS_OUT(ep)) { if (((AIC_UDC_REG->outepcfg[ep_idx] & DEPCTL_EPENA) == 0U) && (ep_idx != 0U)) { AIC_UDC_REG->outepcfg[ep_idx] &= ~(DEPCTL_EPDIS); } AIC_UDC_REG->outepcfg[ep_idx] |= DEPCTL_STALL; } else { if (((AIC_UDC_REG->inepcfg[ep_idx] & DEPCTL_EPENA) == 0U) && (ep_idx != 0U)) { AIC_UDC_REG->inepcfg[ep_idx] &= ~(DEPCTL_EPDIS); } AIC_UDC_REG->inepcfg[ep_idx] |= DEPCTL_STALL; } return 0; } int usbd_ep_clear_stall(const uint8_t ep) { uint8_t ep_idx = USB_EP_GET_IDX(ep); if (USB_EP_DIR_IS_OUT(ep)) { AIC_UDC_REG->outepcfg[ep_idx] &= ~DEPCTL_STALL; if ((g_aic_udc.out_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_INTERRUPT) || (g_aic_udc.out_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_BULK)) { AIC_UDC_REG->outepcfg[ep_idx] |= DEPCTL_SETD0PID; /* DATA0 */ } } else { AIC_UDC_REG->inepcfg[ep_idx] &= ~DEPCTL_STALL; if ((g_aic_udc.in_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_INTERRUPT) || (g_aic_udc.in_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_BULK)) { AIC_UDC_REG->inepcfg[ep_idx] |= DEPCTL_SETD0PID; /* DATA0 */ } } return 0; } int usbd_ep_is_stalled(const uint8_t ep, uint8_t *stalled) { if (USB_EP_DIR_IS_OUT(ep)) { } else { } return 0; } int usbd_ep_write(const uint8_t ep, const uint8_t *data, uint32_t data_len, uint32_t *ret_bytes) { uint8_t ep_idx = USB_EP_GET_IDX(ep); uint32_t len32b; uint32_t pktcnt; if (!data && data_len) { return -1; } if (data_len > g_aic_udc.in_ep[ep_idx].ep_mps) { data_len = g_aic_udc.in_ep[ep_idx].ep_mps; } len32b = (data_len + 3U) / 4U; if (!data_len) { AIC_UDC_REG->ineptsfsiz[ep_idx] &= ~(DXEPTSIZ_PKT_CNT_MASK); AIC_UDC_REG->ineptsfsiz[ep_idx] &= ~(DXEPTSIZ_XFER_SIZE_MASK); AIC_UDC_REG->ineptsfsiz[ep_idx] |= (DXEPTSIZ_PKT_CNT_MASK & (1U << 19)); /* EP enable, IN data in FIFO */ AIC_UDC_REG->inepcfg[ep_idx] |= (DEPCTL_CNAK | DEPCTL_EPENA); return 0; } /* Program the transfer size and packet count * as follows: xfersize = N * maxpacket + * short_packet pktcnt = N + (short_packet * exist ? 1 : 0) */ pktcnt = (uint16_t)((data_len + g_aic_udc.in_ep[ep_idx].ep_mps - 1U) / g_aic_udc.in_ep[ep_idx].ep_mps); AIC_UDC_REG->ineptsfsiz[ep_idx] &= ~(DXEPTSIZ_PKT_CNT_MASK); AIC_UDC_REG->ineptsfsiz[ep_idx] |= (DXEPTSIZ_PKT_CNT_MASK & (pktcnt << 19)); AIC_UDC_REG->ineptsfsiz[ep_idx] &= ~(DXEPTSIZ_XFER_SIZE_MASK); AIC_UDC_REG->ineptsfsiz[ep_idx] |= (DXEPTSIZ_XFER_SIZE_MASK & data_len); /* EP enable, IN data in FIFO */ AIC_UDC_REG->inepcfg[ep_idx] |= (DEPCTL_CNAK | DEPCTL_EPENA); if (g_aic_udc.in_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS) { AIC_UDC_REG->ineptsfsiz[ep_idx] &= ~(DXEPTSIZ_MULCNT_MASK); AIC_UDC_REG->ineptsfsiz[ep_idx] |= (DXEPTSIZ_MULCNT_MASK & (1U << 29)); if ((AIC_UDC_REG->usblinests & (1U << 8)) == 0U) { AIC_UDC_REG->inepcfg[ep_idx] |= DEPCTL_SETD1PID; } else { AIC_UDC_REG->inepcfg[ep_idx] |= DEPCTL_SETD0PID; } } for (uint8_t i = 0U; i < len32b; i++) { AIC_EP_FIFO(ep_idx) = ((uint32_t *)data)[i]; } if (ret_bytes) { *ret_bytes = data_len; } return 0; } int usbd_ep_read(const uint8_t ep, uint8_t *data, uint32_t max_data_len, uint32_t *read_bytes) { uint8_t ep_idx = USB_EP_GET_IDX(ep); uint32_t *pdest = (uint32_t *)data; uint32_t len32b; uint32_t read_count; uint32_t pktcnt; if (!data && max_data_len) { return -1; } if (((uint32_t)(unsigned long)data) & 0x03) { return -2; } if (max_data_len > g_aic_udc.out_ep[ep_idx].ep_mps) { max_data_len = g_aic_udc.out_ep[ep_idx].ep_mps; } if (!max_data_len) { if (ep_idx != 0) { /* Program the transfer size and packet count as follows: * pktcnt = N * xfersize = N * maxpacket */ pktcnt = (uint16_t)((max_data_len + g_aic_udc.out_ep[ep_idx].ep_mps - 1U) / g_aic_udc.out_ep[ep_idx].ep_mps); AIC_UDC_REG->outeptsfsiz[ep_idx] &= ~(DXEPTSIZ_PKT_CNT_MASK); AIC_UDC_REG->outeptsfsiz[ep_idx] &= ~(DXEPTSIZ_XFER_SIZE_MASK); AIC_UDC_REG->outeptsfsiz[ep_idx] |= (DXEPTSIZ_PKT_CNT_MASK & (1 << 19)); AIC_UDC_REG->outeptsfsiz[ep_idx] |= (DXEPTSIZ_XFER_SIZE_MASK & g_aic_udc.out_ep[ep_idx].ep_mps * pktcnt); /* EP enable */ AIC_UDC_REG->outepcfg[ep_idx] |= (DEPCTL_CNAK | DEPCTL_EPENA); } return 0; } read_count = g_aic_udc.read_len; read_count = MIN(read_count, max_data_len); len32b = ((uint32_t)read_count + 3U) / 4U; for (uint8_t i = 0U; i < len32b; i++) { *pdest = AIC_EP_FIFO(0U); pdest++; } if (read_bytes) { *read_bytes = read_count; } g_aic_udc.read_len = 0; return 0; } irqreturn_t USBD_IRQHandler(int irq, void * data) { uint32_t gint_status, temp, epnum, ep_intr, epint; gint_status = aic_get_glb_intstatus(); /* Avoid spurious interrupt */ if (gint_status == 0) { return IRQ_HANDLED; } if (gint_status & INT_RESET) { AIC_UDC_REG->usbintsts |= INT_RESET; if (g_aic_udc.rst_allow){ usb_dc_rst(); }else{ g_aic_udc.rst_allow = 1; } } //if (gint_status & INT_RESET) { if (0) { AIC_UDC_REG->usbintsts |= INT_RESET; AIC_UDC_REG->usbdevfunc &= ~USBDEVFUNC_RMTWKUPSIG; g_aic_udc.tx_fifo_map = 0; aic_flush_txfifo(0x10U); aic_flush_rxfifo(); for (uint8_t i = 0U; i < USB_NUM_BIDIR_ENDPOINTS; i++) { AIC_UDC_REG->inepint[i] = 0xFB7FU; AIC_UDC_REG->inepcfg[i] &= ~DEPCTL_STALL; AIC_UDC_REG->inepcfg[i] |= DEPCTL_SNAK; AIC_UDC_REG->outepint[i] = 0xFB7FU; AIC_UDC_REG->outepcfg[i] &= ~DEPCTL_STALL; AIC_UDC_REG->outepcfg[i] |= DEPCTL_SNAK; } AIC_UDC_REG->usbepintmsk |= 0x10001U; AIC_UDC_REG->outeptsfsiz[0] = 0U; AIC_UDC_REG->outeptsfsiz[0] |= (DXEPTSIZ_PKT_CNT_MASK & (1U << 19)); AIC_UDC_REG->outeptsfsiz[0] |= (3U * 8U); AIC_UDC_REG->outeptsfsiz[0] |= DXEPTSIZ_MULCNT_MASK; AIC_UDC_REG->outepcfg[0] |= DEPCTL_EPENA | DEPCTL_CNAK; usbd_event_notify_handler(USBD_EVENT_RESET, NULL); } /* Handle RxQLevel Interrupt */ if (gint_status & INT_RX_FIFO_NOT_EMPTY) { AIC_UDC_REG->usbintmsk &= ~(INT_RX_FIFO_NOT_EMPTY); temp = AIC_UDC_REG->rxfifosts; epnum = temp & RXFIFOSTS_EPNUM_MASK; g_aic_udc.read_len = (temp & RXFIFOSTS_BCNT_MASK) >> 4; if ((temp & RXFIFOSTS_PKTSTS_MASK) == PKTSTS_OUT_DATA_PKT_REC) { if (g_aic_udc.read_len != 0U) { if (epnum == 0) { usbd_event_notify_handler(USBD_EVENT_EP0_OUT_NOTIFY, NULL); } else { usbd_event_notify_handler(USBD_EVENT_EP_OUT_NOTIFY, (void *)(unsigned long)(epnum | USB_EP_DIR_OUT)); } } } else if ((temp & RXFIFOSTS_PKTSTS_MASK) == PKTSTS_SETUP_DATA_PKT_REC) { usbd_event_notify_handler(USBD_EVENT_SETUP_NOTIFY, NULL); } else { /* ... */ } AIC_UDC_REG->usbintmsk |= INT_RX_FIFO_NOT_EMPTY; } if (gint_status & INT_OUT_EP) { epnum = 0; ep_intr = aic_get_outeps_intstatus(); while (ep_intr != 0U) { if ((ep_intr & 0x1U) != 0U) { epint = aic_get_outep_intstatus(epnum); AIC_UDC_REG->outepint[epnum] = epint; if ((epint & CTRL_OUT_EP_SETUP_PHASE_DONE) == CTRL_OUT_EP_SETUP_PHASE_DONE) { AIC_UDC_REG->outeptsfsiz[0] = 1U << DXEPTSIZ_PKT_CNT_SHIFT | (AIC_UDC_REG->outepcfg[0] & DEPCTL_MPS_MASK) << DXEPTSIZ_XFER_SIZE_SHIFT; AIC_UDC_REG->outepcfg[0] |= (DEPCTL_EPENA | DEPCTL_CNAK); } if ((epint & TRANSFER_DONE) == TRANSFER_DONE) { if (epnum == 0) { AIC_UDC_REG->outeptsfsiz[0] = 1U << DXEPTSIZ_PKT_CNT_SHIFT | (AIC_UDC_REG->outepcfg[0] & DEPCTL_MPS_MASK) << DXEPTSIZ_XFER_SIZE_SHIFT; AIC_UDC_REG->outepcfg[0] |= (DEPCTL_EPENA | DEPCTL_CNAK); } } } ep_intr >>= 1U; epnum++; } } if (gint_status & INT_IN_EP) { epnum = 0U; ep_intr = aic_get_ineps_intstatus(); while (ep_intr != 0U) { if ((ep_intr & 0x1U) != 0U) { epint = aic_get_inep_intstatus(epnum); AIC_UDC_REG->inepint[epnum] = epint; if ((epint & TRANSFER_DONE) == TRANSFER_DONE) { if (epnum == 0) { usbd_event_notify_handler(USBD_EVENT_EP0_IN_NOTIFY, NULL); } else { usbd_event_notify_handler(USBD_EVENT_EP_IN_NOTIFY, (void *)(unsigned long)(epnum | USB_EP_DIR_IN)); } } } ep_intr >>= 1U; epnum++; } } if (gint_status & INT_ENUMDONE) { AIC_UDC_REG->usbintsts |= INT_ENUMDONE; AIC_UDC_REG->usbdevfunc |= USBDEVFUNC_CGNPINNAK; } if (gint_status & INT_SOF) { AIC_UDC_REG->usbintsts |= INT_SOF; } if (gint_status & INT_SUSPEND) { AIC_UDC_REG->usbintsts |= INT_SUSPEND; } return IRQ_HANDLED; }