diff options
Diffstat (limited to 'firmware/target/arm/as3525/usb-drv-as3525v2.c')
-rw-r--r-- | firmware/target/arm/as3525/usb-drv-as3525v2.c | 113 |
1 files changed, 43 insertions, 70 deletions
diff --git a/firmware/target/arm/as3525/usb-drv-as3525v2.c b/firmware/target/arm/as3525/usb-drv-as3525v2.c index 9a1947f53e..b9030b850a 100644 --- a/firmware/target/arm/as3525/usb-drv-as3525v2.c +++ b/firmware/target/arm/as3525/usb-drv-as3525v2.c | |||
@@ -224,20 +224,20 @@ static void prepare_setup_ep0(void) | |||
224 | { | 224 | { |
225 | logf("usb-drv: prepare EP0"); | 225 | logf("usb-drv: prepare EP0"); |
226 | /* setup DMA */ | 226 | /* setup DMA */ |
227 | DOEPDMA(0) = (void*)AS3525_PHYSICAL_ADDR(&_ep0_setup_pkt); | 227 | DEPDMA(0, true) = (void*)AS3525_PHYSICAL_ADDR(&_ep0_setup_pkt); |
228 | 228 | ||
229 | /* Setup EP0 OUT with the following parameters: | 229 | /* Setup EP0 OUT with the following parameters: |
230 | * packet count = 1 | 230 | * packet count = 1 |
231 | * setup packet count = 1 | 231 | * setup packet count = 1 |
232 | * transfer size = 8 (setup packet) | 232 | * transfer size = 8 (setup packet) |
233 | */ | 233 | */ |
234 | DOEPTSIZ(0) = (1 << DEPTSIZ0_supcnt_bitp) | 234 | DEPTSIZ(0, true) = (1 << DEPTSIZ0_supcnt_bitp) |
235 | | (1 << DEPTSIZ0_pkcnt_bitp) | 235 | | (1 << DEPTSIZ0_pkcnt_bitp) |
236 | | 8; | 236 | | 8; |
237 | 237 | ||
238 | /* Enable endpoint, clear nak */ | 238 | /* Enable endpoint, clear nak */ |
239 | ep0_state = EP0_WAIT_SETUP; | 239 | ep0_state = EP0_WAIT_SETUP; |
240 | DOEPCTL(0) |= DEPCTL_epena | DEPCTL_cnak; | 240 | DEPCTL(0, true) |= DEPCTL_epena | DEPCTL_cnak; |
241 | } | 241 | } |
242 | 242 | ||
243 | static void handle_ep0_complete(bool is_ack) | 243 | static void handle_ep0_complete(bool is_ack) |
@@ -305,10 +305,9 @@ static void reset_endpoints(void) | |||
305 | endpoints[ep][DIR_IN].wait = false; | 305 | endpoints[ep][DIR_IN].wait = false; |
306 | semaphore_release(&endpoints[ep][DIR_IN].complete); | 306 | semaphore_release(&endpoints[ep][DIR_IN].complete); |
307 | } | 307 | } |
308 | if(DIEPCTL(ep) & DEPCTL_epena) | 308 | DEPCTL(ep, false) = (DEPCTL(ep, false) & DEPCTL_epena) |
309 | DIEPCTL(ep) = DEPCTL_snak; | 309 | ? DEPCTL_snak |
310 | else | 310 | : 0; |
311 | DIEPCTL(ep) = 0; | ||
312 | } | 311 | } |
313 | 312 | ||
314 | FOR_EACH_OUT_EP_AND_EP0(i, ep) | 313 | FOR_EACH_OUT_EP_AND_EP0(i, ep) |
@@ -321,19 +320,16 @@ static void reset_endpoints(void) | |||
321 | endpoints[ep][DIR_OUT].wait = false; | 320 | endpoints[ep][DIR_OUT].wait = false; |
322 | semaphore_release(&endpoints[ep][DIR_OUT].complete); | 321 | semaphore_release(&endpoints[ep][DIR_OUT].complete); |
323 | } | 322 | } |
324 | if(DOEPCTL(ep) & DEPCTL_epena) | 323 | DEPCTL(ep, true) = (DEPCTL(ep, true) & DEPCTL_epena) ? DEPCTL_snak : 0; |
325 | DOEPCTL(ep) = DEPCTL_snak; | ||
326 | else | ||
327 | DOEPCTL(ep) = 0; | ||
328 | } | 324 | } |
329 | /* 64 bytes packet size, active endpoint */ | 325 | /* 64 bytes packet size, active endpoint */ |
330 | DOEPCTL(0) = (DEPCTL_MPS_64 << DEPCTL_mps_bitp) | DEPCTL_usbactep | DEPCTL_snak; | 326 | DEPCTL(0, true) = (DEPCTL_MPS_64 << DEPCTL_mps_bitp) | DEPCTL_usbactep | DEPCTL_snak; |
331 | DIEPCTL(0) = (DEPCTL_MPS_64 << DEPCTL_mps_bitp) | DEPCTL_usbactep | DEPCTL_snak; | 327 | DEPCTL(0, false) = (DEPCTL_MPS_64 << DEPCTL_mps_bitp) | DEPCTL_usbactep | DEPCTL_snak; |
332 | /* Setup next chain for IN eps */ | 328 | /* Setup next chain for IN eps */ |
333 | FOR_EACH_IN_EP_AND_EP0(i, ep) | 329 | FOR_EACH_IN_EP_AND_EP0(i, ep) |
334 | { | 330 | { |
335 | int next_ep = in_ep_list[(i + 1) % (NUM_IN_EP + 1)]; | 331 | int next_ep = in_ep_list[(i + 1) % (NUM_IN_EP + 1)]; |
336 | DIEPCTL(ep) = (DIEPCTL(ep) & ~bitm(DEPCTL, nextep)) | (next_ep << DEPCTL_nextep_bitp); | 332 | DEPCTL(ep, false) = (DEPCTL(ep, false) & ~bitm(DEPCTL, nextep)) | (next_ep << DEPCTL_nextep_bitp); |
337 | } | 333 | } |
338 | } | 334 | } |
339 | 335 | ||
@@ -353,7 +349,7 @@ static void cancel_all_transfers(bool cancel_ep0) | |||
353 | endpoints[ep][DIR_IN].wait = false; | 349 | endpoints[ep][DIR_IN].wait = false; |
354 | semaphore_release(&endpoints[ep][DIR_IN].complete); | 350 | semaphore_release(&endpoints[ep][DIR_IN].complete); |
355 | } | 351 | } |
356 | DIEPCTL(ep) = (DIEPCTL(ep) & ~DEPCTL_usbactep) | DEPCTL_snak; | 352 | DEPCTL(ep, false) = (DEPCTL(ep, false) & ~DEPCTL_usbactep) | DEPCTL_snak; |
357 | } | 353 | } |
358 | FOR_EACH_OUT_EP_EX(cancel_ep0, i, ep) | 354 | FOR_EACH_OUT_EP_EX(cancel_ep0, i, ep) |
359 | { | 355 | { |
@@ -364,7 +360,7 @@ static void cancel_all_transfers(bool cancel_ep0) | |||
364 | endpoints[ep][DIR_OUT].wait = false; | 360 | endpoints[ep][DIR_OUT].wait = false; |
365 | semaphore_release(&endpoints[ep][DIR_OUT].complete); | 361 | semaphore_release(&endpoints[ep][DIR_OUT].complete); |
366 | } | 362 | } |
367 | DOEPCTL(ep) = (DOEPCTL(ep) & ~DEPCTL_usbactep) | DEPCTL_snak; | 363 | DEPCTL(ep, true) = (DEPCTL(ep, true) & ~DEPCTL_usbactep) | DEPCTL_snak; |
368 | } | 364 | } |
369 | 365 | ||
370 | restore_irq(flags); | 366 | restore_irq(flags); |
@@ -498,7 +494,7 @@ void usb_drv_exit(void) | |||
498 | static void handle_ep_in_int(int ep) | 494 | static void handle_ep_in_int(int ep) |
499 | { | 495 | { |
500 | struct usb_endpoint *endpoint = &endpoints[ep][DIR_IN]; | 496 | struct usb_endpoint *endpoint = &endpoints[ep][DIR_IN]; |
501 | unsigned long sts = DIEPINT(ep); | 497 | unsigned long sts = DEPINT(ep, false); |
502 | if(sts & DIEPINT_ahberr) | 498 | if(sts & DIEPINT_ahberr) |
503 | panicf("usb-drv: ahb error on EP%d IN", ep); | 499 | panicf("usb-drv: ahb error on EP%d IN", ep); |
504 | if(sts & DIEPINT_xfercompl) | 500 | if(sts & DIEPINT_xfercompl) |
@@ -508,7 +504,7 @@ static void handle_ep_in_int(int ep) | |||
508 | endpoint->busy = false; | 504 | endpoint->busy = false; |
509 | endpoint->status = 0; | 505 | endpoint->status = 0; |
510 | /* works even for EP0 */ | 506 | /* works even for EP0 */ |
511 | int size = (DIEPTSIZ(ep) & DEPTSIZ_xfersize_bits); | 507 | int size = (DEPTSIZ(ep, false) & DEPTSIZ_xfersize_bits); |
512 | int transfered = endpoint->len - size; | 508 | int transfered = endpoint->len - size; |
513 | logf("len=%d reg=%d xfer=%d", endpoint->len, size, transfered); | 509 | logf("len=%d reg=%d xfer=%d", endpoint->len, size, transfered); |
514 | /* handle EP0 state if necessary, | 510 | /* handle EP0 state if necessary, |
@@ -542,13 +538,13 @@ static void handle_ep_in_int(int ep) | |||
542 | } | 538 | } |
543 | } | 539 | } |
544 | /* clear interrupts */ | 540 | /* clear interrupts */ |
545 | DIEPINT(ep) = sts; | 541 | DEPINT(ep, false) = sts; |
546 | } | 542 | } |
547 | 543 | ||
548 | static void handle_ep_out_int(int ep) | 544 | static void handle_ep_out_int(int ep) |
549 | { | 545 | { |
550 | struct usb_endpoint *endpoint = &endpoints[ep][DIR_OUT]; | 546 | struct usb_endpoint *endpoint = &endpoints[ep][DIR_OUT]; |
551 | unsigned long sts = DOEPINT(ep); | 547 | unsigned long sts = DEPINT(ep, true); |
552 | if(sts & DOEPINT_ahberr) | 548 | if(sts & DOEPINT_ahberr) |
553 | panicf("usb-drv: ahb error on EP%d OUT", ep); | 549 | panicf("usb-drv: ahb error on EP%d OUT", ep); |
554 | if(sts & DOEPINT_xfercompl) | 550 | if(sts & DOEPINT_xfercompl) |
@@ -559,9 +555,9 @@ static void handle_ep_out_int(int ep) | |||
559 | endpoint->busy = false; | 555 | endpoint->busy = false; |
560 | endpoint->status = 0; | 556 | endpoint->status = 0; |
561 | /* works even for EP0 */ | 557 | /* works even for EP0 */ |
562 | int transfered = endpoint->len - (DOEPTSIZ(ep) & DEPTSIZ_xfersize_bits); | 558 | int transfered = endpoint->len - (DEPTSIZ(ep, true) & DEPTSIZ_xfersize_bits); |
563 | logf("len=%d reg=%ld xfer=%d", endpoint->len, | 559 | logf("len=%d reg=%ld xfer=%d", endpoint->len, |
564 | (DOEPTSIZ(ep) & DEPTSIZ_xfersize_bits), | 560 | (DEPTSIZ(ep, true) & DEPTSIZ_xfersize_bits), |
565 | transfered); | 561 | transfered); |
566 | /* handle EP0 state if necessary, | 562 | /* handle EP0 state if necessary, |
567 | * this is a ack if length is 0 */ | 563 | * this is a ack if length is 0 */ |
@@ -580,7 +576,7 @@ static void handle_ep_out_int(int ep) | |||
580 | logf("usb-drv: setup on EP%d OUT", ep); | 576 | logf("usb-drv: setup on EP%d OUT", ep); |
581 | if(ep != 0) | 577 | if(ep != 0) |
582 | panicf("usb-drv: setup not on EP0, this is impossible"); | 578 | panicf("usb-drv: setup not on EP0, this is impossible"); |
583 | if((DOEPTSIZ(ep) & DEPTSIZ_xfersize_bits) != 0) | 579 | if((DEPTSIZ(ep, true) & DEPTSIZ_xfersize_bits) != 0) |
584 | { | 580 | { |
585 | logf("usb-drv: ignore spurious setup (xfersize=%ld)", DOEPTSIZ(ep) & DEPTSIZ_xfersize_bits); | 581 | logf("usb-drv: ignore spurious setup (xfersize=%ld)", DOEPTSIZ(ep) & DEPTSIZ_xfersize_bits); |
586 | prepare_setup_ep0(); | 582 | prepare_setup_ep0(); |
@@ -601,7 +597,7 @@ static void handle_ep_out_int(int ep) | |||
601 | } | 597 | } |
602 | } | 598 | } |
603 | /* clear interrupts */ | 599 | /* clear interrupts */ |
604 | DOEPINT(ep) = sts; | 600 | DEPINT(ep, true) = sts; |
605 | } | 601 | } |
606 | 602 | ||
607 | static void handle_ep_ints(void) | 603 | static void handle_ep_ints(void) |
@@ -742,13 +738,9 @@ int usb_drv_request_endpoint(int type, int dir) | |||
742 | return -1; | 738 | return -1; |
743 | } | 739 | } |
744 | 740 | ||
745 | unsigned long data = DEPCTL_setd0pid | (type << DEPCTL_eptype_bitp) | 741 | DEPCTL(ep, dir != USB_DIR_IN) = (DEPCTL(ep, true) & ~(bitm(DEPCTL, eptype) | bitm(DEPCTL, mps))) |
746 | | (usb_drv_mps_by_type(type) << DEPCTL_mps_bitp) | 742 | | DEPCTL_setd0pid | (type << DEPCTL_eptype_bitp) |
747 | | DEPCTL_usbactep | DEPCTL_snak; | 743 | | (usb_drv_mps_by_type(type) << DEPCTL_mps_bitp) | DEPCTL_usbactep | DEPCTL_snak; |
748 | unsigned long mask = ~(bitm(DEPCTL, eptype) | bitm(DEPCTL, mps)); | ||
749 | |||
750 | if(dir == USB_DIR_IN) DIEPCTL(ep) = (DIEPCTL(ep) & mask) | data; | ||
751 | else DOEPCTL(ep) = (DOEPCTL(ep) & mask) | data; | ||
752 | 744 | ||
753 | return ret; | 745 | return ret; |
754 | } | 746 | } |
@@ -764,9 +756,10 @@ void usb_drv_cancel_all_transfers() | |||
764 | cancel_all_transfers(false); | 756 | cancel_all_transfers(false); |
765 | } | 757 | } |
766 | 758 | ||
767 | static int usb_drv_transfer(int ep, void *ptr, int len, bool dir_in, bool blocking) | 759 | static void usb_drv_transfer(int ep, void *ptr, int len, bool dir_in, bool blocking) |
768 | { | 760 | { |
769 | ep = EP_NUM(ep); | 761 | ep = EP_NUM(ep); |
762 | struct usb_endpoint *endpoint = &endpoints[ep][dir_in]; | ||
770 | 763 | ||
771 | logf("usb-drv: xfer EP%d, len=%d, dir_in=%d, blocking=%d", ep, | 764 | logf("usb-drv: xfer EP%d, len=%d, dir_in=%d, blocking=%d", ep, |
772 | len, dir_in, blocking); | 765 | len, dir_in, blocking); |
@@ -774,14 +767,6 @@ static int usb_drv_transfer(int ep, void *ptr, int len, bool dir_in, bool blocki | |||
774 | /* disable interrupts to avoid any race */ | 767 | /* disable interrupts to avoid any race */ |
775 | int oldlevel = disable_irq_save(); | 768 | int oldlevel = disable_irq_save(); |
776 | 769 | ||
777 | volatile uint32_t *epctl = dir_in ? &DIEPCTL(ep) : &DOEPCTL(ep); | ||
778 | volatile uint32_t *eptsiz = dir_in ? &DIEPTSIZ(ep) : &DOEPTSIZ(ep); | ||
779 | const void * volatile * epdma = dir_in ? &DIEPDMA(ep) : &DOEPDMA(ep); | ||
780 | struct usb_endpoint *endpoint = &endpoints[ep][dir_in]; | ||
781 | #define DEPCTL *epctl | ||
782 | #define DEPTSIZ *eptsiz | ||
783 | #define DEPDMA *epdma | ||
784 | |||
785 | if(endpoint->busy) | 770 | if(endpoint->busy) |
786 | logf("usb-drv: EP%d %s is already busy", ep, dir_in ? "IN" : "OUT"); | 771 | logf("usb-drv: EP%d %s is already busy", ep, dir_in ? "IN" : "OUT"); |
787 | 772 | ||
@@ -790,21 +775,21 @@ static int usb_drv_transfer(int ep, void *ptr, int len, bool dir_in, bool blocki | |||
790 | endpoint->wait = blocking; | 775 | endpoint->wait = blocking; |
791 | endpoint->status = -1; | 776 | endpoint->status = -1; |
792 | 777 | ||
793 | DEPCTL &= ~DEPCTL_stall; | 778 | DEPCTL(ep, !dir_in) = (DEPCTL(ep, !dir_in) & ~DEPCTL_stall) | DEPCTL_usbactep; |
794 | DEPCTL |= DEPCTL_usbactep; | ||
795 | 779 | ||
796 | int mps = usb_drv_mps_by_type(extract(DEPCTL, eptype)); | 780 | int type = (DEPCTL(ep, !dir_in) >> DEPCTL_eptype_bitp) & DEPCTL_eptype_bits; |
781 | int mps = usb_drv_mps_by_type(type); | ||
797 | int nb_packets = (len + mps - 1) / mps; | 782 | int nb_packets = (len + mps - 1) / mps; |
798 | 783 | ||
799 | if(len == 0) | 784 | if(len == 0) |
800 | { | 785 | { |
801 | DEPDMA = (void*)0x10000000; | 786 | DEPDMA(ep, !dir_in) = (void*)0x10000000; |
802 | DEPTSIZ = 1 << DEPTSIZ_pkcnt_bitp; | 787 | DEPTSIZ(ep, !dir_in) = 1 << DEPTSIZ_pkcnt_bitp; |
803 | } | 788 | } |
804 | else | 789 | else |
805 | { | 790 | { |
806 | DEPDMA = (void*)AS3525_PHYSICAL_ADDR(ptr); | 791 | DEPDMA(ep, !dir_in) = (void*)AS3525_PHYSICAL_ADDR(ptr); |
807 | DEPTSIZ = (nb_packets << DEPTSIZ_pkcnt_bitp) | len; | 792 | DEPTSIZ(ep, !dir_in) = (nb_packets << DEPTSIZ_pkcnt_bitp) | len; |
808 | if(dir_in) | 793 | if(dir_in) |
809 | clean_dcache_range(ptr, len); | 794 | clean_dcache_range(ptr, len); |
810 | else | 795 | else |
@@ -813,37 +798,31 @@ static int usb_drv_transfer(int ep, void *ptr, int len, bool dir_in, bool blocki | |||
813 | 798 | ||
814 | logf("pkt=%d dma=%lx", nb_packets, DEPDMA); | 799 | logf("pkt=%d dma=%lx", nb_packets, DEPDMA); |
815 | 800 | ||
816 | DEPCTL |= DEPCTL_epena | DEPCTL_cnak; | 801 | DEPCTL(ep, !dir_in) |= DEPCTL_epena | DEPCTL_cnak; |
817 | 802 | ||
818 | /* restore interrupts */ | 803 | /* restore interrupts */ |
819 | restore_irq(oldlevel); | 804 | restore_irq(oldlevel); |
820 | 805 | ||
821 | if(blocking) | 806 | if(blocking) |
822 | { | ||
823 | semaphore_wait(&endpoint->complete, TIMEOUT_BLOCK); | 807 | semaphore_wait(&endpoint->complete, TIMEOUT_BLOCK); |
824 | return endpoint->status; | ||
825 | } | ||
826 | |||
827 | return 0; | ||
828 | |||
829 | #undef DEPCTL | ||
830 | #undef DEPTSIZ | ||
831 | #undef DEPDMA | ||
832 | } | 808 | } |
833 | 809 | ||
834 | int usb_drv_recv(int ep, void *ptr, int len) | 810 | int usb_drv_recv(int ep, void *ptr, int len) |
835 | { | 811 | { |
836 | return usb_drv_transfer(ep, ptr, len, false, false); | 812 | usb_drv_transfer(ep, ptr, len, false, false); |
813 | return 0; | ||
837 | } | 814 | } |
838 | 815 | ||
839 | int usb_drv_send(int ep, void *ptr, int len) | 816 | int usb_drv_send(int ep, void *ptr, int len) |
840 | { | 817 | { |
841 | return usb_drv_transfer(ep, ptr, len, true, true); | 818 | usb_drv_transfer(ep, ptr, len, true, true); |
819 | return endpoints[EP_NUM(ep)][1].status; | ||
842 | } | 820 | } |
843 | 821 | ||
844 | int usb_drv_send_nonblocking(int ep, void *ptr, int len) | 822 | int usb_drv_send_nonblocking(int ep, void *ptr, int len) |
845 | { | 823 | { |
846 | return usb_drv_transfer(ep, ptr, len, true, false); | 824 | usb_drv_transfer(ep, ptr, len, true, false); |
825 | return 0; | ||
847 | } | 826 | } |
848 | 827 | ||
849 | 828 | ||
@@ -862,19 +841,13 @@ void usb_drv_set_address(int address) | |||
862 | void usb_drv_stall(int ep, bool stall, bool in) | 841 | void usb_drv_stall(int ep, bool stall, bool in) |
863 | { | 842 | { |
864 | logf("usb-drv: %sstall EP%d %s", stall ? "" : "un", ep, in ? "IN" : "OUT"); | 843 | logf("usb-drv: %sstall EP%d %s", stall ? "" : "un", ep, in ? "IN" : "OUT"); |
865 | if(in) | 844 | if (stall) |
866 | { | 845 | DEPCTL(ep, !in) |= DEPCTL_stall; |
867 | if(stall) DIEPCTL(ep) |= DEPCTL_stall; | ||
868 | else DIEPCTL(ep) &= ~DEPCTL_stall; | ||
869 | } | ||
870 | else | 846 | else |
871 | { | 847 | DEPCTL(ep, !in) &= ~DEPCTL_stall; |
872 | if(stall) DOEPCTL(ep) |= DEPCTL_stall; | ||
873 | else DOEPCTL(ep) &= ~DEPCTL_stall; | ||
874 | } | ||
875 | } | 848 | } |
876 | 849 | ||
877 | bool usb_drv_stalled(int ep, bool in) | 850 | bool usb_drv_stalled(int ep, bool in) |
878 | { | 851 | { |
879 | return (in ? DIEPCTL(ep) : DOEPCTL(ep)) & DEPCTL_stall; | 852 | return DEPCTL(ep, !in) & DEPCTL_stall; |
880 | } | 853 | } |