summaryrefslogtreecommitdiff
path: root/firmware/target/mips/ingenic_jz47xx/usb-jz4760.c
diff options
context:
space:
mode:
authorSolomon Peachy <pizza@shaftnet.org>2020-09-14 20:36:24 -0400
committerSolomon Peachy <pizza@shaftnet.org>2020-09-17 11:26:04 -0400
commitec413f7692de3e33254d79a84c46bd036fd27d0a (patch)
treed5853dd677c5d39233a067a9d7f1dc2d3290a8ae /firmware/target/mips/ingenic_jz47xx/usb-jz4760.c
parenta66b9088014fd77d08c34fc07a4e701051e1525a (diff)
downloadrockbox-ec413f7692de3e33254d79a84c46bd036fd27d0a.tar.gz
rockbox-ec413f7692de3e33254d79a84c46bd036fd27d0a.zip
jz4760: Heavily rework USB driver to add working DMA support
* DMA Bulk IN (ie our TX) results in sequential transfers 33-68% faster. * DMA Bulk OUT (ie RX) is mostly stripped out due to complete brokenness. * Interrupt and control endpoints remain PIO-driven. Other improvements: 1) Use consistent endpoint references (no magic numbers) 2) Greatly enhanced logging 3) DMA support can be compiled out completely 4) Setting lockswitch will disable all DMA operations at runtime 5) Much more robust error checking and recovery Change-Id: I57b82e655e55ced0dfe289e379b0b61d8fe443b4
Diffstat (limited to 'firmware/target/mips/ingenic_jz47xx/usb-jz4760.c')
-rw-r--r--firmware/target/mips/ingenic_jz47xx/usb-jz4760.c383
1 files changed, 244 insertions, 139 deletions
diff --git a/firmware/target/mips/ingenic_jz47xx/usb-jz4760.c b/firmware/target/mips/ingenic_jz47xx/usb-jz4760.c
index 275fd3fd2b..8562d9253c 100644
--- a/firmware/target/mips/ingenic_jz47xx/usb-jz4760.c
+++ b/firmware/target/mips/ingenic_jz47xx/usb-jz4760.c
@@ -7,7 +7,8 @@
7 * \/ \/ \/ \/ \/ 7 * \/ \/ \/ \/ \/
8 * $Id$ 8 * $Id$
9 * 9 *
10 * Copyright (C) 2016 by Roman Stolyarov 10 * Copyright (C) 2016 Roman Stolyarov
11 * Copyright (C) 2020 Solomon Peachy
11 * 12 *
12 * This program is free software; you can redistribute it and/or 13 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License 14 * modify it under the terms of the GNU General Public License
@@ -20,7 +21,7 @@
20 ****************************************************************************/ 21 ****************************************************************************/
21 22
22#include "config.h" 23#include "config.h"
23/*#define LOGF_ENABLE*/ 24//#define LOGF_ENABLE
24#include "logf.h" 25#include "logf.h"
25#include "system.h" 26#include "system.h"
26#include "usb_ch9.h" 27#include "usb_ch9.h"
@@ -29,6 +30,8 @@
29#include "cpu.h" 30#include "cpu.h"
30#include "thread.h" 31#include "thread.h"
31 32
33#define USE_USB_DMA
34
32#define PIN_USB_DET (32*4+19) 35#define PIN_USB_DET (32*4+19)
33#define IRQ_USB_DET GPIO_IRQ(PIN_USB_DET) 36#define IRQ_USB_DET GPIO_IRQ(PIN_USB_DET)
34#define GPIO_USB_DET GPIO147 37#define GPIO_USB_DET GPIO147
@@ -43,6 +46,13 @@
43#define TOTAL_EP() (sizeof(endpoints)/sizeof(struct usb_endpoint)) 46#define TOTAL_EP() (sizeof(endpoints)/sizeof(struct usb_endpoint))
44#define EP_IS_IN(ep) (EP_NUMBER((ep))%2) 47#define EP_IS_IN(ep) (EP_NUMBER((ep))%2)
45 48
49#define TXCSR_WZC_BITS (USB_INCSR_SENTSTALL | USB_INCSR_UNDERRUN | USB_INCSR_FFNOTEMPT | USB_INCSR_INCOMPTX)
50
51/* NOTE: IN/OUT is from the HOST perspective. We're a peripheral, so:
52 IN = DEV->HOST, (ie we send)
53 OUT = HOST->DEV, (ie we recv)
54*/
55
46enum ep_type 56enum ep_type
47{ 57{
48 ep_control, 58 ep_control,
@@ -53,6 +63,16 @@ enum ep_type
53 63
54struct usb_endpoint 64struct usb_endpoint
55{ 65{
66 const enum ep_type type;
67 const long fifo_addr;
68 unsigned short fifo_size;
69 bool allocated;
70 int use_dma; /* -1 = no, 0 = mode_0, 1 = mode_1 */
71
72 struct semaphore complete;
73
74 uint8_t config;
75
56 volatile void *buf; 76 volatile void *buf;
57 volatile size_t length; 77 volatile size_t length;
58 union 78 union
@@ -60,24 +80,14 @@ struct usb_endpoint
60 volatile size_t sent; 80 volatile size_t sent;
61 volatile size_t received; 81 volatile size_t received;
62 }; 82 };
83 volatile int rc;
63 volatile bool busy; 84 volatile bool busy;
64
65 const enum ep_type type;
66 const bool use_dma;
67
68 const long fifo_addr;
69 unsigned short fifo_size;
70
71 volatile bool wait; 85 volatile bool wait;
72 struct semaphore complete;
73
74 volatile int rc;
75 bool allocated;
76}; 86};
77 87
78#define EP_INIT(_type, _fifo_addr, _fifo_size, _buf, _use_dma) \ 88#define EP_INIT(_type, _fifo_addr, _fifo_size, _buf) \
79 { .type = (_type), .fifo_addr = (_fifo_addr), .fifo_size = (_fifo_size), \ 89 { .type = (_type), .fifo_addr = (_fifo_addr), .fifo_size = (_fifo_size), \
80 .buf = (_buf), .use_dma = (_use_dma), \ 90 .buf = (_buf), .use_dma = -1, \
81 .length = 0, .busy = false, .wait = false, .allocated = false } 91 .length = 0, .busy = false, .wait = false, .allocated = false }
82 92
83static union 93static union
@@ -91,12 +101,12 @@ static volatile bool ep0_data_requested = false;
91 101
92static struct usb_endpoint endpoints[] = 102static struct usb_endpoint endpoints[] =
93{ 103{
94 EP_INIT(ep_control, USB_FIFO_EP(0), 64, NULL, false), 104 EP_INIT(ep_control, USB_FIFO_EP(0), 64, NULL),
95 EP_INIT(ep_control, USB_FIFO_EP(0), 64, &ep0_rx.buf, false), 105 EP_INIT(ep_control, USB_FIFO_EP(0), 64, &ep0_rx.buf),
96 EP_INIT(ep_bulk, USB_FIFO_EP(1), 512, NULL, false), 106 EP_INIT(ep_bulk, USB_FIFO_EP(1), 512, NULL),
97 EP_INIT(ep_bulk, USB_FIFO_EP(1), 512, NULL, false), 107 EP_INIT(ep_bulk, USB_FIFO_EP(1), 512, NULL),
98 EP_INIT(ep_interrupt, USB_FIFO_EP(2), 512, NULL, false), 108 EP_INIT(ep_interrupt, USB_FIFO_EP(2), 512, NULL),
99 EP_INIT(ep_interrupt, USB_FIFO_EP(2), 512, NULL, false), 109 EP_INIT(ep_interrupt, USB_FIFO_EP(2), 512, NULL),
100}; 110};
101 111
102static inline void select_endpoint(int ep) 112static inline void select_endpoint(int ep)
@@ -329,7 +339,8 @@ static void EP0_handler(void)
329 EP0_send(); 339 EP0_send();
330} 340}
331 341
332static void EPIN_handler(unsigned int endpoint) 342/* Does new work */
343static void EPIN_send(unsigned int endpoint)
333{ 344{
334 struct usb_endpoint* ep = &endpoints[endpoint*2]; 345 struct usb_endpoint* ep = &endpoints[endpoint*2];
335 unsigned int length, csr; 346 unsigned int length, csr;
@@ -338,45 +349,153 @@ static void EPIN_handler(unsigned int endpoint)
338 csr = REG_USB_INCSR; 349 csr = REG_USB_INCSR;
339 logf("%s(%d): 0x%x", __func__, endpoint, csr); 350 logf("%s(%d): 0x%x", __func__, endpoint, csr);
340 351
341 if(!ep->busy) 352 if (!ep->busy) {
342 {
343 logf("Entered EPIN handler without work!"); 353 logf("Entered EPIN handler without work!");
344 return; 354 return;
345 } 355 }
346 356
347 if(csr & USB_INCSR_SENTSTALL) 357 if (csr & USB_INCSR_INPKTRDY) {
348 { 358 logf("PKTRDY %d", endpoint);
349 REG_USB_INCSR = csr & ~USB_INCSR_SENTSTALL;
350 return; 359 return;
351 } 360 }
352 361
353 if(ep->use_dma) 362 if (csr & USB_INCSR_SENTSTALL) {
363 logf("SENDSTALL %d", endpoint);
364 REG_USB_INCSR = csr & ~USB_INCSR_SENTSTALL;
354 return; 365 return;
366 }
355 367
356 if(csr & USB_INCSR_FFNOTEMPT) 368 if (csr & USB_INCSR_FFNOTEMPT) {
357 {
358 logf("FIFO is not empty! 0x%x", csr); 369 logf("FIFO is not empty! 0x%x", csr);
359 return; 370 return;
360 } 371 }
361 372
373#ifdef USE_USB_DMA
374 if(ep->use_dma >= 0) {
375 logf("DMA busy(%x %x %x)", REG_USB_ADDR(USB_INTR_DMA_BULKIN), REG_USB_COUNT(USB_INTR_DMA_BULKIN),REG_USB_CNTL(USB_INTR_DMA_BULKIN));
376
377 return;
378 }
379#endif
380
362 logf("EP%d: %d -> %d", endpoint, ep->sent, ep->length); 381 logf("EP%d: %d -> %d", endpoint, ep->sent, ep->length);
363 382
383#ifdef USE_USB_DMA
384 /* Can we use DMA? */
385 if (ep->type == ep_bulk && ep->length && (!(((unsigned long)ep->buf + ep->sent) % 4)) && !button_hold()) {
386 if (ep->length >= ep->fifo_size)
387 ep->use_dma = 1;
388 else
389 ep->use_dma = 0;
390 } else {
391 ep->use_dma = -1;
392 }
393
394 if (ep->use_dma >= 0) {
395 commit_discard_dcache_range((void*)ep->buf + ep->sent, ep->length - ep->sent);
396 /* Set up DMA */
397 uint16_t dmacr = USB_CNTL_BURST_16 | USB_CNTL_EP(EP_NUMBER2(ep)) | USB_CNTL_ENA | USB_CNTL_INTR_EN | USB_CNTL_DIR_IN ;
398 if (ep->use_dma > 0)
399 dmacr |= USB_CNTL_MODE_1;
400
401 REG_USB_ADDR(USB_INTR_DMA_BULKIN) = PHYSADDR((unsigned long)ep->buf + ep->sent);
402 REG_USB_COUNT(USB_INTR_DMA_BULKIN) = ep->length - ep->sent;
403 REG_USB_CNTL(USB_INTR_DMA_BULKIN) = dmacr;
404
405 uint16_t csr = REG_USB_INCSR;
406 if (ep->use_dma == 0) {
407 csr &= ~((USB_INCSRH_AUTOSET | USB_INCSRH_DMAREQENAB) << 8);
408 REG_USB_INCSR = csr | TXCSR_WZC_BITS;
409 csr &= ~((USB_INCSRH_DMAREQMODE) << 8);
410 csr |= ((USB_INCSRH_DMAREQENAB | USB_INCSRH_MODE) << 8);
411 } else {
412 csr |= ((USB_INCSRH_DMAREQENAB | USB_INCSRH_MODE | USB_INCSRH_DMAREQMODE) << 8);
413 csr |= ((USB_INCSRH_AUTOSET) << 8);
414 }
415 csr &= ~USB_INCSR_UNDERRUN;
416
417 logf("DMA setup(%d: %x %x %x %x - %d)", EP_NUMBER2(ep), (unsigned int)PHYSADDR((unsigned long)ep->buf), ep->length, dmacr, csr, ep->use_dma);
418
419 REG_USB_INCSR = csr;
420
421 return;
422 }
423#endif
424
425 /* Non-DMA code */
364 if(ep->sent == 0) 426 if(ep->sent == 0)
365 length = MIN(ep->length, ep->fifo_size); 427 length = MIN(ep->length, ep->fifo_size);
366 else 428 else
367 length = MIN(EP_BUF_LEFT(ep), ep->fifo_size); 429 length = MIN(EP_BUF_LEFT(ep), ep->fifo_size);
368 430
369 writeFIFO(ep, length); 431 writeFIFO(ep, length);
370 REG_USB_INCSR = csr | USB_INCSR_INPKTRDY;
371 ep->sent += length; 432 ep->sent += length;
433 csr &= ~USB_INCSR_UNDERRUN;
434 csr |= USB_INCSR_INPKTRDY;
435 logf("Non-DMA TX %x", csr);
436 REG_USB_INCSR = csr;
437}
372 438
373 if(ep->sent >= ep->length) 439static void EPIN_complete(unsigned int endpoint)
374 { 440{
441 struct usb_endpoint* ep = &endpoints[endpoint*2];
442 uint16_t csr;
443
444 select_endpoint(endpoint);
445 csr = REG_USB_INCSR;
446 logf("%s(%d): 0x%x", __func__, endpoint, csr);
447
448 if (csr & USB_INCSR_SENTSTALL) {
449 logf("SENDSTALL %d\n", endpoint);
450 REG_USB_INCSR = csr & ~USB_INCSR_SENTSTALL; // XXX TXCSR_P_WZC_BITS
451 return;
452 }
453
454 if (csr & USB_INCSR_UNDERRUN) {
455 csr |= TXCSR_WZC_BITS;
456 csr &= ~(USB_INCSR_UNDERRUN | USB_INCSR_INPKTRDY);
457 REG_USB_INCSR = csr;
458 logf("underrun! %x", csr);
459 }
460
461 if (!ep->busy) {
462 logf("Entered EPIN_complete without work!");
463 return;
464 }
465
466 if (ep->use_dma >= 0) {
467 logf("DMA status (%x %x %x)", REG_USB_ADDR(USB_INTR_DMA_BULKIN), REG_USB_COUNT(USB_INTR_DMA_BULKIN),REG_USB_CNTL(USB_INTR_DMA_BULKIN));
468 return;
469 }
470
471 /* If we get here, the operation is completed, and we need to clean up */
472
473 /* Make sure DMA engine is idle */
474 if (csr & (USB_INCSRH_DMAREQENAB << 8)) {
475 csr |= TXCSR_WZC_BITS;
476 csr &= ~(USB_INCSR_UNDERRUN | USB_INCSR_INPKTRDY |
477 ((USB_INCSRH_DMAREQENAB | USB_INCSRH_AUTOSET) << 8));
478 REG_USB_INCSR = csr;
479 csr = REG_USB_INCSR;
480 logf("DMA cleanup %x", csr);
481 }
482
483 // XXX send a zero-length packet if necessary.
484 // if tx complete, and ep->length > 0 and ep->length % fifo == 0,
485 // REG_USB_INCSR = MODE | PKTRDY;
486 // Not needed for mass storage as it counts packets but
487 // if we ever enable other protocls...
488
489 logf("EP%d: %d -> %d", endpoint, ep->sent, ep->length);
490
491 if(ep->sent >= ep->length) {
375 if (!ep->wait) 492 if (!ep->wait)
376 usb_core_transfer_complete(endpoint, USB_DIR_IN, 0, ep->sent); 493 usb_core_transfer_complete(endpoint, USB_DIR_IN, 0, ep->sent);
377 ep->rc = 0; 494 ep->rc = 0;
378 ep_transfer_completed(ep); 495 ep_transfer_completed(ep);
379 logf("sent complete"); 496 logf("send complete");
497 } else {
498 EPIN_send(endpoint);
380 } 499 }
381} 500}
382 501
@@ -403,9 +522,6 @@ static void EPOUT_handler(unsigned int endpoint)
403 return; 522 return;
404 } 523 }
405 524
406 if(ep->use_dma)
407 return;
408
409 if(csr & USB_OUTCSR_OUTPKTRDY) /* There is a packet in the fifo */ 525 if(csr & USB_OUTCSR_OUTPKTRDY) /* There is a packet in the fifo */
410 { 526 {
411 size = REG_USB_OUTCOUNT; 527 size = REG_USB_OUTCOUNT;
@@ -430,59 +546,55 @@ static void EPOUT_handler(unsigned int endpoint)
430 } 546 }
431} 547}
432 548
549#ifdef USE_USB_DMA
433static void EPDMA_handler(int number) 550static void EPDMA_handler(int number)
434{ 551{
435 int endpoint = -1; 552 int endpoint = -1;
436 unsigned int size = 0; 553 int size = 0;
437 struct usb_endpoint* ep = NULL; 554 struct usb_endpoint* ep = NULL;
438 555
439 if(number == USB_INTR_DMA_BULKIN) 556 endpoint = (REG_USB_CNTL(number) >> 4) & 0xF;
440 { 557 ep = &endpoints[endpoint*2];
441 endpoint = (REG_USB_CNTL(0) >> 4) & 0xF; 558 if (!(REG_USB_CNTL(number) & USB_CNTL_DIR_IN))
442 ep = &endpoints[endpoint*2]; 559 ep++; /* RX endpoint is +1 in the array */
443 size = (unsigned int)ep->buf - REG_USB_ADDR(0); 560 size = VIRTADDR(REG_USB_ADDR(number)) - ((unsigned int)ep->buf + ep->sent);
444 } 561
445 else if(number == USB_INTR_DMA_BULKOUT) 562 if (number == USB_INTR_DMA_BULKIN) {
446 { 563 if ((ep->use_dma == 0) || (size % ep->fifo_size)) {
447 endpoint = (REG_USB_CNTL(1) >> 4) & 0xF; 564 /* DMA is completed, but the final (short) packet needs to
448 ep = &endpoints[endpoint*2+1]; 565 be manually initiated! */
449 size = (unsigned int)ep->buf - REG_USB_ADDR(1); 566 uint16_t incsr;
450 } 567 select_endpoint(endpoint);
451 568 incsr = REG_USB_INCSR;
452 logf("DMA_BULK%d %d", number, endpoint); 569
453 570 if (ep->use_dma == 1) {
454 if(number == USB_INTR_DMA_BULKOUT) 571 /* Switch to Mode 0 DMA */
455 { 572 incsr &= ~((USB_INCSRH_AUTOSET | USB_INCSRH_DMAREQENAB) << 8);
456 /* Disable DMA */ 573 REG_USB_INCSR = incsr;
457 REG_USB_CNTL(1) = 0; 574 incsr &= ~((USB_INCSRH_DMAREQMODE) << 8);
458 575 incsr |= ((USB_INCSRH_DMAREQENAB) << 8);
459 commit_discard_dcache(); // XXX range? 576 }
460 577 incsr |= USB_INCSR_INPKTRDY;
461 select_endpoint(endpoint); 578 logf("DMA dangling %x", incsr);
462 /* Read out last packet manually */ 579 REG_USB_INCSR = incsr;
463 unsigned int lpack_size = REG_USB_OUTCOUNT;
464 if(lpack_size > 0)
465 {
466 ep->buf += ep->length - lpack_size;
467 readFIFO(ep, lpack_size);
468 REG_USB_OUTCSR &= ~USB_OUTCSR_OUTPKTRDY;
469 } 580 }
470 } 581 logf("DMA TX%d %d @%d/%d", number, size, ep->sent, ep->length);
471 else if(number == USB_INTR_DMA_BULKIN && size % ep->fifo_size) 582 ep->sent += size;
472 { 583 ep->use_dma = -1; /* DMA is complete, mark channel as idle */
473 /* If the last packet is less than MAXP, set INPKTRDY manually */ 584
474 REG_USB_INCSR |= USB_INCSR_INPKTRDY; 585 EPIN_complete(endpoint);
475 } 586 } else if (number == USB_INTR_DMA_BULKOUT) {
476 587 /* RX DMA completed */
477 if (ep) 588 logf("DMA RX%d %d @%d/%d", number, size, ep->received, ep->length);
478 { 589 ep->received += size;
479 int dir = EP_IS_IN(ep) ? USB_DIR_IN : USB_DIR_OUT; 590 ep->use_dma = -1;
480 if ((dir == USB_DIR_OUT) || !ep->wait) 591
481 usb_core_transfer_complete(endpoint, dir, 0, ep->length); 592 EPOUT_handler(endpoint);
482 ep->rc = 0; 593 } else if (ep) {
483 ep_transfer_completed(ep); 594 ep->use_dma = -1;
484 } 595 }
485} 596}
597#endif
486 598
487static void setup_endpoint(struct usb_endpoint *ep) 599static void setup_endpoint(struct usb_endpoint *ep)
488{ 600{
@@ -510,14 +622,13 @@ static void setup_endpoint(struct usb_endpoint *ep)
510 if(ep->type != ep_control) 622 if(ep->type != ep_control)
511 ep->fifo_size = usb_drv_port_speed() ? 512 : 64; 623 ep->fifo_size = usb_drv_port_speed() ? 512 : 64;
512 624
625 ep->config = REG_USB_CONFIGDATA;
626
513 if(EP_IS_IN(ep)) 627 if(EP_IS_IN(ep))
514 { 628 {
515 csr = (USB_INCSR_FF | USB_INCSR_CDT); 629 csr = (USB_INCSR_FF | USB_INCSR_CDT);
516 csrh = USB_INCSRH_MODE; 630 csrh = USB_INCSRH_MODE;
517 631
518 if(ep->use_dma)
519 csrh |= (USB_INCSRH_DMAREQENAB | USB_INCSRH_AUTOSET | USB_INCSRH_DMAREQMODE);
520
521 if(ep->type == ep_interrupt) 632 if(ep->type == ep_interrupt)
522 csrh |= USB_INCSRH_FRCDATATOG; 633 csrh |= USB_INCSRH_FRCDATATOG;
523 634
@@ -525,6 +636,8 @@ static void setup_endpoint(struct usb_endpoint *ep)
525 REG_USB_INCSR = csr; 636 REG_USB_INCSR = csr;
526 REG_USB_INCSRH = csrh; 637 REG_USB_INCSRH = csrh;
527 638
639 logf("IN %d (%x %x %x)", endpoint, ep->fifo_size, csr, csrh);
640
528 if (ep->allocated) 641 if (ep->allocated)
529 REG_USB_INTRINE |= USB_INTR_EP(EP_NUMBER2(ep)); 642 REG_USB_INTRINE |= USB_INTR_EP(EP_NUMBER2(ep));
530 } 643 }
@@ -536,13 +649,12 @@ static void setup_endpoint(struct usb_endpoint *ep)
536 if(ep->type == ep_interrupt) 649 if(ep->type == ep_interrupt)
537 csrh |= USB_OUTCSRH_DNYT; 650 csrh |= USB_OUTCSRH_DNYT;
538 651
539 if(ep->use_dma)
540 csrh |= (USB_OUTCSRH_DMAREQENAB | USB_OUTCSRH_AUTOCLR | USB_OUTCSRH_DMAREQMODE);
541
542 REG_USB_OUTMAXP = ep->fifo_size; 652 REG_USB_OUTMAXP = ep->fifo_size;
543 REG_USB_OUTCSR = csr; 653 REG_USB_OUTCSR = csr;
544 REG_USB_OUTCSRH = csrh; 654 REG_USB_OUTCSRH = csrh;
545 655
656 logf("OUT %d (%x %x %x)", endpoint, ep->fifo_size, csr, csrh);
657
546 if (ep->allocated) 658 if (ep->allocated)
547 REG_USB_INTROUTE |= USB_INTR_EP(EP_NUMBER2(ep)); 659 REG_USB_INTROUTE |= USB_INTR_EP(EP_NUMBER2(ep));
548 } 660 }
@@ -574,8 +686,8 @@ static void udc_reset(void)
574 REG_USB_INTRUSBE = 0; 686 REG_USB_INTRUSBE = 0;
575 687
576 /* Disable DMA */ 688 /* Disable DMA */
577 REG_USB_CNTL(0) = 0; 689 REG_USB_CNTL(USB_INTR_DMA_BULKIN) = 0;
578 REG_USB_CNTL(1) = 0; 690 REG_USB_CNTL(USB_INTR_DMA_BULKOUT) = 0;
579 691
580 /* High speed, softconnect */ 692 /* High speed, softconnect */
581 REG_USB_POWER = (USB_POWER_SOFTCONN | USB_POWER_HSENAB); 693 REG_USB_POWER = (USB_POWER_SOFTCONN | USB_POWER_HSENAB);
@@ -584,6 +696,9 @@ static void udc_reset(void)
584 select_endpoint(0); 696 select_endpoint(0);
585 REG_USB_CSR0 = (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_SVDSETUPEND | USB_CSR0_FLUSHFIFO); 697 REG_USB_CSR0 = (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_SVDSETUPEND | USB_CSR0_FLUSHFIFO);
586 698
699 endpoints[0].config = REG_USB_CONFIGDATA;
700 endpoints[1].config = REG_USB_CONFIGDATA;
701
587 if (endpoints[0].busy) 702 if (endpoints[0].busy)
588 { 703 {
589 if (endpoints[0].wait) 704 if (endpoints[0].wait)
@@ -627,17 +742,19 @@ void OTG(void)
627 unsigned char intrUSB = REG_USB_INTRUSB; 742 unsigned char intrUSB = REG_USB_INTRUSB;
628 unsigned short intrIn = REG_USB_INTRIN; 743 unsigned short intrIn = REG_USB_INTRIN;
629 unsigned short intrOut = REG_USB_INTROUT; 744 unsigned short intrOut = REG_USB_INTROUT;
745#ifdef USE_USB_DMA
630 unsigned char intrDMA = REG_USB_INTR; 746 unsigned char intrDMA = REG_USB_INTR;
747#endif
631 748
632 logf("%x %x %x %x", intrUSB, intrIn, intrOut, intrDMA); 749 logf("IRQ %x %x %x %x", intrUSB, intrIn, intrOut, intrDMA);
633 750
634 /* EPIN & EPOUT are all handled in DMA */ 751 /* EPIN & EPOUT are all handled in DMA */
635 if(intrIn & USB_INTR_EP(0)) 752 if(intrIn & USB_INTR_EP(0))
636 EP0_handler(); 753 EP0_handler();
637 if(intrIn & USB_INTR_EP(1)) 754 if(intrIn & USB_INTR_EP(1))
638 EPIN_handler(1); 755 EPIN_complete(1);
639 if(intrIn & USB_INTR_EP(2)) 756 if(intrIn & USB_INTR_EP(2))
640 EPIN_handler(2); 757 EPIN_complete(2);
641 if(intrOut & USB_INTR_EP(1)) 758 if(intrOut & USB_INTR_EP(1))
642 EPOUT_handler(1); 759 EPOUT_handler(1);
643 if(intrOut & USB_INTR_EP(2)) 760 if(intrOut & USB_INTR_EP(2))
@@ -648,10 +765,12 @@ void OTG(void)
648 logf("USB suspend"); 765 logf("USB suspend");
649 if(intrUSB & USB_INTR_RESUME) 766 if(intrUSB & USB_INTR_RESUME)
650 logf("USB resume"); 767 logf("USB resume");
651 if(intrDMA & USB_INTR_DMA_BULKIN) 768#ifdef USE_USB_DMA
769 if(intrDMA & (1<<USB_INTR_DMA_BULKIN))
652 EPDMA_handler(USB_INTR_DMA_BULKIN); 770 EPDMA_handler(USB_INTR_DMA_BULKIN);
653 if(intrDMA & USB_INTR_DMA_BULKOUT) 771 if(intrDMA & (1<<USB_INTR_DMA_BULKOUT))
654 EPDMA_handler(USB_INTR_DMA_BULKOUT); 772 EPDMA_handler(USB_INTR_DMA_BULKOUT);
773#endif
655} 774}
656 775
657bool usb_drv_stalled(int endpoint, bool in) 776bool usb_drv_stalled(int endpoint, bool in)
@@ -790,6 +909,10 @@ void usb_drv_exit(void)
790{ 909{
791 logf("%s()", __func__); 910 logf("%s()", __func__);
792 911
912 select_endpoint(1);
913
914 logf("DMA X (%x %x %x %x)", REG_USB_ADDR(USB_INTR_DMA_BULKIN), REG_USB_COUNT(USB_INTR_DMA_BULKIN),REG_USB_CNTL(USB_INTR_DMA_BULKIN), REG_USB_INCSR);
915
793 REG_USB_FADDR = 0; 916 REG_USB_FADDR = 0;
794 REG_USB_INDEX = 0; 917 REG_USB_INDEX = 0;
795 918
@@ -798,9 +921,11 @@ void usb_drv_exit(void)
798 REG_USB_INTROUTE = 0; 921 REG_USB_INTROUTE = 0;
799 REG_USB_INTRUSBE = 0; 922 REG_USB_INTRUSBE = 0;
800 923
924#ifdef USE_USB_DMA
801 /* Disable DMA */ 925 /* Disable DMA */
802 REG_USB_CNTL(0) = 0; 926 REG_USB_CNTL(USB_INTR_DMA_BULKIN) = 0;
803 REG_USB_CNTL(1) = 0; 927 REG_USB_CNTL(USB_INTR_DMA_BULKOUT) = 0;
928#endif
804 929
805 /* Disconnect from USB */ 930 /* Disconnect from USB */
806 REG_USB_POWER &= ~USB_POWER_SOFTCONN; 931 REG_USB_POWER &= ~USB_POWER_SOFTCONN;
@@ -817,10 +942,8 @@ static void usb_drv_send_internal(struct usb_endpoint* ep, void* ptr, int length
817{ 942{
818 int flags = disable_irq_save(); 943 int flags = disable_irq_save();
819 944
820 if(ep->type == ep_control) 945 if (ep->type == ep_control) {
821 { 946 if ((ptr == NULL && length == 0) || !ep0_data_requested) {
822 if ((ptr == NULL && length == 0) || !ep0_data_requested)
823 {
824 restore_irq(flags); 947 restore_irq(flags);
825 return; 948 return;
826 } 949 }
@@ -831,36 +954,22 @@ static void usb_drv_send_internal(struct usb_endpoint* ep, void* ptr, int length
831 ep->sent = 0; 954 ep->sent = 0;
832 ep->length = length; 955 ep->length = length;
833 ep->busy = true; 956 ep->busy = true;
834 if(blocking) 957 if(blocking) {
835 {
836 ep->rc = -1; 958 ep->rc = -1;
837 ep->wait = true; 959 ep->wait = true;
960 } else {
961 ep->rc = 0;
838 } 962 }
839 else ep->rc = 0;
840 963
841 if(ep->type == ep_control) 964 if (ep->type == ep_control) {
842 {
843 EP0_send(); 965 EP0_send();
844 } 966 } else {
845 else 967 EPIN_send(EP_NUMBER2(ep));
846 {
847 if(ep->use_dma)
848 {
849 commit_discard_dcache_range(ptr, length);
850 REG_USB_ADDR(0) = PHYSADDR((unsigned long)ptr);
851 REG_USB_COUNT(0) = length;
852 REG_USB_CNTL(0) = (USB_CNTL_INTR_EN | USB_CNTL_MODE_1 |
853 USB_CNTL_DIR_IN | USB_CNTL_ENA |
854 USB_CNTL_EP(EP_NUMBER2(ep)) | USB_CNTL_BURST_16);
855 }
856 else
857 EPIN_handler(EP_NUMBER2(ep));
858 } 968 }
859 969
860 restore_irq(flags); 970 restore_irq(flags);
861 971
862 if(blocking) 972 if(blocking) {
863 {
864 semaphore_wait(&ep->complete, HZ); 973 semaphore_wait(&ep->complete, HZ);
865 ep->wait = false; 974 ep->wait = false;
866 } 975 }
@@ -918,23 +1027,12 @@ int usb_drv_recv(int endpoint, void* ptr, int length)
918 ep->received = 0; 1027 ep->received = 0;
919 ep->length = length; 1028 ep->length = length;
920 ep->busy = true; 1029 ep->busy = true;
921 if(ep->use_dma) 1030
922 { 1031 if (endpoint == EP_CONTROL) {
923 discard_dcache_range(ptr, length); 1032 ep0_data_supplied = false;
924 REG_USB_ADDR(1) = PHYSADDR((unsigned long)ptr); 1033 EP0_handler();
925 REG_USB_COUNT(1) = length; 1034 } else {
926 REG_USB_CNTL(1) = (USB_CNTL_INTR_EN | USB_CNTL_MODE_1 | 1035 EPOUT_handler(endpoint);
927 USB_CNTL_ENA | USB_CNTL_EP(endpoint) |
928 USB_CNTL_BURST_16);
929 }
930 else
931 {
932 if (endpoint == EP_CONTROL)
933 {
934 ep0_data_supplied = false;
935 EP0_handler();
936 }
937 else EPOUT_handler(endpoint);
938 } 1036 }
939 1037
940 restore_irq(flags); 1038 restore_irq(flags);
@@ -976,6 +1074,12 @@ void usb_drv_cancel_all_transfers(void)
976 1074
977 unsigned int i, flags = disable_irq_save(); 1075 unsigned int i, flags = disable_irq_save();
978 1076
1077#ifdef USE_USB_DMA
1078 /* Disable DMA */
1079 REG_USB_CNTL(USB_INTR_DMA_BULKIN) = 0;
1080 REG_USB_CNTL(USB_INTR_DMA_BULKOUT) = 0;
1081#endif
1082
979 for(i=0; i<TOTAL_EP(); i++) 1083 for(i=0; i<TOTAL_EP(); i++)
980 { 1084 {
981 if (endpoints[i].busy) 1085 if (endpoints[i].busy)
@@ -996,6 +1100,7 @@ void usb_drv_cancel_all_transfers(void)
996 select_endpoint(i/2); 1100 select_endpoint(i/2);
997 flushFIFO(&endpoints[i]); 1101 flushFIFO(&endpoints[i]);
998 } 1102 }
1103
999 restore_irq(flags); 1104 restore_irq(flags);
1000} 1105}
1001 1106