From 35f341464b7d9dc2b1bd3f6222da5ec226f34dad Mon Sep 17 00:00:00 2001 From: Maurus Cuelenaere Date: Mon, 3 May 2010 19:18:10 +0000 Subject: Ingenic Jz4740: cleanup USB driver a bit (no externally visible functional changes) git-svn-id: svn://svn.rockbox.org/rockbox/trunk@25796 a1c6a512-1295-4272-9138-f99709370657 --- firmware/target/mips/ingenic_jz47xx/usb-jz4740.c | 237 ++++++++++++----------- 1 file changed, 119 insertions(+), 118 deletions(-) (limited to 'firmware/target/mips/ingenic_jz47xx/usb-jz4740.c') diff --git a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c index 64428ca2d6..81c6bdb1ed 100644 --- a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c @@ -33,12 +33,15 @@ /* The Jz4740 USB controller is called MUSBHSFC in the datasheet. It also seems to be a more generic controller, with support for - up to 15 endpoints (the Jz4740 only has 3). + up to 15 endpoints (the Jz4740 only has 5). */ -#define USB_EP0_IDLE 0 -#define USB_EP0_RX 1 -#define USB_EP0_TX 2 +enum +{ + USB_EP0_IDLE, + USB_EP0_RX, + USB_EP0_TX +}; #define EP_BUF_LEFT(ep) ((ep)->length - (ep)->sent) #define EP_PTR(ep) ((void*)((unsigned int)(ep)->buf + (ep)->sent)) @@ -49,7 +52,10 @@ enum ep_type { - ep_control, ep_bulk, ep_interrupt + ep_control, + ep_bulk, + ep_interrupt, + ep_isochronous }; struct usb_endpoint @@ -69,20 +75,20 @@ struct usb_endpoint const unsigned int fifo_addr; unsigned short fifo_size; + + struct wakeup wakeup; }; static unsigned char ep0_rx_buf[64]; static unsigned char ep0state = USB_EP0_IDLE; static struct usb_endpoint endpoints[] = { -/* buf length sent busy type use_dma wait fifo_addr fifo_size */ - {NULL, 0, {0}, false, ep_control, false, false, USB_FIFO_EP0, 64 }, - {&ep0_rx_buf, 0, {0}, false, ep_control, false, false, USB_FIFO_EP0, 64 }, - {NULL, 0, {0}, false, ep_bulk, false, false, USB_FIFO_EP1, 512}, - {NULL, 0, {0}, false, ep_bulk, false, false, USB_FIFO_EP1, 512}, - {NULL, 0, {0}, false, ep_interrupt, false, false, USB_FIFO_EP2, 64 } + { .type = ep_control, .fifo_addr = USB_FIFO_EP0, .fifo_size = 64 }, + { .type = ep_control, .fifo_addr = USB_FIFO_EP0, .fifo_size = 64, .buf = &ep0_rx_buf }, + { .type = ep_bulk, .fifo_addr = USB_FIFO_EP1, .fifo_size = 512 }, + { .type = ep_bulk, .fifo_addr = USB_FIFO_EP1, .fifo_size = 512 }, + { .type = ep_interrupt, .fifo_addr = USB_FIFO_EP2, .fifo_size = 64 }, }; -static struct wakeup ep_wkup[TOTAL_EP()]; static inline void select_endpoint(int ep) { @@ -91,7 +97,7 @@ static inline void select_endpoint(int ep) static void readFIFO(struct usb_endpoint *ep, unsigned int size) { - logf("readFIFO(EP%d, %d)", EP_NUMBER2(ep), size); + logf("%s(EP%d, %d)", __func__, EP_NUMBER2(ep), size); register unsigned char *ptr = (unsigned char*)EP_PTR(ep); register unsigned int *ptr32 = (unsigned int*)ptr; @@ -112,10 +118,10 @@ static void readFIFO(struct usb_endpoint *ep, unsigned int size) while(s--) { x = REG32(ep->fifo_addr); - *ptr++ = (x >> 0) & 0xFF; - *ptr++ = (x >> 8) & 0xFF; - *ptr++ = (x >> 16) & 0xFF; - *ptr++ = (x >> 24) & 0xFF; + *ptr++ = x & 0xFF; x >>= 8; + *ptr++ = x & 0xFF; x >>= 8; + *ptr++ = x & 0xFF; x >>= 8; + *ptr++ = x; } } @@ -125,41 +131,30 @@ static void readFIFO(struct usb_endpoint *ep, unsigned int size) } } -static void writeFIFO(struct usb_endpoint *ep, unsigned int size) +static void writeFIFO(struct usb_endpoint *ep, size_t size) { - logf("writeFIFO(EP%d, %d)", EP_NUMBER2(ep), size); + logf("%s(EP%d, %d)", __func__, EP_NUMBER2(ep), size); register unsigned int *d32 = (unsigned int *)EP_PTR(ep); - register unsigned char *d8 = (unsigned char *)EP_PTR(ep); - register unsigned int s; + register size_t s = size >> 2; if(size > 0) { - if(UNLIKELY((unsigned int)d8 & 3)) - { - s = size; - while(s--) - REG8(ep->fifo_addr) = *d8++; - } - else + while (s--) + REG32(ep->fifo_addr) = *d32++; + + if( (s = size & 3) ) { - s = size >> 2; + register unsigned char *d8 = (unsigned char *)d32; while (s--) - REG32(ep->fifo_addr) = *d32++; - - if( (s = size & 3) ) - { - d8 = (unsigned char *)d32; - while (s--) - REG8(ep->fifo_addr) = *d8++; - } + REG8(ep->fifo_addr) = *d8++; } } } static void flushFIFO(struct usb_endpoint *ep) { - logf("flushFIFO(%d)", EP_NUMBER(ep)); + logf("%s(%d)", __func__, EP_NUMBER(ep)); switch (ep->type) { @@ -168,6 +163,7 @@ static void flushFIFO(struct usb_endpoint *ep) case ep_bulk: case ep_interrupt: + case ep_isochronous: if(EP_IS_IN(ep)) REG_USB_REG_INCSR |= (USB_INCSR_FF | USB_INCSR_CDT); else @@ -193,9 +189,9 @@ static void EP0_send(void) } if(ep->sent == 0) - length = (ep->length <= ep->fifo_size ? ep->length : ep->fifo_size); + length = MIN(ep->length, ep->fifo_size); else - length = (EP_BUF_LEFT(ep) <= ep->fifo_size ? EP_BUF_LEFT(ep) : ep->fifo_size); + length = MIN(EP_BUF_LEFT(ep), ep->fifo_size); writeFIFO(ep, length); ep->sent += length; @@ -205,7 +201,7 @@ static void EP0_send(void) REG_USB_REG_CSR0 = (csr0 | USB_CSR0_INPKTRDY | USB_CSR0_DATAEND); /* Set data end! */ ep0state = USB_EP0_IDLE; if(ep->wait) - wakeup_signal(&ep_wkup[0]); + wakeup_signal(&ep->wakeup); } else REG_USB_REG_CSR0 = (csr0 | USB_CSR0_INPKTRDY); @@ -213,7 +209,7 @@ static void EP0_send(void) static void EP0_handler(void) { - logf("EP0_handler"); + logf("%s()", __func__); unsigned char csr0; @@ -252,7 +248,7 @@ static void EP0_handler(void) REG_USB_REG_CSR0 = csr0 | USB_CSR0_SVDOUTPKTRDY; /* clear OUTPKTRDY bit */ usb_core_control_request((struct usb_ctrlrequest*)endpoints[1].buf); if(endpoints[1].wait) - wakeup_signal(&ep_wkup[1]); + wakeup_signal(&endpoints[1].wakeup); } } else if(ep0state == USB_EP0_TX) @@ -266,10 +262,13 @@ static void EPIN_handler(unsigned int endpoint) select_endpoint(endpoint); csr = REG_USB_REG_INCSR; - logf("EPIN_handler(%d): 0x%x", endpoint, csr); + logf("%s(%d): 0x%x", __func__, endpoint, csr); if(!ep->busy) + { + logf("Entered EPIN handler without work!"); return; + } if(csr & USB_INCSR_SENTSTALL) { @@ -289,9 +288,9 @@ static void EPIN_handler(unsigned int endpoint) logf("EP%d: %d -> %d", endpoint, ep->sent, ep->length); if(ep->sent == 0) - length = (ep->length <= ep->fifo_size ? ep->length : ep->fifo_size); + length = MIN(ep->length, ep->fifo_size); else - length = (EP_BUF_LEFT(ep) <= ep->fifo_size ? EP_BUF_LEFT(ep) : ep->fifo_size); + length = MIN(EP_BUF_LEFT(ep), ep->fifo_size); writeFIFO(ep, length); REG_USB_REG_INCSR = csr | USB_INCSR_INPKTRDY; @@ -301,7 +300,7 @@ static void EPIN_handler(unsigned int endpoint) { usb_core_transfer_complete(endpoint, USB_DIR_IN, 0, ep->sent); if(ep->wait) - wakeup_signal(&ep_wkup[endpoint*2]); + wakeup_signal(&ep->wakeup); logf("sent complete"); ep->sent = 0; ep->length = 0; @@ -316,12 +315,15 @@ static void EPOUT_handler(unsigned int endpoint) unsigned int size, csr; if(!ep->busy) + { + logf("Entered EPOUT handler without work!"); return; + } select_endpoint(endpoint); while((csr = REG_USB_REG_OUTCSR) & (USB_OUTCSR_SENTSTALL|USB_OUTCSR_OUTPKTRDY)) { - logf("EPOUT_handler(%d): 0x%x", endpoint, csr); + logf("%s(%d): 0x%x", __func__, endpoint, csr); if(csr & USB_OUTCSR_SENTSTALL) { logf("stall sent, flushing fifo.."); @@ -351,13 +353,12 @@ static void EPOUT_handler(unsigned int endpoint) { usb_core_transfer_complete(endpoint, USB_DIR_OUT, 0, ep->received); if(ep->wait) - wakeup_signal(&ep_wkup[endpoint*2+1]); + wakeup_signal(&ep->wakeup); logf("receive transfer_complete"); ep->received = 0; ep->length = 0; ep->buf = NULL; ep->busy = false; - return; } } } @@ -365,8 +366,9 @@ static void EPOUT_handler(unsigned int endpoint) static void EPDMA_handler(int number) { - int endpoint=-1; - unsigned int size=0; + int endpoint = -1; + unsigned int size = 0; + if(number == USB_INTR_DMA_BULKIN) endpoint = (REG_USB_REG_CNTL1 >> 4) & 0xF; else if(number == USB_INTR_DMA_BULKOUT) @@ -398,8 +400,10 @@ static void EPDMA_handler(int number) } } else if(number == USB_INTR_DMA_BULKIN && size % ep->fifo_size) + { /* If the last packet is less than MAXP, set INPKTRDY manually */ REG_USB_REG_INCSR |= USB_INCSR_INPKTRDY; + } usb_core_transfer_complete(endpoint, EP_IS_IN(ep) ? USB_DIR_IN : USB_DIR_OUT, 0, ep->length); @@ -409,7 +413,7 @@ static void EPDMA_handler(int number) ep->length = 0; ep->buf = NULL; if(ep->wait) - wakeup_signal(&ep_wkup[EP_NUMBER(ep)]); + wakeup_signal(&ep->wakeup); } static void setup_endpoint(struct usb_endpoint *ep) @@ -435,15 +439,16 @@ static void setup_endpoint(struct usb_endpoint *ep) { csr = (USB_INCSR_FF | USB_INCSR_CDT); csrh = USB_INCSRH_MODE; + if(ep->use_dma) csrh |= (USB_INCSRH_DMAREQENAB | USB_INCSRH_AUTOSET | USB_INCSRH_DMAREQMODE); if(ep->type == ep_interrupt) csrh |= USB_INCSRH_FRCDATATOG; - REG_USB_REG_INMAXP = ep->fifo_size; - REG_USB_REG_INCSR = csr; - REG_USB_REG_INCSRH = csrh; + REG_USB_REG_INMAXP = ep->fifo_size; + REG_USB_REG_INCSR = csr; + REG_USB_REG_INCSRH = csrh; REG_USB_REG_INTRINE |= USB_INTR_EP(EP_NUMBER2(ep)); } else @@ -457,9 +462,9 @@ static void setup_endpoint(struct usb_endpoint *ep) if(ep->use_dma) csrh |= (USB_OUTCSRH_DMAREQENAB | USB_OUTCSRH_AUTOCLR | USB_OUTCSRH_DMAREQMODE); - REG_USB_REG_OUTMAXP = ep->fifo_size; - REG_USB_REG_OUTCSR = csr; - REG_USB_REG_OUTCSRH = csrh; + REG_USB_REG_OUTMAXP = ep->fifo_size; + REG_USB_REG_OUTCSR = csr; + REG_USB_REG_OUTCSRH = csrh; REG_USB_REG_INTROUTE |= USB_INTR_EP(EP_NUMBER2(ep)); } } @@ -477,7 +482,7 @@ static void udc_reset(void) * Generates a Reset interrupt. */ - logf("udc_reset()"); + logf("%s()", __func__); unsigned int i; @@ -493,9 +498,6 @@ static void udc_reset(void) REG_USB_REG_CNTL1 = 0; REG_USB_REG_CNTL2 = 0; - /* Reset address */ - REG_USB_REG_FADDR = 0; - /* High speed, softconnect and suspend/resume */ REG_USB_REG_POWER = (USB_POWER_SOFTCONN | USB_POWER_HSENAB | USB_POWER_SUSPENDM); @@ -508,7 +510,7 @@ static void udc_reset(void) setup_endpoint(&endpoints[i]); /* Enable interrupts */ - REG_USB_REG_INTRINE |= USB_INTR_EP0; + REG_USB_REG_INTRINE |= USB_INTR_EP0; REG_USB_REG_INTRUSBE |= USB_INTR_RESET; usb_core_bus_reset(); @@ -523,9 +525,6 @@ void UDC(void) unsigned short intrOut = REG_USB_REG_INTROUT; unsigned char intrDMA = REG_USB_REG_INTR; - if(UNLIKELY(intrUSB == 0 && intrIn == 0 && intrOut == 0 && intrDMA == 0)) - return; - logf("%x %x %x %x", intrUSB, intrIn, intrOut, intrDMA); /* EPIN & EPOUT are all handled in DMA */ @@ -559,7 +558,7 @@ bool usb_drv_stalled(int endpoint, bool in) { endpoint &= 0x7F; - logf("usb_drv_stalled(%d, %s)", endpoint, in?"IN":"OUT"); + logf("%s(%d, %s)", __func__, endpoint, in?"IN":"OUT"); select_endpoint(endpoint); @@ -578,7 +577,7 @@ void usb_drv_stall(int endpoint, bool stall, bool in) { endpoint &= 0x7F; - logf("usb_drv_stall(%d,%s,%s)", endpoint, stall?"Y":"N", in?"IN":"OUT"); + logf("%s(%d,%s,%s)", __func__, endpoint, stall?"Y":"N", in?"IN":"OUT"); select_endpoint(endpoint); @@ -629,7 +628,7 @@ void usb_init_device(void) system_enable_irq(IRQ_UDC); for(i=0; itype == ep_control && ptr == NULL && length == 0) + return; /* ACK request, handled by the USB controller */ - logf("usb_drv_send(%d, 0x%x, %d)", endpoint, (int)ptr, length); + int flags = disable_irq_save(); - if(endpoint == EP_CONTROL && ptr == NULL && length == 0) - return 0; /* ACK request, handled by the USB controller */ + ep->buf = ptr; + ep->sent = 0; + ep->length = length; + ep->busy = true; + if(blocking) + ep->wait = true; - if(endpoint == EP_CONTROL) + if(ep->type == ep_control) { - flags = disable_irq_save(); - endpoints[0].buf = ptr; - endpoints[0].sent = 0; - endpoints[0].length = length; ep0state = USB_EP0_TX; EP0_send(); - restore_irq(flags); - - return 0; } else { - flags = disable_irq_save(); - endpoints[endpoint*2].buf = ptr; - endpoints[endpoint*2].sent = 0; - endpoints[endpoint*2].length = length; - endpoints[endpoint*2].busy = true; - if(endpoints[endpoint*2].use_dma) + if(ep->use_dma) { //dma_cache_wback_inv((unsigned long)ptr, length); __dcache_writeback_all(); @@ -745,49 +736,59 @@ int usb_drv_send_nonblocking(int endpoint, void* ptr, int length) REG_USB_REG_COUNT1 = length; REG_USB_REG_CNTL1 = (USB_CNTL_INTR_EN | USB_CNTL_MODE_1 | USB_CNTL_DIR_IN | USB_CNTL_ENA | - USB_CNTL_EP(endpoint) | USB_CNTL_BURST_16); + USB_CNTL_EP(EP_NUMBER2(ep)) | USB_CNTL_BURST_16); } else - EPIN_handler(endpoint); + EPIN_handler(EP_NUMBER2(ep)); + } - restore_irq(flags); - return 0; + restore_irq(flags); + + if(blocking) + { + wakeup_wait(&ep->wakeup, TIMEOUT_BLOCK); + ep->wait = false; } } -int usb_drv_send(int endpoint, void* ptr, int length) +int usb_drv_send_nonblocking(int endpoint, void* ptr, int length) { - int ret; - endpoint &= 0x7F; + logf("%s(%d, 0x%x, %d)", __func__, endpoint, (int)ptr, length); - if(endpoint == EP_CONTROL && ptr == NULL && length == 0) - return 0; /* ACK request, handled by the USB controller */ + usb_drv_send_internal(&endpoints[(endpoint & 0x7F)*2], ptr, length, false); - endpoints[endpoint*2].wait = true; - ret = usb_drv_send_nonblocking(endpoint, ptr, length); - wakeup_wait(&ep_wkup[endpoint*2], TIMEOUT_BLOCK); - endpoints[endpoint*2].wait = false; + return 0; +} + +int usb_drv_send(int endpoint, void* ptr, int length) +{ + logf("%s(%d, 0x%x, %d)", __func__, endpoint, (int)ptr, length); - return ret; + usb_drv_send_internal(&endpoints[(endpoint & 0x7F)*2], ptr, length, true); + + return 0; } int usb_drv_recv(int endpoint, void* ptr, int length) { int flags; + struct usb_endpoint *ep; endpoint &= 0x7F; - logf("usb_drv_recv(%d, 0x%x, %d)", endpoint, (int)ptr, length); + logf("%s(%d, 0x%x, %d)", __func__, endpoint, (int)ptr, length); if(endpoint == EP_CONTROL && ptr == NULL && length == 0) return 0; /* ACK request, handled by the USB controller */ else { flags = disable_irq_save(); - endpoints[endpoint*2+1].buf = ptr; - endpoints[endpoint*2+1].received = 0; - endpoints[endpoint*2+1].length = length; - endpoints[endpoint*2+1].busy = true; - if(endpoints[endpoint*2+1].use_dma) + ep = &endpoints[endpoint*2+1]; + + ep->buf = ptr; + ep->received = 0; + ep->length = length; + ep->busy = true; + if(ep->use_dma) { //dma_cache_wback_inv((unsigned long)ptr, length); __dcache_writeback_all(); @@ -807,7 +808,7 @@ int usb_drv_recv(int endpoint, void* ptr, int length) void usb_drv_set_test_mode(int mode) { - logf("usb_drv_set_test_mode(%d)", mode); + logf("%s(%d)", __func__, mode); switch(mode) { @@ -836,7 +837,7 @@ int usb_drv_port_speed(void) void usb_drv_cancel_all_transfers(void) { - logf("usb_drv_cancel_all_transfers()"); + logf("%s()", __func__); unsigned int i, flags; flags = disable_irq_save(); @@ -860,12 +861,12 @@ void usb_drv_cancel_all_transfers(void) void usb_drv_release_endpoint(int ep) { (void)ep; - logf("usb_drv_release_endpoint(%d, %s)", (ep & 0x7F), (ep >> 7) ? "IN" : "OUT"); + logf("%s(%d, %s)", __func__, (ep & 0x7F), (ep >> 7) ? "IN" : "OUT"); } int usb_drv_request_endpoint(int type, int dir) { - logf("usb_drv_request_endpoint(%d, %s)", type, (dir == USB_DIR_IN) ? "IN" : "OUT"); + logf("%s(%d, %s)", __func__, type, (dir == USB_DIR_IN) ? "IN" : "OUT"); dir &= USB_ENDPOINT_DIR_MASK; type &= USB_ENDPOINT_XFERTYPE_MASK; -- cgit v1.2.3