diff options
-rw-r--r-- | firmware/export/config-ondavx747.h | 4 | ||||
-rw-r--r-- | firmware/export/jz4740.h | 68 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/onda_vx747/lcd-onda_vx747.c | 2 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/system-jz4740.c | 171 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/usb-jz4740.c | 294 |
5 files changed, 444 insertions, 95 deletions
diff --git a/firmware/export/config-ondavx747.h b/firmware/export/config-ondavx747.h index 2856e7e16d..2fe0564e71 100644 --- a/firmware/export/config-ondavx747.h +++ b/firmware/export/config-ondavx747.h @@ -158,7 +158,7 @@ #define CONFIG_USBOTG USBOTG_JZ4740 #define HAVE_USBSTACK -#define USB_VENDOR_ID 0x041e -#define USB_PRODUCT_ID 0x4133 +#define USB_VENDOR_ID 0x07C4 +#define USB_PRODUCT_ID 0xA4A5 #endif diff --git a/firmware/export/jz4740.h b/firmware/export/jz4740.h index e63228ff70..7fbfba283f 100644 --- a/firmware/export/jz4740.h +++ b/firmware/export/jz4740.h @@ -260,28 +260,29 @@ #define CPM_LCR_LPM_SLEEP (0x1 << CPM_LCR_LPM_BIT) /* Clock Gate Register */ -#define CPM_CLKGR_UART1 (1 << 15) +#define CPM_CLKGR_UART1 (1 << 15) #define CPM_CLKGR_UHC (1 << 14) #define CPM_CLKGR_IPU (1 << 13) -#define CPM_CLKGR_DMAC (1 << 12) +#define CPM_CLKGR_DMAC (1 << 12) #define CPM_CLKGR_UDC (1 << 11) #define CPM_CLKGR_LCD (1 << 10) #define CPM_CLKGR_CIM (1 << 9) -#define CPM_CLKGR_SADC (1 << 8) +#define CPM_CLKGR_SADC (1 << 8) #define CPM_CLKGR_MSC (1 << 7) -#define CPM_CLKGR_AIC1 (1 << 6) -#define CPM_CLKGR_AIC2 (1 << 5) +#define CPM_CLKGR_AIC1 (1 << 6) +#define CPM_CLKGR_AIC2 (1 << 5) #define CPM_CLKGR_SSI (1 << 4) #define CPM_CLKGR_I2C (1 << 3) #define CPM_CLKGR_RTC (1 << 2) #define CPM_CLKGR_TCU (1 << 1) -#define CPM_CLKGR_UART0 (1 << 0) +#define CPM_CLKGR_UART0 (1 << 0) /* Sleep Control Register */ -#define CPM_SCR_O1ST_BIT 8 -#define CPM_SCR_O1ST_MASK (0xff << CPM_SCR_O1ST_BIT) +#define CPM_SCR_O1ST_BIT 8 +#define CPM_SCR_O1ST_MASK (0xff << CPM_SCR_O1ST_BIT) +#define CPM_SCR_USBHOST_SUSPEND (1 << 7) #define CPM_SCR_USBPHY_ENABLE (1 << 6) -#define CPM_SCR_OSC_ENABLE (1 << 4) +#define CPM_SCR_OSC_ENABLE (1 << 4) /* Hibernate Control Register */ #define CPM_HCR_PD (1 << 0) @@ -2419,7 +2420,7 @@ #define USB_INTR_OUTEP1 0x0002 #define USB_INTR_OUTEP2 0x0004 -#define USB_INTR_EP(n) (n*2) +#define USB_INTR_EP(n) ((n)==0 ? 1 : ((n)*2)) /* CSR0 bit masks */ #define USB_CSR0_OUTPKTRDY 0x01 @@ -3282,56 +3283,59 @@ do { \ #define __cpm_sleep_mode() \ (REG_CPM_LCR = (REG_CPM_LCR & ~CPM_LCR_LPM_MASK) | CPM_LCR_LPM_SLEEP) -#define __cpm_stop_all() (REG_CPM_CLKGR = 0xffff) -#define __cpm_stop_uart1() (REG_CPM_CLKGR |= CPM_CLKGR_UART1) -#define __cpm_stop_uhc() (REG_CPM_CLKGR |= CPM_CLKGR_UHC) -#define __cpm_stop_ipu() (REG_CPM_CLKGR |= CPM_CLKGR_IPU) +#define __cpm_stop_all() (REG_CPM_CLKGR = 0xffff) +#define __cpm_stop_uart1() (REG_CPM_CLKGR |= CPM_CLKGR_UART1) +#define __cpm_stop_uhc() (REG_CPM_CLKGR |= CPM_CLKGR_UHC) +#define __cpm_stop_ipu() (REG_CPM_CLKGR |= CPM_CLKGR_IPU) #define __cpm_stop_dmac() (REG_CPM_CLKGR |= CPM_CLKGR_DMAC) -#define __cpm_stop_udc() (REG_CPM_CLKGR |= CPM_CLKGR_UDC) -#define __cpm_stop_lcd() (REG_CPM_CLKGR |= CPM_CLKGR_LCD) -#define __cpm_stop_cim() (REG_CPM_CLKGR |= CPM_CLKGR_CIM) +#define __cpm_stop_udc() (REG_CPM_CLKGR |= CPM_CLKGR_UDC) +#define __cpm_stop_lcd() (REG_CPM_CLKGR |= CPM_CLKGR_LCD) +#define __cpm_stop_cim() (REG_CPM_CLKGR |= CPM_CLKGR_CIM) #define __cpm_stop_sadc() (REG_CPM_CLKGR |= CPM_CLKGR_SADC) -#define __cpm_stop_msc() (REG_CPM_CLKGR |= CPM_CLKGR_MSC) +#define __cpm_stop_msc() (REG_CPM_CLKGR |= CPM_CLKGR_MSC) #define __cpm_stop_aic1() (REG_CPM_CLKGR |= CPM_CLKGR_AIC1) #define __cpm_stop_aic2() (REG_CPM_CLKGR |= CPM_CLKGR_AIC2) -#define __cpm_stop_ssi() (REG_CPM_CLKGR |= CPM_CLKGR_SSI) -#define __cpm_stop_i2c() (REG_CPM_CLKGR |= CPM_CLKGR_I2C) -#define __cpm_stop_rtc() (REG_CPM_CLKGR |= CPM_CLKGR_RTC) -#define __cpm_stop_tcu() (REG_CPM_CLKGR |= CPM_CLKGR_TCU) -#define __cpm_stop_uart0() (REG_CPM_CLKGR |= CPM_CLKGR_UART0) - -#define __cpm_start_all() (REG_CPM_CLKGR = 0x0) -#define __cpm_start_uart1() (REG_CPM_CLKGR &= ~CPM_CLKGR_UART1) +#define __cpm_stop_ssi() (REG_CPM_CLKGR |= CPM_CLKGR_SSI) +#define __cpm_stop_i2c() (REG_CPM_CLKGR |= CPM_CLKGR_I2C) +#define __cpm_stop_rtc() (REG_CPM_CLKGR |= CPM_CLKGR_RTC) +#define __cpm_stop_tcu() (REG_CPM_CLKGR |= CPM_CLKGR_TCU) +#define __cpm_stop_uart0() (REG_CPM_CLKGR |= CPM_CLKGR_UART0) + +#define __cpm_start_all() (REG_CPM_CLKGR = 0x0) +#define __cpm_start_uart1() (REG_CPM_CLKGR &= ~CPM_CLKGR_UART1) #define __cpm_start_uhc() (REG_CPM_CLKGR &= ~CPM_CLKGR_UHC) #define __cpm_start_ipu() (REG_CPM_CLKGR &= ~CPM_CLKGR_IPU) -#define __cpm_start_dmac() (REG_CPM_CLKGR &= ~CPM_CLKGR_DMAC) +#define __cpm_start_dmac() (REG_CPM_CLKGR &= ~CPM_CLKGR_DMAC) #define __cpm_start_udc() (REG_CPM_CLKGR &= ~CPM_CLKGR_UDC) #define __cpm_start_lcd() (REG_CPM_CLKGR &= ~CPM_CLKGR_LCD) #define __cpm_start_cim() (REG_CPM_CLKGR &= ~CPM_CLKGR_CIM) -#define __cpm_start_sadc() (REG_CPM_CLKGR &= ~CPM_CLKGR_SADC) +#define __cpm_start_sadc() (REG_CPM_CLKGR &= ~CPM_CLKGR_SADC) #define __cpm_start_msc() (REG_CPM_CLKGR &= ~CPM_CLKGR_MSC) -#define __cpm_start_aic1() (REG_CPM_CLKGR &= ~CPM_CLKGR_AIC1) -#define __cpm_start_aic2() (REG_CPM_CLKGR &= ~CPM_CLKGR_AIC2) +#define __cpm_start_aic1() (REG_CPM_CLKGR &= ~CPM_CLKGR_AIC1) +#define __cpm_start_aic2() (REG_CPM_CLKGR &= ~CPM_CLKGR_AIC2) #define __cpm_start_ssi() (REG_CPM_CLKGR &= ~CPM_CLKGR_SSI) #define __cpm_start_i2c() (REG_CPM_CLKGR &= ~CPM_CLKGR_I2C) #define __cpm_start_rtc() (REG_CPM_CLKGR &= ~CPM_CLKGR_RTC) #define __cpm_start_tcu() (REG_CPM_CLKGR &= ~CPM_CLKGR_TCU) -#define __cpm_start_uart0() (REG_CPM_CLKGR &= ~CPM_CLKGR_UART0) +#define __cpm_start_uart0() (REG_CPM_CLKGR &= ~CPM_CLKGR_UART0) #define __cpm_get_o1st() \ ((REG_CPM_SCR & CPM_SCR_O1ST_MASK) >> CPM_SCR_O1ST_BIT) #define __cpm_set_o1st(v) \ (REG_CPM_SCR = (REG_CPM_SCR & ~CPM_SCR_O1ST_MASK) | ((v) << (CPM_SCR_O1ST_BIT))) #define __cpm_suspend_usbphy() (REG_CPM_SCR |= CPM_SCR_USBPHY_SUSPEND) +#define __cpm_suspend_usbhost() (REG_CPM_SCR |= CPM_SCR_USBHOST_SUSPEND) #define __cpm_enable_osc_in_sleep() (REG_CPM_SCR |= CPM_SCR_OSC_ENABLE) +#define CFG_EXTAL 12000000 + #ifdef CFG_EXTAL #define JZ_EXTAL CFG_EXTAL #else #define JZ_EXTAL 3686400 #endif -#define JZ_EXTAL2 32768 /* RTC clock */ +#define JZ_EXTAL2 32768 /* RTC clock */ /* PLL output frequency */ static __inline__ unsigned int __cpm_get_pllout(void) diff --git a/firmware/target/mips/ingenic_jz47xx/onda_vx747/lcd-onda_vx747.c b/firmware/target/mips/ingenic_jz47xx/onda_vx747/lcd-onda_vx747.c index 40d9bb6106..faed5ecda2 100644 --- a/firmware/target/mips/ingenic_jz47xx/onda_vx747/lcd-onda_vx747.c +++ b/firmware/target/mips/ingenic_jz47xx/onda_vx747/lcd-onda_vx747.c @@ -203,7 +203,7 @@ static void _set_lcd_clock(void) __cpm_stop_lcd(); pll_div = ( REG_CPM_CPCCR & CPM_CPCCR_PCS ); /* clock source, 0:pllout/2 1: pllout */ - pll_div = pll_div ? 1 : 2 ; + pll_div = pll_div ? 1 : 2; val = ( __cpm_get_pllout()/pll_div ) / __cpm_get_pclk(); val--; if ( val > 0x1ff ) diff --git a/firmware/target/mips/ingenic_jz47xx/system-jz4740.c b/firmware/target/mips/ingenic_jz47xx/system-jz4740.c index 48fb192810..c741d9f311 100644 --- a/firmware/target/mips/ingenic_jz47xx/system-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/system-jz4740.c @@ -663,6 +663,168 @@ void dma_disable(void) } } +static inline void pll_convert(unsigned int pllin, unsigned int *pll_cfcr, unsigned int *pll_plcr1) +{ + register unsigned int cfcr, plcr1; + int div[5] = {1, 3, 3, 3, 3}; /* divisors of I:S:P:L:M */ + int nf; + + cfcr = CPM_CPCCR_CLKOEN | + (div[0] << CPM_CPCCR_CDIV_BIT) | + (div[1] << CPM_CPCCR_HDIV_BIT) | + (div[2] << CPM_CPCCR_PDIV_BIT) | + (div[3] << CPM_CPCCR_MDIV_BIT) | + (div[4] << CPM_CPCCR_LDIV_BIT); + + //nf = pllin * 2 / CFG_EXTAL; + nf = pllin * 2 / 375299969; + plcr1 = ((nf - 2) << CPM_CPPCR_PLLM_BIT) | /* FD */ + (0 << CPM_CPPCR_PLLN_BIT) | /* RD=0, NR=2 */ + (0 << CPM_CPPCR_PLLOD_BIT) | /* OD=0, NO=1 */ + (0xa << CPM_CPPCR_PLLST_BIT) | /* PLL stable time */ + CPM_CPPCR_PLLEN; /* enable PLL */ + + /* init PLL */ + *pll_cfcr = cfcr; + *pll_plcr1 = plcr1; +} + +static inline void sdram_convert(unsigned int pllin, unsigned int *sdram_freq) +{ + register unsigned int ns, tmp; + + ns = 1000000000 / pllin; + tmp = 15625 / ns; + + /* Set refresh registers */ + tmp = tmp / 64 + 1; + + if(tmp > 0xff) + tmp = 0xff; + + *sdram_freq = tmp; +} + +static inline void set_cpu_freq(unsigned int pllin, unsigned int div) +{ + unsigned int sdram_freq; + unsigned int pll_cfcr, pll_plcr1; + int div_preq[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; + + if(pllin < 25000000 || pllin > 420000000) + panicf("PLL should be >25000000 and <420000000 !"); + + unsigned long t = read_c0_status(); + write_c0_status(t & ~1); + + pll_convert(pllin, &pll_cfcr, &pll_plcr1); + + sdram_convert(pllin / div_preq[div], &sdram_freq); + + REG_CPM_CPCCR &= ~CPM_CPCCR_CE; + + REG_CPM_CPCCR = pll_cfcr; + REG_CPM_CPPCR = pll_plcr1; + + REG_EMC_RTCOR = sdram_freq; + REG_EMC_RTCNT = sdram_freq; + + REG_CPM_CPCCR |= CPM_CPCCR_CE; + + detect_clock(); + + write_c0_status(t); +} + +static void OF_init_clocks(void) +{ + unsigned int prog_entry = ((unsigned int)OF_init_clocks >> 5) << 5; + unsigned int i, prog_size = 1024; + + for(i = prog_entry; i < prog_entry + prog_size; i += 32) + __asm__ __volatile__("cache 0x1c, 0x00(%0) \n" + : + : "r" (i) + ); + + /* disable PLL clock */ + REG_CPM_CPPCR &= ~CPM_CPPCR_PLLEN; + REG_CPM_CPCCR |= CPM_CPCCR_CE; + + unsigned long old_clocks = REG_CPM_CLKGR; + /* + REG_CPM_CLKGR = ~( CPM_CLKGR_UART0 | CPM_CLKGR_TCU | + CPM_CLKGR_RTC | CPM_CLKGR_SADC | + CPM_CLKGR_LCD ); + */ + + unsigned long old_scr = REG_CPM_SCR; + REG_CPM_SCR &= ~CPM_SCR_OSC_ENABLE; /* O1SE: 12M oscillator is disabled in Sleep mode */ + + REG_EMC_DMCR |= (EMC_DMCR_RMODE | EMC_DMCR_RFSH); /* self refresh + refresh is performed */ + REG_EMC_DMCR = (REG_EMC_DMCR & ~EMC_DMCR_RMODE) | 1; /* -> RMODE = auto refresh + -> CAS mode = 2 cycles */ + __asm__ __volatile__("wait \n"); + + REG_CPM_CLKGR = old_clocks; + REG_CPM_SCR = old_scr; + + for(i=0; i<90; i++); + + set_cpu_freq(336000000, 1); + + for(i=0; i<60; i++); +} + +static void my_init_clocks(void) +{ + unsigned long t = read_c0_status(); + write_c0_status(t & ~1); + + unsigned int prog_entry = ((unsigned int)my_init_clocks / 32 - 1) * 32; + unsigned int i, prog_size = 1024; + + for(i = prog_entry; i < prog_entry + prog_size; i += 32) + __asm__ __volatile__("cache 0x1c, 0x00(%0) \n" + : + : "r" (i) + ); + + unsigned int sdram_freq, plcr1, cfcr; + + sdram_convert(336000000/3, &sdram_freq); + + cfcr = CPM_CPCCR_CLKOEN | + (6 << CPM_CPCCR_UDIV_BIT) | + CPM_CPCCR_UCS | + CPM_CPCCR_PCS | + (0 << CPM_CPCCR_CDIV_BIT) | + (2 << CPM_CPCCR_HDIV_BIT) | + (2 << CPM_CPCCR_PDIV_BIT) | + (2 << CPM_CPCCR_MDIV_BIT) | + (2 << CPM_CPCCR_LDIV_BIT); + + plcr1 = (54 << CPM_CPPCR_PLLM_BIT) | /* FD */ + (0 << CPM_CPPCR_PLLN_BIT) | /* RD=0, NR=2 */ + (0 << CPM_CPPCR_PLLOD_BIT) | /* OD=0, NO=1 */ + (0x20 << CPM_CPPCR_PLLST_BIT)| /* PLL stable time */ + CPM_CPPCR_PLLEN; /* enable PLL */ + + REG_CPM_CPCCR &= ~CPM_CPCCR_CE; + + REG_CPM_CPCCR = cfcr; + REG_CPM_CPPCR = plcr1; + + REG_EMC_RTCOR = sdram_freq; + REG_EMC_RTCNT = sdram_freq; + + REG_CPM_CPCCR |= CPM_CPCCR_CE; + + REG_CPM_LPCDR = (REG_CPM_LPCDR & ~CPM_LPCDR_PIXDIV_MASK) | (11 << CPM_LPCDR_PIXDIV_BIT); + + write_c0_status(t); +} + extern int main(void); extern void except_common_entry(void); @@ -696,6 +858,15 @@ void system_main(void) /* Disable unneeded clocks, clocks are enabled when needed */ __cpm_stop_all(); + __cpm_suspend_usbhost(); + +#if 0 + my_init_clocks(); + /*__cpm_stop_udc(); + REG_CPM_CPCCR |= CPM_CPCCR_UCS; + REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_UDIV_MASK) | (3 << CPM_CPCCR_UDIV_BIT); + __cpm_start_udc();*/ +#endif /* Enable interrupts at core level */ sti(); diff --git a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c index f06e796e05..eda3fb3b88 100644 --- a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c @@ -34,11 +34,12 @@ #define USB_EP0_RX 1 #define USB_EP0_TX 2 -#define EP_BUF_LEFT(ep) (ep->length - ep->sent) -#define EP_PTR(ep) ((void*)((unsigned int)ep->buf + ep->sent)) -#define EP_NUMBER(ep) (((int)ep - (int)&endpoints[0])/sizeof(struct usb_endpoint)) +#define EP_BUF_LEFT(ep) ((ep)->length - (ep)->sent) +#define EP_PTR(ep) ((void*)((unsigned int)(ep)->buf + (ep)->sent)) +#define EP_NUMBER(ep) (((int)(ep) - (int)&endpoints[0])/sizeof(struct usb_endpoint)) +#define EP_NUMBER2(ep) (EP_NUMBER((ep))/2) #define TOTAL_EP() (sizeof(endpoints)/sizeof(struct usb_endpoint)) -#define EP_IS_IN(ep) (EP_NUMBER(ep)%2) +#define EP_IS_IN(ep) (EP_NUMBER((ep))%2) enum ep_type { @@ -66,11 +67,11 @@ static unsigned char ep0_rx_buf[64]; static unsigned char ep0state = USB_EP0_IDLE; static struct usb_endpoint endpoints[] = { - /* buf length sent type use_dma fifo_addr fifo_size */ + /* buf length sent type use_dma fifo_addr fifo_size */ {&ep0_rx_buf, 0, {0}, ep_control, false, USB_FIFO_EP0, 64 }, {NULL, 0, {0}, ep_control, false, USB_FIFO_EP0, 64 }, - {NULL, 0, {0}, ep_bulk, true, USB_FIFO_EP1, 512}, - {NULL, 0, {0}, ep_bulk, true, USB_FIFO_EP1, 512}, + {NULL, 0, {0}, ep_bulk, false, USB_FIFO_EP1, 512}, + {NULL, 0, {0}, ep_bulk, false, USB_FIFO_EP1, 512}, {NULL, 0, {0}, ep_interrupt, false, USB_FIFO_EP2, 64 } }; @@ -81,7 +82,7 @@ static inline void select_endpoint(int ep) static void readFIFO(struct usb_endpoint *ep, unsigned int size) { - logf("readFIFO(EP%d, %d)", EP_NUMBER(ep), size); + logf("readFIFO(EP%d, %d)", EP_NUMBER2(ep), size); register unsigned char *ptr = (unsigned char*)EP_PTR(ep); register unsigned int *ptr32 = (unsigned int*)ptr; @@ -117,19 +118,19 @@ static void readFIFO(struct usb_endpoint *ep, unsigned int size) static void writeFIFO(struct usb_endpoint *ep, unsigned int size) { - logf("writeFIFO(EP%d, %d)", EP_NUMBER(ep), size); + //logf("writeFIFO(EP%d, %d)", EP_NUMBER2(ep), size); register unsigned int *d = (unsigned int *)EP_PTR(ep); register unsigned char *c; register int s; - if (size > 0) + if(size > 0) { s = size >> 2; while (s--) REG32(ep->fifo_addr) = *d++; - if ( (s = size & 3) ) + if( (s = size & 3) ) { c = (unsigned char *)d; while (s--) @@ -140,18 +141,43 @@ static void writeFIFO(struct usb_endpoint *ep, unsigned int size) REG32(ep->fifo_addr) = 0; } +static void flushFIFO(struct usb_endpoint *ep) +{ + //logf("flushFIFO(%d)", EP_NUMBER(ep)); + + switch (ep->type) + { + case ep_control: + break; + + case ep_bulk: + case ep_interrupt: + if(EP_IS_IN(ep)) + REG_USB_REG_INCSR |= USB_INCSR_FF; + else + REG_USB_REG_OUTCSR |= USB_OUTCSR_FF; + break; + } +} + static void EP0_send(void) { register struct usb_endpoint* ep = &endpoints[1]; register unsigned int length; + if(ep->length == 0) + { + select_endpoint(0); + REG_USB_REG_CSR0 |= (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND); + return; + } + if(ep->sent == 0) length = (ep->length <= ep->fifo_size ? ep->length : ep->fifo_size); else length = (EP_BUF_LEFT(ep) <= ep->fifo_size ? EP_BUF_LEFT(ep) : ep->fifo_size); select_endpoint(0); - writeFIFO(ep, length); ep->sent += length; @@ -166,6 +192,7 @@ static void EP0_send(void) static void EP0_handler(void) { +logf("EP0_handler"); register unsigned char csr0; /* Read CSR0 */ @@ -208,46 +235,127 @@ static void EP0_handler(void) EP0_send(); } +static void EPIN_handler(unsigned int endpoint) +{ +logf("EPIN_handler(%d)", endpoint); + struct usb_endpoint* ep = &endpoints[endpoint*2+1]; + unsigned int length, csr; + + select_endpoint(endpoint); + csr = REG_USB_REG_INCSR; + + if(ep->length == 0) + { + REG_USB_REG_INCSR = csr | USB_INCSR_INPKTRDY; + return; + } + + if(csr & USB_INCSR_SENTSTALL) + { + REG_USB_REG_INCSR = csr & ~USB_INCSR_SENTSTALL; + return; + } + + if(ep->sent == 0) + length = (ep->length <= ep->fifo_size ? ep->length : ep->fifo_size); + else + length = (EP_BUF_LEFT(ep) <= ep->fifo_size ? EP_BUF_LEFT(ep) : ep->fifo_size); + + writeFIFO(ep, length); + ep->sent += length; + + REG_USB_REG_INCSR = csr | USB_INCSR_INPKTRDY; + if(ep->sent >= ep->length) + usb_core_transfer_complete(endpoint|USB_DIR_IN, USB_DIR_IN, 0, ep->sent); +} + +static void EPOUT_handler(unsigned int endpoint) +{ +logf("EPOUT_handler(%d)", endpoint); + struct usb_endpoint* ep = &endpoints[endpoint*2]; + unsigned int size, csr; + + select_endpoint(endpoint); + csr = REG_USB_REG_OUTCSR; + + if(ep->buf == NULL && ep->length == 0) + { + REG_USB_REG_OUTCSR = csr & ~USB_OUTCSR_OUTPKTRDY; + return; + } + + if(csr & USB_OUTCSR_SENTSTALL) + { + REG_USB_REG_OUTCSR = csr & ~USB_OUTCSR_SENTSTALL; + return; + } + + size = REG_USB_REG_OUTCOUNT; + ep->received += size; + + readFIFO(ep, size); + + REG_USB_REG_OUTCSR = csr & ~USB_OUTCSR_OUTPKTRDY; + + logf("received: %d length: %d", ep->received, ep->length); + + //if(ep->received >= ep->length) + usb_core_transfer_complete(endpoint|USB_DIR_OUT, USB_DIR_OUT, 0, ep->received); +} + static void setup_endpoint(struct usb_endpoint *ep) { + int csr; ep->sent = 0; ep->length = 0; + select_endpoint(EP_NUMBER2(ep)); + + if(ep->type == ep_bulk) + { + if(REG_USB_REG_POWER & USB_POWER_HSMODE) + ep->fifo_size = 512; + else + ep->fifo_size = 64; + } + if(EP_IS_IN(ep)) { - if(ep->type == ep_bulk) - { - register int size; - - if((REG_USB_REG_POWER & USB_POWER_HSMODE) == 0) - size = 64; - else - size = 512; - - REG_USB_REG_INMAXP = size; - ep->fifo_size = size; - } + REG_USB_REG_INMAXP = ep->fifo_size; + csr = (USB_INCSR_FF | USB_INCSR_CDT | USB_INCSRH_MODE); + if(ep->use_dma) + csr |= (USB_INCSRH_DMAREQENAB | USB_INCSRH_AUTOSET); else - REG_USB_REG_INMAXP = ep->fifo_size; + REG_USB_REG_INTRINE |= USB_INTR_EP(EP_NUMBER2(ep)); - REG_USB_REG_INCSR = (USB_INCSR_FF | USB_INCSR_CDT | USB_INCSRH_MODE); - REG_USB_REG_INTRINE |= USB_INTR_EP(EP_NUMBER(ep)); + REG_USB_REG_INCSR = csr; } else - { + { REG_USB_REG_OUTMAXP = ep->fifo_size; - REG_USB_REG_OUTCSR = (USB_OUTCSR_FF | USB_OUTCSR_CDT); - REG_USB_REG_INTROUTE |= USB_INTR_EP(EP_NUMBER(ep)); + csr = (USB_OUTCSR_FF | USB_OUTCSR_CDT); + + if(ep->type == ep_interrupt) + csr |= USB_OUTCSRH_DNYT; + + if(ep->use_dma) + csr |= (USB_OUTCSRH_DMAREQENAB | USB_OUTCSRH_AUTOCLR | USB_OUTCSRH_DMAREQMODE); + else + REG_USB_REG_INTROUTE |= USB_INTR_EP(EP_NUMBER2(ep)); + + csr = REG_USB_REG_OUTCSR; } + + //flushFIFO(ep); } static void udc_reset(void) { - logf("udc_reset"); + logf("udc_reset()"); register unsigned int i; - /* data init */ + /* EP0 init */ ep0state = USB_EP0_IDLE; /* Disable interrupts */ @@ -261,19 +369,20 @@ static void udc_reset(void) /* Reset address */ REG_USB_REG_FADDR = 0; - //REG_USB_REG_POWER = (USB_POWER_SOFTCONN | USB_POWER_HSENAB); /* High speed and softconnect */ + + /* High speed and softconnect */ + //REG_USB_REG_POWER = (USB_POWER_SOFTCONN | USB_POWER_HSENAB); REG_USB_REG_POWER = USB_POWER_SOFTCONN; + /* Enable SUSPEND */ /* REG_USB_REG_POWER |= USB_POWER_SUSPENDM; */ + /* Reset EP0 */ select_endpoint(0); REG_USB_REG_CSR0 = (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_SVDSETUPEND); for(i=2; i<TOTAL_EP(); i++) /* Skip EP0 */ - { - select_endpoint(i); setup_endpoint(&endpoints[i]); - } /* Enable interrupts */ REG_USB_REG_INTRINE |= USB_INTR_EP0; @@ -297,19 +406,31 @@ void UDC(void) /* EPIN & EPOUT are all handled in DMA */ if(intrIn & USB_INTR_EP0) EP0_handler(); + if(intrIn & USB_INTR_INEP1) + EPIN_handler(1); + if(intrIn & USB_INTR_INEP2) + EPIN_handler(2); + if(intrOut & USB_INTR_OUTEP1) + EPOUT_handler(1); + if(intrOut & USB_INTR_OUTEP2) + EPOUT_handler(2); if(intrUSB & USB_INTR_RESET) udc_reset(); - if(intrUSB & USB_INTR_SUSPEND); - if(intrUSB & USB_INTR_RESUME); + //if(intrUSB & USB_INTR_SUSPEND); + //if(intrUSB & USB_INTR_RESUME); if(intrDMA & USB_INTR_DMA_BULKIN) { logf("DMA_BULKIN %d", ((REG_USB_REG_CNTL1 >> 4) & 0xF)); - usb_core_transfer_complete(((REG_USB_REG_CNTL1 >> 4) & 0xF) | USB_DIR_IN, USB_DIR_IN, 0, 0); + usb_core_transfer_complete(1 | USB_DIR_IN, USB_DIR_IN, 0, 0); } if(intrDMA & USB_INTR_DMA_BULKOUT) { logf("DMA_BULKOUT %d", ((REG_USB_REG_CNTL2 >> 4) & 0xF)); - usb_core_transfer_complete(((REG_USB_REG_CNTL2 >> 4) & 0xF) | USB_DIR_OUT, USB_DIR_OUT, 0, 0); + + select_endpoint(1); + REG_USB_REG_OUTCSR &= ~(USB_OUTCSRH_DMAREQENAB | USB_OUTCSR_OUTPKTRDY); + + usb_core_transfer_complete(1 | USB_DIR_OUT, USB_DIR_OUT, 0, 0); } } @@ -317,7 +438,7 @@ bool usb_drv_stalled(int endpoint, bool in) { logf("usb_drv_stalled(%d, %s)", endpoint, in?"IN":"OUT"); - select_endpoint(endpoint); + select_endpoint(endpoint & 0x7F); if(endpoint == 0) return (REG_USB_REG_CSR0 & USB_CSR0_SENDSTALL) != 0; @@ -332,7 +453,7 @@ bool usb_drv_stalled(int endpoint, bool in) void usb_drv_stall(int endpoint, bool stall, bool in) { - logf("usb_drv_stall(%d,%s,%s)", endpoint, stall?"y":"n", in?"IN":"OUT"); + logf("usb_drv_stall(%d,%s,%s)", endpoint, stall?"Y":"N", in?"IN":"OUT"); select_endpoint(endpoint); @@ -350,14 +471,14 @@ void usb_drv_stall(int endpoint, bool stall, bool in) if(stall) REG_USB_REG_INCSR |= USB_INCSR_SENDSTALL; else - REG_USB_REG_INCSR &= ~USB_INCSR_SENDSTALL; + REG_USB_REG_INCSR = (REG_USB_REG_INCSR & ~USB_INCSR_SENDSTALL) | USB_INCSR_CDT; } else { if(stall) REG_USB_REG_OUTCSR |= USB_OUTCSR_SENDSTALL; else - REG_USB_REG_OUTCSR &= ~USB_OUTCSR_SENDSTALL; + REG_USB_REG_OUTCSR = (REG_USB_REG_OUTCSR & ~USB_OUTCSR_SENDSTALL) | USB_OUTCSR_CDT; } } } @@ -388,12 +509,13 @@ void usb_enable(bool on) void usb_drv_init(void) { + logf("usb_drv_init()"); + /* Set this bit to allow the UDC entering low-power mode when * there are no actions on the USB bus. * UDC still works during this bit was set. */ //__cpm_stop_udc(); - __cpm_start_udc(); /* Enable the USB PHY */ @@ -404,6 +526,8 @@ void usb_drv_init(void) void usb_drv_exit(void) { + logf("usb_drv_exit()"); + /* Disable interrupts */ REG_USB_REG_INTRINE = 0; REG_USB_REG_INTROUTE = 0; @@ -413,7 +537,7 @@ void usb_drv_exit(void) REG_USB_REG_CNTL1 = 0; REG_USB_REG_CNTL2 = 0; - /* Disconnect from usb */ + /* Disconnect from USB */ REG_USB_REG_POWER &= ~USB_POWER_SOFTCONN; /* Disable the USB PHY */ @@ -431,32 +555,71 @@ void usb_drv_set_address(int address) int usb_drv_send(int endpoint, void* ptr, int length) { - logf("usb_drv_send(%d, 0x%x, %d)", endpoint, (int)ptr, length); - - if(endpoint == EP_CONTROL && ptr == NULL && length == 0) /* ACK request */ - return 0; + int flags; + endpoint &= 0x7F; + logf("usb_drv_send(%d, 0x%x, %d)", endpoint, (int)ptr, length); + if(endpoint == EP_CONTROL) { + flags = disable_irq_save(); endpoints[1].buf = ptr; endpoints[1].sent = 0; endpoints[1].length = length; ep0state = USB_EP0_TX; EP0_send(); + + restore_irq(flags); return 0; } - else + else if(endpoint == 1) + { +#if 0 + select_endpoint(endpoint); + + REG_USB_REG_ADDR2 = ((unsigned long)ptr) & 0x7fffffff; + REG_USB_REG_COUNT2 = length; + REG_USB_REG_CNTL2 = 1; +#else + flags = disable_irq_save(); + endpoints[3].buf = ptr; + endpoints[3].sent = 0; + endpoints[3].length = length; + EPIN_handler(1); + restore_irq(flags); +#endif return 0; + } + else + return -1; +} + +int usb_drv_send_nonblocking(int endpoint, void* ptr, int length) +{ + return usb_drv_send(endpoint, ptr, length); } int usb_drv_recv(int endpoint, void* ptr, int length) { + int flags; + endpoint &= 0x7F; + logf("usb_drv_recv(%d, 0x%x, %d)", endpoint, (int)ptr, length); - if(endpoint == EP_CONTROL && ptr == NULL && length == 0) /* ACK request */ + if(endpoint == EP_CONTROL && ptr == NULL && length == 0) + return 0; /* ACK request, handled by the USB controller */ + else if(endpoint == 1) + { + logf("EP1 handled: %d", length); + flags = disable_irq_save(); + endpoints[2].buf = ptr; + endpoints[2].received = 0; + endpoints[2].length = length; + restore_irq(flags); return 0; - - return -1; + } + else + return -1; } void usb_drv_set_test_mode(int mode) @@ -492,13 +655,18 @@ void usb_drv_cancel_all_transfers(void) { logf("usb_drv_cancel_all_transfers()"); - unsigned int i; + unsigned int i, flags; + flags = disable_irq_save(); + for(i=0; i<TOTAL_EP(); i++) { endpoints[i].sent = 0; endpoints[i].length = 0; - /* TODO: flush FIFO's ? */ + + select_endpoint(i/2); + flushFIFO(&endpoints[i]); } + restore_irq(flags); ep0state = USB_EP0_IDLE; } @@ -512,8 +680,14 @@ void usb_drv_release_endpoint(int ep) int usb_drv_request_endpoint(int dir) { - logf("usb_drv_request_endpoint(%d)", dir); - - (void)dir; - return -1; + logf("usb_drv_request_endpoint(%s)", dir == USB_DIR_IN ? "IN" : "OUT"); + + /* There are only 3+2 endpoints, so hardcode this ... */ + /* Currently only BULK endpoints ... */ + if(dir == USB_DIR_OUT) + return (1 | USB_DIR_OUT); + else if(dir == USB_DIR_IN) + return (1 | USB_DIR_IN); + else + return -1; } |