summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobias Diedrich <ranma+coreboot@tdiedrich.de>2010-06-22 05:46:54 +0000
committerTobias Diedrich <ranma+coreboot@tdiedrich.de>2010-06-22 05:46:54 +0000
commit072c0a15cbf8a9114de681406a6ba1bdb55a27a3 (patch)
treeb3d3504be52be53d18e2d7abc6ca326acab2c49b
parent831707d99191cfd7ed7d72725821bc2d9844baed (diff)
downloadrockbox-072c0a15cbf8a9114de681406a6ba1bdb55a27a3.tar.gz
rockbox-072c0a15cbf8a9114de681406a6ba1bdb55a27a3.zip
usb_storage seems to be working now, enable USE_ROCKBOX_USB on C200v2, other AMSv1 untested.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27039 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/export/config/sansac200v2.h5
-rw-r--r--firmware/target/arm/as3525/usb-drv-as3525.c127
-rw-r--r--firmware/target/arm/as3525/usb-drv-as3525.h1
-rw-r--r--firmware/usbstack/usb_storage.c18
4 files changed, 121 insertions, 30 deletions
diff --git a/firmware/export/config/sansac200v2.h b/firmware/export/config/sansac200v2.h
index 4bb175ad4d..99cd0d2f2f 100644
--- a/firmware/export/config/sansac200v2.h
+++ b/firmware/export/config/sansac200v2.h
@@ -173,8 +173,9 @@
173 173
174/* enable these for the experimental usb stack */ 174/* enable these for the experimental usb stack */
175#define HAVE_USBSTACK 175#define HAVE_USBSTACK
176#define USB_HANDLED_BY_OF 176//#define USB_HANDLED_BY_OF
177//#define USE_ROCKBOX_USB 177#define USE_ROCKBOX_USB
178//#define USB_ENABLE_SERIAL
178#define USB_VENDOR_ID 0x0781 179#define USB_VENDOR_ID 0x0781
179#define USB_PRODUCT_ID 0x7452 180#define USB_PRODUCT_ID 0x7452
180 181
diff --git a/firmware/target/arm/as3525/usb-drv-as3525.c b/firmware/target/arm/as3525/usb-drv-as3525.c
index d41acc7f81..42e13d7c86 100644
--- a/firmware/target/arm/as3525/usb-drv-as3525.c
+++ b/firmware/target/arm/as3525/usb-drv-as3525.c
@@ -77,6 +77,8 @@ void usb_attach(void)
77 usb_enable(true); 77 usb_enable(true);
78} 78}
79 79
80static void usb_tick(void);
81
80static void usb_phy_on(void) 82static void usb_phy_on(void)
81{ 83{
82 /* PHY clock */ 84 /* PHY clock */
@@ -174,10 +176,20 @@ static void reset_endpoints(int init)
174 int mps = i == 0 ? 64 : (usb_drv_port_speed() ? 512 : 64); 176 int mps = i == 0 ? 64 : (usb_drv_port_speed() ? 512 : 64);
175 177
176 if (init) { 178 if (init) {
179 if (endpoints[i][0].state & EP_STATE_BUSY) {
180 if (endpoints[i][0].state & EP_STATE_ASYNC) {
181 endpoints[i][0].rc = -1;
182 wakeup_signal(&endpoints[i][0].complete);
183 } else {
184 usb_core_transfer_complete(i, USB_DIR_IN, -1, 0);
185 }
186 }
177 endpoints[i][0].state = 0; 187 endpoints[i][0].state = 0;
178 wakeup_init(&endpoints[i][0].complete); 188 wakeup_init(&endpoints[i][0].complete);
179 189
180 if (i != 2) { /* Skip the OUT EP0 alias */ 190 if (i != 2) { /* Skip the OUT EP0 alias */
191 if (endpoints[i][1].state & EP_STATE_BUSY)
192 usb_core_transfer_complete(i, USB_DIR_OUT, -1, 0);
181 endpoints[i][1].state = 0; 193 endpoints[i][1].state = 0;
182 wakeup_init(&endpoints[i][1].complete); 194 wakeup_init(&endpoints[i][1].complete);
183 USB_OEP_SUP_PTR(i) = 0; 195 USB_OEP_SUP_PTR(i) = 0;
@@ -189,15 +201,15 @@ static void reset_endpoints(int init)
189 USB_IEP_MPS (i) = mps; /* in bytes */ 201 USB_IEP_MPS (i) = mps; /* in bytes */
190 /* We don't care about the 'IN token received' event */ 202 /* We don't care about the 'IN token received' event */
191 USB_IEP_STS_MASK(i) = USB_EP_STAT_IN; /* OF: 0x840 */ 203 USB_IEP_STS_MASK(i) = USB_EP_STAT_IN; /* OF: 0x840 */
192 USB_IEP_TXFSIZE (i) = mps/2; /* in dwords => mps*2 bytes */ 204 USB_IEP_TXFSIZE (i) = mps/4; /* in dwords => mps*2 bytes */
193 USB_IEP_STS (i) = 0xffffffff; /* clear status */ 205 USB_IEP_STS (i) = 0xffffffff; /* clear status */
194 USB_IEP_DESC_PTR(i) = 0; 206 USB_IEP_DESC_PTR(i) = 0;
195 207
196 if (i != 2) { /* Skip the OUT EP0 alias */ 208 if (i != 2) { /* Skip the OUT EP0 alias */
197 dma_desc_init(i, 1); 209 dma_desc_init(i, 1);
198 USB_OEP_CTRL (i) = USB_EP_CTRL_FLUSH|USB_EP_CTRL_SNAK; 210 USB_OEP_CTRL (i) = USB_EP_CTRL_FLUSH|USB_EP_CTRL_SNAK;
199 USB_OEP_MPS (i) = (mps/2 << 23) | mps; 211 USB_OEP_MPS (i) = (mps/4 << 16) | mps;
200 USB_OEP_STS_MASK(i) = 0x0000; /* OF: 0x1800 */ 212 USB_OEP_STS_MASK(i) = USB_EP_STAT_BNA; /* OF: 0x1800 */
201 USB_OEP_RXFR (i) = 0; /* Always 0 in OF trace? */ 213 USB_OEP_RXFR (i) = 0; /* Always 0 in OF trace? */
202 USB_OEP_STS (i) = 0xffffffff; /* clear status */ 214 USB_OEP_STS (i) = 0xffffffff; /* clear status */
203 USB_OEP_DESC_PTR(i) = 0; 215 USB_OEP_DESC_PTR(i) = 0;
@@ -281,10 +293,12 @@ void usb_drv_init(void)
281 | USB_GPIO_HS_INTR 293 | USB_GPIO_HS_INTR
282 | USB_GPIO_CLK_SEL10; /* 0x06180000; */ 294 | USB_GPIO_CLK_SEL10; /* 0x06180000; */
283 295
296 tick_add_task(usb_tick);
284} 297}
285 298
286void usb_drv_exit(void) 299void usb_drv_exit(void)
287{ 300{
301 tick_remove_task(usb_tick);
288 USB_DEV_CTRL |= (1<<10); /* soft disconnect */ 302 USB_DEV_CTRL |= (1<<10); /* soft disconnect */
289 /* 303 /*
290 * mask all interrupts _before_ writing to VIC_INT_EN_CLEAR, 304 * mask all interrupts _before_ writing to VIC_INT_EN_CLEAR,
@@ -383,16 +397,20 @@ int usb_drv_recv(int ep, void *ptr, int len)
383 ep &= 0x7f; 397 ep &= 0x7f;
384 logf("usb_drv_recv(%d,%x,%d)\n", ep, (int)ptr, len); 398 logf("usb_drv_recv(%d,%x,%d)\n", ep, (int)ptr, len);
385 399
400 if (len > USB_DMA_DESC_RXTX_BYTES)
401 panicf("usb_recv: len=%d > %d", len, USB_DMA_DESC_RXTX_BYTES);
402
386 if ((int)ptr & 31) { 403 if ((int)ptr & 31) {
387 logf("addr %08x not aligned!\n", (int)ptr); 404 logf("addr %08x not aligned!\n", (int)ptr);
388 } 405 }
389 406
390 endpoints[ep][1].state |= EP_STATE_BUSY; 407 endpoints[ep][1].state |= EP_STATE_BUSY;
391 endpoints[ep][1].len = len; 408 endpoints[ep][1].len = len;
392 endpoints[ep][1].rc = -1; 409 endpoints[ep][1].rc = -1;
410 endpoints[ep][1].buf = ptr;
393 411
394 /* remove data buffer from cache */ 412 /* remove data buffer from cache */
395 dump_dcache_range(ptr, len); 413 invalidate_dcache();
396 414
397 /* DMA setup */ 415 /* DMA setup */
398 uc_desc->status = USB_DMA_DESC_BS_HST_RDY | 416 uc_desc->status = USB_DMA_DESC_BS_HST_RDY |
@@ -406,7 +424,27 @@ int usb_drv_recv(int ep, void *ptr, int len)
406 } 424 }
407 USB_OEP_DESC_PTR(ep) = (int)&dmadescs[ep][1]; 425 USB_OEP_DESC_PTR(ep) = (int)&dmadescs[ep][1];
408 USB_OEP_STS(ep) = USB_EP_STAT_OUT_RCVD; /* clear status */ 426 USB_OEP_STS(ep) = USB_EP_STAT_OUT_RCVD; /* clear status */
409 USB_OEP_CTRL(ep) |= USB_EP_CTRL_CNAK; 427
428 /* Make sure receive DMA is on */
429 if (!(USB_DEV_CTRL & USB_DEV_CTRL_RDE)){
430 logf("enabling receive DMA\n");
431 USB_DEV_CTRL |= USB_DEV_CTRL_RDE;
432 if (!(USB_DEV_CTRL & USB_DEV_CTRL_RDE))
433 logf("failed to enable!\n");
434 }
435
436 USB_OEP_CTRL(ep) |= USB_EP_CTRL_CNAK; /* Go! */
437
438 if (USB_OEP_CTRL(ep) & USB_EP_CTRL_NAK) {
439 int i = 0;
440 logf("CNAK fail? CTRL=%x\n", (int)USB_OEP_CTRL(ep));
441 while (USB_OEP_CTRL(ep) & USB_EP_CTRL_NAK) {
442 USB_OEP_CTRL(ep) |= USB_EP_CTRL_CNAK; /* Go! */
443 i++;
444 }
445 if (i>2)
446 panicf("CNAK needed %d retries\n", i);
447 }
410 448
411 return 0; 449 return 0;
412} 450}
@@ -443,7 +481,7 @@ void ep_send(int ep, void *ptr, int len)
443 endpoints[ep][0].rc = -1; 481 endpoints[ep][0].rc = -1;
444 482
445 /* Make sure data is committed to memory */ 483 /* Make sure data is committed to memory */
446 clean_dcache_range(ptr, len); 484 clean_dcache();
447 485
448 logf("xx%s\n", make_hex(ptr, len)); 486 logf("xx%s\n", make_hex(ptr, len));
449 487
@@ -493,8 +531,9 @@ static void handle_in_ep(int ep)
493 USB_IEP_STS(ep) = ep_sts; /* ack */ 531 USB_IEP_STS(ep) = ep_sts; /* ack */
494 532
495 if (ep_sts & USB_EP_STAT_BNA) { /* Buffer was not set up */ 533 if (ep_sts & USB_EP_STAT_BNA) { /* Buffer was not set up */
496 logf("ep%d IN, status %x (BNA)\n", ep, ep_sts); 534 int ctrl = USB_IEP_CTRL(ep);
497 panicf("ep%d IN 0x%x (BNA)", ep, ep_sts); 535 logf("ep%d IN, status %x ctrl %x (BNA)\n", ep, ep_sts, ctrl);
536 panicf("ep%d IN 0x%x 0x%x (BNA)", ep, ep_sts, ctrl);
498 } 537 }
499 538
500 if (ep_sts & USB_EP_STAT_TDC) { 539 if (ep_sts & USB_EP_STAT_TDC) {
@@ -517,17 +556,12 @@ static void handle_in_ep(int ep)
517 logf("ep%d IN, hwstat %lx, epstat %x\n", ep, USB_IEP_STS(ep), endpoints[ep][0].state); 556 logf("ep%d IN, hwstat %lx, epstat %x\n", ep, USB_IEP_STS(ep), endpoints[ep][0].state);
518 panicf("ep%d IN 0x%x", ep, ep_sts); 557 panicf("ep%d IN 0x%x", ep, ep_sts);
519 } 558 }
520
521 /* HW automatically disables RDE, re-enable it */
522 /* But this an IN ep, I wonder... */
523 USB_DEV_CTRL |= USB_DEV_CTRL_RDE;
524} 559}
525 560
526static void handle_out_ep(int ep) 561static void handle_out_ep(int ep)
527{ 562{
528 struct usb_ctrlrequest *req = (void*)AS3525_UNCACHED_ADDR(&setup_desc->data1); 563 struct usb_ctrlrequest *req = (void*)AS3525_UNCACHED_ADDR(&setup_desc->data1);
529 int ep_sts = USB_OEP_STS(ep) & ~USB_OEP_STS_MASK(ep); 564 int ep_sts = USB_OEP_STS(ep) & ~USB_OEP_STS_MASK(ep);
530 struct usb_dev_dma_desc *uc_desc = endpoints[ep][1].uc_desc;
531 565
532 if (ep > 3) 566 if (ep > 3)
533 panicf("out_ep > 3!?"); 567 panicf("out_ep > 3!?");
@@ -535,11 +569,14 @@ static void handle_out_ep(int ep)
535 USB_OEP_STS(ep) = ep_sts; /* ACK */ 569 USB_OEP_STS(ep) = ep_sts; /* ACK */
536 570
537 if (ep_sts & USB_EP_STAT_BNA) { /* Buffer was not set up */ 571 if (ep_sts & USB_EP_STAT_BNA) { /* Buffer was not set up */
538 logf("ep%d OUT, status %x (BNA)\n", ep, ep_sts); 572 int ctrl = USB_OEP_CTRL(ep);
539 panicf("ep%d OUT 0x%x (BNA)", ep, ep_sts); 573 logf("ep%d OUT, status %x ctrl %x (BNA)\n", ep, ep_sts, ctrl);
574 panicf("ep%d OUT 0x%x 0x%x (BNA)", ep, ep_sts, ctrl);
575 ep_sts &= ~USB_EP_STAT_BNA;
540 } 576 }
541 577
542 if (ep_sts & USB_EP_STAT_OUT_RCVD) { 578 if (ep_sts & USB_EP_STAT_OUT_RCVD) {
579 struct usb_dev_dma_desc *uc_desc = endpoints[ep][1].uc_desc;
543 int dma_sts = uc_desc->status; 580 int dma_sts = uc_desc->status;
544 int dma_len = dma_sts & 0xffff; 581 int dma_len = dma_sts & 0xffff;
545 582
@@ -553,7 +590,7 @@ static void handle_out_ep(int ep)
553 dump_dcache_range(uc_desc->data_ptr, dma_len); 590 dump_dcache_range(uc_desc->data_ptr, dma_len);
554 } else{ 591 } else{
555 logf("EP%d OUT token, st:%08x frm:%x (no data)\n", ep, 592 logf("EP%d OUT token, st:%08x frm:%x (no data)\n", ep,
556 dma_mst, dma_frm); 593 dma_sts & 0xf8000000, (dma_sts >> 16) & 0x7ff);
557 } 594 }
558 595
559 if (endpoints[ep][1].state & EP_STATE_BUSY) { 596 if (endpoints[ep][1].state & EP_STATE_BUSY) {
@@ -565,7 +602,6 @@ static void handle_out_ep(int ep)
565 } 602 }
566 603
567 USB_OEP_CTRL(ep) |= USB_EP_CTRL_SNAK; /* make sure NAK is set */ 604 USB_OEP_CTRL(ep) |= USB_EP_CTRL_SNAK; /* make sure NAK is set */
568
569 ep_sts &= ~USB_EP_STAT_OUT_RCVD; 605 ep_sts &= ~USB_EP_STAT_OUT_RCVD;
570 } 606 }
571 607
@@ -592,9 +628,58 @@ static void handle_out_ep(int ep)
592 panicf("ep%d OUT 0x%x", ep, ep_sts); 628 panicf("ep%d OUT 0x%x", ep, ep_sts);
593 } 629 }
594 630
631#if 0
595 /* HW automatically disables RDE, re-enable it */ 632 /* HW automatically disables RDE, re-enable it */
596 /* THEORY: Because we only set up one DMA buffer... */ 633 /* THEORY: Because we only set up one DMA buffer... */
597 USB_DEV_CTRL |= USB_DEV_CTRL_RDE; 634 USB_DEV_CTRL |= USB_DEV_CTRL_RDE;
635#endif
636
637 if (!(USB_DEV_CTRL & USB_DEV_CTRL_RDE)){
638 logf("receive DMA is disabled!\n");
639 //USB_DEV_CTRL |= USB_DEV_CTRL_RDE;
640 }
641}
642
643/*
644 * This is a simplified version of the timer based RDE enable from
645 * the Linux amd5536udc.c driver.
646 * We need this because of the following hw issue:
647 * The usb_storage buffer is 63KB, but Linux sends 120KB.
648 * We get the first part, but upon re-enabling receive dma we
649 * get a 'buffer not available' error from the hardware, since
650 * we haven't gotten the next usb_drv_recv() from the stack yet.
651 * It seems the NAK bit is ignored here and the HW tries to dma
652 * the incoming data anyway.
653 * In theory I think the BNA error should be recoverable, but
654 * I haven't figured out how to do that yet and this approach seems
655 * to work for now.
656 */
657static void usb_tick(void)
658{
659 static int rde_timer = 0;
660 static int rde_fails = 0;
661
662 if (USB_DEV_CTRL & USB_DEV_CTRL_RDE)
663 return;
664
665 if (!(USB_DEV_STS & USB_DEV_STS_RXF_EMPTY)) {
666 if (rde_timer == 0)
667 logf("usb_tick: fifo got filled\n");
668 rde_timer++;
669 }
670
671 if (rde_timer > 2) {
672 logf("usb_tick: re-enabling RDE\n");
673 USB_DEV_CTRL |= USB_DEV_CTRL_RDE;
674 rde_timer = 0;
675 if (USB_DEV_CTRL & USB_DEV_CTRL_RDE) {
676 rde_fails = 0;
677 } else {
678 rde_fails++;
679 if (rde_fails > 3)
680 panicf("usb_tick: failed to set RDE");
681 }
682 }
598} 683}
599 684
600/* interrupt service routine */ 685/* interrupt service routine */
@@ -696,12 +781,6 @@ void INT_USB(void)
696 if (intr) 781 if (intr)
697 panicf("usb devirq 0x%x", intr); 782 panicf("usb devirq 0x%x", intr);
698 } 783 }
699
700 if (!(USB_DEV_CTRL & USB_DEV_CTRL_RDE)){
701 logf("re-enabling receive DMA\n");
702 USB_DEV_CTRL |= USB_DEV_CTRL_RDE;
703 }
704
705} 784}
706 785
707/* (not essential? , not implemented in usb-tcc.c) */ 786/* (not essential? , not implemented in usb-tcc.c) */
diff --git a/firmware/target/arm/as3525/usb-drv-as3525.h b/firmware/target/arm/as3525/usb-drv-as3525.h
index 3a434170d7..d4ec8067ac 100644
--- a/firmware/target/arm/as3525/usb-drv-as3525.h
+++ b/firmware/target/arm/as3525/usb-drv-as3525.h
@@ -237,6 +237,7 @@ typedef struct {
237#define USB_DEV_INTR_SOF 0x00000020 /* SOF seen on bus */ 237#define USB_DEV_INTR_SOF 0x00000020 /* SOF seen on bus */
238#define USB_DEV_INTR_ENUM_DONE 0x00000040 /* usb speed enum done */ 238#define USB_DEV_INTR_ENUM_DONE 0x00000040 /* usb speed enum done */
239#define USB_DEV_INTR_SVC 0x00000080 /* USB_DEV_STS changed */ 239#define USB_DEV_INTR_SVC 0x00000080 /* USB_DEV_STS changed */
240#define USB_DEV_INTR_MYSTERY 0x00000200 /* Unknown, maybe Host Error */
240 241
241/* EP Control Register Fields */ 242/* EP Control Register Fields */
242#define USB_EP_CTRL_STALL 0x00000001 243#define USB_EP_CTRL_STALL 0x00000001
diff --git a/firmware/usbstack/usb_storage.c b/firmware/usbstack/usb_storage.c
index 1d47772362..fa723c07b0 100644
--- a/firmware/usbstack/usb_storage.c
+++ b/firmware/usbstack/usb_storage.c
@@ -59,8 +59,13 @@
59#ifdef USB_READ_BUFFER_SIZE 59#ifdef USB_READ_BUFFER_SIZE
60#define READ_BUFFER_SIZE USB_READ_BUFFER_SIZE 60#define READ_BUFFER_SIZE USB_READ_BUFFER_SIZE
61#else 61#else
62#if CONFIG_CPU == AS3525
63/* We'd need to implement multidescriptor dma for sizes >65535 */
64#define READ_BUFFER_SIZE (1024*63)
65#else
62#define READ_BUFFER_SIZE (1024*64) 66#define READ_BUFFER_SIZE (1024*64)
63#endif 67#endif /* CONFIG_CPU == AS3525 */
68#endif /* USB_READ_BUFFER_SIZE */
64 69
65#define MAX_CBW_SIZE 1024 70#define MAX_CBW_SIZE 1024
66 71
@@ -68,11 +73,16 @@
68#define WRITE_BUFFER_SIZE USB_WRITE_BUFFER_SIZE 73#define WRITE_BUFFER_SIZE USB_WRITE_BUFFER_SIZE
69#else 74#else
70#if (CONFIG_STORAGE & STORAGE_SD) 75#if (CONFIG_STORAGE & STORAGE_SD)
76#if CONFIG_CPU == AS3525
77/* We'd need to implement multidescriptor dma for sizes >65535 */
78#define WRITE_BUFFER_SIZE (1024*63)
79#else
71#define WRITE_BUFFER_SIZE (1024*64) 80#define WRITE_BUFFER_SIZE (1024*64)
81#endif /* CONFIG_CPU == AS3525 */
72#else 82#else
73#define WRITE_BUFFER_SIZE (1024*24) 83#define WRITE_BUFFER_SIZE (1024*24)
74#endif 84#endif /* (CONFIG_STORAGE & STORAGE_SD) */
75#endif 85#endif /* USB_WRITE_BUFFER_SIZE */
76 86
77#define ALLOCATE_BUFFER_SIZE (2*MAX(READ_BUFFER_SIZE,WRITE_BUFFER_SIZE)) 87#define ALLOCATE_BUFFER_SIZE (2*MAX(READ_BUFFER_SIZE,WRITE_BUFFER_SIZE))
78 88
@@ -466,7 +476,7 @@ void usb_storage_init_connection(void)
466 unsigned char * audio_buffer; 476 unsigned char * audio_buffer;
467 477
468 audio_buffer = audio_get_buffer(false,&bufsize); 478 audio_buffer = audio_get_buffer(false,&bufsize);
469#ifdef UNCACHED_ADDR 479#if defined(UNCACHED_ADDR) && CONFIG_CPU != AS3525
470 cbw_buffer = (void *)UNCACHED_ADDR((unsigned int)(audio_buffer+31) & 0xffffffe0); 480 cbw_buffer = (void *)UNCACHED_ADDR((unsigned int)(audio_buffer+31) & 0xffffffe0);
471#else 481#else
472 cbw_buffer = (void *)((unsigned int)(audio_buffer+31) & 0xffffffe0); 482 cbw_buffer = (void *)((unsigned int)(audio_buffer+31) & 0xffffffe0);