diff options
-rw-r--r-- | firmware/export/jz4760b.h | 12 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/system-target.h | 1 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/usb-jz4760.c | 383 | ||||
-rw-r--r-- | utils/hwstub/stub/jz4760b/jz4760b.h | 5 |
4 files changed, 262 insertions, 139 deletions
diff --git a/firmware/export/jz4760b.h b/firmware/export/jz4760b.h index e61689105c..589f67800a 100644 --- a/firmware/export/jz4760b.h +++ b/firmware/export/jz4760b.h | |||
@@ -6992,8 +6992,12 @@ do { \ | |||
6992 | #define USB_OUTCSRH (USB_BASE + 0x17) /* EP1-15 OUT CSR MSB 8-bit */ | 6992 | #define USB_OUTCSRH (USB_BASE + 0x17) /* EP1-15 OUT CSR MSB 8-bit */ |
6993 | #define USB_OUTCOUNT (USB_BASE + 0x18) /* EP1-15 OUT FIFO count 16-bit */ | 6993 | #define USB_OUTCOUNT (USB_BASE + 0x18) /* EP1-15 OUT FIFO count 16-bit */ |
6994 | 6994 | ||
6995 | #define USB_CONFIGDATA (USB_BASE + 0x1f) /* Fixed config */ | ||
6996 | |||
6995 | #define USB_FIFO_EP(n) (USB_BASE + (n)*4 + 0x20) | 6997 | #define USB_FIFO_EP(n) (USB_BASE + (n)*4 + 0x20) |
6996 | 6998 | ||
6999 | #define USB_HWVERS (USB_BASE + 0x6c) | ||
7000 | |||
6997 | #define USB_EPINFO (USB_BASE + 0x78) /* Endpoint information */ | 7001 | #define USB_EPINFO (USB_BASE + 0x78) /* Endpoint information */ |
6998 | #define USB_RAMINFO (USB_BASE + 0x79) /* RAM information */ | 7002 | #define USB_RAMINFO (USB_BASE + 0x79) /* RAM information */ |
6999 | 7003 | ||
@@ -7034,6 +7038,7 @@ do { \ | |||
7034 | #define USB_INCSRH_DMAREQENAB 0x10 | 7038 | #define USB_INCSRH_DMAREQENAB 0x10 |
7035 | #define USB_INCSRH_FRCDATATOG 0x08 | 7039 | #define USB_INCSRH_FRCDATATOG 0x08 |
7036 | #define USB_INCSRH_DMAREQMODE 0x04 | 7040 | #define USB_INCSRH_DMAREQMODE 0x04 |
7041 | #define USB_INCSR_INCOMPTX 0x80 | ||
7037 | #define USB_INCSR_CDT 0x40 | 7042 | #define USB_INCSR_CDT 0x40 |
7038 | #define USB_INCSR_SENTSTALL 0x20 | 7043 | #define USB_INCSR_SENTSTALL 0x20 |
7039 | #define USB_INCSR_SENDSTALL 0x10 | 7044 | #define USB_INCSR_SENDSTALL 0x10 |
@@ -7077,6 +7082,10 @@ do { \ | |||
7077 | #define USB_CNTL_BURST_8 (2 << 9) | 7082 | #define USB_CNTL_BURST_8 (2 << 9) |
7078 | #define USB_CNTL_BURST_16 (3 << 9) | 7083 | #define USB_CNTL_BURST_16 (3 << 9) |
7079 | 7084 | ||
7085 | /* USB HW revision */ | ||
7086 | #define USB_HWVERS_MAJOR(x) ((x >> 10) & 0x1f) | ||
7087 | #define USB_HWVERS_MINOR(x) (x & 0x3ff) | ||
7088 | |||
7080 | /* DMA interrupt bits */ | 7089 | /* DMA interrupt bits */ |
7081 | #define USB_INTR_DMA_BULKIN 1 | 7090 | #define USB_INTR_DMA_BULKIN 1 |
7082 | #define USB_INTR_DMA_BULKOUT 2 | 7091 | #define USB_INTR_DMA_BULKOUT 2 |
@@ -7104,6 +7113,7 @@ do { \ | |||
7104 | #define REG_USB_OUTCSRH REG8(USB_OUTCSRH) | 7113 | #define REG_USB_OUTCSRH REG8(USB_OUTCSRH) |
7105 | #define REG_USB_OUTCOUNT REG16(USB_OUTCOUNT) | 7114 | #define REG_USB_OUTCOUNT REG16(USB_OUTCOUNT) |
7106 | 7115 | ||
7116 | #define REG_USB_CONFIGDATA REG8(USB_CONFIGDATA) | ||
7107 | #define REG_USB_FIFO_EP(n) REG32(USB_FIFO_EP(n)) | 7117 | #define REG_USB_FIFO_EP(n) REG32(USB_FIFO_EP(n)) |
7108 | 7118 | ||
7109 | #define REG_USB_INTR REG8(USB_INTR) | 7119 | #define REG_USB_INTR REG8(USB_INTR) |
@@ -7111,6 +7121,8 @@ do { \ | |||
7111 | #define REG_USB_ADDR(n) REG32(USB_ADDR(n)) | 7121 | #define REG_USB_ADDR(n) REG32(USB_ADDR(n)) |
7112 | #define REG_USB_COUNT(n) REG32(USB_COUNT(n)) | 7122 | #define REG_USB_COUNT(n) REG32(USB_COUNT(n)) |
7113 | 7123 | ||
7124 | #define REG_USB_HWVERS REG16(USB_HWVERS) | ||
7125 | |||
7114 | #define REG_USB_EPINFO REG8(USB_EPINFO) | 7126 | #define REG_USB_EPINFO REG8(USB_EPINFO) |
7115 | #define REG_USB_RAMINFO REG8(USB_RAMINFO) | 7127 | #define REG_USB_RAMINFO REG8(USB_RAMINFO) |
7116 | 7128 | ||
diff --git a/firmware/target/mips/ingenic_jz47xx/system-target.h b/firmware/target/mips/ingenic_jz47xx/system-target.h index 30c1668bf7..9dc1a5c8c8 100644 --- a/firmware/target/mips/ingenic_jz47xx/system-target.h +++ b/firmware/target/mips/ingenic_jz47xx/system-target.h | |||
@@ -83,6 +83,7 @@ static inline void restore_interrupt(int status) | |||
83 | #define UNCACHED_ADDRESS(addr) ((unsigned int)(addr) | 0xA0000000) | 83 | #define UNCACHED_ADDRESS(addr) ((unsigned int)(addr) | 0xA0000000) |
84 | #define UNCACHED_ADDR(x) UNCACHED_ADDRESS((x)) | 84 | #define UNCACHED_ADDR(x) UNCACHED_ADDRESS((x)) |
85 | #define PHYSADDR(x) ((x) & 0x1fffffff) | 85 | #define PHYSADDR(x) ((x) & 0x1fffffff) |
86 | #define VIRTADDR(x) ((x) | 0xA0000000) | ||
86 | 87 | ||
87 | void system_enable_irq(unsigned int irq); | 88 | void system_enable_irq(unsigned int irq); |
88 | void udelay(unsigned int usec); | 89 | void udelay(unsigned int usec); |
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 | |||
46 | enum ep_type | 56 | enum ep_type |
47 | { | 57 | { |
48 | ep_control, | 58 | ep_control, |
@@ -53,6 +63,16 @@ enum ep_type | |||
53 | 63 | ||
54 | struct usb_endpoint | 64 | struct 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 | ||
83 | static union | 93 | static union |
@@ -91,12 +101,12 @@ static volatile bool ep0_data_requested = false; | |||
91 | 101 | ||
92 | static struct usb_endpoint endpoints[] = | 102 | static 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 | ||
102 | static inline void select_endpoint(int ep) | 112 | static 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 | ||
332 | static void EPIN_handler(unsigned int endpoint) | 342 | /* Does new work */ |
343 | static 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) | 439 | static 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 | ||
433 | static void EPDMA_handler(int number) | 550 | static 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 | ||
487 | static void setup_endpoint(struct usb_endpoint *ep) | 599 | static 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 | ||
657 | bool usb_drv_stalled(int endpoint, bool in) | 776 | bool 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 | ||
diff --git a/utils/hwstub/stub/jz4760b/jz4760b.h b/utils/hwstub/stub/jz4760b/jz4760b.h index 97ef74a56c..d07a039f70 100644 --- a/utils/hwstub/stub/jz4760b/jz4760b.h +++ b/utils/hwstub/stub/jz4760b/jz4760b.h | |||
@@ -6966,6 +6966,8 @@ do { \ | |||
6966 | 6966 | ||
6967 | #define USB_FIFO_EP(n) (USB_BASE + (n)*4 + 0x20) | 6967 | #define USB_FIFO_EP(n) (USB_BASE + (n)*4 + 0x20) |
6968 | 6968 | ||
6969 | #define USB_HWVERS (USB_BASE + 0x6c) | ||
6970 | |||
6969 | #define USB_EPINFO (USB_BASE + 0x78) /* Endpoint information */ | 6971 | #define USB_EPINFO (USB_BASE + 0x78) /* Endpoint information */ |
6970 | #define USB_RAMINFO (USB_BASE + 0x79) /* RAM information */ | 6972 | #define USB_RAMINFO (USB_BASE + 0x79) /* RAM information */ |
6971 | 6973 | ||
@@ -7006,6 +7008,7 @@ do { \ | |||
7006 | #define USB_INCSRH_DMAREQENAB 0x10 | 7008 | #define USB_INCSRH_DMAREQENAB 0x10 |
7007 | #define USB_INCSRH_FRCDATATOG 0x08 | 7009 | #define USB_INCSRH_FRCDATATOG 0x08 |
7008 | #define USB_INCSRH_DMAREQMODE 0x04 | 7010 | #define USB_INCSRH_DMAREQMODE 0x04 |
7011 | #define USB_INCSR_INCOMPTX 0x80 | ||
7009 | #define USB_INCSR_CDT 0x40 | 7012 | #define USB_INCSR_CDT 0x40 |
7010 | #define USB_INCSR_SENTSTALL 0x20 | 7013 | #define USB_INCSR_SENTSTALL 0x20 |
7011 | #define USB_INCSR_SENDSTALL 0x10 | 7014 | #define USB_INCSR_SENDSTALL 0x10 |
@@ -7083,6 +7086,8 @@ do { \ | |||
7083 | #define REG_USB_ADDR(n) REG32(USB_ADDR(n)) | 7086 | #define REG_USB_ADDR(n) REG32(USB_ADDR(n)) |
7084 | #define REG_USB_COUNT(n) REG32(USB_COUNT(n)) | 7087 | #define REG_USB_COUNT(n) REG32(USB_COUNT(n)) |
7085 | 7088 | ||
7089 | #define REG_USB_HWVERS REG16(USB_HWVERS) | ||
7090 | |||
7086 | #define REG_USB_EPINFO REG8(USB_EPINFO) | 7091 | #define REG_USB_EPINFO REG8(USB_EPINFO) |
7087 | #define REG_USB_RAMINFO REG8(USB_RAMINFO) | 7092 | #define REG_USB_RAMINFO REG8(USB_RAMINFO) |
7088 | 7093 | ||