summaryrefslogtreecommitdiff
path: root/firmware/target/arm/as3525/usb-drv-as3525.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/as3525/usb-drv-as3525.c')
-rw-r--r--firmware/target/arm/as3525/usb-drv-as3525.c97
1 files changed, 45 insertions, 52 deletions
diff --git a/firmware/target/arm/as3525/usb-drv-as3525.c b/firmware/target/arm/as3525/usb-drv-as3525.c
index 61a1265f42..ca484d0395 100644
--- a/firmware/target/arm/as3525/usb-drv-as3525.c
+++ b/firmware/target/arm/as3525/usb-drv-as3525.c
@@ -53,7 +53,9 @@ typedef struct {
53/* 4 input endpoints */ 53/* 4 input endpoints */
54#define USB_IEP_CTRL(i) USB_REG(0x0000 + i*0x20) 54#define USB_IEP_CTRL(i) USB_REG(0x0000 + i*0x20)
55#define USB_IEP_STS(i) USB_REG(0x0004 + i*0x20) 55#define USB_IEP_STS(i) USB_REG(0x0004 + i*0x20)
56/* txfsize: bits 0-15 */
56#define USB_IEP_TXFSIZE(i) USB_REG(0x0008 + i*0x20) 57#define USB_IEP_TXFSIZE(i) USB_REG(0x0008 + i*0x20)
58/* mps: bits 0-10 (max 2047) */
57#define USB_IEP_MPS(i) USB_REG(0x000C + i*0x20) 59#define USB_IEP_MPS(i) USB_REG(0x000C + i*0x20)
58#define USB_IEP_DESC_PTR(i) USB_REG(0x0014 + i*0x20) 60#define USB_IEP_DESC_PTR(i) USB_REG(0x0014 + i*0x20)
59#define USB_IEP_STS_MASK(i) USB_REG(0x0018 + i*0x20) 61#define USB_IEP_STS_MASK(i) USB_REG(0x0018 + i*0x20)
@@ -61,7 +63,9 @@ typedef struct {
61/* 4 output endpoints */ 63/* 4 output endpoints */
62#define USB_OEP_CTRL(i) USB_REG(0x0200 + i*0x20) 64#define USB_OEP_CTRL(i) USB_REG(0x0200 + i*0x20)
63#define USB_OEP_STS(i) USB_REG(0x0204 + i*0x20) 65#define USB_OEP_STS(i) USB_REG(0x0204 + i*0x20)
66/* 'rx packet frame number' */
64#define USB_OEP_RXFR(i) USB_REG(0x0208 + i*0x20) 67#define USB_OEP_RXFR(i) USB_REG(0x0208 + i*0x20)
68/* mps: bits 0-10 (max 2047), bits 23-31 are fifo size */
65#define USB_OEP_MPS(i) USB_REG(0x020C + i*0x20) 69#define USB_OEP_MPS(i) USB_REG(0x020C + i*0x20)
66#define USB_OEP_SUP_PTR(i) USB_REG(0x0210 + i*0x20) 70#define USB_OEP_SUP_PTR(i) USB_REG(0x0210 + i*0x20)
67#define USB_OEP_DESC_PTR(i) USB_REG(0x0214 + i*0x20) 71#define USB_OEP_DESC_PTR(i) USB_REG(0x0214 + i*0x20)
@@ -298,13 +302,8 @@ static struct usb_endpoint endpoints[USB_NUM_EPS][2];
298 * dmadescs may share with each other, since we only access them uncached. 302 * dmadescs may share with each other, since we only access them uncached.
299 */ 303 */
300static struct usb_dev_dma_desc dmadescs[USB_NUM_EPS][2] __attribute__((aligned(32))); 304static struct usb_dev_dma_desc dmadescs[USB_NUM_EPS][2] __attribute__((aligned(32)));
301 305/* reuse unused EP2 OUT descriptor here */
302static struct usb_dev_setup_buf setup_desc; 306static struct usb_dev_setup_buf *setup_desc = (void*)&dmadescs[2][1];
303/* Dummy buffer, to keep rx_buf out of this cacheline */
304static struct usb_dev_setup_buf dummy __attribute__((unused));
305
306static char rx_buf[1024];
307static char tx_buf[1024];
308 307
309#if AS3525_MCLK_SEL != AS3525_CLK_PLLB 308#if AS3525_MCLK_SEL != AS3525_CLK_PLLB
310static inline void usb_enable_pll(void) 309static inline void usb_enable_pll(void)
@@ -402,17 +401,12 @@ static void dma_desc_init(int ep, int dir)
402 401
403 endpoints[ep][dir].uc_desc = uc_desc; 402 endpoints[ep][dir].uc_desc = uc_desc;
404 403
405 if (dir == 0) { 404 uc_desc->status = USB_DMA_DESC_BS_DMA_DONE | \
406 uc_desc->status = USB_DMA_DESC_BS_DMA_DONE | USB_DMA_DESC_LAST | 0x40; 405 USB_DMA_DESC_LAST | \
407 uc_desc->resv = 0xffffffff; 406 USB_DMA_DESC_ZERO_LEN;
408 uc_desc->data_ptr = tx_buf; 407 uc_desc->resv = 0xffffffff;
409 uc_desc->next_desc = 0; 408 uc_desc->data_ptr = 0;
410 } else { 409 uc_desc->next_desc = 0;
411 uc_desc->status = USB_DMA_DESC_BS_HST_RDY | /*USB_DMA_DESC_LAST |*/ 0x40;
412 uc_desc->resv = 0xffffffff;
413 uc_desc->data_ptr = rx_buf;
414 uc_desc->next_desc = 0;
415 }
416} 410}
417 411
418static void reset_endpoints(int init) 412static void reset_endpoints(int init)
@@ -430,7 +424,13 @@ static void reset_endpoints(int init)
430 endpoints[2][1].state |= EP_STATE_ALLOCATED; 424 endpoints[2][1].state |= EP_STATE_ALLOCATED;
431 425
432 for(i = 0; i < USB_NUM_EPS; i++) { 426 for(i = 0; i < USB_NUM_EPS; i++) {
433 int mps = i == 0 ? 64 : 2048; /* For HS */ 427 /*
428 * LS: 8 (control), no bulk available
429 * FS: 64 (control), 64 (bulk)
430 * HS: 64 (control), 512 (bulk)
431 * TODO: switch depending on speed.
432 */
433 int mps = i == 0 ? 64 : 512;
434 434
435 if (init) { 435 if (init) {
436 endpoints[i][0].state = 0; 436 endpoints[i][0].state = 0;
@@ -448,23 +448,23 @@ static void reset_endpoints(int init)
448 USB_IEP_MPS (i) = mps; 448 USB_IEP_MPS (i) = mps;
449 /* We don't care about the 'IN token received' event */ 449 /* We don't care about the 'IN token received' event */
450 USB_IEP_STS_MASK(i) = USB_EP_STAT_IN; /* OF: 0x840 */ 450 USB_IEP_STS_MASK(i) = USB_EP_STAT_IN; /* OF: 0x840 */
451 USB_IEP_TXFSIZE (i) = 0x20; 451 USB_IEP_TXFSIZE (i) = mps/2;
452 USB_IEP_STS (i) = 0xffffffff; /* clear status */ 452 USB_IEP_STS (i) = 0xffffffff; /* clear status */
453 USB_IEP_DESC_PTR(i) = 0; 453 USB_IEP_DESC_PTR(i) = 0;
454 454
455 if (i != 2) { /* Skip the OUT EP0 alias */ 455 if (i != 2) { /* Skip the OUT EP0 alias */
456 dma_desc_init(i, 1); 456 dma_desc_init(i, 1);
457 USB_OEP_CTRL (i) = USB_EP_CTRL_FLUSH|USB_EP_CTRL_SNAK; 457 USB_OEP_CTRL (i) = USB_EP_CTRL_FLUSH|USB_EP_CTRL_SNAK;
458 USB_OEP_MPS (i) = 0x08000000|mps; 458 USB_OEP_MPS (i) = (mps/2 << 23) | mps;
459 USB_OEP_STS_MASK(i) = 0x0000; /* OF: 0x1800 */ 459 USB_OEP_STS_MASK(i) = 0x0000; /* OF: 0x1800 */
460 USB_OEP_RXFR (i) = 0x00; 460 USB_OEP_RXFR (i) = 0; /* Always 0 in OF trace? */
461 USB_OEP_STS (i) = 0xffffffff; /* clear status */ 461 USB_OEP_STS (i) = 0xffffffff; /* clear status */
462 USB_OEP_DESC_PTR(i) = 0; 462 USB_OEP_DESC_PTR(i) = 0;
463 } 463 }
464 } 464 }
465 465
466 setup_desc_init(&setup_desc); 466 setup_desc_init(setup_desc);
467 USB_OEP_SUP_PTR(0) = (int)&setup_desc; 467 USB_OEP_SUP_PTR(0) = (int)setup_desc;
468} 468}
469 469
470void usb_drv_init(void) 470void usb_drv_init(void)
@@ -582,7 +582,7 @@ int usb_drv_request_endpoint(int type, int dir)
582 (type << 4); 582 (type << 4);
583 USB_DEV_EP_INTR_MASK &= ~(1<<(16+i)); 583 USB_DEV_EP_INTR_MASK &= ~(1<<(16+i));
584 } 584 }
585 logf("usb_drv_request_endpoint(%d, %d): returning %02x\n", type, dir, i | dir); 585 /* logf("usb_drv_request_endpoint(%d, %d): returning %02x\n", type, dir, i | dir); */
586 return i | dir; 586 return i | dir;
587 } 587 }
588 588
@@ -610,7 +610,7 @@ void usb_drv_release_endpoint(int ep)
610 if (!(endpoints[i][d].state & EP_STATE_ALLOCATED)) 610 if (!(endpoints[i][d].state & EP_STATE_ALLOCATED))
611 return; 611 return;
612 612
613 logf("usb_drv_release_endpoint(%d, %d)\n", i, d); 613 /* logf("usb_drv_release_endpoint(%d, %d)\n", i, d); */
614 endpoints[i][d].state = 0; 614 endpoints[i][d].state = 0;
615 USB_DEV_EP_INTR_MASK |= (1<<(16*d+i)); 615 USB_DEV_EP_INTR_MASK |= (1<<(16*d+i));
616 USB_EP_CTRL(i, !d) = USB_EP_CTRL_FLUSH | USB_EP_CTRL_SNAK; 616 USB_EP_CTRL(i, !d) = USB_EP_CTRL_FLUSH | USB_EP_CTRL_SNAK;
@@ -705,11 +705,6 @@ void ep_send(int ep, void *ptr, int len)
705 endpoints[ep][0].len = len; 705 endpoints[ep][0].len = len;
706 endpoints[ep][0].rc = -1; 706 endpoints[ep][0].rc = -1;
707 707
708 USB_IEP_CTRL(ep) |= USB_EP_CTRL_CNAK;
709
710 /* TEST: delay a little here */
711 for (i=0; i<1000; i++) asm volatile ("nop\n");
712
713 /* Make sure data is committed to memory */ 708 /* Make sure data is committed to memory */
714 clean_dcache(); 709 clean_dcache();
715 710
@@ -723,11 +718,11 @@ void ep_send(int ep, void *ptr, int len)
723 718
724 uc_desc->data_ptr = virt_to_bus(ptr); 719 uc_desc->data_ptr = virt_to_bus(ptr);
725 720
726 USB_IEP_CTRL(ep) |= USB_EP_CTRL_FLUSH;
727 USB_IEP_DESC_PTR(ep) = (int)&dmadescs[ep][0]; 721 USB_IEP_DESC_PTR(ep) = (int)&dmadescs[ep][0];
728 USB_IEP_STS(ep) = 0xffffffff; /* clear status */ 722 USB_IEP_STS(ep) = 0xffffffff; /* clear status */
729 /* start transfer */ 723 /* start transfer */
730 USB_IEP_CTRL(ep) |= USB_EP_CTRL_PD; 724 USB_IEP_CTRL(ep) |= USB_EP_CTRL_CNAK | USB_EP_CTRL_PD;
725 /* HW automatically sets NAK bit later */
731} 726}
732 727
733int usb_drv_send(int ep, void *ptr, int len) 728int usb_drv_send(int ep, void *ptr, int len)
@@ -760,14 +755,17 @@ static void handle_in_ep(int ep)
760 755
761 USB_IEP_STS(ep) = ep_sts; /* ack */ 756 USB_IEP_STS(ep) = ep_sts; /* ack */
762 757
758 if (ep_sts & USB_EP_STAT_BNA) { /* Buffer was not set up */
759 logf("ep%d IN, status %x (BNA)\n", ep, ep_sts);
760 panicf("ep%d IN 0x%x (BNA)", ep, ep_sts);
761 }
762
763 if (ep_sts & USB_EP_STAT_TDC) { 763 if (ep_sts & USB_EP_STAT_TDC) {
764 ep_sts &= ~USB_EP_STAT_TDC; 764 USB_IEP_CTRL(ep) |= USB_EP_CTRL_FLUSH;
765 /* OF does SNAK and FLUSH at once here */
766 USB_IEP_CTRL(ep) |= USB_EP_CTRL_SNAK | USB_EP_CTRL_FLUSH;
767 endpoints[ep][0].state &= ~EP_STATE_BUSY; 765 endpoints[ep][0].state &= ~EP_STATE_BUSY;
768 endpoints[ep][0].rc = 0; 766 endpoints[ep][0].rc = 0;
769 logf("EP%d %stx done len %x stat %08x\n", 767 logf("EP%d %x %stx done len %x stat %08x\n",
770 ep, endpoints[ep][0].state & EP_STATE_ASYNC ? "async " :"", 768 ep, ep_sts, endpoints[ep][0].state & EP_STATE_ASYNC ? "async " :"",
771 endpoints[ep][0].len, 769 endpoints[ep][0].len,
772 endpoints[ep][0].uc_desc->status); 770 endpoints[ep][0].uc_desc->status);
773 if (endpoints[ep][0].state & EP_STATE_ASYNC) { 771 if (endpoints[ep][0].state & EP_STATE_ASYNC) {
@@ -776,6 +774,7 @@ static void handle_in_ep(int ep)
776 } else { 774 } else {
777 wakeup_signal(&endpoints[ep][0].complete); 775 wakeup_signal(&endpoints[ep][0].complete);
778 } 776 }
777 ep_sts &= ~USB_EP_STAT_TDC;
779 } 778 }
780 779
781 if (ep_sts) { 780 if (ep_sts) {
@@ -790,7 +789,7 @@ static void handle_in_ep(int ep)
790 789
791static void handle_out_ep(int ep) 790static void handle_out_ep(int ep)
792{ 791{
793 struct usb_ctrlrequest *req = (void*)UNCACHED_ADDR(&setup_desc.data1); 792 struct usb_ctrlrequest *req = (void*)UNCACHED_ADDR(&setup_desc->data1);
794 int ep_sts = USB_OEP_STS(ep) & ~USB_OEP_STS_MASK(ep); 793 int ep_sts = USB_OEP_STS(ep) & ~USB_OEP_STS_MASK(ep);
795 struct usb_dev_dma_desc *uc_desc = endpoints[ep][1].uc_desc; 794 struct usb_dev_dma_desc *uc_desc = endpoints[ep][1].uc_desc;
796 795
@@ -810,28 +809,23 @@ static void handle_out_ep(int ep)
810 int dma_frm = (dma_sts >> 16) & 0x7ff; 809 int dma_frm = (dma_sts >> 16) & 0x7ff;
811 int dma_mst = dma_sts & 0xf8000000; 810 int dma_mst = dma_sts & 0xf8000000;
812 811
813 uc_desc->status = USB_DMA_DESC_BS_HST_RDY |
814 USB_DMA_DESC_LAST |
815 0x40;
816 uc_desc->data_ptr = rx_buf;
817 USB_OEP_DESC_PTR(ep) = (int)&dmadescs[ep][1];
818
819 if (!(dma_sts & USB_DMA_DESC_ZERO_LEN)) { 812 if (!(dma_sts & USB_DMA_DESC_ZERO_LEN)) {
820 logf("EP%d OUT token, st:%08x len:%d frm:%x data=%s\n", ep, 813 logf("EP%d OUT token, st:%08x len:%d frm:%x data=%s epstate=%d\n", ep,
821 dma_mst, dma_len, dma_frm, make_hex(uc_desc->data_ptr, dma_len)); 814 dma_mst, dma_len, dma_frm, make_hex(uc_desc->data_ptr, dma_len),
815 endpoints[ep][1].state);
822 /* 816 /*
823 * If parts of the just dmaed range are in cache, dump them now. 817 * If parts of the just dmaed range are in cache, dump them now.
824 */ 818 */
825 dump_dcache_range(uc_desc->data_ptr, dma_len); 819 dump_dcache_range(uc_desc->data_ptr, dma_len);
826 } else{ 820 } else{
827 logf("EP%d OUT token, st:%08x len:%d frm:%x\n", ep, 821 logf("EP%d OUT token, st:%08x frm:%x (no data)\n", ep,
828 dma_mst, dma_len, dma_frm); 822 dma_mst, dma_frm);
829 } 823 }
830 824
831 if (endpoints[ep][1].state & EP_STATE_BUSY) { 825 if (endpoints[ep][1].state & EP_STATE_BUSY) {
832 endpoints[ep][1].state &= ~EP_STATE_BUSY; 826 endpoints[ep][1].state &= ~EP_STATE_BUSY;
833 endpoints[ep][1].rc = 0; 827 endpoints[ep][1].rc = 0;
834 usb_core_transfer_complete(ep, 0, 0, endpoints[ep][0].len); 828 usb_core_transfer_complete(ep, USB_DIR_OUT, 0, dma_len);
835 } else { 829 } else {
836 logf("EP%d OUT, but no one was listening?\n", ep); 830 logf("EP%d OUT, but no one was listening?\n", ep);
837 } 831 }
@@ -854,7 +848,7 @@ static void handle_out_ep(int ep)
854 req->wLength); 848 req->wLength);
855 849
856 usb_core_control_request(&req_copy); 850 usb_core_control_request(&req_copy);
857 setup_desc_init(&setup_desc); 851 setup_desc_init(setup_desc);
858 852
859 ep_sts &= ~USB_EP_STAT_SETUP_RCVD; 853 ep_sts &= ~USB_EP_STAT_SETUP_RCVD;
860 } 854 }
@@ -1029,7 +1023,6 @@ void usb_drv_set_test_mode(int mode)
1029 (void)mode; 1023 (void)mode;
1030} 1024}
1031 1025
1032/* handled internally by controller */
1033void usb_drv_set_address(int address) 1026void usb_drv_set_address(int address)
1034{ 1027{
1035 (void)address; 1028 (void)address;