summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/target/mips/ingenic_jz47xx/usb-jz4740.c158
1 files changed, 80 insertions, 78 deletions
diff --git a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c
index cc8d5afa20..0916a9414a 100644
--- a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c
+++ b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c
@@ -20,7 +20,6 @@
20 ****************************************************************************/ 20 ****************************************************************************/
21 21
22#include "config.h" 22#include "config.h"
23#define LOGF_ENABLE
24#include "logf.h" 23#include "logf.h"
25#include "system.h" 24#include "system.h"
26#include "usb_ch9.h" 25#include "usb_ch9.h"
@@ -72,13 +71,12 @@ struct usb_endpoint
72static unsigned char ep0_rx_buf[64]; 71static unsigned char ep0_rx_buf[64];
73static unsigned char ep0state = USB_EP0_IDLE; 72static unsigned char ep0state = USB_EP0_IDLE;
74static struct usb_endpoint endpoints[] = 73static struct usb_endpoint endpoints[] =
75{ 74{/* buf length sent type use_dma fifo_addr fifo_size */
76 /* buf length sent type use_dma fifo_addr fifo_size */ 75 {&ep0_rx_buf, 0, {0}, ep_control, false, USB_FIFO_EP0, 64 },
77 {&ep0_rx_buf, 0, {0}, ep_control, false, USB_FIFO_EP0, 64 }, 76 {NULL, 0, {0}, ep_control, false, USB_FIFO_EP0, 64 },
78 {NULL, 0, {0}, ep_control, false, USB_FIFO_EP0, 64 }, 77 {NULL, 0, {0}, ep_bulk, false, USB_FIFO_EP1, 512},
79 {NULL, 0, {0}, ep_bulk, false, USB_FIFO_EP1, 512}, 78 {NULL, 0, {0}, ep_bulk, false, USB_FIFO_EP1, 512},
80 {NULL, 0, {0}, ep_bulk, false, USB_FIFO_EP1, 512}, 79 {NULL, 0, {0}, ep_interrupt, false, USB_FIFO_EP2, 64 }
81 {NULL, 0, {0}, ep_interrupt, false, USB_FIFO_EP2, 64 }
82}; 80};
83 81
84static inline void select_endpoint(int ep) 82static inline void select_endpoint(int ep)
@@ -97,7 +95,7 @@ static void readFIFO(struct usb_endpoint *ep, unsigned int size)
97 95
98 if(size > 0) 96 if(size > 0)
99 { 97 {
100 if( ((int)ptr & 3) == 0 ) 98 if( ((unsigned int)ptr & 3) == 0 )
101 { 99 {
102 while(s--) 100 while(s--)
103 *ptr32++ = REG32(ep->fifo_addr); 101 *ptr32++ = REG32(ep->fifo_addr);
@@ -109,10 +107,10 @@ static void readFIFO(struct usb_endpoint *ep, unsigned int size)
109 while(s--) 107 while(s--)
110 { 108 {
111 x = REG32(ep->fifo_addr); 109 x = REG32(ep->fifo_addr);
112 *ptr++ = (x >> 0) & 0xff; 110 *ptr++ = (x >> 0) & 0xFF;
113 *ptr++ = (x >> 8) & 0xff; 111 *ptr++ = (x >> 8) & 0xFF;
114 *ptr++ = (x >> 16) & 0xff; 112 *ptr++ = (x >> 16) & 0xFF;
115 *ptr++ = (x >> 24) & 0xff; 113 *ptr++ = (x >> 24) & 0xFF;
116 } 114 }
117 } 115 }
118 116
@@ -124,11 +122,11 @@ static void readFIFO(struct usb_endpoint *ep, unsigned int size)
124 122
125static void writeFIFO(struct usb_endpoint *ep, unsigned int size) 123static void writeFIFO(struct usb_endpoint *ep, unsigned int size)
126{ 124{
127 //logf("writeFIFO(EP%d, %d)", EP_NUMBER2(ep), size); 125 logf("writeFIFO(EP%d, %d)", EP_NUMBER2(ep), size);
128 126
129 register unsigned int *d = (unsigned int *)EP_PTR(ep); 127 register unsigned int *d = (unsigned int *)EP_PTR(ep);
130 register unsigned char *c; 128 register unsigned char *c;
131 register int s; 129 register unsigned int s;
132 130
133 if(size > 0) 131 if(size > 0)
134 { 132 {
@@ -143,13 +141,11 @@ static void writeFIFO(struct usb_endpoint *ep, unsigned int size)
143 REG8(ep->fifo_addr) = *c++; 141 REG8(ep->fifo_addr) = *c++;
144 } 142 }
145 } 143 }
146 else
147 REG32(ep->fifo_addr) = 0;
148} 144}
149 145
150static void flushFIFO(struct usb_endpoint *ep) 146static void flushFIFO(struct usb_endpoint *ep)
151{ 147{
152 //logf("flushFIFO(%d)", EP_NUMBER(ep)); 148 logf("flushFIFO(%d)", EP_NUMBER(ep));
153 149
154 switch (ep->type) 150 switch (ep->type)
155 { 151 {
@@ -202,7 +198,7 @@ static void EP0_handler(void)
202{ 198{
203 logf("EP0_handler"); 199 logf("EP0_handler");
204 200
205 register unsigned char csr0; 201 unsigned char csr0;
206 202
207 /* Read CSR0 */ 203 /* Read CSR0 */
208 select_endpoint(0); 204 select_endpoint(0);
@@ -211,7 +207,7 @@ static void EP0_handler(void)
211 /* Check for SentStall: 207 /* Check for SentStall:
212 This bit is set when a STALL handshake is transmitted. The CPU should clear this bit. 208 This bit is set when a STALL handshake is transmitted. The CPU should clear this bit.
213 */ 209 */
214 if (csr0 & USB_CSR0_SENTSTALL) 210 if(csr0 & USB_CSR0_SENTSTALL)
215 { 211 {
216 REG_USB_REG_CSR0 = csr0 & ~USB_CSR0_SENTSTALL; 212 REG_USB_REG_CSR0 = csr0 & ~USB_CSR0_SENTSTALL;
217 ep0state = USB_EP0_IDLE; 213 ep0state = USB_EP0_IDLE;
@@ -223,7 +219,7 @@ static void EP0_handler(void)
223 An interrupt will be generated and the FIFO flushed at this time. 219 An interrupt will be generated and the FIFO flushed at this time.
224 The bit is cleared by the CPU writing a 1 to the ServicedSetupEnd bit. 220 The bit is cleared by the CPU writing a 1 to the ServicedSetupEnd bit.
225 */ 221 */
226 if (csr0 & USB_CSR0_SETUPEND) 222 if(csr0 & USB_CSR0_SETUPEND)
227 { 223 {
228 REG_USB_REG_CSR0 = csr0 | USB_CSR0_SVDSETUPEND; 224 REG_USB_REG_CSR0 = csr0 | USB_CSR0_SVDSETUPEND;
229 ep0state = USB_EP0_IDLE; 225 ep0state = USB_EP0_IDLE;
@@ -231,7 +227,7 @@ static void EP0_handler(void)
231 } 227 }
232 228
233 /* Call relevant routines for endpoint 0 state */ 229 /* Call relevant routines for endpoint 0 state */
234 if (ep0state == USB_EP0_IDLE) 230 if(ep0state == USB_EP0_IDLE)
235 { 231 {
236 if(csr0 & USB_CSR0_OUTPKTRDY) /* There is data in the fifo */ 232 if(csr0 & USB_CSR0_OUTPKTRDY) /* There is data in the fifo */
237 { 233 {
@@ -240,25 +236,21 @@ static void EP0_handler(void)
240 usb_core_control_request((struct usb_ctrlrequest*)endpoints[0].buf); 236 usb_core_control_request((struct usb_ctrlrequest*)endpoints[0].buf);
241 } 237 }
242 } 238 }
243 else if (ep0state == USB_EP0_TX) 239 else if(ep0state == USB_EP0_TX)
244 EP0_send(); 240 EP0_send();
245} 241}
246 242
247static void EPIN_handler(unsigned int endpoint) 243static void EPIN_handler(unsigned int endpoint)
248{ 244{
249 logf("EPIN_handler(%d)", endpoint);
250
251 struct usb_endpoint* ep = &endpoints[endpoint*2+1]; 245 struct usb_endpoint* ep = &endpoints[endpoint*2+1];
252 unsigned int length, csr; 246 unsigned int length, csr;
253 247
254 select_endpoint(endpoint); 248 select_endpoint(endpoint);
255 csr = REG_USB_REG_INCSR; 249 csr = REG_USB_REG_INCSR;
250 logf("EPIN_handler(%d): 0x%x", endpoint, csr);
256 251
257 if(ep->buf == NULL || ep->length == 0) 252 if(ep->buf == NULL || ep->length == 0)
258 {
259 REG_USB_REG_INCSR = csr | USB_INCSR_INPKTRDY;
260 return; 253 return;
261 }
262 254
263 if(csr & USB_INCSR_SENTSTALL) 255 if(csr & USB_INCSR_SENTSTALL)
264 { 256 {
@@ -266,15 +258,24 @@ static void EPIN_handler(unsigned int endpoint)
266 return; 258 return;
267 } 259 }
268 260
261 if(ep->use_dma == true)
262 return;
263
264 if(csr & USB_INCSR_FFNOTEMPT)
265 {
266 logf("FIFO is not empty!");
267 return;
268 }
269
269 if(ep->sent == 0) 270 if(ep->sent == 0)
270 length = (ep->length <= ep->fifo_size ? ep->length : ep->fifo_size); 271 length = (ep->length <= ep->fifo_size ? ep->length : ep->fifo_size);
271 else 272 else
272 length = (EP_BUF_LEFT(ep) <= ep->fifo_size ? EP_BUF_LEFT(ep) : ep->fifo_size); 273 length = (EP_BUF_LEFT(ep) <= ep->fifo_size ? EP_BUF_LEFT(ep) : ep->fifo_size);
273 274
274 writeFIFO(ep, length); 275 writeFIFO(ep, length);
276 REG_USB_REG_INCSR = csr | USB_INCSR_INPKTRDY;
275 ep->sent += length; 277 ep->sent += length;
276 278
277 REG_USB_REG_INCSR = csr | USB_INCSR_INPKTRDY;
278 if(ep->sent >= ep->length) 279 if(ep->sent >= ep->length)
279 { 280 {
280 usb_core_transfer_complete(endpoint, USB_DIR_IN, 0, ep->sent); 281 usb_core_transfer_complete(endpoint, USB_DIR_IN, 0, ep->sent);
@@ -286,19 +287,15 @@ static void EPIN_handler(unsigned int endpoint)
286 287
287static void EPOUT_handler(unsigned int endpoint) 288static void EPOUT_handler(unsigned int endpoint)
288{ 289{
289 logf("EPOUT_handler(%d)", endpoint);
290
291 struct usb_endpoint* ep = &endpoints[endpoint*2]; 290 struct usb_endpoint* ep = &endpoints[endpoint*2];
292 unsigned int size, csr; 291 unsigned int size, csr;
293 292
294 select_endpoint(endpoint); 293 select_endpoint(endpoint);
295 csr = REG_USB_REG_OUTCSR; 294 csr = REG_USB_REG_OUTCSR;
295 logf("EPOUT_handler(%d): 0x%x", endpoint, csr);
296 296
297 if(ep->buf == NULL || ep->length == 0) 297 if(ep->buf == NULL || ep->length == 0)
298 {
299 REG_USB_REG_OUTCSR = csr & ~USB_OUTCSR_OUTPKTRDY;
300 return; 298 return;
301 }
302 299
303 if(csr & USB_OUTCSR_SENTSTALL) 300 if(csr & USB_OUTCSR_SENTSTALL)
304 { 301 {
@@ -318,6 +315,7 @@ static void EPOUT_handler(unsigned int endpoint)
318 if(size < ep->fifo_size || ep->received >= ep->length) 315 if(size < ep->fifo_size || ep->received >= ep->length)
319 { 316 {
320 usb_core_transfer_complete(endpoint, USB_DIR_OUT, 0, ep->received); 317 usb_core_transfer_complete(endpoint, USB_DIR_OUT, 0, ep->received);
318 logf("receive transfer_complete");
321 ep->received = 0; 319 ep->received = 0;
322 ep->length = 0; 320 ep->length = 0;
323 ep->buf = NULL; 321 ep->buf = NULL;
@@ -346,9 +344,8 @@ static void setup_endpoint(struct usb_endpoint *ep)
346 csr = (USB_INCSR_FF | USB_INCSR_CDT | USB_INCSRH_MODE); 344 csr = (USB_INCSR_FF | USB_INCSR_CDT | USB_INCSRH_MODE);
347 if(ep->use_dma) 345 if(ep->use_dma)
348 csr |= (USB_INCSRH_DMAREQENAB | USB_INCSRH_AUTOSET); 346 csr |= (USB_INCSRH_DMAREQENAB | USB_INCSRH_AUTOSET);
349 else
350 REG_USB_REG_INTRINE |= USB_INTR_EP(EP_NUMBER2(ep));
351 347
348 REG_USB_REG_INTRINE |= USB_INTR_EP(EP_NUMBER2(ep));
352 REG_USB_REG_INCSR = csr; 349 REG_USB_REG_INCSR = csr;
353 } 350 }
354 else 351 else
@@ -361,13 +358,10 @@ static void setup_endpoint(struct usb_endpoint *ep)
361 358
362 if(ep->use_dma) 359 if(ep->use_dma)
363 csr |= (USB_OUTCSRH_DMAREQENAB | USB_OUTCSRH_AUTOCLR | USB_OUTCSRH_DMAREQMODE); 360 csr |= (USB_OUTCSRH_DMAREQENAB | USB_OUTCSRH_AUTOCLR | USB_OUTCSRH_DMAREQMODE);
364 else
365 REG_USB_REG_INTROUTE |= USB_INTR_EP(EP_NUMBER2(ep));
366 361
367 csr = REG_USB_REG_OUTCSR; 362 REG_USB_REG_INTROUTE |= USB_INTR_EP(EP_NUMBER2(ep));
363 REG_USB_REG_OUTCSR = csr;
368 } 364 }
369
370 //flushFIFO(ep);
371} 365}
372 366
373static void udc_reset(void) 367static void udc_reset(void)
@@ -385,7 +379,7 @@ static void udc_reset(void)
385 379
386 logf("udc_reset()"); 380 logf("udc_reset()");
387 381
388 register unsigned int i; 382 unsigned int i;
389 383
390 /* EP0 init */ 384 /* EP0 init */
391 ep0state = USB_EP0_IDLE; 385 ep0state = USB_EP0_IDLE;
@@ -402,11 +396,8 @@ static void udc_reset(void)
402 /* Reset address */ 396 /* Reset address */
403 REG_USB_REG_FADDR = 0; 397 REG_USB_REG_FADDR = 0;
404 398
405 /* High speed and softconnect */ 399 /* High speed, softconnect and suspend/resume */
406 REG_USB_REG_POWER = (USB_POWER_SOFTCONN | USB_POWER_HSENAB); 400 REG_USB_REG_POWER = (USB_POWER_SOFTCONN | USB_POWER_HSENAB | USB_POWER_SUSPENDM);
407
408 /* Enable SUSPEND */
409 /* REG_USB_REG_POWER |= USB_POWER_SUSPENDM; */
410 401
411 /* Reset EP0 */ 402 /* Reset EP0 */
412 select_endpoint(0); 403 select_endpoint(0);
@@ -426,12 +417,12 @@ static void udc_reset(void)
426void UDC(void) 417void UDC(void)
427{ 418{
428 /* Read interrupt registers */ 419 /* Read interrupt registers */
429 register unsigned char intrUSB = REG_USB_REG_INTRUSB & 0x07; /* Mask SOF */ 420 unsigned char intrUSB = REG_USB_REG_INTRUSB & 0x07; /* Mask SOF */
430 register unsigned short intrIn = REG_USB_REG_INTRIN; 421 unsigned short intrIn = REG_USB_REG_INTRIN;
431 register unsigned short intrOut = REG_USB_REG_INTROUT; 422 unsigned short intrOut = REG_USB_REG_INTROUT;
432 register unsigned char intrDMA = REG_USB_REG_INTR; 423 unsigned char intrDMA = REG_USB_REG_INTR;
433 424
434 if(intrUSB == 0 && intrIn == 0 && intrOut == 0 && intrDMA == 0) 425 if(UNLIKELY(intrUSB == 0 && intrIn == 0 && intrOut == 0 && intrDMA == 0))
435 return; 426 return;
436 427
437 /* EPIN & EPOUT are all handled in DMA */ 428 /* EPIN & EPOUT are all handled in DMA */
@@ -447,12 +438,27 @@ void UDC(void)
447 EPOUT_handler(2); 438 EPOUT_handler(2);
448 if(intrUSB & USB_INTR_RESET) 439 if(intrUSB & USB_INTR_RESET)
449 udc_reset(); 440 udc_reset();
450 //if(intrUSB & USB_INTR_SUSPEND); 441 if(intrUSB & USB_INTR_SUSPEND)
451 //if(intrUSB & USB_INTR_RESUME); 442 {
443 logf("USB suspend");
444 }
445 if(intrUSB & USB_INTR_RESUME)
446 {
447 logf("USB resume");
448 }
449#if 0
452 if(intrDMA & USB_INTR_DMA_BULKIN) 450 if(intrDMA & USB_INTR_DMA_BULKIN)
453 { 451 {
454 logf("DMA_BULKIN %d", ((REG_USB_REG_CNTL1 >> 4) & 0xF)); 452 logf("DMA_BULKIN %d", ((REG_USB_REG_CNTL1 >> 4) & 0xF));
455 usb_core_transfer_complete(1 | USB_DIR_IN, USB_DIR_IN, 0, 0); 453 unsigned int size = (unsigned int)endpoints[3].buf - REG_USB_REG_ADDR2;
454 if(size < endpoints[3].length)
455 {
456 select_endpoint(1);
457 writeFIFO(endpoints[3], endpoints[3].length - size);
458 REG_USB_REG_INCSR |= USB_INCSR_INPKTRDY;
459 }
460
461 usb_core_transfer_complete(1, USB_DIR_IN, 0, endpoints[3].length);
456 } 462 }
457 if(intrDMA & USB_INTR_DMA_BULKOUT) 463 if(intrDMA & USB_INTR_DMA_BULKOUT)
458 { 464 {
@@ -461,8 +467,9 @@ void UDC(void)
461 select_endpoint(1); 467 select_endpoint(1);
462 REG_USB_REG_OUTCSR &= ~(USB_OUTCSRH_DMAREQENAB | USB_OUTCSR_OUTPKTRDY); 468 REG_USB_REG_OUTCSR &= ~(USB_OUTCSRH_DMAREQENAB | USB_OUTCSR_OUTPKTRDY);
463 469
464 usb_core_transfer_complete(1 | USB_DIR_OUT, USB_DIR_OUT, 0, 0); 470 usb_core_transfer_complete(1, USB_DIR_OUT, 0, 0);
465 } 471 }
472#endif
466} 473}
467 474
468bool usb_drv_stalled(int endpoint, bool in) 475bool usb_drv_stalled(int endpoint, bool in)
@@ -606,26 +613,25 @@ int usb_drv_send(int endpoint, void* ptr, int length)
606 restore_irq(flags); 613 restore_irq(flags);
607 return 0; 614 return 0;
608 } 615 }
609 else if(endpoint == 1) 616 else
610 { 617 {
618 flags = disable_irq_save();
619 endpoints[endpoint*2+1].buf = ptr;
620 endpoints[endpoint*2+1].sent = 0;
621 endpoints[endpoint*2+1].length = length;
611#if 0 622#if 0
612 select_endpoint(endpoint); 623 select_endpoint(endpoint);
613 624
614 REG_USB_REG_ADDR2 = ((unsigned long)ptr) & 0x7fffffff; 625 REG_USB_REG_ADDR2 = ((unsigned long)ptr) & 0x7fffffff;
615 REG_USB_REG_COUNT2 = length; 626 REG_USB_REG_COUNT2 = length;
616 REG_USB_REG_CNTL2 = 1; 627 REG_USB_REG_CNTL2 = (USB_CNTL_INTR_EN | USB_CNTL_MODE_1 | USB_CNTL_DIR_IN | USB_CNTL_ENA);
617#else 628#else
618 flags = disable_irq_save(); 629
619 endpoints[3].buf = ptr; 630 EPIN_handler(endpoint);
620 endpoints[3].sent = 0;
621 endpoints[3].length = length;
622 EPIN_handler(1);
623 restore_irq(flags);
624#endif 631#endif
632 restore_irq(flags);
625 return 0; 633 return 0;
626 } 634 }
627 else
628 return -1;
629} 635}
630 636
631int usb_drv_send_nonblocking(int endpoint, void* ptr, int length) 637int usb_drv_send_nonblocking(int endpoint, void* ptr, int length)
@@ -642,18 +648,15 @@ int usb_drv_recv(int endpoint, void* ptr, int length)
642 648
643 if(endpoint == EP_CONTROL && ptr == NULL && length == 0) 649 if(endpoint == EP_CONTROL && ptr == NULL && length == 0)
644 return 0; /* ACK request, handled by the USB controller */ 650 return 0; /* ACK request, handled by the USB controller */
645 else if(endpoint == 1) 651 else
646 { 652 {
647 logf("EP1 handled: %d", length);
648 flags = disable_irq_save(); 653 flags = disable_irq_save();
649 endpoints[2].buf = ptr; 654 endpoints[endpoint*2].buf = ptr;
650 endpoints[2].received = 0; 655 endpoints[endpoint*2].received = 0;
651 endpoints[2].length = length; 656 endpoints[endpoint*2].length = length;
652 restore_irq(flags); 657 restore_irq(flags);
653 return 0; 658 return 0;
654 } 659 }
655 else
656 return -1;
657} 660}
658 661
659void usb_drv_set_test_mode(int mode) 662void usb_drv_set_test_mode(int mode)
@@ -682,7 +685,7 @@ void usb_drv_set_test_mode(int mode)
682 685
683int usb_drv_port_speed(void) 686int usb_drv_port_speed(void)
684{ 687{
685 return ((REG_USB_REG_POWER & USB_POWER_HSMODE) != 0) ? 1 : 0; 688 return (REG_USB_REG_POWER & USB_POWER_HSMODE) ? 1 : 0;
686} 689}
687 690
688void usb_drv_cancel_all_transfers(void) 691void usb_drv_cancel_all_transfers(void)
@@ -710,14 +713,13 @@ void usb_drv_cancel_all_transfers(void)
710 713
711void usb_drv_release_endpoint(int ep) 714void usb_drv_release_endpoint(int ep)
712{ 715{
713 //logf("usb_drv_release_endpoint(%d)", ep);
714
715 (void)ep; 716 (void)ep;
717 logf("usb_drv_release_endpoint(%d, %s)", (ep & 0x7F), (ep >> 7) ? "IN" : "OUT");
716} 718}
717 719
718int usb_drv_request_endpoint(int dir) 720int usb_drv_request_endpoint(int dir)
719{ 721{
720 logf("usb_drv_request_endpoint(%s)", dir == USB_DIR_IN ? "IN" : "OUT"); 722 logf("usb_drv_request_endpoint(%s)", (dir == USB_DIR_IN) ? "IN" : "OUT");
721 723
722 /* There are only 3+2 endpoints, so hardcode this ... */ 724 /* There are only 3+2 endpoints, so hardcode this ... */
723 /* Currently only BULK endpoints ... */ 725 /* Currently only BULK endpoints ... */