summaryrefslogtreecommitdiff
path: root/firmware/target/arm/as3525/usb-drv-as3525v2.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/as3525/usb-drv-as3525v2.c')
-rw-r--r--firmware/target/arm/as3525/usb-drv-as3525v2.c113
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
243static void handle_ep0_complete(bool is_ack) 243static 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)
498static void handle_ep_in_int(int ep) 494static 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
548static void handle_ep_out_int(int ep) 544static 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
607static void handle_ep_ints(void) 603static 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
767static int usb_drv_transfer(int ep, void *ptr, int len, bool dir_in, bool blocking) 759static 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
834int usb_drv_recv(int ep, void *ptr, int len) 810int 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
839int usb_drv_send(int ep, void *ptr, int len) 816int 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
844int usb_drv_send_nonblocking(int ep, void *ptr, int len) 822int 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)
862void usb_drv_stall(int ep, bool stall, bool in) 841void 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
877bool usb_drv_stalled(int ep, bool in) 850bool 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}