/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id: usb-drv-as3525.c 25996 2010-05-13 14:07:59Z ranma $ * * Copyright © 2009 Rafaël Carré * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/ #include "system.h" #include "usb.h" #include "usb_drv.h" #include "as3525.h" #include "clock-target.h" #include "ascodec.h" #include "as3514.h" #include #include "panic.h" /*#define LOGF_ENABLE*/ #define LOGF_ENABLE #include "logf.h" #include "usb_ch9.h" #include "usb_core.h" #include "string.h" /* 4 input endpoints */ #define USB_IEP_CTRL(i) *((volatile unsigned long*) (USB_BASE + 0x0000 + (i*0x20))) #define USB_IEP_STS(i) *((volatile unsigned long*) (USB_BASE + 0x0004 + (i*0x20))) #define USB_IEP_TXFSIZE(i) *((volatile unsigned long*) (USB_BASE + 0x0008 + (i*0x20))) #define USB_IEP_MPS(i) *((volatile unsigned long*) (USB_BASE + 0x000C + (i*0x20))) #define USB_IEP_DESC_PTR(i) *((volatile unsigned long*) (USB_BASE + 0x0014 + (i*0x20))) #define USB_IEP_STS_MASK(i) *((volatile unsigned long*) (USB_BASE + 0x0018 + (i*0x20))) /* 4 output endpoints */ #define USB_OEP_CTRL(i) *((volatile unsigned long*) (USB_BASE + 0x0200 + (i*0x20))) #define USB_OEP_STS(i) *((volatile unsigned long*) (USB_BASE + 0x0204 + (i*0x20))) #define USB_OEP_RXFR(i) *((volatile unsigned long*) (USB_BASE + 0x0208 + (i*0x20))) #define USB_OEP_MPS(i) *((volatile unsigned long*) (USB_BASE + 0x020C + (i*0x20))) #define USB_OEP_SUP_PTR(i) *((volatile unsigned long*) (USB_BASE + 0x0210 + (i*0x20))) #define USB_OEP_DESC_PTR(i) *((volatile unsigned long*) (USB_BASE + 0x0214 + (i*0x20))) #define USB_OEP_STS_MASK(i) *((volatile unsigned long*) (USB_BASE + 0x0218 + (i*0x20))) #define USB_DEV_CFG *((volatile unsigned long*) (USB_BASE + 0x0400)) #define USB_DEV_CTRL *((volatile unsigned long*) (USB_BASE + 0x0404)) #define USB_DEV_STS *((volatile unsigned long*) (USB_BASE + 0x0408)) #define USB_DEV_INTR *((volatile unsigned long*) (USB_BASE + 0x040C)) #define USB_DEV_INTR_MASK *((volatile unsigned long*) (USB_BASE + 0x0410)) #define USB_DEV_EP_INTR *((volatile unsigned long*) (USB_BASE + 0x0414)) #define USB_DEV_EP_INTR_MASK *((volatile unsigned long*) (USB_BASE + 0x0418)) #define USB_PHY_EP0_INFO *((volatile unsigned long*) (USB_BASE + 0x0504)) #define USB_PHY_EP1_INFO *((volatile unsigned long*) (USB_BASE + 0x0508)) #define USB_PHY_EP2_INFO *((volatile unsigned long*) (USB_BASE + 0x050C)) #define USB_PHY_EP3_INFO *((volatile unsigned long*) (USB_BASE + 0x0510)) #define USB_PHY_EP4_INFO *((volatile unsigned long*) (USB_BASE + 0x0514)) #define USB_PHY_EP5_INFO *((volatile unsigned long*) (USB_BASE + 0x0518)) /* 4 channels */ #define USB_HOST_CH_SPLT(i) *((volatile unsigned long*) (USB_BASE + 0x1000 + (i*0x20))) #define USB_HOST_CH_STS(i) *((volatile unsigned long*) (USB_BASE + 0x1004 + (i*0x20))) #define USB_HOST_CH_TXFSIZE(i) *((volatile unsigned long*) (USB_BASE + 0x1008 + (i*0x20))) #define USB_HOST_CH_REQ(i) *((volatile unsigned long*) (USB_BASE + 0x100C + (i*0x20))) #define USB_HOST_CH_PER_INFO(i) *((volatile unsigned long*) (USB_BASE + 0x1010 + (i*0x20))) #define USB_HOST_CH_DESC_PTR(i) *((volatile unsigned long*) (USB_BASE + 0x1014 + (i*0x20))) #define USB_HOST_CH_STS_MASK(i) *((volatile unsigned long*) (USB_BASE + 0x1018 + (i*0x20))) #define USB_HOST_CFG *((volatile unsigned long*) (USB_BASE + 0x1400)) #define USB_HOST_CTRL *((volatile unsigned long*) (USB_BASE + 0x1404)) #define USB_HOST_INTR *((volatile unsigned long*) (USB_BASE + 0x140C)) #define USB_HOST_INTR_MASK *((volatile unsigned long*) (USB_BASE + 0x1410)) #define USB_HOST_CH_INTR *((volatile unsigned long*) (USB_BASE + 0x1414)) #define USB_HOST_CH_INTR_MASK *((volatile unsigned long*) (USB_BASE + 0x1418)) #define USB_HOST_FRAME_INT *((volatile unsigned long*) (USB_BASE + 0x141C)) #define USB_HOST_FRAME_REM *((volatile unsigned long*) (USB_BASE + 0x1420)) #define USB_HOST_FRAME_NUM *((volatile unsigned long*) (USB_BASE + 0x1424)) #define USB_HOST_PORT0_CTRL_STS *((volatile unsigned long*) (USB_BASE + 0x1500)) #define USB_OTG_CSR *((volatile unsigned long*) (USB_BASE + 0x2000)) #define USB_I2C_CSR *((volatile unsigned long*) (USB_BASE + 0x2004)) #define USB_GPIO_CSR *((volatile unsigned long*) (USB_BASE + 0x2008)) #define USB_SNPSID_CSR *((volatile unsigned long*) (USB_BASE + 0x200C)) #define USB_USERID_CSR *((volatile unsigned long*) (USB_BASE + 0x2010)) #define USB_USER_CONF1 *((volatile unsigned long*) (USB_BASE + 0x2014)) #define USB_USER_CONF2 *((volatile unsigned long*) (USB_BASE + 0x2018)) #define USB_USER_CONF3 *((volatile unsigned long*) (USB_BASE + 0x201C)) #define USB_USER_CONF4 *((volatile unsigned long*) (USB_BASE + 0x2020)) #define USB_USER_CONF5 *((volatile unsigned long*) (USB_BASE + 0x2024)) /* write bits 31..16 */ #define USB_GPIO_IDDIG_SEL (1<<30) #define USB_GPIO_FS_DATA_EXT (1<<29) #define USB_GPIO_FS_SE0_EXT (1<<28) #define USB_GPIO_FS_XCVR_OWNER (1<<27) #define USB_GPIO_TX_ENABLE_N (1<<26) #define USB_GPIO_TX_BIT_STUFF_EN (1<<25) #define USB_GPIO_BSESSVLD_EXT (1<<24) #define USB_GPIO_ASESSVLD_EXT (1<<23) #define USB_GPIO_VBUS_VLD_EXT (1<<22) #define USB_GPIO_VBUS_VLD_EXT_SEL (1<<21) #define USB_GPIO_XO_ON (1<<20) #define USB_GPIO_CLK_SEL11 (3<<18) #define USB_GPIO_CLK_SEL10 (2<<18) #define USB_GPIO_CLK_SEL01 (1<<18) #define USB_GPIO_CLK_SEL00 (0<<18) #define USB_GPIO_XO_EXT_CLK_ENBN (1<<17) #define USB_GPIO_XO_REFCLK_ENB (1<<16) /* readronly bits 15..0 */ #define USB_GPIO_PHY_VBUSDRV (1<< 1) #define USB_GPIO_HS_INTR (1<< 0) /* Device Control Register and bit fields */ #define USB_DEV_CTRL_REMOTE_WAKEUP 0x00000001 // set remote wake-up signal #define USB_DEV_CTRL_RDE 0x00000004 // receive dma enable #define USB_DEV_CTRL_DESC_UPDATE 0x00000010 // descriptor update #define USB_DEV_CTRL_THRES_ENABLE 0x00000080 // threshold enable #define USB_DEV_CTRL_BURST_CONTROL 0x00000100 // burst control #define USB_DEV_CTRL_SOFT_DISCONN 0x00000400 // soft disconnect #define USB_DEV_CTRL_APCSR_DONE 0x00002000 // app Prog CSR Done #define USB_DEV_CTRL_MASK_BURST_LEN 0x000f0000 // mask for burst length #define USB_DEV_CTRL_MASK_THRESHOLD_LEN 0xff000000 // mask for threshold length /* settings of burst length for maskBurstLen_c field */ #define USB_DEV_CTRL_BLEN_1DWORD 0x00000000 #define USB_DEV_CTRL_BLEN_2DWORDS 0x00010000 #define USB_DEV_CTRL_BLEN_4DWORDS 0x00020000 #define USB_DEV_CTRL_BLEN_8DWORDS 0x00030000 #define USB_DEV_CTRL_BLEN_16DWORDS 0x00040000 #define USB_DEV_CTRL_BLEN_32DWORDS 0x00050000 #define USB_DEV_CTRL_BLEN_64DWORDS 0x00060000 #define USB_DEV_CTRL_BLEN_128DWORDS 0x00070000 #define USB_DEV_CTRL_BLEN_256DWORDS 0x00080000 #define USB_DEV_CTRL_BLEN_512DWORDS 0x00090000 /* settings of threshold length for maskThresholdLen_c field */ #define USB_DEV_CTRL_TLEN_1DWORD 0x00000000 #define USB_DEV_CTRL_TLEN_HALFMAXSIZE 0x01000000 #define USB_DEV_CTRL_TLEN_4THMAXSIZE 0x02000000 #define USB_DEV_CTRL_TLEN_8THMAXSIZE 0x03000000 #define USB_DEV_CFG_HS 0x00000000 #define USB_DEV_CFG_FS 0x00000001 /* 30 or 60MHz */ #define USB_DEV_CFG_LS 0x00000002 #define USB_DEV_CFG_FS_48 0x00000003 /* 48MHz */ #define USB_DEV_CFG_REMOTE_WAKEUP 0x00000004 #define USB_DEV_CFG_SELF_POWERED 0x00000008 #define USB_DEV_CFG_SYNC_FRAME 0x00000010 #define USB_DEV_CFG_PI_16BIT 0x00000000 #define USB_DEV_CFG_PI_8BIT 0x00000020 #define USB_DEV_CFG_UNI_DIR 0x00000000 #define USB_DEV_CFG_BI_DIR 0x00000040 #define USB_DEV_CFG_STAT_ACK 0x00000000 #define USB_DEV_CFG_STAT_STALL 0x00000080 /* EP Control Register Fields */ #define USB_EP_CTRL_STALL 0x00000001 #define USB_EP_CTRL_FLUSH 0x00000002 /* EP In data fifo Flush */ #define USB_EP_CTRL_SNOOP_MODE 0x00000004 // snoop mode for out endpoint #define USB_EP_CTRL_PD 0x00000008 /* EP Poll Demand */ #define USB_EP_CTRL_EPTYPE_MASK 0x00000030 // bit 5-4: endpoint types #define USB_EP_TYPE_CONTROL 0x00000000 // control endpoint #define USB_EP_TYPE_ISO 0x00000010 // isochronous endpoint #define USB_EP_TYPE_BULK 0x00000020 // bulk endpoint #define USB_EP_TYPE_INTERRUPT 0x00000030 // interrupt endpoint #define USB_EP_CTRL_NAK 0x00000040 /* EP NAK Status */ #define USB_EP_CTRL_SNAK 0x00000080 /* EP Set NAK Bit */ #define USB_EP_CTRL_CNAK 0x00000100 /* EP Clr NAK Bit */ #define USB_EP_CTRL_ACT 0x00000400 /* EP Clr NAK Bit */ /*-------------------------*/ /* DMA Related Definitions */ /*-------------------------*/ /* Description of the status quadlets */ #define USB_DMA_DESC_BUFF_STS 0x80000000 /* Buffer Status */ #define USB_DMA_DESC_BS_HST_RDY 0x80000000 /* Host Ready */ #define USB_DMA_DESC_BS_DMA_DONE 0x00000000 /* DMA Done */ #define USB_DMA_DESC_ZERO_LEN 0x40000000 /* zero length packet */ #define USB_DMA_DESC_EARY_INTR 0x20000000 /* early interrupt */ #define USB_DMA_DESC_RXTX_STS 0x10000000 #define USB_DMA_DESC_RTS_SUCC 0x00000000 /* Success */ #define USB_DMA_DESC_RTS_BUFERR 0x10000000 /* Buffer Error */ #define USB_DMA_DESC_LAST 0x08000000 #define USB_DMA_DESC_MASK_FRAM_NUM 0x07ff0000 // bits 26-16: frame number for iso #define USB_DMA_DESC_RXTX_BYTES 0x0000FFFF /* setup descriptor */ #define SETUP_MASK_CONFIG_STAT 0x0fff0000 #define SETUP_MASK_CONFIG_NUM 0x0f000000 #define SETUP_MASK_IF_NUM 0x00f00000 #define SETUP_MASK_ALT_SETNUM 0x000f0000 struct usb_endpoint { void *buf; unsigned int len; union { unsigned int sent; unsigned int received; }; bool wait; bool busy; }; static struct usb_endpoint endpoints[USB_NUM_ENDPOINTS*2]; struct usb_dev_dma_desc { volatile int status; volatile int resv; volatile void *data_ptr; volatile void *next_desc; }; struct usb_dev_setup_buf { volatile int status; volatile int resv; volatile int data1; /* first 4 bytes of data */ volatile int data2; /* last 4 bytes of data */ }; static struct usb_dev_dma_desc desc[2]; static struct usb_dev_dma_desc *uc_desc[2]; static struct usb_dev_setup_buf setup_desc; static char rx_buf[512]; static char tx_buf[512]; void usb_attach(void) { usb_enable(true); } static inline void usb_delay(int delay) { //TUNEME : delay is in milliseconds delay <<= 14; while(delay--) ; } static void usb_phy_on(void) { /* PHY clock */ CGU_USB = 1<<5 /* enable */ | (CLK_DIV(AS3525_PLLB_FREQ, 48000000) / 2) << 2 | 2; /* source = PLLB */ /* UVDD on */ ascodec_write(AS3517_USB_UTIL, ascodec_read(AS3517_USB_UTIL) | (1<<4)); usb_delay(100); /* reset */ CCU_SRC = CCU_SRC_USB_AHB_EN|CCU_SRC_USB_PHY_EN; CCU_SRL = CCU_SRL_MAGIC_NUMBER; usb_delay(1); CCU_SRC = CCU_SRC_USB_AHB_EN; usb_delay(1); CCU_SRC = CCU_SRL = 0; USB_GPIO_CSR = USB_GPIO_TX_ENABLE_N | USB_GPIO_TX_BIT_STUFF_EN | USB_GPIO_XO_ON | USB_GPIO_CLK_SEL10; /* 0x06180000; */ } static void usb_phy_suspend(void) { USB_GPIO_CSR |= USB_GPIO_ASESSVLD_EXT | USB_GPIO_BSESSVLD_EXT | USB_GPIO_VBUS_VLD_EXT; usb_delay(3); USB_GPIO_CSR |= USB_GPIO_VBUS_VLD_EXT_SEL; usb_delay(10); } static void usb_phy_resume(void) { USB_GPIO_CSR &= ~(USB_GPIO_ASESSVLD_EXT | USB_GPIO_BSESSVLD_EXT | USB_GPIO_VBUS_VLD_EXT); usb_delay(3); USB_GPIO_CSR &= ~USB_GPIO_VBUS_VLD_EXT_SEL; usb_delay(10); } #if 0 static void extmem_read_loop(void) { int *extmem_start = (int*)0x30000000; int *extmem_end = (int*)0x301fffff; int *ptr = extmem_start; disable_irq_save(); GPIOA_PIN(5) = 0; GPIOA_PIN(7) = 0; while (1) { asm volatile ("ldr r0, [%0] \n" "ldr r0, [%0, #4] \n" "ldr r0, [%0, #8] \n" "ldr r0, [%0, #12]" :: "r"(ptr)); ptr+=4; if (ptr >= extmem_end) ptr = extmem_start; } } static void intmem_read_loop(void) { int *intmem_start = (int*)0x00000000; int *intmem_end = (int*)0x0005ffff; int *ptr = intmem_start; disable_irq_save(); GPIOA_PIN(5) = 0; GPIOA_PIN(7) = 0; while (1) { asm volatile ("ldr r0, [%0] \n" "ldr r0, [%0, #4] \n" "ldr r0, [%0, #8] \n" "ldr r0, [%0, #12]" :: "r"(ptr)); ptr+=4; if (ptr >= intmem_end) ptr = intmem_start; } } #endif static void setup_desc_init(struct usb_dev_setup_buf *desc) { struct usb_dev_setup_buf *uc_desc = UNCACHED_ADDR(desc); uc_desc->status = USB_DMA_DESC_BS_HST_RDY; uc_desc->resv = 0xffffffff; uc_desc->data1 = 0xffffffff; uc_desc->data2 = 0xffffffff; } static void dma_desc_init(void) { uc_desc[0] = UNCACHED_ADDR(&desc[0]); uc_desc[1] = UNCACHED_ADDR(&desc[1]); uc_desc[0]->status = USB_DMA_DESC_BS_DMA_DONE | USB_DMA_DESC_LAST | 0x40; uc_desc[0]->resv = 0xffffffff; uc_desc[0]->data_ptr = tx_buf; uc_desc[0]->next_desc = &desc[0]; USB_IEP_DESC_PTR(0) = (int)&desc[0]; uc_desc[1]->status = USB_DMA_DESC_BS_HST_RDY | USB_DMA_DESC_LAST | 0x40; uc_desc[1]->resv = 0xffffffff; uc_desc[1]->data_ptr = rx_buf; uc_desc[1]->next_desc = &desc[1]; USB_OEP_DESC_PTR(0) = (int)&desc[1]; setup_desc_init(&setup_desc); USB_OEP_SUP_PTR(0) = (int)&setup_desc; } void usb_drv_init(void) { int i; for(i = 0; i < USB_NUM_ENDPOINTS * 2; i++) endpoints[i].busy = false; logf("usb_drv_init() !!!!\n"); /* length regulator: normal operation */ ascodec_write(AS3514_CVDD_DCDC3, ascodec_read(AS3514_CVDD_DCDC3) | 1<<2); /* AHB part */ CGU_PERI |= CGU_USB_CLOCK_ENABLE; /* reset AHB */ CCU_SRC = CCU_SRC_USB_AHB_EN; CCU_SRL = CCU_SRL_MAGIC_NUMBER; usb_delay(1); CCU_SRC = CCU_SRL = 0; USB_GPIO_CSR = USB_GPIO_TX_ENABLE_N | USB_GPIO_TX_BIT_STUFF_EN | USB_GPIO_XO_ON | USB_GPIO_CLK_SEL10; /* 0x06180000; */ /* bug workaround according to linux patch */ USB_DEV_CFG = (USB_DEV_CFG & ~3) | 1; /* full speed */ /* enable soft disconnect */ USB_DEV_CTRL |= USB_DEV_CTRL_SOFT_DISCONN; usb_phy_on(); usb_phy_suspend(); USB_DEV_CTRL |= USB_DEV_CTRL_SOFT_DISCONN; USB_IEP_CTRL(0) &= (3 << 4); /* control endpoint */ USB_IEP_DESC_PTR(0) = 0; USB_OEP_CTRL(0) &= (3 << 4); /* control endpoint */ USB_OEP_DESC_PTR(0) = 0; USB_DEV_INTR_MASK &= ~0x7f; /* unmask all flags */ USB_DEV_INTR_MASK |= 0x20; /* mask SOF */ USB_DEV_CFG = USB_DEV_CFG_STAT_ACK | USB_DEV_CFG_UNI_DIR | USB_DEV_CFG_PI_16BIT | USB_DEV_CFG_HS | USB_DEV_CFG_SELF_POWERED | 0x20200; USB_DEV_CTRL = USB_DEV_CTRL_BLEN_1DWORD | USB_DEV_CTRL_DESC_UPDATE | USB_DEV_CTRL_THRES_ENABLE | USB_DEV_CTRL_RDE | 0x04000000; USB_DEV_EP_INTR_MASK &= ~((1<<0) | (1<<16)); /* ep 0 */ USB_DEV_EP_INTR_MASK = 0; /* FIXME: test */ dma_desc_init(); USB_IEP_MPS(0) = 0x40; USB_IEP_STS_MASK(0) = 0x0040; /* OF: 0x840 */ USB_IEP_TXFSIZE(0) = 0x20; USB_OEP_MPS(0) = 0x08000040; USB_OEP_STS_MASK(0) = 0x0000; /* OF: 0x1800 */ USB_OEP_RXFR(0) = 0x00; USB_IEP_CTRL(0) |= USB_EP_CTRL_FLUSH|USB_EP_CTRL_SNAK; /* set NAK */ USB_OEP_CTRL(0) |= USB_EP_CTRL_FLUSH|USB_EP_CTRL_SNAK; /* set NAK */ /* clear pending interrupts */ USB_DEV_EP_INTR = 0xffffffff; USB_DEV_INTR = 0xffffffff; VIC_INT_ENABLE = INTERRUPT_USB; usb_phy_resume(); USB_DEV_CTRL &= ~USB_DEV_CTRL_SOFT_DISCONN; USB_GPIO_CSR = USB_GPIO_TX_ENABLE_N | USB_GPIO_TX_BIT_STUFF_EN | USB_GPIO_XO_ON | USB_GPIO_HS_INTR | USB_GPIO_CLK_SEL10; /* 0x06180000; */ } void usb_drv_exit(void) { USB_DEV_CTRL |= (1<<10); /* soft disconnect */ VIC_INT_EN_CLEAR = INTERRUPT_USB; #if 0 CGU_USB &= ~(1<<5); CGU_PERI &= ~CGU_USB_CLOCK_ENABLE; /* Disable UVDD generating LDO */ ascodec_write(AS3517_USB_UTIL, ascodec_read(AS3517_USB_UTIL) & ~(1<<4)); #endif logf("usb_drv_exit() !!!!\n"); } int usb_drv_port_speed(void) { return (USB_DEV_CFG & 3) ? 0 : 1; } int usb_drv_request_endpoint(int type, int dir) { /* type 2, dir 128: bulk, in (to host) */ /* logf("%s(type=%d,dir=%d)\n",__func__,type,dir); */ (void) type; int i = dir == USB_DIR_IN ? 2 : 3; /* skip the control ep */ for(; i < USB_NUM_ENDPOINTS * 2; i += 2) if(!endpoints[i].busy) { endpoints[i].busy = true; i >>= 1; if (dir == USB_DIR_IN) { USB_DEV_EP_INTR_MASK &= ~(1<= 2) return -1; return -1; } volatile int tx_done; static char hexbuf[1025]; static char hextab[16] = "0123456789abcdef"; char *make_hex(char *data, int len) { int i; if (len > 512) len = 512; for (i=0; i> 4 ]; hexbuf[2*i+1] = hextab[(unsigned char)data[i] & 0xf]; } hexbuf[2*i] = 0; return hexbuf; } int usb_drv_send(int ep, void *ptr, int len) { logf("usb_drv_send(%d,%x,%d)\n", ep, (int)ptr, len); tx_done = 0; if ((ep & 1) != 0) panicf("%s(%d,%x,%d) not in ep?", __func__, ep,(int)ptr,len); if (ep == 0) { void *uc_buf = UNCACHED_ADDR((void*)tx_buf); char *data = ptr; if (len>64) panicf("%s(%d,%x,%d) len>64!", __func__, ep,(int)ptr,len); logf("sending: %s\n", make_hex(data, len)); memcpy(uc_buf, ptr, len); uc_desc[0]->status = USB_DMA_DESC_BS_HST_RDY | USB_DMA_DESC_LAST | len; /* uc_desc[0]->status = USB_DMA_DESC_BS_HST_RDY | USB_DMA_DESC_LAST | 64; */ uc_desc[0]->resv = 0xffffffff; uc_desc[0]->next_desc = &desc[0]; uc_desc[0]->data_ptr = tx_buf; /*USB_IEP_TXFSIZE(0) = len;*/ USB_IEP_CTRL(0) |= USB_EP_CTRL_FLUSH; USB_IEP_DESC_PTR(0) = (int)&desc[0]; USB_IEP_STS(0) = USB_IEP_STS(0); /* clear status */ USB_IEP_CTRL(0) |= USB_EP_CTRL_CNAK|USB_EP_CTRL_PD; /* signal poll demand */ while (!tx_done); return 0; } if(ep >= 2) panicf("%s(%d,%x,%d)", __func__,ep,(int)ptr,len); return -1; return -1; } int usb_drv_send_nonblocking(int ep, void *ptr, int len) { logf("usb_drv_send_nonblocking(%d,%x,%d)\n", ep, (int)ptr, len); /* TODO */ return usb_drv_send(ep, ptr, len); } int irq_4 = 0; int irq_8 = 0; int irq_10 = 0; int irq_20 = 0; int irq_40 = 0; /* interrupt service routine */ void INT_USB(void) { int ep = USB_DEV_EP_INTR & ~USB_DEV_EP_INTR_MASK; // = 0x10001 (in/out) int intr = USB_DEV_INTR & ~USB_DEV_INTR_MASK; struct usb_ctrlrequest *req = (void*)UNCACHED_ADDR(&setup_desc.data1); logf("INT_USB(ep=%x[r:%lx,m:%lx],intr=%x[r:%lx,m:%lx])\n", ep, USB_DEV_EP_INTR, USB_DEV_EP_INTR_MASK, intr, USB_DEV_INTR, USB_DEV_INTR_MASK); GPIOA_PIN(5) ^= 0xff; if(ep) { USB_DEV_EP_INTR = ep; if(ep & (1<<0)) // ctrl in { int ep_sts = USB_IEP_STS(0) & ~USB_IEP_STS_MASK(0); ep &= ~(1<<0); logf("ctrl in, status %lx\n", USB_IEP_STS(0)); USB_IEP_STS(0) = ep_sts; /* ack */ if (ep_sts & 0x40) { char *uc_buf = UNCACHED_ADDR((void*)tx_buf); ep_sts &= ~0x40; logf("IN, resending?\n"); uc_buf[0] = 0x5a; uc_buf[1] = 0xa5; uc_desc[0]->status |= USB_DMA_DESC_BS_HST_RDY; /* uc_desc[0]->status = USB_DMA_DESC_BS_HST_RDY | USB_DMA_DESC_LAST | 64; */ USB_IEP_CTRL(0) |= /*USB_EP_CTRL_SNAK|*/USB_EP_CTRL_PD; } if (ep_sts & 0x400) { ep_sts &= ~0x400; /*USB_IEP_CTRL(0) |= USB_EP_CTRL_SNAK|USB_EP_CTRL_FLUSH*/; USB_IEP_CTRL(0) |= USB_EP_CTRL_SNAK; logf("tx done\n"); /* usb_core_transfer_complete(0, USB_DIR_IN, 0, 12); */ tx_done = 1; } if (ep_sts) { panicf("ctrl in 0x%x %x",(int)USB_IEP_STS(0),ep); } } if(ep & (1<<1)) // bulk in { } if(ep & (1<<3)) // intr in { } if(ep & (1<<16)) // ctrl out { int ep_sts = USB_OEP_STS(0) & ~USB_OEP_STS_MASK(0); ep &= ~(1<<16); logf("ctrl out, status %lx\n", USB_OEP_STS(0)); /* struct usb_dev_setup_buf *uc_desc = UNCACHED_ADDR(&setup_desc); panicf("ctrl out 0x%x %x %x %x %x",(int)USB_OEP_STS(0),ep, uc_desc->status, uc_desc->data1, uc_desc->data2); */ USB_OEP_STS(0) = ep_sts; /* ACK */ if (ep_sts & 0x10) { ep_sts &= ~0x10; logf("got out token, status=%08x\n", uc_desc[1]->status); uc_desc[1]->status = USB_DMA_DESC_BS_HST_RDY | USB_DMA_DESC_LAST | 0x40; } if (ep_sts & 0x20) { static struct usb_ctrlrequest req_copy; ep_sts &= ~0x20; req_copy = *req; logf("got setup packet: type=%d req=%d val=%d ind=%d len=%d\n", req->bRequestType, req->bRequest, req->wValue, req->wIndex, req->wLength); usb_core_control_request(&req_copy); setup_desc_init(&setup_desc); } else { panicf("in: %x %x %x", setup_desc.status, setup_desc.data1, setup_desc.data2); } } if(ep & (1<<17)) // bulk out { } if (ep) panicf("USB : 0x%x", ep); } if(intr) { USB_DEV_INTR = intr; /* ack interrupt */ if (intr & 0x4) {/* idle >3ms detected */ intr &= ~0x4; irq_4++; logf("usb idle\n"); } if (intr & 0x8) {/* usb reset from host? */ intr &= ~0x8; irq_8++; logf("usb reset\n"); } if (intr & 0x10) {/* suspend req from host? */ intr &= ~0x10; irq_10++; logf("usb suspend\n"); } if (intr & 0x20) {/* sof received */ intr &= ~0x20; irq_20++; logf("sof\n"); } if (intr & 0x40) {/* speed enumeration complete */ int spd = USB_DEV_STS & 0x00006000; /* Enumerated Speed */ intr &= ~0x40; irq_40++; logf("speed enum complete: "); if (spd == 0x0000) logf("hs\n"); if (spd == 0x2000) logf("fs\n"); if (spd == 0x4000) logf("ls\n"); USB_PHY_EP0_INFO = 0x00200000; USB_DEV_CTRL |= USB_DEV_CTRL_APCSR_DONE; USB_IEP_CTRL(0) |= USB_EP_CTRL_ACT; USB_OEP_CTRL(0) |= USB_EP_CTRL_ACT; USB_IEP_CTRL(0) |= USB_EP_CTRL_CNAK|USB_EP_CTRL_FLUSH; /* clear NAK */ USB_OEP_CTRL(0) |= USB_EP_CTRL_CNAK|USB_EP_CTRL_FLUSH; /* clear NAK */ } if (intr) panicf("usb devirq 0x%x", intr); } USB_DEV_CTRL |= USB_DEV_CTRL_RDE; } /* (not essential? , not implemented in usb-tcc.c) */ void usb_drv_set_test_mode(int mode) { (void)mode; } void usb_drv_set_address(int address) { (void)address; } void usb_drv_stall(int ep, bool stall, bool in) { (void)ep;(void)stall;(void)in; } bool usb_drv_stalled(int ep, bool in) { (void)ep;(void)in; return true; }