From a41000a0002d66b9ee741a2d32862941f0aa77a2 Mon Sep 17 00:00:00 2001 From: sakumisu <1203593632@qq.com> Date: Tue, 6 May 2025 21:45:03 +0800 Subject: [PATCH] update(port/aic): sync code from luban lite Signed-off-by: sakumisu <1203593632@qq.com> --- port/aic/usb_dc_aic.c | 915 ++++++++++++++++++++++++++------------ port/aic/usb_dc_aic_ll.c | 23 +- port/aic/usb_dc_aic_reg.h | 13 +- 3 files changed, 668 insertions(+), 283 deletions(-) diff --git a/port/aic/usb_dc_aic.c b/port/aic/usb_dc_aic.c index 46cbfea8..fafa6118 100644 --- a/port/aic/usb_dc_aic.c +++ b/port/aic/usb_dc_aic.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Artinchip Technology Co., Ltd + * Copyright (c) 2023-2024, ArtInChip Technology Co., Ltd * * SPDX-License-Identifier: Apache-2.0 */ @@ -48,12 +48,16 @@ #define USB_NUM_BIDIR_ENDPOINTS 5 /* define with minimum value*/ #endif +/* USB_P_TXFIFO_NUM: + * There are only 2 Periodic_TXFIFO, and each Interrupt/Isochronous In ep + * needs to request one P_TXFIFO. So, only two Interrupt/Isochronous In ep + * can be requested for at most. + */ +#define USB_P_TXFIFO_NUM 2 + #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)) -static uint8_t g_aic_udc_ibuf[USB_RAM_SIZE] __ALIGNED(CACHE_LINE_SIZE); -static uint8_t g_aic_udc_obuf[USB_RAM_SIZE] __ALIGNED(CACHE_LINE_SIZE); - /* Endpoint state */ struct aic_ep_state { uint16_t ep_mps; /* Endpoint max packet size */ @@ -75,13 +79,23 @@ extern uint32_t usbd_clk; USB_MEM_ALIGNX struct usb_setup_packet setup; USB_MEM_ALIGNX 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; + struct usb_endpoint_descriptor in_ep_desc[USB_NUM_BIDIR_ENDPOINTS]; + uint32_t p_txfifo_map; /* map which periodic_txfifo is used */ + uint32_t np_txfifo_map; /* map no-periodic_txfifo is used */ } g_aic_udc; -uint8_t rst_allow = 0; +#define AIC_EP0_SETUP 1 +#define AIC_EP0_DATA_IN 2 +#define AIC_EP0_STATUS_OUT 3 +#define AIC_EP0_DATA_OUT 12 +#define AIC_EP0_STATUS_IN 13 + uint8_t ep0_ctrl_stage = 0; /* 1 = setup stage, 2 = data stage, 3 = status stage */ #ifdef CONFIG_USB_AIC_DMA_ENABLE +static uint8_t g_aic_udc_ibuf[USB_RAM_SIZE] __ALIGNED(CACHE_LINE_SIZE); +static uint8_t g_aic_udc_obuf[USB_RAM_SIZE] __ALIGNED(CACHE_LINE_SIZE); + void aic_udc_dcache_clean(uintptr_t addr, uint32_t len) { aicos_dcache_clean_range((size_t *)addr, len); @@ -109,6 +123,7 @@ static int aic_udc_ep_buf_alloc(struct aic_ep_state *ep, uint32_t len, if (ep->xfer_align_len > USB_RAM_SIZE) { ep->xfer_align_buf = aicos_malloc_align(0, ep->xfer_align_len, CACHE_LINE_SIZE); + USB_LOG_DBG("aicos_malloc_align %d bytes.", ep->xfer_align_len); if (!ep->xfer_align_buf) { USB_LOG_ERR("alloc error.\r\n"); return -5; @@ -126,8 +141,10 @@ static void aic_udc_ep_buf_free(struct aic_ep_state *ep, uint8_t *sbuf) return; /* Whether the buf is allocated dynamically */ - if (ep->xfer_align_buf != sbuf) + if (ep->xfer_align_buf != sbuf) { + USB_LOG_DBG("aicos_free_align %d bytes.", ep->xfer_align_len); aicos_free_align(0, ep->xfer_align_buf); + } ep->xfer_align_buf = NULL; ep->xfer_align_len = 0; @@ -161,36 +178,44 @@ static void aic_udc_obuf_free(struct aic_ep_state *ep) static void aic_set_dma_nextep(void) { uint32_t i; + uint32_t inepcfg = 0; /* 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; + inepcfg = readl(&AIC_UDC_REG->inepcfg[i]); + inepcfg &= ~DEPCTL_NEXT_EP_MASK; + inepcfg |= next; + writel(inepcfg, &AIC_UDC_REG->inepcfg[i]); } } static inline int aic_reset(void) { uint32_t count = 0U; + uint32_t tmpreg = 0; /* Wait for AHB master IDLE state. */ do { if (++count > 200000U) { return -1; } - } while ((AIC_UDC_REG->ahbbasic & AHBBASIC_AHBIDLE) == 0U); + tmpreg = readl(&AIC_UDC_REG->ahbbasic); + } while ((tmpreg & AHBBASIC_AHBIDLE) == 0U); /* Core Soft Reset */ count = 0U; - AIC_UDC_REG->usbdevinit |= USBDEVINIT_CSFTRST; + tmpreg = readl(&AIC_UDC_REG->usbdevinit); + tmpreg |= USBDEVINIT_CSFTRST; + writel(tmpreg, &AIC_UDC_REG->usbdevinit); do { if (++count > 200000U) { return -1; } - } while ((AIC_UDC_REG->usbdevinit & USBDEVINIT_CSFTRST) == USBDEVINIT_CSFTRST); + tmpreg = readl(&AIC_UDC_REG->usbdevinit); + } while ((tmpreg & USBDEVINIT_CSFTRST) == USBDEVINIT_CSFTRST); return 0; } @@ -213,12 +238,12 @@ static inline int aic_core_init(void) | 0 << 3 /* UTMI+ PHY 0:8bit, 1:16bit (ULPI PHY set 8bit) */ | 0x7 << 0; /* HS/FS timeout calibration**/ + /* Activate the USB Transceiver */ + writel(usb_gusbcfg, &AIC_UDC_REG->usbphyif); + /* Reset after a PHY select */ ret = aic_reset(); - /* Activate the USB Transceiver */ - AIC_UDC_REG->usbphyif = usb_gusbcfg; - aic_set_dma_nextep(); return ret; @@ -227,14 +252,18 @@ static inline int aic_core_init(void) static inline int aic_flush_rxfifo(void) { uint32_t count = 0; + uint32_t tmpreg = 0; - AIC_UDC_REG->usbdevinit |= USBDEVINIT_RXFFLSH; + tmpreg = readl(&AIC_UDC_REG->usbdevinit); + tmpreg |= USBDEVINIT_RXFFLSH; + writel(tmpreg, &AIC_UDC_REG->usbdevinit); do { if (++count > 200000U) { return -1; } - } while ((AIC_UDC_REG->usbdevinit & USBDEVINIT_RXFFLSH) == USBDEVINIT_RXFFLSH); + tmpreg = readl(&AIC_UDC_REG->usbdevinit); + } while ((tmpreg & USBDEVINIT_RXFFLSH) == USBDEVINIT_RXFFLSH); return 0; } @@ -242,14 +271,20 @@ static inline int aic_flush_rxfifo(void) static inline int aic_flush_txfifo(uint32_t num) { uint32_t count = 0U; + uint32_t tmpreg = 0; - AIC_UDC_REG->usbdevinit |= USBDEVINIT_TXFNUM(num & USBDEVINIT_TXFNUM_LIMIT); + tmpreg = readl(&AIC_UDC_REG->usbdevinit); + tmpreg &= ~ USBDEVINIT_TXFNUM(USBDEVINIT_TXFNUM_LIMIT); + tmpreg |= USBDEVINIT_TXFNUM(num & USBDEVINIT_TXFNUM_LIMIT) + | USBDEVINIT_TXFFLSH; + writel(tmpreg, &AIC_UDC_REG->usbdevinit); do { if (++count > 200000U) { return -1; } - } while ((AIC_UDC_REG->usbdevinit & USBDEVINIT_TXFFLSH) == USBDEVINIT_TXFFLSH); + tmpreg = readl(&AIC_UDC_REG->usbdevinit); + } while ((tmpreg & USBDEVINIT_TXFFLSH) == USBDEVINIT_TXFFLSH); return 0; } @@ -257,6 +292,7 @@ static inline int aic_flush_txfifo(uint32_t num) static void aic_set_turnaroundtime(uint32_t hclk, uint8_t speed) { uint32_t UsbTrd; + uint32_t tmpreg = 0; /* The USBTRD is configured according to the tables below, depending on AHB frequency used by application. In the low AHB frequency range it is used to stretch enough the USB response @@ -300,11 +336,12 @@ static void aic_set_turnaroundtime(uint32_t hclk, uint8_t speed) UsbTrd = USBPHYIF_DEFAULT_TRDT_VALUE; } - AIC_UDC_REG->usbphyif |= USBPHYIF_TOUTCAL_LIMIT; - - AIC_UDC_REG->usbphyif &= ~USBPHYIF_USBTRDTIM_MASK; - AIC_UDC_REG->usbphyif |= (uint32_t)((UsbTrd << USBPHYIF_USBTRDTIM_SHIFT) - & USBPHYIF_USBTRDTIM_MASK); + tmpreg = readl(&AIC_UDC_REG->usbphyif); + tmpreg |= USBPHYIF_TOUTCAL_LIMIT; + tmpreg &= ~USBPHYIF_USBTRDTIM_MASK; + tmpreg |= (uint32_t)((UsbTrd << USBPHYIF_USBTRDTIM_SHIFT) + & USBPHYIF_USBTRDTIM_MASK); + writel(tmpreg, &AIC_UDC_REG->usbphyif); } #if 0 @@ -342,8 +379,9 @@ static void aic_set_txfifo(uint8_t fifo, uint16_t size) static uint8_t aic_get_devspeed(void) { uint8_t speed; - uint32_t DevEnumSpeed = AIC_UDC_REG->usblinests & USB_ENUM_SPEED_MASK; + uint32_t DevEnumSpeed = readl(&AIC_UDC_REG->usblinests); + DevEnumSpeed &= USB_ENUM_SPEED_MASK; if (DevEnumSpeed == USB_HIGH_30_60MHZ) { speed = USB_ENUM_SPEED_HIGH; } else if (DevEnumSpeed == USB_FULL_30_60MHZ) { @@ -357,23 +395,28 @@ static uint8_t aic_get_devspeed(void) static void aic_ep0_start_read_setup(uint8_t *psetup) { + uint32_t outepcfg = 0; + g_aic_udc.out_ep[0].xfer_buf = psetup; g_aic_udc.out_ep[0].xfer_len = 8; - ep0_ctrl_stage = 1; + ep0_ctrl_stage = AIC_EP0_SETUP; + + USB_LOG_DBG("\r\n"); + USB_LOG_DBG("[1]: Control transfer start read setup."); aic_udc_dcache_invalidate((uintptr_t)psetup, CACHE_LINE_SIZE); - 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; + writel((1<<29) | (DXEPTSIZ_PKT_CNT_MASK & (1U << 19)) | (8U), &AIC_UDC_REG->outeptsfsiz[0]); #ifdef CONFIG_USB_AIC_DMA_ENABLE - AIC_UDC_REG->outepdmaaddr[0] = (uint32_t)(uintptr_t)psetup; + writel((uint32_t)(uintptr_t)psetup, &AIC_UDC_REG->outepdmaaddr[0]); #endif + writel(0xFFFFFFFFU, &AIC_UDC_REG->outepint[0]); /* EP enable */ - AIC_UDC_REG->outepcfg[0] |= DEPCTL_CNAK | DEPCTL_EPENA | DEPCTL_USBACTEP; + outepcfg = readl(&AIC_UDC_REG->outepcfg[0]); + outepcfg |= DEPCTL_CNAK | DEPCTL_EPENA | DEPCTL_USBACTEP; + writel(outepcfg, &AIC_UDC_REG->outepcfg[0]); } void aic_ep_write(uint8_t ep_idx, uint8_t *src, uint16_t len) @@ -435,11 +478,12 @@ static void aic_tx_fifo_empty_procecss(uint8_t ep_idx) static inline uint32_t aic_get_glb_intstatus(void) { uint32_t tmpreg; + uint32_t mask; - tmpreg = AIC_UDC_REG->usbintsts; - tmpreg &= AIC_UDC_REG->usbintmsk; + tmpreg = readl(&AIC_UDC_REG->usbintsts); + mask = readl(&AIC_UDC_REG->usbintmsk); - return tmpreg; + return tmpreg & mask; } /** @@ -449,11 +493,12 @@ static inline uint32_t aic_get_glb_intstatus(void) static inline uint32_t aic_get_outeps_intstatus(void) { uint32_t tmpreg; + uint32_t mask; - tmpreg = AIC_UDC_REG->usbepint; - tmpreg &= AIC_UDC_REG->usbepintmsk; + tmpreg = readl(&AIC_UDC_REG->usbepint); + mask = readl(&AIC_UDC_REG->usbepintmsk); - return ((tmpreg & 0xffff0000U) >> 16); + return (((tmpreg & mask) & 0xffff0000U) >> 16); } /** @@ -463,11 +508,12 @@ static inline uint32_t aic_get_outeps_intstatus(void) static inline uint32_t aic_get_ineps_intstatus(void) { uint32_t tmpreg; + uint32_t mask; - tmpreg = AIC_UDC_REG->usbepint; - tmpreg &= AIC_UDC_REG->usbepintmsk; + tmpreg = readl(&AIC_UDC_REG->usbepint); + mask = readl(&AIC_UDC_REG->usbepintmsk); - return ((tmpreg & 0xFFFFU)); + return ((tmpreg & mask) & 0xFFFFU); } /** @@ -479,11 +525,13 @@ static inline uint32_t aic_get_ineps_intstatus(void) static inline uint32_t aic_get_outep_intstatus(uint8_t epnum) { uint32_t tmpreg; + uint32_t mask; - tmpreg = AIC_UDC_REG->outepint[epnum]; - tmpreg &= AIC_UDC_REG->outepintmsk; + tmpreg = readl(&AIC_UDC_REG->outepint[epnum]); + USB_LOG_DBG("[int]: Out ep%d outepint = 0x%x [%d].", epnum, tmpreg, ep0_ctrl_stage); + mask = readl(&AIC_UDC_REG->outepintmsk); - return tmpreg; + return tmpreg & mask; } /** @@ -495,11 +543,13 @@ static inline uint32_t aic_get_outep_intstatus(uint8_t epnum) static inline uint32_t aic_get_inep_intstatus(uint8_t epnum) { uint32_t tmpreg; + uint32_t mask; - tmpreg = AIC_UDC_REG->inepint[epnum]; - tmpreg &= AIC_UDC_REG->inepintmsk; + tmpreg = readl(&AIC_UDC_REG->inepint[epnum]); + USB_LOG_DBG("[int]: In ep%d inepint = 0x%x [%d].", epnum, tmpreg, ep0_ctrl_stage); + mask = readl(&AIC_UDC_REG->inepintmsk); - return tmpreg; + return tmpreg & mask; } __WEAK void usb_dc_low_level_init(void) @@ -512,29 +562,40 @@ __WEAK void usb_dc_low_level_deinit(void) int usb_dc_rst(void) { + uint32_t outepintmsk = 0; + uint32_t inepintmsk = 0; + + USB_LOG_DBG("usb_dc_rst.\n"); + + usbd_set_address(0); + + aic_flush_txfifo(0x10U); + aic_flush_rxfifo(); + for (uint8_t i = 0U; i < USB_NUM_BIDIR_ENDPOINTS; i++) { if (i == 0U) { - AIC_UDC_REG->inepcfg[i] = DEPCTL_SNAK; - AIC_UDC_REG->outepcfg[i] = DEPCTL_SNAK; + writel(DEPCTL_SNAK, &AIC_UDC_REG->inepcfg[i]); + writel(DEPCTL_SNAK, &AIC_UDC_REG->outepcfg[i]); } else { usbd_ep_close(i); usbd_ep_close(i | 0x80); } - AIC_UDC_REG->ineptsfsiz[i] = 0U; - AIC_UDC_REG->inepint[i] = 0xFBFFU; - AIC_UDC_REG->outeptsfsiz[i] = 0U; - AIC_UDC_REG->outepint[i] = 0xFBFFU; + + writel(0U, &AIC_UDC_REG->ineptsfsiz[i]); + writel(0xFFFFFFFFU, &AIC_UDC_REG->inepint[i]); + writel(0U, &AIC_UDC_REG->outeptsfsiz[i]); + writel(0xFFFFFFFFU, &AIC_UDC_REG->outepint[i]); } - AIC_UDC_REG->usbepintmsk |= 0x10001U; - AIC_UDC_REG->outepintmsk = CTRL_OUT_EP_SETUP_PHASE_DONE | TRANSFER_DONE; - AIC_UDC_REG->inepintmsk = TRANSFER_DONE; + writel(0, &AIC_UDC_REG->usbepintmsk); + outepintmsk = TRANSFER_DONE | CTRL_OUT_EP_SETUP_PHASE_DONE | CTRL_OUT_EP_STATUS_PHASE_RCVD; + inepintmsk = TRANSFER_DONE | NON_ISO_IN_EP_TIMEOUT | INTKNEPMIS; #ifndef CONFIG_USB_AIC_DMA_ENABLE - AIC_UDC_REG->inepintmsk |= INTKN_TXFEMP; + outepintmsk |= CTRL_OUT_EP_SETUP_PHASE_DONE; + inepintmsk |= INTKN_TXFEMP; #endif - - aic_flush_txfifo(0x10U); - aic_flush_rxfifo(); + writel(outepintmsk, &AIC_UDC_REG->outepintmsk); + writel(inepintmsk, &AIC_UDC_REG->inepintmsk); aic_set_dma_nextep(); @@ -557,96 +618,117 @@ int usb_dc_init(uint8_t busid) { int ret; uint32_t base = 0; + uint32_t tmpreg = 0; memset(&g_aic_udc, 0, sizeof(struct aic_udc)); usb_dc_low_level_init(); /* Disconnect */ - AIC_UDC_REG->usbdevfunc |= USBDEVFUNC_SFTDISCON; + tmpreg = readl(&AIC_UDC_REG->usbdevfunc); + tmpreg |= USBDEVFUNC_SFTDISCON; + writel(tmpreg, &AIC_UDC_REG->usbdevfunc); /* Disable Interrupt */ - AIC_UDC_REG->usbdevinit &= ~USBDEVINIT_GLBL_INTR_EN; + tmpreg = readl(&AIC_UDC_REG->usbdevinit); + tmpreg &= ~USBDEVINIT_GLBL_INTR_EN; + writel(tmpreg, &AIC_UDC_REG->usbdevinit); ret = aic_core_init(); for (uint8_t i = 0U; i < 2U; i++) { - AIC_UDC_REG->txfifosiz[i] = 0U; + writel(0, &AIC_UDC_REG->txfifosiz[i]); } /* Device mode configuration */ - AIC_UDC_REG->usbdevconf |= PERIOD_FRAME_INTERVAL_80; + tmpreg = readl(&AIC_UDC_REG->usbdevconf); + tmpreg |= 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; + tmpreg |= DEV_SPEED_HIGH_SPEED_20; #else - - AIC_UDC_REG->usbdevconf |= DEV_SPEED_FULL_SPEED_20; + tmpreg |= DEV_SPEED_FULL_SPEED_20; #endif + writel(tmpreg, &AIC_UDC_REG->usbdevconf); ret = aic_flush_txfifo(0x10U); ret = aic_flush_rxfifo(); /* Clear all pending Device Interrupts */ - AIC_UDC_REG->inepintmsk = 0U; - AIC_UDC_REG->outepintmsk = 0U; - AIC_UDC_REG->usbepintmsk = 0U; + writel(0, &AIC_UDC_REG->inepintmsk); + writel(0, &AIC_UDC_REG->outepintmsk); + writel(0, &AIC_UDC_REG->usbepintmsk); /* Disable all interrupts. */ - AIC_UDC_REG->usbintmsk = 0U; + writel(0, &AIC_UDC_REG->usbintmsk); /* Clear any pending interrupts */ - AIC_UDC_REG->usbintsts = 0xBFFFFFFFU; + writel(0xBFFFFFFFU, &AIC_UDC_REG->usbintsts); /* Enable interrupts matching to the Device mode ONLY */ - AIC_UDC_REG->usbintmsk = INT_RESET | INT_ENUMDONE | - INT_OUT_EP | INT_IN_EP | - INT_INCOMP_ISO_IN_INT | INT_INCOMP_ISO_OUT_INT; + tmpreg = INT_RESET | INT_ENUMDONE | + INT_OUT_EP | INT_IN_EP | + INT_INCOMP_ISO_IN_INT | INT_INCOMP_ISO_OUT_INT | INT_SUSPEND; + writel(tmpreg, &AIC_UDC_REG->usbintmsk); #ifdef CONFIG_USB_AIC_DMA_ENABLE - AIC_UDC_REG->usbdevinit |= (USBDEVINIT_HBSTLEN_INCR4 << USBDEVINIT_HBSTLEN_SHIFT); - AIC_UDC_REG->usbdevinit |= USBDEVINIT_DMA_EN; + tmpreg = readl(&AIC_UDC_REG->usbdevinit); + tmpreg |= (USBDEVINIT_HBSTLEN_INCR4 << USBDEVINIT_HBSTLEN_SHIFT); + tmpreg |= USBDEVINIT_DMA_EN; + writel(tmpreg, &AIC_UDC_REG->usbdevinit); #else - AIC_UDC_REG->usbintmsk |= INT_RX_FIFO_NOT_EMPTY; + tmpreg = readl(&AIC_UDC_REG->usbintmsk); + tmpreg |= INT_RX_FIFO_NOT_EMPTY; + writel(tmpreg, &AIC_UDC_REG->usbintmsk); #endif /* Assign FIFO */ base = 0; - AIC_UDC_REG->rxfifosiz = AIC_RX_FIFO_SIZE; + writel(AIC_RX_FIFO_SIZE, &AIC_UDC_REG->rxfifosiz); base += AIC_RX_FIFO_SIZE; - AIC_UDC_REG->nptxfifosiz = (AIC_NP_TX_FIFO_SIZE << 16) | base; + writel((AIC_NP_TX_FIFO_SIZE << 16) | base, &AIC_UDC_REG->nptxfifosiz); base += AIC_NP_TX_FIFO_SIZE; - AIC_UDC_REG->txfifosiz[0] = (AIC_PERIOD_TX_FIFO1_SIZE << 16) | base; + writel((AIC_PERIOD_TX_FIFO1_SIZE << 16) | base, &AIC_UDC_REG->txfifosiz[0]); base += AIC_PERIOD_TX_FIFO1_SIZE; - AIC_UDC_REG->txfifosiz[1] = (AIC_PERIOD_TX_FIFO2_SIZE << 16) | base; + writel((AIC_PERIOD_TX_FIFO2_SIZE << 16) | base, &AIC_UDC_REG->txfifosiz[1]); usb_dc_rst(); /* Enable Interrupt */ - AIC_UDC_REG->usbdevinit |= USBDEVINIT_GLBL_INTR_EN; + tmpreg = readl(&AIC_UDC_REG->usbdevinit); + tmpreg |= USBDEVINIT_GLBL_INTR_EN; + writel(tmpreg, &AIC_UDC_REG->usbdevinit); /* Connect */ - AIC_UDC_REG->usbdevfunc &= ~USBDEVFUNC_SFTDISCON; + tmpreg = readl(&AIC_UDC_REG->usbdevfunc); + tmpreg &= ~USBDEVFUNC_SFTDISCON; + writel(tmpreg, &AIC_UDC_REG->usbdevfunc); return ret; } int usb_dc_deinit(uint8_t busid) { + uint32_t tmpreg = 0; + + usbd_event_suspend_handler(); + /* 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; + writel(0xFB7FU, &AIC_UDC_REG->outepint[i]); + writel(0xFB7FU, &AIC_UDC_REG->inepint[i]); } /* Clear interrupt masks */ - AIC_UDC_REG->inepintmsk = 0U; - AIC_UDC_REG->outepintmsk = 0U; - AIC_UDC_REG->usbepintmsk = 0U; + writel(0, &AIC_UDC_REG->inepintmsk); + writel(0, &AIC_UDC_REG->outepintmsk); + writel(0, &AIC_UDC_REG->usbepintmsk); /* Flush the FIFO */ aic_flush_txfifo(0x10U); aic_flush_rxfifo(); - AIC_UDC_REG->usbdevfunc |= USBDEVFUNC_SFTDISCON; + tmpreg = readl(&AIC_UDC_REG->usbdevfunc); + tmpreg |= USBDEVFUNC_SFTDISCON; + writel(tmpreg, &AIC_UDC_REG->usbdevfunc); usb_dc_low_level_deinit(); return 0; @@ -654,22 +736,22 @@ int usb_dc_deinit(uint8_t busid) int usbd_set_address(uint8_t busid, const uint8_t addr) { - AIC_UDC_REG->usbdevconf &= ~(DEVICE_ADDRESS_MASK); - AIC_UDC_REG->usbdevconf |= ((uint32_t)addr << 4) & DEVICE_ADDRESS_MASK; + uint32_t tmpreg = 0; + + tmpreg = readl(&AIC_UDC_REG->usbdevconf); + tmpreg &= ~(DEVICE_ADDRESS_MASK); + tmpreg |= ((uint32_t)addr << 4) & DEVICE_ADDRESS_MASK; + writel(tmpreg, &AIC_UDC_REG->usbdevconf); - rst_allow = 1; return 0; } -int usbd_set_remote_wakeup(uint8_t busid) -{ - return -1; -} - -uint8_t usbd_get_port_speed(uint8_t busid) +uint8_t usbd_get_port_speed(uint8_t busid, const uint8_t port) { uint8_t speed; - uint32_t DevEnumSpeed = AIC_UDC_REG->usblinests & USB_ENUM_SPEED_MASK; + uint32_t DevEnumSpeed = readl(&AIC_UDC_REG->usblinests); + + DevEnumSpeed &= USB_ENUM_SPEED_MASK; if (DevEnumSpeed == USB_HIGH_30_60MHZ) { speed = USB_SPEED_HIGH; @@ -688,53 +770,60 @@ int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep) uint16_t ep_mps; uint8_t tx_fifo_num = 0; uint32_t i; + uint32_t usbepintmsk = 0; + uint32_t epcfg = 0; if (ep_idx > (USB_NUM_BIDIR_ENDPOINTS - 1)) { USB_LOG_ERR("Ep addr %d overflow\r\n", ep->bEndpointAddress); return -1; } + ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize); + if (ep_idx == 0) { + switch (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; + } + } + + usbepintmsk = readl(&AIC_UDC_REG->usbepintmsk); if (USB_EP_DIR_IS_OUT(ep->bEndpointAddress)) { g_aic_udc.out_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize); g_aic_udc.out_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes); - AIC_UDC_REG->usbepintmsk |= DAINT_OUT_MASK & (uint32_t)(1UL << (16 + ep_idx)); - - ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize); - if (ep_idx == 0) { - switch (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)USB_GET_ENDPOINT_TYPE(ep->bmAttributes) << 18) | - DEPCTL_SETD0PID | - DEPCTL_USBACTEP; + usbepintmsk |= DAINT_OUT_MASK & (uint32_t)(1UL << (16 + ep_idx)); + writel(usbepintmsk, &AIC_UDC_REG->usbepintmsk); + epcfg = readl(&AIC_UDC_REG->outepcfg[ep_idx]); + epcfg |= (ep_mps & DEPCTL_MPS_MASK) | + ((uint32_t)USB_GET_ENDPOINT_TYPE(ep->bmAttributes) << 18) | + DEPCTL_SETD0PID | + DEPCTL_USBACTEP; + writel(epcfg, &AIC_UDC_REG->outepcfg[ep_idx]); } else { + g_aic_udc.in_ep_desc[ep_idx] = *ep; g_aic_udc.in_ep[ep_idx].ep_mps = USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize); g_aic_udc.in_ep[ep_idx].ep_type = USB_GET_ENDPOINT_TYPE(ep->bmAttributes); - AIC_UDC_REG->usbepintmsk |= DAINT_IN_MASK & (uint32_t)(1UL << ep_idx); + usbepintmsk |= DAINT_IN_MASK & (uint32_t)(1UL << ep_idx); + writel(usbepintmsk, &AIC_UDC_REG->usbepintmsk); /* Period IN EP alloc fifo num */ - if (( USB_GET_ENDPOINT_TYPE(ep->bmAttributes) == USB_ENDPOINT_TYPE_INTERRUPT) || - ( USB_GET_ENDPOINT_TYPE(ep->bmAttributes) == USB_ENDPOINT_TYPE_ISOCHRONOUS)) { - for (i=1; i<=2; i++) { - if (g_aic_udc.tx_fifo_map & (1<bmAttributes) == USB_ENDPOINT_TYPE_INTERRUPT) || + (USB_GET_ENDPOINT_TYPE(ep->bmAttributes) == USB_ENDPOINT_TYPE_ISOCHRONOUS)) { + for (i = 1; i <= USB_P_TXFIFO_NUM; i++) { + if (g_aic_udc.p_txfifo_map & (1 << i)) continue; - g_aic_udc.tx_fifo_map |= (1 << i); + g_aic_udc.p_txfifo_map |= (1 << i); tx_fifo_num = i; break; } @@ -743,13 +832,17 @@ int usbd_ep_open(uint8_t busid, const struct usb_endpoint_descriptor *ep) return -1; aic_flush_txfifo(tx_fifo_num); + } else { + g_aic_udc.np_txfifo_map |= (1 << ep_idx); } - AIC_UDC_REG->inepcfg[ep_idx] |= (USB_GET_MAXPACKETSIZE(ep->wMaxPacketSize) & DEPCTL_MPS_MASK) | - ((uint32_t)USB_GET_ENDPOINT_TYPE(ep->bmAttributes) << 18) | - (tx_fifo_num << 22) | - DEPCTL_SETD0PID | - DEPCTL_USBACTEP; + epcfg = readl(&AIC_UDC_REG->inepcfg[ep_idx]); + epcfg |= (ep_mps & DEPCTL_MPS_MASK) | + ((uint32_t)USB_GET_ENDPOINT_TYPE(ep->bmAttributes) << 18) | + (tx_fifo_num << 22) | + DEPCTL_SETD0PID | + DEPCTL_USBACTEP; + writel(epcfg, &AIC_UDC_REG->inepcfg[ep_idx]); } return 0; } @@ -759,16 +852,30 @@ int usbd_ep_close(uint8_t busid, const uint8_t ep) uint8_t ep_idx = USB_EP_GET_IDX(ep); uint8_t tx_fifo_num = 0; int i = 0; + uint32_t outepcfg = 0; + uint32_t outepint = 0; + uint32_t inepcfg = 0; + uint32_t inepint = 0; + uint32_t usbintsts = 0; + uint32_t usbdevfunc = 0; + uint32_t usbepintmsk = 0; + #define DIS_EP_TIMOUT 100 if (USB_EP_DIR_IS_OUT(ep)) { - if (AIC_UDC_REG->outepcfg[ep_idx] & DEPCTL_EPENA) { + outepcfg = readl(&AIC_UDC_REG->outepcfg[ep_idx]); + if (outepcfg & DEPCTL_EPENA) { /* (1) Wait for global nak to take effect */ - if (!(AIC_UDC_REG->usbintsts & INT_GOUTNAKEFF)) - AIC_UDC_REG->usbdevfunc |= USBDEVFUNC_SGOUTNAK; + usbintsts = readl(&AIC_UDC_REG->usbintsts); + if (!(usbintsts & INT_GOUTNAKEFF)) { + usbdevfunc = readl(&AIC_UDC_REG->usbdevfunc); + usbdevfunc |= USBDEVFUNC_SGOUTNAK; + writel(usbdevfunc, &AIC_UDC_REG->usbdevfunc); + } for (i = 0; i < DIS_EP_TIMOUT; i++) { - if (AIC_UDC_REG->usbintsts & INT_GOUTNAKEFF) + usbintsts = readl(&AIC_UDC_REG->usbintsts); + if (usbintsts & INT_GOUTNAKEFF) break; aic_udelay(1); } @@ -777,11 +884,14 @@ int usbd_ep_close(uint8_t busid, const uint8_t ep) USB_LOG_ERR("%s: timeout USBINTSTS.GOUTNAKEFF\n", __func__); /* (2) Disable ep */ - AIC_UDC_REG->outepcfg[ep_idx] |= DEPCTL_SNAK; - AIC_UDC_REG->outepcfg[ep_idx] |= DEPCTL_EPDIS; + outepcfg = readl(&AIC_UDC_REG->outepcfg[ep_idx]); + outepcfg |= DEPCTL_SNAK; + outepcfg |= DEPCTL_EPDIS; + writel(outepcfg, &AIC_UDC_REG->outepcfg[ep_idx]); - for (i = 0; i < DIS_EP_TIMOUT; i++) { - if (AIC_UDC_REG->outepint[ep_idx] & EPDISBLD) + for (i = 0; i < DIS_EP_TIMOUT*10; i++) { + outepint = readl(&AIC_UDC_REG->outepint[ep_idx]); + if (outepint & EPDISBLD) break; aic_udelay(1); } @@ -790,24 +900,34 @@ int usbd_ep_close(uint8_t busid, const uint8_t ep) USB_LOG_ERR("%s: timeout OUTEPCFG.EPDisable\n", __func__); /* Clear EPDISBLD interrupt */ - AIC_UDC_REG->outepint[ep_idx] |= EPDISBLD; + outepint = readl(&AIC_UDC_REG->outepint[ep_idx]); + outepint |= EPDISBLD; + writel(outepint, &AIC_UDC_REG->outepint[ep_idx]); /* (3) Remove global NAKs */ - AIC_UDC_REG->usbdevfunc |= USBDEVFUNC_CGOUTNAK; + usbdevfunc = readl(&AIC_UDC_REG->usbdevfunc); + usbdevfunc |= USBDEVFUNC_CGOUTNAK; + writel(usbdevfunc, &AIC_UDC_REG->usbdevfunc); } - AIC_UDC_REG->usbepintmsk &= ~(DAINT_OUT_MASK & (uint32_t)(1UL << (16 + ep_idx))); - AIC_UDC_REG->outepcfg[ep_idx] = 0; + usbepintmsk = readl(&AIC_UDC_REG->usbepintmsk); + usbepintmsk &= ~(DAINT_OUT_MASK & (uint32_t)(1UL << (16 + ep_idx))); + writel(usbepintmsk, &AIC_UDC_REG->usbepintmsk); + writel(0, &AIC_UDC_REG->outepcfg[ep_idx]); } else { - tx_fifo_num = (AIC_UDC_REG->inepcfg[ep_idx] & DEPCTL_TXFIFONUM_MASK) >> DEPCTL_TXFIFONUM_SHIFT; + inepcfg = readl(&AIC_UDC_REG->inepcfg[ep_idx]); + tx_fifo_num = (inepcfg & DEPCTL_TXFIFONUM_MASK) >> DEPCTL_TXFIFONUM_SHIFT; - if (AIC_UDC_REG->inepcfg[ep_idx] & DEPCTL_EPENA) { + inepcfg = readl(&AIC_UDC_REG->inepcfg[ep_idx]); + if (inepcfg & DEPCTL_EPENA) { if (tx_fifo_num) { /* (1) Wait for Nak effect */ - AIC_UDC_REG->inepcfg[ep_idx] |= DEPCTL_SNAK; + inepcfg |= DEPCTL_SNAK; + writel(inepcfg, &AIC_UDC_REG->inepcfg[ep_idx]); for (i = 0; i < DIS_EP_TIMOUT; i++) { - if (AIC_UDC_REG->inepint[ep_idx] & INEP_NAKEFF) + inepint = readl(&AIC_UDC_REG->inepint[ep_idx]); + if (inepint & INEP_NAKEFF) break; aic_udelay(1); } @@ -816,10 +936,13 @@ int usbd_ep_close(uint8_t busid, const uint8_t ep) USB_LOG_ERR("%s: timeout INEPINT.NAKEFF\n", __func__); } else { /* (1) Wait for Nak effect */ - AIC_UDC_REG->usbdevfunc |= USBDEVFUNC_SGNPINNAK; + usbdevfunc = readl(&AIC_UDC_REG->usbdevfunc); + usbdevfunc |= USBDEVFUNC_SGNPINNAK; + writel(usbdevfunc, &AIC_UDC_REG->usbdevfunc); for (i = 0; i < DIS_EP_TIMOUT; i++) { - if (AIC_UDC_REG->usbintsts & INT_GINNAKEFF) + usbintsts = readl(&AIC_UDC_REG->usbintsts); + if (usbintsts & INT_GINNAKEFF) break; aic_udelay(1); } @@ -829,11 +952,14 @@ int usbd_ep_close(uint8_t busid, const uint8_t ep) } /* (2) Disable ep */ - AIC_UDC_REG->inepcfg[ep_idx] |= DEPCTL_SNAK; - AIC_UDC_REG->inepcfg[ep_idx] |= DEPCTL_EPDIS; + inepcfg = readl(&AIC_UDC_REG->inepcfg[ep_idx]); + inepcfg |= DEPCTL_SNAK; + inepcfg |= DEPCTL_EPDIS; + writel(inepcfg, &AIC_UDC_REG->inepcfg[ep_idx]); for (i = 0; i < DIS_EP_TIMOUT; i++) { - if (AIC_UDC_REG->inepint[ep_idx] & EPDISBLD) + inepint = readl(&AIC_UDC_REG->inepint[ep_idx]); + if (inepint & EPDISBLD) break; aic_udelay(1); } @@ -842,22 +968,31 @@ int usbd_ep_close(uint8_t busid, const uint8_t ep) USB_LOG_ERR("%s: timeout OUTEPCFG.EPDisable\n", __func__); /* Clear EPDISBLD interrupt */ - AIC_UDC_REG->inepint[ep_idx] |= EPDISBLD; + inepint = readl(&AIC_UDC_REG->inepint[ep_idx]); + inepint |= EPDISBLD; + writel(inepint, &AIC_UDC_REG->inepint[ep_idx]); - /* (3) Clear Global In NP NAK in Shared FIFO for non periodic ep */ - if (!tx_fifo_num) - AIC_UDC_REG->usbdevfunc |= USBDEVFUNC_CGNPINNAK; + /* (3) Flush TX FIFO */ + aic_flush_txfifo(tx_fifo_num); + + /* Period IN EP free fifo num */ + if (tx_fifo_num > 0) + g_aic_udc.p_txfifo_map &= ~(1 << tx_fifo_num); + else + g_aic_udc.np_txfifo_map &= ~(1 << ep_idx); + + /* (4) Clear Global In NP NAK in Shared FIFO for non periodic ep */ + if (!tx_fifo_num) { + usbdevfunc = readl(&AIC_UDC_REG->usbdevfunc); + usbdevfunc |= USBDEVFUNC_CGNPINNAK; + writel(usbdevfunc, &AIC_UDC_REG->usbdevfunc); + } } - AIC_UDC_REG->usbepintmsk &= ~(DAINT_OUT_MASK & (uint32_t)(1UL << ep_idx)); - AIC_UDC_REG->inepcfg[ep_idx] = 0; - - /* Flush TX FIFO */ - aic_flush_txfifo(tx_fifo_num); - - /* Period IN EP free fifo num */ - if (tx_fifo_num > 0) - g_aic_udc.tx_fifo_map &= ~(1<usbepintmsk); + usbepintmsk &= ~(DAINT_OUT_MASK & (uint32_t)(1UL << ep_idx)); + writel(usbepintmsk, &AIC_UDC_REG->usbepintmsk); + writel(0, &AIC_UDC_REG->inepcfg[ep_idx]); } #ifdef CONFIG_USB_AIC_DMA_ENABLE @@ -871,20 +1006,143 @@ int usbd_ep_close(uint8_t busid, const uint8_t ep) return 0; } +int usbd_npinep_rewrite(const uint8_t ep) +{ + int i = 0; + int j = 0; + int fail = 0; + unsigned int pending_map = 0; + //int data_len = 0; + uint32_t tmpreg = 0; + + for (i = 0U, j = 0; i < USB_NUM_BIDIR_ENDPOINTS; i++) { + tmpreg = readl(&AIC_UDC_REG->inepcfg[i]); + if (!((g_aic_udc.np_txfifo_map & (1 << i)) && + (tmpreg & DEPCTL_EPENA))) + continue; + + j++; + + pending_map |= (1 << i); + } + if (j <= 1) + return 0; + + /* (1) close all no-periodic ep */ + /* (1.1) Set Global In NP NAK in Shared FIFO for non periodic ep */ + tmpreg = readl(&AIC_UDC_REG->usbdevfunc); + tmpreg |= USBDEVFUNC_SGNPINNAK; + writel(tmpreg, &AIC_UDC_REG->usbdevfunc); + + for (i = 0; i < DIS_EP_TIMOUT; i++) { + tmpreg = readl(&AIC_UDC_REG->usbintsts); + if (tmpreg & INT_GINNAKEFF) + break; + aic_udelay(1); + } + + if (i == DIS_EP_TIMOUT) + USB_LOG_ERR("%s: timeout USBINTSTS.GOUTNAKEFF\n", __func__); + + /* (1.2) Disable ep */ + for (i = 0U; i < USB_NUM_BIDIR_ENDPOINTS; i++) { + tmpreg = readl(&AIC_UDC_REG->inepcfg[i]); + if (!((g_aic_udc.np_txfifo_map & (1 << i)) && + (tmpreg & DEPCTL_EPENA))) + continue; + + tmpreg |= DEPCTL_SNAK; + tmpreg |= DEPCTL_EPDIS; + writel(tmpreg, &AIC_UDC_REG->inepcfg[i]); + + /* remain data */ + #if 0 + tmpreg = readl(&AIC_UDC_REG->ineptsfsiz[i]); + data_len = tmpreg & DXEPTSIZ_XFER_SIZE_MASK; + g_aic_udc.in_ep[ep].xfer_buf += g_aic_udc.in_ep[ep].xfer_len - data_len; + g_aic_udc.in_ep[ep].xfer_len = data_len; + #endif + + //pending_map |= (1 << i); + } + + for (j = 0; j < DIS_EP_TIMOUT; j++) { + fail = 0; + for (i = 0U; i < USB_NUM_BIDIR_ENDPOINTS; i++) { + if (!(pending_map & (1 << i))) + continue; + tmpreg = readl(&AIC_UDC_REG->inepint[i]); + if (!(tmpreg & EPDISBLD)) { + fail = i+1; + break; + } + } + if (!fail) + break; + aic_udelay(1); + } + + if (j == DIS_EP_TIMOUT) + USB_LOG_ERR("%s: ep%d timeout OUTEPCFG.EPDisable\n", __func__, fail-1); + + /* Clear EPDISBLD interrupt */ + for (i = 0U; i < USB_NUM_BIDIR_ENDPOINTS; i++) { + if (!(pending_map & (1 << i))) + continue; + tmpreg = readl(&AIC_UDC_REG->inepint[i]); + tmpreg |= EPDISBLD; + writel(tmpreg, &AIC_UDC_REG->inepint[i]); + } + + /* (1.3) Flush TX FIFO0 */ + aic_flush_txfifo(0); + + /* (1.4) Clear Global In NP NAK in Shared FIFO for non periodic ep */ + tmpreg = readl(&AIC_UDC_REG->usbdevfunc); + tmpreg |= USBDEVFUNC_CGNPINNAK; + writel(tmpreg, &AIC_UDC_REG->usbdevfunc); + + /* (2) reopen current ep */ + usbd_ep_open(&g_aic_udc.in_ep_desc[ep]); + + /* (3) rewrite current ep */ + if (pending_map & (1 << ep)) { + usbd_ep_start_write(ep, g_aic_udc.in_ep[ep].xfer_buf, + g_aic_udc.in_ep[ep].xfer_len); + } + + /* (4) reopen & rewrite other ep, let's receive ep mismtach interrupt */ + for (i = 0U; i < USB_NUM_BIDIR_ENDPOINTS; i++) { + if (!(pending_map & (1 << i)) || + (i == ep)) + continue; + usbd_ep_open(&g_aic_udc.in_ep_desc[i]); + usbd_ep_start_write(i, g_aic_udc.in_ep[i].xfer_buf, + g_aic_udc.in_ep[i].xfer_len); + } + + return 0; +} + int usbd_ep_set_stall(uint8_t busid, const uint8_t ep) { uint8_t ep_idx = USB_EP_GET_IDX(ep); + uint32_t tmpreg = 0; 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); + tmpreg = readl(&AIC_UDC_REG->outepcfg[ep_idx]); + if (((tmpreg & DEPCTL_EPENA) == 0U) && (ep_idx != 0U)) { + tmpreg &= ~(DEPCTL_EPDIS); } - AIC_UDC_REG->outepcfg[ep_idx] |= DEPCTL_STALL; + tmpreg |= DEPCTL_STALL; + writel(tmpreg, &AIC_UDC_REG->outepcfg[ep_idx]); } else { - if (((AIC_UDC_REG->inepcfg[ep_idx] & DEPCTL_EPENA) == 0U) && (ep_idx != 0U)) { - AIC_UDC_REG->inepcfg[ep_idx] &= ~(DEPCTL_EPDIS); + tmpreg = readl(&AIC_UDC_REG->inepcfg[ep_idx]); + if (((tmpreg & DEPCTL_EPENA) == 0U) && (ep_idx != 0U)) { + tmpreg &= ~(DEPCTL_EPDIS); } - AIC_UDC_REG->inepcfg[ep_idx] |= DEPCTL_STALL; + tmpreg |= DEPCTL_STALL; + writel(tmpreg, &AIC_UDC_REG->inepcfg[ep_idx]); } #ifdef CONFIG_USB_AIC_DMA_ENABLE @@ -898,19 +1156,24 @@ int usbd_ep_set_stall(uint8_t busid, const uint8_t ep) int usbd_ep_clear_stall(uint8_t busid, const uint8_t ep) { uint8_t ep_idx = USB_EP_GET_IDX(ep); + uint32_t tmpreg = 0; if (USB_EP_DIR_IS_OUT(ep)) { - AIC_UDC_REG->outepcfg[ep_idx] &= ~DEPCTL_STALL; + tmpreg = readl(&AIC_UDC_REG->outepcfg[ep_idx]); + tmpreg &= ~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 */ + tmpreg |= DEPCTL_SETD0PID; /* DATA0 */ } + writel(tmpreg, &AIC_UDC_REG->outepcfg[ep_idx]); } else { - AIC_UDC_REG->inepcfg[ep_idx] &= ~DEPCTL_STALL; + tmpreg = readl(&AIC_UDC_REG->inepcfg[ep_idx]); + tmpreg &= ~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 */ + tmpreg |= DEPCTL_SETD0PID; /* DATA0 */ } + writel(tmpreg, &AIC_UDC_REG->inepcfg[ep_idx]); } return 0; @@ -924,18 +1187,22 @@ 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) +int usbd_ep_start_write_raw(const uint8_t ep, const uint8_t *data, uint32_t data_len, uint8_t cache_align) { uint8_t ep_idx = USB_EP_GET_IDX(ep); uint32_t pktcnt = 0; + uint32_t inepcfg = 0; + uint32_t ineptsfsiz = 0; + uint32_t usblinests = 0; if (!data && data_len) { return -1; } - if (AIC_UDC_REG->inepcfg[ep_idx] & DEPCTL_EPENA) { + inepcfg = readl(&AIC_UDC_REG->inepcfg[ep_idx]); + if (inepcfg & DEPCTL_EPENA) { return -2; } - if (ep_idx && !(AIC_UDC_REG->inepcfg[ep_idx] & DEPCTL_MPS_MASK)) { + if (ep_idx && !(inepcfg & DEPCTL_MPS_MASK)) { return -3; } if ((uint32_t)(uintptr_t)data & 0x03) { @@ -947,7 +1214,7 @@ int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, ui g_aic_udc.in_ep[ep_idx].actual_xfer_len = 0; #ifdef CONFIG_USB_AIC_DMA_ENABLE - if ((ep_idx != 0) && (data_len > 0) && + if (cache_align && (ep_idx != 0) && (data_len > 0) && ((((uint32_t)(uintptr_t)data % CACHE_LINE_SIZE) != 0) || (((uint32_t)(uintptr_t)(data + data_len) % CACHE_LINE_SIZE) != 0))) { @@ -969,13 +1236,15 @@ int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, ui aic_udc_dcache_clean((uintptr_t)data, ALIGN_UP(data_len, CACHE_LINE_SIZE)); #endif - 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_MULCNT_MASK); + ineptsfsiz = readl(&AIC_UDC_REG->ineptsfsiz[ep_idx]); + ineptsfsiz &= ~(DXEPTSIZ_PKT_CNT_MASK); + ineptsfsiz &= ~(DXEPTSIZ_XFER_SIZE_MASK); if (data_len == 0) { - AIC_UDC_REG->ineptsfsiz[ep_idx] |= (DXEPTSIZ_PKT_CNT_MASK & (1U << 19)); - AIC_UDC_REG->inepcfg[ep_idx] |= (DEPCTL_CNAK | DEPCTL_EPENA); + ineptsfsiz |= (DXEPTSIZ_PKT_CNT_MASK & (1U << 19)); + writel(ineptsfsiz, &AIC_UDC_REG->ineptsfsiz[ep_idx]); + inepcfg |= (DEPCTL_CNAK | DEPCTL_EPENA); + writel(inepcfg, &AIC_UDC_REG->inepcfg[ep_idx]); return 0; } @@ -984,56 +1253,77 @@ int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, ui data_len = g_aic_udc.in_ep[ep_idx].ep_mps; } g_aic_udc.in_ep[ep_idx].xfer_len = data_len; - AIC_UDC_REG->ineptsfsiz[ep_idx] |= (DXEPTSIZ_PKT_CNT_MASK & (1U << 19)); - AIC_UDC_REG->ineptsfsiz[ep_idx] |= (DXEPTSIZ_XFER_SIZE_MASK & data_len); + ineptsfsiz |= (DXEPTSIZ_PKT_CNT_MASK & (1U << 19)); + ineptsfsiz |= (DXEPTSIZ_XFER_SIZE_MASK & data_len); } else { 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 & (pktcnt << 19)); - AIC_UDC_REG->ineptsfsiz[ep_idx] |= (DXEPTSIZ_XFER_SIZE_MASK & data_len); - } - - if ((g_aic_udc.in_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS) || - (g_aic_udc.in_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_INTERRUPT)) { - AIC_UDC_REG->ineptsfsiz[ep_idx] |= (1<usblinests & (1U << 8)) == 0U) { - AIC_UDC_REG->inepcfg[ep_idx] &= ~DEPCTL_SETD0PID; - AIC_UDC_REG->inepcfg[ep_idx] |= DEPCTL_SETD1PID; + usblinests = readl(&AIC_UDC_REG->usblinests); + if ((usblinests & (1U << 8)) == 0U) { + inepcfg &= ~DEPCTL_SETD0PID; + inepcfg |= DEPCTL_SETD1PID; } else { - AIC_UDC_REG->inepcfg[ep_idx] &= ~DEPCTL_SETD1PID; - AIC_UDC_REG->inepcfg[ep_idx] |= DEPCTL_SETD0PID; + inepcfg &= ~DEPCTL_SETD1PID; + inepcfg |= DEPCTL_SETD0PID; } - AIC_UDC_REG->ineptsfsiz[ep_idx] &= ~(DXEPTSIZ_MULCNT_MASK); - AIC_UDC_REG->ineptsfsiz[ep_idx] |= (1U << DXEPTSIZ_MULCNT_SHIFT); + ineptsfsiz &= ~(DXEPTSIZ_MULCNT_MASK); + ineptsfsiz |= ((pktcnt << DXEPTSIZ_MULCNT_SHIFT) & DXEPTSIZ_MULCNT_MASK); } else if (g_aic_udc.in_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_INTERRUPT) { - AIC_UDC_REG->ineptsfsiz[ep_idx] &= ~(DXEPTSIZ_MULCNT_MASK); - AIC_UDC_REG->ineptsfsiz[ep_idx] |= (1U << DXEPTSIZ_MULCNT_SHIFT); + ineptsfsiz &= ~(DXEPTSIZ_MULCNT_MASK); + ineptsfsiz |= (1U << DXEPTSIZ_MULCNT_SHIFT); } + writel(ineptsfsiz, &AIC_UDC_REG->ineptsfsiz[ep_idx]); #ifdef CONFIG_USB_AIC_DMA_ENABLE - AIC_UDC_REG->inepdmaaddr[ep_idx] = (uint32_t)(uintptr_t)data; + writel((uint32_t)(uintptr_t)data, &AIC_UDC_REG->inepdmaaddr[ep_idx]); #endif - AIC_UDC_REG->inepcfg[ep_idx] |= (DEPCTL_CNAK | DEPCTL_EPENA); + writel(0xFFFFFFFFU, &AIC_UDC_REG->inepint[ep_idx]); + + inepcfg |= (DEPCTL_CNAK | DEPCTL_EPENA); + writel(inepcfg, &AIC_UDC_REG->inepcfg[ep_idx]); return 0; } -int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t data_len) + +int usbd_ep_start_write(uint8_t busid, const uint8_t ep, const uint8_t *data, uint32_t data_len) +{ + return usbd_ep_start_write_raw(ep, data, data_len, 1); +} + +int usbd_ep_start_read_raw(const uint8_t ep, uint8_t *data, uint32_t data_len, uint8_t cache_align) { uint8_t ep_idx = USB_EP_GET_IDX(ep); uint32_t pktcnt = 0; + uint32_t i = 0; + uint32_t outepcfg = 0; + uint32_t outeptsfsiz = 0; + uint32_t usblinests = 0; if (!data && data_len) { return -1; } - if (AIC_UDC_REG->outepcfg[ep_idx] & DEPCTL_EPENA) { - return -2; + outepcfg = readl(&AIC_UDC_REG->outepcfg[ep_idx]); + if (outepcfg & DEPCTL_EPENA) { + for (i = 0; i < 100000; i++) { + outepcfg = readl(&AIC_UDC_REG->outepcfg[ep_idx]); + if (!(outepcfg & DEPCTL_EPENA)) + break; + } + if (i == 1000000) { + g_aic_udc.out_ep[ep_idx].xfer_len = data_len; + USB_LOG_ERR("ep%d AIC_UDC_REG->outepcfg[ep_idx] = 0x%x.\n", + (unsigned int)ep_idx, (unsigned int)outepcfg); + return -2; + } } - if (ep_idx && !(AIC_UDC_REG->outepcfg[ep_idx] & DEPCTL_MPS_MASK)) { + if (ep_idx && !(outepcfg & DEPCTL_MPS_MASK)) { return -3; } if (((uint32_t)(uintptr_t)data) & 0x03) { @@ -1045,7 +1335,7 @@ int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t g_aic_udc.out_ep[ep_idx].actual_xfer_len = 0; #ifdef CONFIG_USB_AIC_DMA_ENABLE - if ((ep_idx != 0) && (data_len > 0) && + if (cache_align && (ep_idx != 0) && (data_len > 0) && ((((uint32_t)(uintptr_t)data % CACHE_LINE_SIZE) != 0) || (((uint32_t)(uintptr_t)(data + data_len) % CACHE_LINE_SIZE) != 0))) { @@ -1066,12 +1356,17 @@ int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t aic_udc_dcache_invalidate((uintptr_t)data, ALIGN_UP(data_len, CACHE_LINE_SIZE)); #endif - AIC_UDC_REG->outeptsfsiz[ep_idx] &= ~(DXEPTSIZ_PKT_CNT_MASK); - AIC_UDC_REG->outeptsfsiz[ep_idx] &= ~(DXEPTSIZ_XFER_SIZE_MASK); + outeptsfsiz = readl(&AIC_UDC_REG->outeptsfsiz[ep_idx]); + outeptsfsiz &= ~(DXEPTSIZ_PKT_CNT_MASK); + outeptsfsiz &= ~(DXEPTSIZ_XFER_SIZE_MASK); + outeptsfsiz &= ~(DXEPTSIZ_MULCNT_MASK); + if (data_len == 0) { - 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); - AIC_UDC_REG->outepcfg[ep_idx] |= (DEPCTL_CNAK | DEPCTL_EPENA); + outeptsfsiz |= (DXEPTSIZ_PKT_CNT_MASK & (1 << 19)); + outeptsfsiz |= (DXEPTSIZ_XFER_SIZE_MASK & g_aic_udc.out_ep[ep_idx].ep_mps); + writel(outeptsfsiz, &AIC_UDC_REG->outeptsfsiz[ep_idx]); + outepcfg |= (DEPCTL_CNAK | DEPCTL_EPENA); + writel(outepcfg, &AIC_UDC_REG->outepcfg[ep_idx]); return 0; } @@ -1080,34 +1375,46 @@ int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t data_len = g_aic_udc.out_ep[ep_idx].ep_mps; } g_aic_udc.out_ep[ep_idx].xfer_len = data_len; - AIC_UDC_REG->outeptsfsiz[ep_idx] |= (DXEPTSIZ_PKT_CNT_MASK & (1U << 19)); - AIC_UDC_REG->outeptsfsiz[ep_idx] |= (DXEPTSIZ_XFER_SIZE_MASK & data_len); + outeptsfsiz |= (DXEPTSIZ_PKT_CNT_MASK & (1U << 19)); + outeptsfsiz |= (DXEPTSIZ_XFER_SIZE_MASK & data_len); + writel(outeptsfsiz, &AIC_UDC_REG->outeptsfsiz[ep_idx]); } else { pktcnt = (uint16_t)((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 & (pktcnt << 19)); - AIC_UDC_REG->outeptsfsiz[ep_idx] |= (DXEPTSIZ_XFER_SIZE_MASK & data_len); + outeptsfsiz |= (DXEPTSIZ_PKT_CNT_MASK & (pktcnt << 19)); + outeptsfsiz |= (DXEPTSIZ_XFER_SIZE_MASK & data_len); + writel(outeptsfsiz, &AIC_UDC_REG->outeptsfsiz[ep_idx]); } #ifdef CONFIG_USB_AIC_DMA_ENABLE - AIC_UDC_REG->outepdmaaddr[ep_idx] = (uint32_t)(uintptr_t)data; + writel((uint32_t)(uintptr_t)data, &AIC_UDC_REG->outepdmaaddr[ep_idx]); #endif if (g_aic_udc.out_ep[ep_idx].ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS) { - if ((AIC_UDC_REG->usblinests & (1U << 8)) == 0U) { - AIC_UDC_REG->outepcfg[ep_idx] &= ~DEPCTL_SETD0PID; - AIC_UDC_REG->outepcfg[ep_idx] |= DEPCTL_SETD1PID; + usblinests = readl(&AIC_UDC_REG->usblinests); + if ((usblinests & (1U << 8)) == 0U) { + outepcfg &= ~DEPCTL_SETD0PID; + outepcfg |= DEPCTL_SETD1PID; } else { - AIC_UDC_REG->outepcfg[ep_idx] &= ~DEPCTL_SETD1PID; - AIC_UDC_REG->outepcfg[ep_idx] |= DEPCTL_SETD0PID; + outepcfg &= ~DEPCTL_SETD1PID; + outepcfg |= DEPCTL_SETD0PID; } } - AIC_UDC_REG->outepcfg[ep_idx] |= (DEPCTL_CNAK | DEPCTL_EPENA); + writel(0xFFFFFFFFU, &AIC_UDC_REG->outepint[ep_idx]); + outepcfg |= (DEPCTL_CNAK | DEPCTL_EPENA); + writel(outepcfg, &AIC_UDC_REG->outepcfg[ep_idx]); + return 0; } + +int usbd_ep_start_read(uint8_t busid, const uint8_t ep, uint8_t *data, uint32_t data_len) +{ + return usbd_ep_start_read_raw(ep, data, data_len, 1); +} + void USBD_IRQHandler(void) { - uint32_t gint_status, ep_idx, ep_intr, epint, daintmask; + uint32_t gint_status, ep_idx, ep_intr, epint, daintmask, tmpreg, tmpreg01; gint_status = aic_get_glb_intstatus(); /* Avoid spurious interrupt */ @@ -1121,9 +1428,11 @@ void USBD_IRQHandler(void) /* Handle RxQLevel Interrupt */ if (gint_status & INT_RX_FIFO_NOT_EMPTY) { - AIC_UDC_REG->usbintmsk &= ~(INT_RX_FIFO_NOT_EMPTY); + tmpreg = readl(&AIC_UDC_REG->usbintmsk); + tmpreg &= ~(INT_RX_FIFO_NOT_EMPTY); + writel(tmpreg, &AIC_UDC_REG->usbintmsk); - temp = AIC_UDC_REG->rxfifosts_pop; + temp = readl(&AIC_UDC_REG->rxfifosts_pop); ep_idx = temp & RXFIFOSTS_EPNUM_MASK; if ((temp & RXFIFOSTS_PKTSTS_MASK) == PKTSTS_OUT_DATA_PKT_REC) { @@ -1138,7 +1447,9 @@ void USBD_IRQHandler(void) } else { /* ... */ } - AIC_UDC_REG->usbintmsk |= INT_RX_FIFO_NOT_EMPTY; + tmpreg = readl(&AIC_UDC_REG->usbintmsk); + tmpreg |= INT_RX_FIFO_NOT_EMPTY; + writel(tmpreg, &AIC_UDC_REG->usbintmsk); } #endif if (gint_status & INT_OUT_EP) { @@ -1147,42 +1458,70 @@ void USBD_IRQHandler(void) while (ep_intr != 0U) { if ((ep_intr & 0x1U) != 0U) { epint = aic_get_outep_intstatus(ep_idx); - uint32_t DoepintReg = AIC_UDC_REG->outepint[ep_idx]; - AIC_UDC_REG->outepint[ep_idx] = DoepintReg; + writel(epint, &AIC_UDC_REG->outepint[ep_idx]); struct aic_ep_state *ep = &g_aic_udc.out_ep[ep_idx]; - if ((epint & TRANSFER_DONE) == TRANSFER_DONE) { + + if ((ep_idx == 0)) { #ifdef CONFIG_USB_AIC_DMA_ENABLE + extern void usb_dc_sync_dma(void); + usb_dc_sync_dma(); if (ep->xfer_align_buf) memcpy(ep->xfer_buf, ep->xfer_align_buf, ep->xfer_len); #endif - if ((ep_idx == 0)) { - if (ep0_ctrl_stage == 1) { - ep0_ctrl_stage = 2; + + if (ep0_ctrl_stage == AIC_EP0_SETUP) { + /* Setup data-out will send STATUS_PHASE_RCVD interrupt when next setup. + Attemp to re-read setup data. */ + if (epint & CTRL_OUT_EP_STATUS_PHASE_RCVD) { + aic_ep0_start_read_setup((uint8_t *)&g_aic_udc.setup); + } + + /* Normal setup handle */ + if (epint & CTRL_OUT_EP_SETUP_PHASE_DONE) { + if (g_aic_udc.setup.wLength) + if ((g_aic_udc.setup.bmRequestType & USB_REQUEST_DIR_MASK) == USB_REQUEST_DIR_OUT) + ep0_ctrl_stage = AIC_EP0_DATA_OUT; + else + ep0_ctrl_stage = AIC_EP0_DATA_IN; + else + ep0_ctrl_stage = AIC_EP0_STATUS_IN; usbd_event_ep0_setup_complete_handler(0, (uint8_t *)&g_aic_udc.setup); - } else { + } + } else { + if ((epint & TRANSFER_DONE) == TRANSFER_DONE) { if (ep->xfer_len == 0) { /* Out status, start reading setup */ aic_ep0_start_read_setup((uint8_t *)&g_aic_udc.setup); } else { - ep->actual_xfer_len = ep->xfer_len - ((AIC_UDC_REG->outeptsfsiz[ep_idx]) & DXEPTSIZ_XFER_SIZE_MASK); + //ep->actual_xfer_len = ep->xfer_len - ((AIC_UDC_REG->outeptsfsiz[ep_idx]) & DXEPTSIZ_XFER_SIZE_MASK); + ep->actual_xfer_len = ep->xfer_len; ep->xfer_len = 0; usbd_event_ep_out_complete_handler(0, 0x00, ep->actual_xfer_len); } } - } else { - ep->actual_xfer_len = ep->xfer_len - ((AIC_UDC_REG->outeptsfsiz[ep_idx]) & DXEPTSIZ_XFER_SIZE_MASK); - ep->xfer_len = 0; - usbd_event_ep_out_complete_handler(0, ep_idx, ep->actual_xfer_len); } + } else { + #ifdef CONFIG_USB_AIC_DMA_ENABLE + extern void usb_dc_sync_dma(void); + usb_dc_sync_dma(); + if (ep->xfer_align_buf) + memcpy(ep->xfer_buf, ep->xfer_align_buf, ep->xfer_len); + #endif + tmpreg = readl(&AIC_UDC_REG->outeptsfsiz[ep_idx]); + ep->actual_xfer_len = ep->xfer_len - (tmpreg & DXEPTSIZ_XFER_SIZE_MASK); + ep->xfer_len = 0; + usbd_event_ep_out_complete_handler(0, ep_idx, ep->actual_xfer_len); } +#ifndef CONFIG_USB_AIC_DMA_ENABLE if ((epint & CTRL_OUT_EP_SETUP_PHASE_DONE) == CTRL_OUT_EP_SETUP_PHASE_DONE) { if (ep0_ctrl_stage == 1) { ep0_ctrl_stage = 2; usbd_event_ep0_setup_complete_handler(0, (uint8_t *)&g_aic_udc.setup); } } +#endif } ep_intr >>= 1U; ep_idx++; @@ -1191,7 +1530,9 @@ void USBD_IRQHandler(void) #ifndef CONFIG_USB_AIC_DMA_ENABLE if (gint_status & INT_NP_TX_FIFO_EMPTY) { - AIC_UDC_REG->usbintmsk &= ~(INT_NP_TX_FIFO_EMPTY); + tmpreg = readl(&AIC_UDC_REG->usbintmsk); + tmpreg &= ~(INT_NP_TX_FIFO_EMPTY); + writel(tmpreg, &AIC_UDC_REG->usbintmsk); aic_tx_fifo_empty_procecss(0); } #endif @@ -1202,24 +1543,29 @@ void USBD_IRQHandler(void) while (ep_intr != 0U) { if ((ep_intr & 0x1U) != 0U) { epint = aic_get_inep_intstatus(ep_idx); - uint32_t DiepintReg = AIC_UDC_REG->inepint[ep_idx]; - AIC_UDC_REG->inepint[ep_idx] = DiepintReg; + writel(epint, &AIC_UDC_REG->inepint[ep_idx]); + + if (epint & INTKNEPMIS) { + aic_udelay(100); + usbd_npinep_rewrite(ep_idx); + } if ((epint & TRANSFER_DONE) == TRANSFER_DONE) { if (ep_idx == 0) { - g_aic_udc.in_ep[ep_idx].actual_xfer_len = g_aic_udc.in_ep[ep_idx].xfer_len - ((AIC_UDC_REG->ineptsfsiz[ep_idx]) & DXEPTSIZ_XFER_SIZE_MASK); - g_aic_udc.in_ep[ep_idx].xfer_len = 0; - usbd_event_ep_in_complete_handler(0, 0x80, g_aic_udc.in_ep[ep_idx].actual_xfer_len); - if (g_aic_udc.setup.wLength && ((g_aic_udc.setup.bmRequestType & USB_REQUEST_DIR_MASK) == USB_REQUEST_DIR_OUT)) { /* In status, start reading setup */ aic_ep0_start_read_setup((uint8_t *)&g_aic_udc.setup); } else if (g_aic_udc.setup.wLength == 0) { /* In status, start reading setup */ aic_ep0_start_read_setup((uint8_t *)&g_aic_udc.setup); + } else { + g_aic_udc.in_ep[ep_idx].actual_xfer_len = g_aic_udc.in_ep[ep_idx].xfer_len - ((AIC_UDC_REG->ineptsfsiz[ep_idx]) & DXEPTSIZ_XFER_SIZE_MASK); + g_aic_udc.in_ep[ep_idx].xfer_len = 0; + usbd_event_ep_in_complete_handler(0, 0x80, g_aic_udc.in_ep[ep_idx].actual_xfer_len); } } else { - g_aic_udc.in_ep[ep_idx].actual_xfer_len = g_aic_udc.in_ep[ep_idx].xfer_len - ((AIC_UDC_REG->ineptsfsiz[ep_idx]) & DXEPTSIZ_XFER_SIZE_MASK); + tmpreg = readl(&AIC_UDC_REG->ineptsfsiz[ep_idx]); + g_aic_udc.in_ep[ep_idx].actual_xfer_len = g_aic_udc.in_ep[ep_idx].xfer_len - (tmpreg & DXEPTSIZ_XFER_SIZE_MASK); g_aic_udc.in_ep[ep_idx].xfer_len = 0; usbd_event_ep_in_complete_handler(0, ep_idx | 0x80, g_aic_udc.in_ep[ep_idx].actual_xfer_len); } @@ -1236,69 +1582,80 @@ void USBD_IRQHandler(void) } } if (gint_status & INT_RESET) { - AIC_UDC_REG->usbintsts |= INT_RESET; - AIC_UDC_REG->usbdevfunc &= ~USBDEVFUNC_RMTWKUPSIG; + writel(INT_RESET, &AIC_UDC_REG->usbintsts); + tmpreg = readl(&AIC_UDC_REG->usbdevfunc); + tmpreg &= ~USBDEVFUNC_RMTWKUPSIG; + writel(tmpreg, &AIC_UDC_REG->usbdevfunc); usb_dc_rst(); } if (gint_status & INT_ENUMDONE) { - AIC_UDC_REG->usbintsts |= INT_ENUMDONE; + writel(INT_ENUMDONE, &AIC_UDC_REG->usbintsts); aic_set_turnaroundtime(usbd_clk, aic_get_devspeed()); - AIC_UDC_REG->usbdevfunc |= USBDEVFUNC_CGNPINNAK; + tmpreg = readl(&AIC_UDC_REG->usbdevfunc); + tmpreg |= USBDEVFUNC_CGNPINNAK; + writel(tmpreg, &AIC_UDC_REG->usbdevfunc); } if (gint_status & INT_INCOMP_ISO_OUT_INT) { - daintmask = AIC_UDC_REG->usbepintmsk; + daintmask = readl(&AIC_UDC_REG->usbepintmsk); daintmask >>= 16; for (ep_idx = 1; ep_idx < USB_NUM_BIDIR_ENDPOINTS; ep_idx++) { if ((BIT(ep_idx) & ~daintmask) || (g_aic_udc.out_ep[ep_idx].ep_type != USB_ENDPOINT_TYPE_ISOCHRONOUS)) continue; - if (!(AIC_UDC_REG->outepcfg[ep_idx] & DEPCTL_USBACTEP)) - continue; - if ((AIC_UDC_REG->usblinests & (1U << 8)) != 0U) { - AIC_UDC_REG->outepcfg[ep_idx] |= DEPCTL_SETD0PID; - AIC_UDC_REG->outepcfg[ep_idx] &= ~DEPCTL_SETD1PID; + tmpreg = readl(&AIC_UDC_REG->outepcfg[ep_idx]); + if (!(tmpreg & DEPCTL_USBACTEP)) + continue; + tmpreg01 = readl(&AIC_UDC_REG->usblinests); + if ((tmpreg01 & (1U << 8)) != 0U) { + tmpreg |= DEPCTL_SETD0PID; + tmpreg &= ~DEPCTL_SETD1PID; } else { - AIC_UDC_REG->outepcfg[ep_idx] &= ~DEPCTL_SETD0PID; - AIC_UDC_REG->outepcfg[ep_idx] |= DEPCTL_SETD1PID; + tmpreg &= ~DEPCTL_SETD0PID; + tmpreg |= DEPCTL_SETD1PID; } + writel(tmpreg, &AIC_UDC_REG->outepcfg[ep_idx]); } - AIC_UDC_REG->usbintsts |= INT_INCOMP_ISO_OUT_INT; + writel(INT_INCOMP_ISO_OUT_INT, &AIC_UDC_REG->usbintsts); } if (gint_status & INT_INCOMP_ISO_IN_INT) { - daintmask = AIC_UDC_REG->usbepintmsk; - daintmask >>= 16; + daintmask = readl(&AIC_UDC_REG->usbepintmsk); + daintmask &= 0xFFFF; for (ep_idx = 1; ep_idx < USB_NUM_BIDIR_ENDPOINTS; ep_idx++) { if (((BIT(ep_idx) & ~daintmask)) || (g_aic_udc.in_ep[ep_idx].ep_type != USB_ENDPOINT_TYPE_ISOCHRONOUS)) continue; - if (!(AIC_UDC_REG->inepcfg[ep_idx] & DEPCTL_USBACTEP)) + tmpreg = readl(&AIC_UDC_REG->inepcfg[ep_idx]); + if (!(tmpreg & DEPCTL_USBACTEP)) continue; - - if ((AIC_UDC_REG->usblinests & (1U << 8)) != 0U) { - AIC_UDC_REG->inepcfg[ep_idx] |= DEPCTL_SETD0PID; - AIC_UDC_REG->inepcfg[ep_idx] &= ~DEPCTL_SETD1PID; + tmpreg01 = readl(&AIC_UDC_REG->usblinests); + if ((tmpreg01 & (1U << 8)) != 0U) { + tmpreg |= DEPCTL_SETD0PID; + tmpreg &= ~DEPCTL_SETD1PID; } else { - AIC_UDC_REG->inepcfg[ep_idx] &= ~DEPCTL_SETD0PID; - AIC_UDC_REG->inepcfg[ep_idx] |= DEPCTL_SETD1PID; + tmpreg &= ~DEPCTL_SETD0PID; + tmpreg |= DEPCTL_SETD1PID; } + writel(tmpreg, &AIC_UDC_REG->inepcfg[ep_idx]); } - AIC_UDC_REG->usbintsts |= INT_INCOMP_ISO_IN_INT; + + writel(INT_INCOMP_ISO_IN_INT, &AIC_UDC_REG->usbintsts); } if (gint_status & INT_SOF) { - AIC_UDC_REG->usbintsts |= INT_SOF; + writel(INT_SOF, &AIC_UDC_REG->usbintsts); } if (gint_status & INT_SUSPEND) { - AIC_UDC_REG->usbintsts |= INT_SUSPEND; + writel(INT_SUSPEND, &AIC_UDC_REG->usbintsts); + usbd_event_suspend_handler(0); } if (gint_status & INT_RESUME) { - AIC_UDC_REG->usbintsts |= INT_RESUME; + writel(INT_RESUME, &AIC_UDC_REG->usbintsts); } } diff --git a/port/aic/usb_dc_aic_ll.c b/port/aic/usb_dc_aic_ll.c index d2db1b5d..e9b5b692 100644 --- a/port/aic/usb_dc_aic_ll.c +++ b/port/aic/usb_dc_aic_ll.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Artinchip Technology Co., Ltd + * Copyright (c) 2022-2024, ArtInChip Technology Co., Ltd * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,12 +13,19 @@ extern irqreturn_t USBD_IRQHandler(int irq, void * data); uint32_t usbd_clk; +static unsigned char dma_sync_buffer[CACHE_LINE_SIZE] __attribute__((aligned(CACHE_LINE_SIZE))); + +void usb_dc_sync_dma(void) +{ + asm volatile("sw t0, (%0)" : : "r"(dma_sync_buffer)); + csi_dcache_clean_range((phy_addr_t)(ptr_t)dma_sync_buffer, CACHE_LINE_SIZE); +} void usb_dc_low_level_init(void) { /* set usb0 phy switch: Host/Device */ -#ifdef AIC_USING_USB0_DEVICE - syscfg_usb_phy0_sw_host(0); +#if defined(AIC_USING_USB0_DEVICE) || defined(AIC_USING_USB0_OTG) + hal_syscfg_usb_phy0_sw_host(0); #endif /* set pin-mux */ @@ -41,3 +48,13 @@ void usb_dc_low_level_init(void) aicos_irq_enable(CONFIG_USB_AIC_DC_IRQ_NUM); } +void usb_dc_low_level_deinit(void) +{ + aicos_irq_disable(CONFIG_USB_AIC_DC_IRQ_NUM); + + hal_reset_assert(CONFIG_USB_AIC_DC_PHY_RESET); + hal_reset_assert(CONFIG_USB_AIC_DC_RESET); + hal_clk_disable(CONFIG_USB_AIC_DC_PHY_CLK); + hal_clk_disable(CONFIG_USB_AIC_DC_CLK); +} + diff --git a/port/aic/usb_dc_aic_reg.h b/port/aic/usb_dc_aic_reg.h index 80e6997a..b35b8d4f 100644 --- a/port/aic/usb_dc_aic_reg.h +++ b/port/aic/usb_dc_aic_reg.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Artinchip Technology Co., Ltd + * Copyright (c) 2022-2024, Artinchip Technology Co., Ltd * * SPDX-License-Identifier: Apache-2.0 */ @@ -142,10 +142,19 @@ typedef struct { #define EPS_NUM 5 #define PERIOD_IN_EP_NUM 2 #define TOTAL_FIFO_SIZE 0x3f6 +#ifdef LPKG_CHERRYUSB_DEVICE_VIDEO_DVP_TEMPLATE +/* video_dvp_template must use 2K Bytes period_tx_fifo */ +#define AIC_RX_FIFO_SIZE 0x99 +#define AIC_NP_TX_FIFO_SIZE 0x100 +#define AIC_PERIOD_TX_FIFO1_SIZE 0x200 +#define AIC_PERIOD_TX_FIFO2_SIZE 0x0 +#else +/* default configuration */ #define AIC_RX_FIFO_SIZE 0x119 #define AIC_NP_TX_FIFO_SIZE 0x100 #define AIC_PERIOD_TX_FIFO1_SIZE 0x100 #define AIC_PERIOD_TX_FIFO2_SIZE 0xDD +#endif #define DEPCTL_TXFNUM_0 (0x0 << 22) #define DEPCTL_TXFNUM_1 (0x1 << 22) @@ -244,9 +253,11 @@ typedef struct { #define DIEPCTL0_NEXT_EP_BIT (11) /* INEPINT/OUTEPINT device IN/OUT endpoint interrupt register */ +#define CTRL_OUT_EP_SETUP_RCVD (0x1 << 15) #define TXFIFO_EMP_INT (0x1 << 7) #define INEP_NAKEFF (0x1 << 6) #define BACK2BACK_SETUP_RECEIVED (0x1 << 6) +#define CTRL_OUT_EP_STATUS_PHASE_RCVD (0x1 << 5) #define INTKNEPMIS (0x1 << 5) #define INTKN_TXFEMP (0x1 << 4) #define NON_ISO_IN_EP_TIMEOUT (0x1 << 3)