diff options
Diffstat (limited to 'firmware/target/arm')
-rw-r--r-- | firmware/target/arm/usb-s3c6400x.c | 69 |
1 files changed, 36 insertions, 33 deletions
diff --git a/firmware/target/arm/usb-s3c6400x.c b/firmware/target/arm/usb-s3c6400x.c index 71bd127dab..7bcfcedc89 100644 --- a/firmware/target/arm/usb-s3c6400x.c +++ b/firmware/target/arm/usb-s3c6400x.c | |||
@@ -515,7 +515,7 @@ int usb_drv_send(int ep, void *ptr, int len) | |||
515 | } | 515 | } |
516 | #else | 516 | #else |
517 | 517 | ||
518 | static struct ep_type endpoints[USB_NUM_ENDPOINTS]; | 518 | static struct ep_type endpoints[USB_NUM_ENDPOINTS][2]; |
519 | 519 | ||
520 | /* USB control requests may be up to 64 bytes in size. | 520 | /* USB control requests may be up to 64 bytes in size. |
521 | Even though we never use anything more than the 8 header bytes, | 521 | Even though we never use anything more than the 8 header bytes, |
@@ -535,15 +535,15 @@ static volatile bool plugged = false; | |||
535 | 535 | ||
536 | static void reset_endpoints(int reinit) | 536 | static void reset_endpoints(int reinit) |
537 | { | 537 | { |
538 | unsigned int i; | 538 | for (unsigned i = 0; i < sizeof(endpoints)/(2*sizeof(struct ep_type)); i++) |
539 | for (i = 0; i < sizeof(endpoints)/sizeof(struct ep_type); i++) | 539 | for (unsigned dir = 0; dir < 2; dir++) |
540 | { | 540 | { |
541 | if (reinit) endpoints[i].active = false; | 541 | if (reinit) endpoints[i][dir].active = false; |
542 | endpoints[i].busy = false; | 542 | endpoints[i][dir].busy = false; |
543 | endpoints[i].status = -1; | 543 | endpoints[i][dir].status = -1; |
544 | endpoints[i].done = true; | 544 | endpoints[i][dir].done = true; |
545 | semaphore_release(&endpoints[i].complete); | 545 | semaphore_release(&endpoints[i][dir].complete); |
546 | } | 546 | } |
547 | 547 | ||
548 | DEPCTL(0, false) = DEPCTL_usbactep | (1 << DEPCTL_nextep_bitp); | 548 | DEPCTL(0, false) = DEPCTL_usbactep | (1 << DEPCTL_nextep_bitp); |
549 | DEPCTL(0, true) = DEPCTL_usbactep; | 549 | DEPCTL(0, true) = DEPCTL_usbactep; |
@@ -575,26 +575,28 @@ static void reset_endpoints(int reinit) | |||
575 | int usb_drv_request_endpoint(int type, int dir) | 575 | int usb_drv_request_endpoint(int type, int dir) |
576 | { | 576 | { |
577 | bool out = dir == USB_DIR_OUT; | 577 | bool out = dir == USB_DIR_OUT; |
578 | for(size_t ep = out ? 2 : 1; ep < USB_NUM_ENDPOINTS; ep += 2) | 578 | for(size_t ep = out ? 2 : 1; ep < USB_NUM_ENDPOINTS; ep += 2) { |
579 | if (!endpoints[ep].active) | 579 | if (!endpoints[ep][out ? DIR_OUT : DIR_IN].active) |
580 | { | 580 | { |
581 | endpoints[ep].active = true; | 581 | endpoints[ep][out ? DIR_OUT : DIR_IN].active = true; |
582 | DEPCTL(ep, out) = (DEPCTL(ep, out) & ~(DEPCTL_eptype_bits << DEPCTL_eptype_bitp)) | | 582 | DEPCTL(ep, out) = (DEPCTL(ep, out) & ~(DEPCTL_eptype_bits << DEPCTL_eptype_bitp)) | |
583 | (type << DEPCTL_eptype_bitp); | 583 | (type << DEPCTL_eptype_bitp); |
584 | return ep | dir; | 584 | return ep | dir; |
585 | } | 585 | } |
586 | } | ||
586 | 587 | ||
587 | return -1; | 588 | return -1; |
588 | } | 589 | } |
589 | 590 | ||
590 | void usb_drv_release_endpoint(int ep) | 591 | void usb_drv_release_endpoint(int ep) |
591 | { | 592 | { |
593 | bool out = !(ep & USB_DIR_IN); | ||
592 | ep = ep & 0x7f; | 594 | ep = ep & 0x7f; |
593 | 595 | ||
594 | if (ep < 1 || ep > USB_NUM_ENDPOINTS) | 596 | if (ep < 1 || ep > USB_NUM_ENDPOINTS) |
595 | return; | 597 | return; |
596 | 598 | ||
597 | endpoints[ep].active = false; | 599 | endpoints[ep][out ? DIR_OUT : DIR_IN].active = false; |
598 | } | 600 | } |
599 | 601 | ||
600 | static void usb_reset(void) | 602 | static void usb_reset(void) |
@@ -646,14 +648,14 @@ static void handle_ep_int(bool out) | |||
646 | { | 648 | { |
647 | if (!out) inflight = false; | 649 | if (!out) inflight = false; |
648 | commit_discard_dcache(); | 650 | commit_discard_dcache(); |
649 | int bytes = endpoints[ep].size - (DEPTSIZ(ep, out) & (DEPTSIZ_xfersize_bits < DEPTSIZ_xfersize_bitp)); | 651 | int bytes = endpoints[ep][out ? DIR_OUT : DIR_IN].size - (DEPTSIZ(ep, out) & (DEPTSIZ_xfersize_bits < DEPTSIZ_xfersize_bitp)); |
650 | if (endpoints[ep].busy) | 652 | if (endpoints[ep][out ? DIR_OUT : DIR_IN].busy) |
651 | { | 653 | { |
652 | endpoints[ep].busy = false; | 654 | endpoints[ep][out ? DIR_OUT : DIR_IN].busy = false; |
653 | endpoints[ep].status = 0; | 655 | endpoints[ep][out ? DIR_OUT : DIR_IN].status = 0; |
654 | endpoints[ep].done = true; | 656 | endpoints[ep][out ? DIR_OUT : DIR_IN].done = true; |
655 | usb_core_transfer_complete(ep, out ? USB_DIR_OUT : USB_DIR_IN, 0, bytes); | 657 | usb_core_transfer_complete(ep, out ? USB_DIR_OUT : USB_DIR_IN, 0, bytes); |
656 | semaphore_release(&endpoints[ep].complete); | 658 | semaphore_release(&endpoints[ep][out ? DIR_OUT : DIR_IN].complete); |
657 | } | 659 | } |
658 | } | 660 | } |
659 | 661 | ||
@@ -662,12 +664,12 @@ static void handle_ep_int(bool out) | |||
662 | 664 | ||
663 | if (!out && (epints & DIEPINT_timeout)) | 665 | if (!out && (epints & DIEPINT_timeout)) |
664 | { | 666 | { |
665 | if (endpoints[ep].busy) | 667 | if (endpoints[ep][out ? DIR_OUT : DIR_IN].busy) |
666 | { | 668 | { |
667 | endpoints[ep].busy = false; | 669 | endpoints[ep][out ? DIR_OUT : DIR_IN].busy = false; |
668 | endpoints[ep].status = 1; | 670 | endpoints[ep][out ? DIR_OUT : DIR_IN].status = 1; |
669 | endpoints[ep].done = true; | 671 | endpoints[ep][out ? DIR_OUT : DIR_IN].done = true; |
670 | semaphore_release(&endpoints[ep].complete); | 672 | semaphore_release(&endpoints[ep][out ? DIR_OUT : DIR_IN].complete); |
671 | } | 673 | } |
672 | } | 674 | } |
673 | 675 | ||
@@ -735,8 +737,8 @@ static void ep_transfer(int ep, void *ptr, int len, bool out) | |||
735 | /* disable interrupts to avoid any race */ | 737 | /* disable interrupts to avoid any race */ |
736 | int oldlevel = disable_irq_save(); | 738 | int oldlevel = disable_irq_save(); |
737 | if (!out) inflight = true; | 739 | if (!out) inflight = true; |
738 | endpoints[ep].busy = true; | 740 | endpoints[ep][out ? DIR_OUT : DIR_IN].busy = true; |
739 | endpoints[ep].size = len; | 741 | endpoints[ep][out ? DIR_OUT : DIR_IN].size = len; |
740 | 742 | ||
741 | if (out) DEPCTL(ep, out) &= ~DEPCTL_stall; | 743 | if (out) DEPCTL(ep, out) &= ~DEPCTL_stall; |
742 | 744 | ||
@@ -762,11 +764,11 @@ static void ep_transfer(int ep, void *ptr, int len, bool out) | |||
762 | int usb_drv_send(int endpoint, void *ptr, int length) | 764 | int usb_drv_send(int endpoint, void *ptr, int length) |
763 | { | 765 | { |
764 | endpoint = EP_NUM(endpoint); | 766 | endpoint = EP_NUM(endpoint); |
765 | endpoints[endpoint].done = false; | 767 | endpoints[endpoint][1].done = false; |
766 | ep_transfer(endpoint, ptr, length, false); | 768 | ep_transfer(endpoint, ptr, length, false); |
767 | while (!endpoints[endpoint].done && endpoints[endpoint].busy) | 769 | while (!endpoints[endpoint][1].done && endpoints[endpoint][1].busy) |
768 | semaphore_wait(&endpoints[endpoint].complete, TIMEOUT_BLOCK); | 770 | semaphore_wait(&endpoints[endpoint][1].complete, TIMEOUT_BLOCK); |
769 | return endpoints[endpoint].status; | 771 | return endpoints[endpoint][1].status; |
770 | } | 772 | } |
771 | 773 | ||
772 | void usb_drv_cancel_all_transfers(void) | 774 | void usb_drv_cancel_all_transfers(void) |
@@ -778,8 +780,9 @@ void usb_drv_cancel_all_transfers(void) | |||
778 | 780 | ||
779 | void usb_drv_init(void) | 781 | void usb_drv_init(void) |
780 | { | 782 | { |
781 | for (unsigned i = 0; i < sizeof(endpoints)/sizeof(struct ep_type); i++) | 783 | for (unsigned i = 0; i < sizeof(endpoints)/(2*sizeof(struct ep_type)); i++) |
782 | semaphore_init(&endpoints[i].complete, 1, 0); | 784 | for (unsigned dir = 0; dir < 2; dir++) |
785 | semaphore_init(&endpoints[i][dir].complete, 1, 0); | ||
783 | 786 | ||
784 | /* Enable USB clock */ | 787 | /* Enable USB clock */ |
785 | #if CONFIG_CPU==S5L8701 | 788 | #if CONFIG_CPU==S5L8701 |