summaryrefslogtreecommitdiff
path: root/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/mips/ingenic_jz47xx/usb-jz4740.c')
-rw-r--r--firmware/target/mips/ingenic_jz47xx/usb-jz4740.c261
1 files changed, 166 insertions, 95 deletions
diff --git a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c
index 7bd0ba4ae5..2dd73c01a4 100644
--- a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c
+++ b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c
@@ -127,21 +127,30 @@ static void writeFIFO(struct usb_endpoint *ep, unsigned int size)
127{ 127{
128 logf("writeFIFO(EP%d, %d)", EP_NUMBER2(ep), size); 128 logf("writeFIFO(EP%d, %d)", EP_NUMBER2(ep), size);
129 129
130 register unsigned int *d = (unsigned int *)EP_PTR(ep); 130 register unsigned int *d32 = (unsigned int *)EP_PTR(ep);
131 register unsigned char *c; 131 register unsigned char *d8 = (unsigned char *)EP_PTR(ep);
132 register unsigned int s; 132 register unsigned int s;
133 133
134 if(size > 0) 134 if(size > 0)
135 { 135 {
136 s = size >> 2; 136 if(UNLIKELY((unsigned int)d8 & 3))
137 while (s--) 137 {
138 REG32(ep->fifo_addr) = *d++; 138 s = size;
139 139 while(s--)
140 if( (s = size & 3) ) 140 REG8(ep->fifo_addr) = *d8++;
141 }
142 else
141 { 143 {
142 c = (unsigned char *)d; 144 s = size >> 2;
143 while (s--) 145 while (s--)
144 REG8(ep->fifo_addr) = *c++; 146 REG32(ep->fifo_addr) = *d32++;
147
148 if( (s = size & 3) )
149 {
150 d8 = (unsigned char *)d32;
151 while (s--)
152 REG8(ep->fifo_addr) = *d8++;
153 }
145 } 154 }
146 } 155 }
147} 156}
@@ -158,9 +167,9 @@ static void flushFIFO(struct usb_endpoint *ep)
158 case ep_bulk: 167 case ep_bulk:
159 case ep_interrupt: 168 case ep_interrupt:
160 if(EP_IS_IN(ep)) 169 if(EP_IS_IN(ep))
161 REG_USB_REG_INCSR |= USB_INCSR_FF; 170 REG_USB_REG_INCSR |= (USB_INCSR_FF | USB_INCSR_CDT);
162 else 171 else
163 REG_USB_REG_OUTCSR |= USB_OUTCSR_FF; 172 REG_USB_REG_OUTCSR |= (USB_OUTCSR_FF | USB_OUTCSR_CDT);
164 break; 173 break;
165 } 174 }
166} 175}
@@ -249,7 +258,7 @@ static void EP0_handler(void)
249} 258}
250 259
251static void EPIN_handler(unsigned int endpoint) 260static void EPIN_handler(unsigned int endpoint)
252{ 261{
253 struct usb_endpoint* ep = &endpoints[endpoint*2+1]; 262 struct usb_endpoint* ep = &endpoints[endpoint*2+1];
254 unsigned int length, csr; 263 unsigned int length, csr;
255 264
@@ -266,14 +275,12 @@ static void EPIN_handler(unsigned int endpoint)
266 return; 275 return;
267 } 276 }
268 277
269#if 0 278 if(ep->use_dma)
270 if(ep->use_dma == true)
271 return; 279 return;
272#endif
273 280
274 if(csr & USB_INCSR_FFNOTEMPT) 281 if(csr & USB_INCSR_FFNOTEMPT)
275 { 282 {
276 logf("FIFO is not empty!: 0x%x", csr); 283 logf("FIFO is not empty! 0x%x", csr);
277 return; 284 return;
278 } 285 }
279 286
@@ -306,56 +313,113 @@ static void EPOUT_handler(unsigned int endpoint)
306 struct usb_endpoint* ep = &endpoints[endpoint*2]; 313 struct usb_endpoint* ep = &endpoints[endpoint*2];
307 unsigned int size, csr; 314 unsigned int size, csr;
308 315
309 select_endpoint(endpoint);
310 csr = REG_USB_REG_OUTCSR;
311 logf("EPOUT_handler(%d): 0x%x", endpoint, csr);
312
313 if(!ep->busy) 316 if(!ep->busy)
314 return; 317 return;
315
316 if(csr & USB_OUTCSR_SENTSTALL)
317 {
318 logf("stall sent, flushing fifo..");
319 flushFIFO(ep);
320 REG_USB_REG_OUTCSR = csr & ~USB_OUTCSR_SENTSTALL;
321 return;
322 }
323 318
324 if(csr & USB_OUTCSR_OUTPKTRDY) /* There is a packet in the fifo */ 319 select_endpoint(endpoint);
320 while((csr = REG_USB_REG_OUTCSR) & (USB_OUTCSR_SENTSTALL|USB_OUTCSR_OUTPKTRDY))
325 { 321 {
326 size = REG_USB_REG_OUTCOUNT; 322 logf("EPOUT_handler(%d): 0x%x", endpoint, csr);
323 if(csr & USB_OUTCSR_SENTSTALL)
324 {
325 logf("stall sent, flushing fifo..");
326 flushFIFO(ep);
327 REG_USB_REG_OUTCSR = csr & ~USB_OUTCSR_SENTSTALL;
328 return;
329 }
327 330
328 readFIFO(ep, size); 331 if(ep->use_dma)
329 ep->received += size; 332 return;
333
334 if(csr & USB_OUTCSR_OUTPKTRDY) /* There is a packet in the fifo */
335 {
336 size = REG_USB_REG_OUTCOUNT;
337
338 readFIFO(ep, size);
339 ep->received += size;
340
341 /*if(csr & USB_OUTCSR_FFFULL)
342 csr &= ~USB_OUTCSR_FFFULL;*/
343
344 REG_USB_REG_OUTCSR = csr & ~USB_OUTCSR_OUTPKTRDY;
345
346 logf("received: %d max length: %d", ep->received, ep->length);
347
348 if(size < ep->fifo_size || ep->received >= ep->length)
349 {
350 usb_core_transfer_complete(endpoint, USB_DIR_OUT, 0, ep->received);
351 if(ep->wait)
352 wakeup_signal(&ep_wkup[endpoint*2]);
353 logf("receive transfer_complete");
354 ep->received = 0;
355 ep->length = 0;
356 ep->buf = NULL;
357 ep->busy = false;
358 return;
359 }
360 }
361 }
362}
330 363
331 REG_USB_REG_OUTCSR = csr & ~USB_OUTCSR_OUTPKTRDY; 364static void EPDMA_handler(int number)
365{
366 int endpoint=-1;
367 unsigned int size=0;
368 if(number == USB_INTR_DMA_BULKIN)
369 endpoint = (REG_USB_REG_CNTL1 >> 4) & 0xF;
370 else if(number == USB_INTR_DMA_BULKOUT)
371 endpoint = (REG_USB_REG_CNTL2 >> 4) & 0xF;
372
373 struct usb_endpoint* ep = &endpoints[endpoint];
374 logf("DMA_BULK%d %d", number, endpoint);
375
376 if(number == USB_INTR_DMA_BULKIN)
377 size = (unsigned int)ep->buf - REG_USB_REG_ADDR1;
378 else if(number == USB_INTR_DMA_BULKOUT)
379 size = (unsigned int)ep->buf - REG_USB_REG_ADDR2;
380
381 if(number == USB_INTR_DMA_BULKOUT)
382 {
383 /* Disable DMA */
384 REG_USB_REG_CNTL2 = 0;
332 385
333 logf("received: %d max length: %d", ep->received, ep->length); 386 __dcache_invalidate_all();
334 387
335 if(size < ep->fifo_size || ep->received >= ep->length) 388 select_endpoint(endpoint);
389 /* Read out last packet manually */
390 unsigned int lpack_size = REG_USB_REG_OUTCOUNT;
391 if(lpack_size > 0)
336 { 392 {
337 usb_core_transfer_complete(endpoint, USB_DIR_OUT, 0, ep->received); 393 ep->buf += ep->length - lpack_size;
338 if(ep->wait) 394 readFIFO(ep, lpack_size);
339 wakeup_signal(&ep_wkup[endpoint*2]); 395 REG_USB_REG_OUTCSR &= ~USB_OUTCSR_OUTPKTRDY;
340 logf("receive transfer_complete");
341 ep->received = 0;
342 ep->length = 0;
343 ep->buf = NULL;
344 ep->busy = false;
345 } 396 }
346 } 397 }
398 else if(number == USB_INTR_DMA_BULKIN && size % ep->fifo_size)
399 /* If the last packet is less than MAXP, set INPKTRDY manually */
400 REG_USB_REG_INCSR |= USB_INCSR_INPKTRDY;
401
402 usb_core_transfer_complete(endpoint, EP_IS_IN(ep) ? USB_DIR_IN : USB_DIR_OUT,
403 0, ep->length);
404
405 ep->busy = false;
406 ep->sent = 0;
407 ep->length = 0;
408 ep->buf = NULL;
409 if(ep->wait)
410 wakeup_signal(&ep_wkup[EP_NUMBER(ep)]);
347} 411}
348 412
349static void setup_endpoint(struct usb_endpoint *ep) 413static void setup_endpoint(struct usb_endpoint *ep)
350{ 414{
351 int csr; 415 int csr, csrh;
352 ep->sent = 0;
353 ep->length = 0;
354 416
355 select_endpoint(EP_NUMBER2(ep)); 417 select_endpoint(EP_NUMBER2(ep));
356 418
357 ep->busy = false; 419 ep->busy = false;
358 ep->wait = false; 420 ep->wait = false;
421 ep->sent = 0;
422 ep->length = 0;
359 423
360 if(ep->type == ep_bulk) 424 if(ep->type == ep_bulk)
361 { 425 {
@@ -367,27 +431,31 @@ static void setup_endpoint(struct usb_endpoint *ep)
367 431
368 if(EP_IS_IN(ep)) 432 if(EP_IS_IN(ep))
369 { 433 {
370 REG_USB_REG_INMAXP = ep->fifo_size; 434 csr = (USB_INCSR_FF | USB_INCSR_CDT);
371 csr = (USB_INCSR_FF | USB_INCSR_CDT | USB_INCSRH_MODE); 435 csrh = USB_INCSRH_MODE;
372 if(ep->use_dma) 436 if(ep->use_dma)
373 csr |= (USB_INCSRH_DMAREQENAB | USB_INCSRH_AUTOSET); 437 csrh |= (USB_INCSRH_DMAREQENAB | USB_INCSRH_AUTOSET | USB_INCSRH_DMAREQMODE);
374 438
375 REG_USB_REG_INTRINE |= USB_INTR_EP(EP_NUMBER2(ep)); 439 REG_USB_REG_INMAXP = ep->fifo_size;
376 REG_USB_REG_INCSR = csr; 440 REG_USB_REG_INCSR = csr;
441 REG_USB_REG_INCSRH = csrh;
442 REG_USB_REG_INTRINE |= USB_INTR_EP(EP_NUMBER2(ep));
377 } 443 }
378 else 444 else
379 { 445 {
380 REG_USB_REG_OUTMAXP = ep->fifo_size;
381 csr = (USB_OUTCSR_FF | USB_OUTCSR_CDT); 446 csr = (USB_OUTCSR_FF | USB_OUTCSR_CDT);
447 csrh = 0;
382 448
383 if(ep->type == ep_interrupt) 449 if(ep->type == ep_interrupt)
384 csr |= USB_OUTCSRH_DNYT; 450 csrh |= USB_OUTCSRH_DNYT;
385 451
386 if(ep->use_dma) 452 if(ep->use_dma)
387 csr |= (USB_OUTCSRH_DMAREQENAB | USB_OUTCSRH_AUTOCLR | USB_OUTCSRH_DMAREQMODE); 453 csrh |= (USB_OUTCSRH_DMAREQENAB | USB_OUTCSRH_AUTOCLR | USB_OUTCSRH_DMAREQMODE);
388 454
389 REG_USB_REG_INTROUTE |= USB_INTR_EP(EP_NUMBER2(ep)); 455 REG_USB_REG_OUTMAXP = ep->fifo_size;
390 REG_USB_REG_OUTCSR = csr; 456 REG_USB_REG_OUTCSR = csr;
457 REG_USB_REG_OUTCSRH = csrh;
458 REG_USB_REG_INTROUTE |= USB_INTR_EP(EP_NUMBER2(ep));
391 } 459 }
392} 460}
393 461
@@ -395,13 +463,13 @@ static void udc_reset(void)
395{ 463{
396 /* From the datasheet: 464 /* From the datasheet:
397 465
398 When a reset condition is detected on the USB, the controller performs the following actions: 466 When a reset condition is detected on the USB, the controller performs the following actions:
399 * Sets FAddr to 0. 467 * Sets FAddr to 0.
400 * Sets Index to 0. 468 * Sets Index to 0.
401 * Flushes all endpoint FIFOs. 469 * Flushes all endpoint FIFOs.
402 * Clears all control/status registers. 470 * Clears all control/status registers.
403 * Enables all endpoint interrupts. 471 * Enables all endpoint interrupts.
404 * Generates a Reset interrupt. 472 * Generates a Reset interrupt.
405 */ 473 */
406 474
407 logf("udc_reset()"); 475 logf("udc_reset()");
@@ -430,7 +498,8 @@ static void udc_reset(void)
430 select_endpoint(0); 498 select_endpoint(0);
431 REG_USB_REG_CSR0 = (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_SVDSETUPEND); 499 REG_USB_REG_CSR0 = (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_SVDSETUPEND);
432 500
433 for(i=2; i<TOTAL_EP(); i++) /* Skip EP0 */ 501 /* Reset other endpoints */
502 for(i=2; i<TOTAL_EP(); i++)
434 setup_endpoint(&endpoints[i]); 503 setup_endpoint(&endpoints[i]);
435 504
436 /* Enable interrupts */ 505 /* Enable interrupts */
@@ -451,6 +520,8 @@ void UDC(void)
451 520
452 if(UNLIKELY(intrUSB == 0 && intrIn == 0 && intrOut == 0 && intrDMA == 0)) 521 if(UNLIKELY(intrUSB == 0 && intrIn == 0 && intrOut == 0 && intrDMA == 0))
453 return; 522 return;
523
524 logf("%x %x %x %x", intrUSB, intrIn, intrOut, intrDMA);
454 525
455 /* EPIN & EPOUT are all handled in DMA */ 526 /* EPIN & EPOUT are all handled in DMA */
456 if(intrIn & USB_INTR_EP0) 527 if(intrIn & USB_INTR_EP0)
@@ -473,30 +544,10 @@ void UDC(void)
473 { 544 {
474 logf("USB resume"); 545 logf("USB resume");
475 } 546 }
476#if 0
477 if(intrDMA & USB_INTR_DMA_BULKIN) 547 if(intrDMA & USB_INTR_DMA_BULKIN)
478 { 548 EPDMA_handler(USB_INTR_DMA_BULKIN);
479 logf("DMA_BULKIN %d", ((REG_USB_REG_CNTL1 >> 4) & 0xF));
480 unsigned int size = (unsigned int)endpoints[3].buf - REG_USB_REG_ADDR2;
481 if(size < endpoints[3].length)
482 {
483 select_endpoint(1);
484 writeFIFO(endpoints[3], endpoints[3].length - size);
485 REG_USB_REG_INCSR |= USB_INCSR_INPKTRDY;
486 }
487
488 usb_core_transfer_complete(1, USB_DIR_IN, 0, endpoints[3].length);
489 }
490 if(intrDMA & USB_INTR_DMA_BULKOUT) 549 if(intrDMA & USB_INTR_DMA_BULKOUT)
491 { 550 EPDMA_handler(USB_INTR_DMA_BULKOUT);
492 logf("DMA_BULKOUT %d", ((REG_USB_REG_CNTL2 >> 4) & 0xF));
493
494 select_endpoint(1);
495 REG_USB_REG_OUTCSR &= ~(USB_OUTCSRH_DMAREQENAB | USB_OUTCSR_OUTPKTRDY);
496
497 usb_core_transfer_complete(1, USB_DIR_OUT, 0, 0);
498 }
499#endif
500} 551}
501 552
502bool usb_drv_stalled(int endpoint, bool in) 553bool usb_drv_stalled(int endpoint, bool in)
@@ -610,6 +661,10 @@ void usb_drv_init(void)
610 /* Enable the USB PHY */ 661 /* Enable the USB PHY */
611 REG_CPM_SCR |= CPM_SCR_USBPHY_ENABLE; 662 REG_CPM_SCR |= CPM_SCR_USBPHY_ENABLE;
612 663
664 /* Dis- and reconnect from USB */
665 REG_USB_REG_POWER &= ~USB_POWER_SOFTCONN;
666 REG_USB_REG_POWER |= USB_POWER_SOFTCONN;
667
613 udc_reset(); 668 udc_reset();
614} 669}
615 670
@@ -660,8 +715,8 @@ int usb_drv_send_nonblocking(int endpoint, void* ptr, int length)
660 endpoints[1].length = length; 715 endpoints[1].length = length;
661 ep0state = USB_EP0_TX; 716 ep0state = USB_EP0_TX;
662 EP0_send(); 717 EP0_send();
663
664 restore_irq(flags); 718 restore_irq(flags);
719
665 return 0; 720 return 0;
666 } 721 }
667 else 722 else
@@ -671,15 +726,19 @@ int usb_drv_send_nonblocking(int endpoint, void* ptr, int length)
671 endpoints[endpoint*2+1].sent = 0; 726 endpoints[endpoint*2+1].sent = 0;
672 endpoints[endpoint*2+1].length = length; 727 endpoints[endpoint*2+1].length = length;
673 endpoints[endpoint*2+1].busy = true; 728 endpoints[endpoint*2+1].busy = true;
674#if 0 729 if(endpoints[endpoint*2+1].use_dma)
675 select_endpoint(endpoint); 730 {
731 //dma_cache_wback_inv((unsigned long)ptr, length);
732 __dcache_writeback_all();
733 REG_USB_REG_ADDR1 = (unsigned long)ptr & 0x7fffffff;
734 REG_USB_REG_COUNT1 = length;
735 REG_USB_REG_CNTL1 = (USB_CNTL_INTR_EN | USB_CNTL_MODE_1 |
736 USB_CNTL_DIR_IN | USB_CNTL_ENA |
737 USB_CNTL_EP(endpoint) | USB_CNTL_BURST_16);
738 }
739 else
740 EPIN_handler(endpoint);
676 741
677 REG_USB_REG_ADDR2 = ((unsigned long)ptr) & 0x7fffffff;
678 REG_USB_REG_COUNT2 = length;
679 REG_USB_REG_CNTL2 = (USB_CNTL_INTR_EN | USB_CNTL_MODE_1 | USB_CNTL_DIR_IN | USB_CNTL_ENA);
680#else
681 EPIN_handler(endpoint);
682#endif
683 restore_irq(flags); 742 restore_irq(flags);
684 return 0; 743 return 0;
685 } 744 }
@@ -717,8 +776,20 @@ int usb_drv_recv(int endpoint, void* ptr, int length)
717 endpoints[endpoint*2].received = 0; 776 endpoints[endpoint*2].received = 0;
718 endpoints[endpoint*2].length = length; 777 endpoints[endpoint*2].length = length;
719 endpoints[endpoint*2].busy = true; 778 endpoints[endpoint*2].busy = true;
720 restore_irq(flags); 779 if(endpoints[endpoint*2].use_dma)
780 {
781 //dma_cache_wback_inv((unsigned long)ptr, length);
782 __dcache_writeback_all();
783 REG_USB_REG_ADDR2 = (unsigned long)ptr & 0x7fffffff;
784 REG_USB_REG_COUNT2 = length;
785 REG_USB_REG_CNTL2 = (USB_CNTL_INTR_EN | USB_CNTL_MODE_1 |
786 USB_CNTL_ENA | USB_CNTL_EP(endpoint) |
787 USB_CNTL_BURST_16);
788 }
789 else
790 EPOUT_handler(endpoint);
721 791
792 restore_irq(flags);
722 return 0; 793 return 0;
723 } 794 }
724} 795}