summaryrefslogtreecommitdiff
path: root/firmware/target
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target')
-rw-r--r--firmware/target/arm/as3525/usb-drv-as3525v2.c119
1 files changed, 74 insertions, 45 deletions
diff --git a/firmware/target/arm/as3525/usb-drv-as3525v2.c b/firmware/target/arm/as3525/usb-drv-as3525v2.c
index 36791e8dc9..24487c0981 100644
--- a/firmware/target/arm/as3525/usb-drv-as3525v2.c
+++ b/firmware/target/arm/as3525/usb-drv-as3525v2.c
@@ -43,17 +43,30 @@ static int __out_ep_list_ep0[NUM_OUT_EP + 1] = {0, OUT_EP_LIST};
43 43
44/* iterate through each in/out ep except EP0 44/* iterate through each in/out ep except EP0
45 * 'counter' is the counter, 'ep' is the actual value */ 45 * 'counter' is the counter, 'ep' is the actual value */
46#define FOR_EACH_EP(list, size, counter, ep) \
47 for(counter = 0, ep = (list)[0]; \
48 counter < (size); \
49 counter++, ep = (list)[counter])
50
51#define FOR_EACH_IN_EP_EX(include_ep0, counter, ep) \
52 FOR_EACH_EP(include_ep0 ? __in_ep_list_ep0 : __in_ep_list, \
53 include_ep0 ? NUM_IN_EP : NUM_IN_EP + 1, counter, ep)
54
55#define FOR_EACH_OUT_EP_EX(include_ep0, counter, ep) \
56 FOR_EACH_EP(include_ep0 ? __out_ep_list_ep0 : __out_ep_list, \
57 include_ep0 ? NUM_OUT_EP : NUM_OUT_EP + 1, counter, ep)
58
46#define FOR_EACH_IN_EP(counter, ep) \ 59#define FOR_EACH_IN_EP(counter, ep) \
47 for(counter = 0, ep = __in_ep_list[0]; counter < NUM_IN_EP; counter++, ep = __in_ep_list[counter]) 60 FOR_EACH_IN_EP_EX(false, counter, ep)
48 61
49#define FOR_EACH_IN_EP_AND_EP0(counter, ep) \ 62#define FOR_EACH_IN_EP_AND_EP0(counter, ep) \
50 for(counter = 0, ep = __in_ep_list_ep0[0]; counter <= NUM_IN_EP; counter++, ep = __in_ep_list_ep0[counter]) 63 FOR_EACH_IN_EP_EX(true, counter, ep)
51 64
52#define FOR_EACH_OUT_EP(counter, ep) \ 65#define FOR_EACH_OUT_EP(counter, ep) \
53 for(counter = 0, ep = __out_ep_list[0]; counter < NUM_OUT_EP; counter++, ep = __out_ep_list[counter]) 66 FOR_EACH_OUT_EP_EX(false, counter, ep)
54 67
55#define FOR_EACH_OUT_EP_AND_EP0(counter, ep) \ 68#define FOR_EACH_OUT_EP_AND_EP0(counter, ep) \
56 for(counter = 0, ep = __out_ep_list_ep0[0]; counter <= NUM_OUT_EP; counter++, ep = __out_ep_list_ep0[counter]) 69 FOR_EACH_OUT_EP_EX(true, counter, ep)
57 70
58struct usb_endpoint 71struct usb_endpoint
59{ 72{
@@ -222,6 +235,31 @@ static void reset_endpoints(void)
222 prepare_setup_ep0(); 235 prepare_setup_ep0();
223} 236}
224 237
238static void cancel_all_transfers(bool cancel_ep0)
239{
240 logf("usb-drv: cancel all transfers");
241 int flags = disable_irq_save();
242 unsigned i, ep;
243 FOR_EACH_IN_EP_EX(cancel_ep0, i, ep)
244 {
245 endpoints[ep][DIR_IN].status = 1;
246 endpoints[ep][DIR_IN].wait = false;
247 endpoints[ep][DIR_IN].busy = false;
248 wakeup_signal(&endpoints[ep][DIR_IN].complete);
249 DIEPCTL(ep) = (DIEPCTL(ep) & ~DEPCTL_usbactep) | DEPCTL_epdis;
250 }
251 FOR_EACH_OUT_EP_EX(cancel_ep0, i, ep)
252 {
253 endpoints[ep][DIR_OUT].status = 1;
254 endpoints[ep][DIR_OUT].wait = false;
255 endpoints[ep][DIR_OUT].busy = false;
256 wakeup_signal(&endpoints[ep][DIR_OUT].complete);
257 DOEPCTL(ep) = (DOEPCTL(ep) & ~DEPCTL_usbactep) | DEPCTL_epdis;
258 }
259
260 restore_irq(flags);
261}
262
225static void core_dev_init(void) 263static void core_dev_init(void)
226{ 264{
227 unsigned int i, ep; 265 unsigned int i, ep;
@@ -383,7 +421,6 @@ static void handle_ep_int(int ep, bool dir_in)
383 * so we setup EP0 to receive next setup */ 421 * so we setup EP0 to receive next setup */
384 if(ep == 0 && endpoint->len == 0) 422 if(ep == 0 && endpoint->len == 0)
385 prepare_setup_ep0(); 423 prepare_setup_ep0();
386 DIEPCTL(ep) |= DEPCTL_snak;
387 usb_core_transfer_complete(ep, USB_DIR_IN, 0, transfered); 424 usb_core_transfer_complete(ep, USB_DIR_IN, 0, transfered);
388 wakeup_signal(&endpoint->complete); 425 wakeup_signal(&endpoint->complete);
389 } 426 }
@@ -435,12 +472,12 @@ static void handle_ep_int(int ep, bool dir_in)
435 if(DOEPINT(ep) & DOEPINT_setup) 472 if(DOEPINT(ep) & DOEPINT_setup)
436 { 473 {
437 logf("usb-drv: setup on EP%d OUT", ep); 474 logf("usb-drv: setup on EP%d OUT", ep);
438 logf("rt=%x r=%x", ep0_setup_pkt.bRequestType, ep0_setup_pkt.bRequest);
439 if(ep != 0) 475 if(ep != 0)
440 panicf("usb-drv: setup not on EP0, this is impossible"); 476 panicf("usb-drv: setup not on EP0, this is impossible");
441 DOEPCTL(ep) |= DEPCTL_snak; 477 DOEPCTL(ep) |= DEPCTL_snak;
442 /* handle the set address here because of a bug in the usb core */ 478 /* handle the set address here because of a bug in the usb core */
443 invalidate_dcache_range((void*)&ep0_setup_pkt, sizeof ep0_setup_pkt); /* force write back */ 479 invalidate_dcache_range((void*)&ep0_setup_pkt, sizeof ep0_setup_pkt); /* force write back */
480 logf(" rt=%x r=%x", ep0_setup_pkt.bRequestType, ep0_setup_pkt.bRequest);
444 if(ep0_setup_pkt.bRequestType == USB_TYPE_STANDARD && 481 if(ep0_setup_pkt.bRequestType == USB_TYPE_STANDARD &&
445 ep0_setup_pkt.bRequest == USB_REQ_SET_ADDRESS) 482 ep0_setup_pkt.bRequest == USB_REQ_SET_ADDRESS)
446 usb_drv_set_address(ep0_setup_pkt.wValue); 483 usb_drv_set_address(ep0_setup_pkt.wValue);
@@ -484,6 +521,7 @@ void INT_USB(void)
484 /* Clear the Remote Wakeup Signalling */ 521 /* Clear the Remote Wakeup Signalling */
485 //DCTL &= ~DCTL_rmtwkupsig; 522 //DCTL &= ~DCTL_rmtwkupsig;
486 523
524 cancel_all_transfers(true);
487 /* Flush FIFOs */ 525 /* Flush FIFOs */
488 flush_tx_fifos(0x10); 526 flush_tx_fifos(0x10);
489 flush_rx_fifos(); 527 flush_rx_fifos();
@@ -501,18 +539,10 @@ void INT_USB(void)
501 logf("usb-drv: enum done"); 539 logf("usb-drv: enum done");
502 540
503 /* read speed */ 541 /* read speed */
504 switch(extract(DSTS, enumspd)) 542 if(usb_drv_port_speed())
505 { 543 logf("usb-drv: HS");
506 case DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ: 544 else
507 logf("usb-drv: HS"); 545 logf("usb-drv: FS");
508 break;
509 case DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ:
510 case DSTS_ENUMSPD_FS_PHY_48MHZ:
511 logf("usb-drv: FS");
512 break;
513 case DSTS_ENUMSPD_LS_PHY_6MHZ:
514 panicf("usb-drv: LS is not supported");
515 }
516 546
517 /* fixme: change EP0 mps here */ 547 /* fixme: change EP0 mps here */
518 } 548 }
@@ -523,14 +553,32 @@ void INT_USB(void)
523 } 553 }
524 554
525 if(sts & GINTMSK_disconnect) 555 if(sts & GINTMSK_disconnect)
556 {
526 panicf("usb-drv: disconnect"); 557 panicf("usb-drv: disconnect");
558 cancel_all_transfers(true);
559 usb_enable(false);
560 }
527 561
528 GINTSTS = GINTSTS; 562 GINTSTS = GINTSTS;
529} 563}
530 564
531int usb_drv_port_speed(void) 565int usb_drv_port_speed(void)
532{ 566{
533 return 0; 567 switch(extract(DSTS, enumspd))
568 {
569 case DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ:
570 return 1;
571 case DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ:
572 case DSTS_ENUMSPD_FS_PHY_48MHZ:
573 return 0;
574 break;
575 case DSTS_ENUMSPD_LS_PHY_6MHZ:
576 panicf("usb-drv: LS is not supported");
577 return 0;
578 default:
579 panicf("usb-drv: wtf is this speed ?");
580 return 0;
581 }
534} 582}
535 583
536int usb_drv_request_endpoint(int type, int dir) 584int usb_drv_request_endpoint(int type, int dir)
@@ -547,29 +595,9 @@ void usb_drv_release_endpoint(int ep)
547 endpoints[EP_NUM(ep)][EP_DIR(ep)].active = false; 595 endpoints[EP_NUM(ep)][EP_DIR(ep)].active = false;
548} 596}
549 597
550void usb_drv_cancel_all_transfers(void) 598void usb_drv_cancel_all_transfers()
551{ 599{
552 logf("usb-drv: cancel all transfers"); 600 cancel_all_transfers(false);
553 int flags = disable_irq_save();
554 unsigned i, ep;
555 FOR_EACH_IN_EP(i, ep)
556 {
557 endpoints[ep][DIR_IN].status = 1;
558 endpoints[ep][DIR_IN].wait = false;
559 endpoints[ep][DIR_IN].busy = false;
560 wakeup_signal(&endpoints[ep][DIR_IN].complete);
561 DIEPCTL(ep) = (DIEPCTL(ep) & ~DEPCTL_usbactep) | DEPCTL_epdis;
562 }
563 FOR_EACH_OUT_EP(i, ep)
564 {
565 endpoints[ep][DIR_OUT].status = 1;
566 endpoints[ep][DIR_OUT].wait = false;
567 endpoints[ep][DIR_OUT].busy = false;
568 wakeup_signal(&endpoints[ep][DIR_OUT].complete);
569 DOEPCTL(ep) = (DOEPCTL(ep) & ~DEPCTL_usbactep) | DEPCTL_epdis;
570 }
571
572 restore_irq(flags);
573} 601}
574 602
575static int usb_drv_transfer(int ep, void *ptr, int len, bool dir_in, bool blocking) 603static int usb_drv_transfer(int ep, void *ptr, int len, bool dir_in, bool blocking)
@@ -586,14 +614,15 @@ static int usb_drv_transfer(int ep, void *ptr, int len, bool dir_in, bool blocki
586 #define DEPTSIZ *eptsiz 614 #define DEPTSIZ *eptsiz
587 #define DEPDMA *epdma 615 #define DEPDMA *epdma
588 616
589 if(endpoint->busy)
590 panicf("usb-drv: EP%d %s is already busy", ep, dir_in ? "IN" : "OUT");
591
592 if(DEPCTL & DEPCTL_stall) 617 if(DEPCTL & DEPCTL_stall)
593 { 618 {
594 logf("usb-drv: cannot receive on a stalled endpoint"); 619 logf("usb-drv: cannot receive/send on a stalled endpoint");
595 return -1; 620 return -1;
596 } 621 }
622
623 if(endpoint->busy)
624 logf("usb-drv: EP%d %s is already busy", ep, dir_in ? "IN" : "OUT");
625
597 endpoint->busy = true; 626 endpoint->busy = true;
598 endpoint->len = len; 627 endpoint->len = len;
599 endpoint->wait = blocking; 628 endpoint->wait = blocking;