summaryrefslogtreecommitdiff
path: root/firmware/target/arm/usb-drv-pp502x.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/usb-drv-pp502x.c')
-rw-r--r--firmware/target/arm/usb-drv-pp502x.c184
1 files changed, 147 insertions, 37 deletions
diff --git a/firmware/target/arm/usb-drv-pp502x.c b/firmware/target/arm/usb-drv-pp502x.c
index 1db3ebd42f..413d905293 100644
--- a/firmware/target/arm/usb-drv-pp502x.c
+++ b/firmware/target/arm/usb-drv-pp502x.c
@@ -294,7 +294,7 @@ struct transfer_descriptor {
294 unsigned int reserved; 294 unsigned int reserved;
295} __attribute__ ((packed)); 295} __attribute__ ((packed));
296 296
297static struct transfer_descriptor _td_array[NUM_ENDPOINTS*2] __attribute((aligned (32))); 297static struct transfer_descriptor _td_array[32] __attribute((aligned (32)));
298static struct transfer_descriptor* td_array; 298static struct transfer_descriptor* td_array;
299 299
300/* manual: 32.13.1 Endpoint Queue Head (dQH) */ 300/* manual: 32.13.1 Endpoint Queue Head (dQH) */
@@ -317,9 +317,15 @@ static const unsigned int pipe2mask[NUM_ENDPOINTS*2] = {
317 0x04, 0x040000, 317 0x04, 0x040000,
318}; 318};
319 319
320static struct transfer_descriptor* first_td;
321static struct transfer_descriptor* last_td;
322
320/*-------------------------------------------------------------------------*/ 323/*-------------------------------------------------------------------------*/
321static void transfer_completed(void); 324static void transfer_completed(void);
322static int prime_transfer(int endpoint, void* ptr, int len, bool send); 325static int prime_transfer(int endpoint, void* ptr, int len, bool send);
326static void prepare_td(struct transfer_descriptor* td,
327 struct transfer_descriptor* previous_td,
328 void *ptr, int len);
323static void bus_reset(void); 329static void bus_reset(void);
324static void init_queue_heads(void); 330static void init_queue_heads(void);
325static void init_endpoints(void); 331static void init_endpoints(void);
@@ -340,6 +346,10 @@ void usb_drv_init(void)
340 346
341 REG_USBMODE = USBMODE_CTRL_MODE_DEVICE; 347 REG_USBMODE = USBMODE_CTRL_MODE_DEVICE;
342 348
349 /* Force device to full speed */
350 /* See 32.9.5.9.2 */
351 REG_PORTSC1 |= PORTSCX_PORT_FORCE_FULL_SPEED;
352
343 td_array = (struct transfer_descriptor*)UNCACHED_ADDR(&_td_array); 353 td_array = (struct transfer_descriptor*)UNCACHED_ADDR(&_td_array);
344 qh_array = (struct queue_head*)UNCACHED_ADDR(&_qh_array); 354 qh_array = (struct queue_head*)UNCACHED_ADDR(&_qh_array);
345 init_queue_heads(); 355 init_queue_heads();
@@ -467,6 +477,10 @@ void usb_drv_wait(int endpoint, bool send)
467 } 477 }
468} 478}
469 479
480int usb_drv_port_speed(void)
481{
482 return (REG_PORTSC1 & 0x08000000) ? 1 : 0;
483}
470 484
471void usb_drv_set_address(int address) 485void usb_drv_set_address(int address)
472{ 486{
@@ -482,44 +496,87 @@ void usb_drv_reset_endpoint(int endpoint, bool send)
482 while (REG_ENDPTFLUSH & mask); 496 while (REG_ENDPTFLUSH & mask);
483} 497}
484 498
499int usb_drv_get_last_transfer_length(void)
500{
501 struct transfer_descriptor* current_td = first_td;
502 int length = 0;
503
504 while (!((unsigned int)current_td & DTD_NEXT_TERMINATE)) {
505 if ((current_td->size_ioc_sts & 0xff) != 0)
506 return -1;
507
508 length += current_td->reserved -
509 ((current_td->size_ioc_sts & DTD_PACKET_SIZE) >> DTD_LENGTH_BIT_POS);
510 current_td = (struct transfer_descriptor*)current_td->next_td_ptr;
511 }
512 return length;
513}
514int usb_drv_get_last_transfer_status(void)
515{
516 struct transfer_descriptor* current_td = first_td;
517
518 while (!((unsigned int)current_td & DTD_NEXT_TERMINATE)) {
519 if ((current_td->size_ioc_sts & 0xff) != 0)
520 return current_td->size_ioc_sts & 0xff;
521
522 current_td = (struct transfer_descriptor*)current_td->next_td_ptr;
523 }
524 return 0;
525}
526
485/*-------------------------------------------------------------------------*/ 527/*-------------------------------------------------------------------------*/
486 528
487/* manual: 32.14.5.2 */ 529/* manual: 32.14.5.2 */
488static int prime_transfer(int endpoint, void* ptr, int len, bool send) 530static int prime_transfer(int endpoint, void* ptr, int len, bool send)
489{ 531{
490 int timeout;
491 int pipe = endpoint * 2 + (send ? 1 : 0); 532 int pipe = endpoint * 2 + (send ? 1 : 0);
492 unsigned int mask = pipe2mask[pipe]; 533 unsigned int mask = pipe2mask[pipe];
493 struct transfer_descriptor* td = &td_array[pipe]; 534 last_td = 0;
494 struct queue_head* qh = &qh_array[pipe]; 535 struct queue_head* qh = &qh_array[pipe];
536 static long last_tick;
495 537
538/*
496 if (send && endpoint > EP_CONTROL) { 539 if (send && endpoint > EP_CONTROL) {
497 logf("usb: sent %d bytes", len); 540 logf("usb: sent %d bytes", len);
498 } 541 }
542*/
499 543
500 memset(td, 0, sizeof(struct transfer_descriptor)); 544 if (len==0) {
501 td->next_td_ptr = DTD_NEXT_TERMINATE; 545 struct transfer_descriptor* new_td = &td_array[0];
502 td->size_ioc_sts = (len << DTD_LENGTH_BIT_POS) | 546 prepare_td(new_td, 0, ptr, 0);
503 DTD_STATUS_ACTIVE | DTD_IOC; 547
504 td->buff_ptr0 = (unsigned int)ptr; 548 last_td = new_td;
505 td->buff_ptr1 = (unsigned int)ptr + 0x1000; 549 first_td = new_td;
506 td->buff_ptr2 = (unsigned int)ptr + 0x2000; 550 }
507 td->buff_ptr3 = (unsigned int)ptr + 0x3000; 551 else {
508 td->buff_ptr4 = (unsigned int)ptr + 0x4000; 552 int td_idx = 0;
509 td->reserved = len; 553 while (len > 0) {
510 qh->dtd.next_td_ptr = (unsigned int)td; 554 int current_transfer_length = MIN(16384,len);
555 struct transfer_descriptor* new_td = &td_array[td_idx];
556 prepare_td(new_td, last_td, ptr, current_transfer_length);
557
558 last_td = new_td;
559 len -= current_transfer_length;
560 td_idx++;
561 ptr += current_transfer_length;
562 }
563 first_td = &td_array[0];
564 }
565
566 qh->dtd.next_td_ptr = (unsigned int)first_td;
511 qh->dtd.size_ioc_sts &= ~(QH_STATUS_HALT | QH_STATUS_ACTIVE); 567 qh->dtd.size_ioc_sts &= ~(QH_STATUS_HALT | QH_STATUS_ACTIVE);
512 568
513 REG_ENDPTPRIME |= mask; 569 REG_ENDPTPRIME |= mask;
514 570
515 timeout = 10000; 571 last_tick = current_tick;
516 while ((REG_ENDPTPRIME & mask) && --timeout) { 572 while ((REG_ENDPTPRIME & mask)) {
517 if (REG_USBSTS & USBSTS_RESET) 573 if (REG_USBSTS & USBSTS_RESET)
518 return -1; 574 return -1;
519 } 575
520 if (!timeout) { 576 if (TIME_AFTER(current_tick, last_tick + HZ/4)) {
521 logf("prime timeout"); 577 logf("prime timeout");
522 return -2; 578 return -2;
579 }
523 } 580 }
524 581
525 if (!(REG_ENDPTSTATUS & mask)) { 582 if (!(REG_ENDPTSTATUS & mask)) {
@@ -529,23 +586,54 @@ static int prime_transfer(int endpoint, void* ptr, int len, bool send)
529 586
530 if (send) { 587 if (send) {
531 /* wait for transfer to finish */ 588 /* wait for transfer to finish */
532 timeout = 100000; 589 struct transfer_descriptor* current_td = first_td;
533 while ((td->size_ioc_sts & DTD_STATUS_ACTIVE) && --timeout) { 590
534 if (REG_ENDPTCOMPLETE & mask) 591 while (!((unsigned int)current_td & DTD_NEXT_TERMINATE)) {
535 REG_ENDPTCOMPLETE |= mask; 592 while ((current_td->size_ioc_sts & 0xff) == DTD_STATUS_ACTIVE) {
536 593 if (REG_ENDPTCOMPLETE & mask)
537 if (REG_USBSTS & USBSTS_RESET) 594 REG_ENDPTCOMPLETE |= mask;
538 return -4; 595
539 } 596 /* let the host handle timeouts */
540 if (!timeout) { 597 if (REG_USBSTS & USBSTS_RESET) {
541 logf("td never finished"); 598 logf("td interrupted by reset");
542 return -5; 599 return -4;
600 }
601 }
602 if ((current_td->size_ioc_sts & 0xff) != 0) {
603 logf("td failed with error %X",(current_td->size_ioc_sts & 0xff));
604 return -6;
605 }
606 //logf("td finished : %X",current_td->size_ioc_sts & 0xff);
607 current_td=(struct transfer_descriptor*)current_td->next_td_ptr;
543 } 608 }
609 //logf("all tds done");
544 } 610 }
545 611
546 return 0; 612 return 0;
547} 613}
548 614
615static void prepare_td(struct transfer_descriptor* td,
616 struct transfer_descriptor* previous_td,
617 void *ptr, int len)
618{
619 //logf("adding a td : %d",len);
620 memset(td, 0, sizeof(struct transfer_descriptor));
621 td->next_td_ptr = DTD_NEXT_TERMINATE;
622 td->size_ioc_sts = (len<< DTD_LENGTH_BIT_POS) |
623 DTD_STATUS_ACTIVE | DTD_IOC;
624 td->buff_ptr0 = (unsigned int)ptr;
625 td->buff_ptr1 = ((unsigned int)ptr & 0xfffff000) + 0x1000;
626 td->buff_ptr2 = ((unsigned int)ptr & 0xfffff000) + 0x2000;
627 td->buff_ptr3 = ((unsigned int)ptr & 0xfffff000) + 0x3000;
628 td->buff_ptr4 = ((unsigned int)ptr & 0xfffff000) + 0x4000;
629 td->reserved = len;
630
631 if (previous_td != 0) {
632 previous_td->next_td_ptr=(unsigned int)td;
633 previous_td->size_ioc_sts&=~DTD_IOC;// Only an interrupt on the last one
634 }
635}
636
549static void transfer_completed(void) 637static void transfer_completed(void)
550{ 638{
551 int i; 639 int i;
@@ -557,13 +645,16 @@ static void transfer_completed(void)
557 for (i=0; i<NUM_ENDPOINTS; i++) { 645 for (i=0; i<NUM_ENDPOINTS; i++) {
558 int x; 646 int x;
559 for (x=0; x<2; x++) { 647 for (x=0; x<2; x++) {
648 unsigned int status;
560 int pipe = i * 2 + x; 649 int pipe = i * 2 + x;
650
561 if (mask & pipe2mask[pipe]) 651 if (mask & pipe2mask[pipe])
562 usb_core_transfer_complete(i, x ? true : false); 652 usb_core_transfer_complete(i, x ? true : false);
563 653
654 status = usb_drv_get_last_transfer_status();
564 if ((mask & pipe2mask[pipe]) && 655 if ((mask & pipe2mask[pipe]) &&
565 (td_array[pipe].size_ioc_sts & DTD_ERROR_MASK)) { 656 status & DTD_ERROR_MASK) {
566 logf("pipe %d err %x", pipe, td_array[pipe].size_ioc_sts & DTD_ERROR_MASK); 657 logf("pipe %d err %x", pipe, status & DTD_ERROR_MASK);
567 } 658 }
568 } 659 }
569 } 660 }
@@ -600,23 +691,42 @@ static void bus_reset(void)
600 if (!(REG_PORTSC1 & PORTSCX_PORT_RESET)) { 691 if (!(REG_PORTSC1 & PORTSCX_PORT_RESET)) {
601 logf("usb: slow reset!"); 692 logf("usb: slow reset!");
602 } 693 }
694
695 logf("PTS : %X",(REG_PORTSC1 & 0xC0000000)>>30);
696 logf("STS : %X",(REG_PORTSC1 & 0x20000000)>>29);
697 logf("PTW : %X",(REG_PORTSC1 & 0x10000000)>>28);
698 logf("PSPD : %X",(REG_PORTSC1 & 0x0C000000)>>26);
699 logf("PFSC : %X",(REG_PORTSC1 & 0x01000000)>>24);
700 logf("PTC : %X",(REG_PORTSC1 & 0x000F0000)>>16);
701 logf("PO : %X",(REG_PORTSC1 & 0x00002000)>>13);
603} 702}
604 703
605/* manual: 32.14.4.1 Queue Head Initialization */ 704/* manual: 32.14.4.1 Queue Head Initialization */
606static void init_queue_heads(void) 705static void init_queue_heads(void)
607{ 706{
707 int tx_packetsize;
708 int rx_packetsize;
709
710 if (usb_drv_port_speed()) {
711 rx_packetsize = 512;
712 tx_packetsize = 512;
713 }
714 else {
715 rx_packetsize = 16;
716 tx_packetsize = 16;
717 }
608 memset(qh_array, 0, sizeof _qh_array); 718 memset(qh_array, 0, sizeof _qh_array);
609 719
610 /*** control ***/ 720 /*** control ***/
611 qh_array[EP_CONTROL].max_pkt_length = 512 << QH_MAX_PKT_LEN_POS | QH_IOS; 721 qh_array[EP_CONTROL].max_pkt_length = 64 << QH_MAX_PKT_LEN_POS | QH_IOS;
612 qh_array[EP_CONTROL].dtd.next_td_ptr = QH_NEXT_TERMINATE; 722 qh_array[EP_CONTROL].dtd.next_td_ptr = QH_NEXT_TERMINATE;
613 qh_array[EP_CONTROL+1].max_pkt_length = 512 << QH_MAX_PKT_LEN_POS; 723 qh_array[EP_CONTROL+1].max_pkt_length = 64 << QH_MAX_PKT_LEN_POS;
614 qh_array[EP_CONTROL+1].dtd.next_td_ptr = QH_NEXT_TERMINATE; 724 qh_array[EP_CONTROL+1].dtd.next_td_ptr = QH_NEXT_TERMINATE;
615 725
616 /*** bulk ***/ 726 /*** bulk ***/
617 qh_array[EP_RX*2].max_pkt_length = 512 << QH_MAX_PKT_LEN_POS; 727 qh_array[EP_RX*2].max_pkt_length = rx_packetsize << QH_MAX_PKT_LEN_POS | QH_ZLT_SEL;
618 qh_array[EP_RX*2].dtd.next_td_ptr = QH_NEXT_TERMINATE; 728 qh_array[EP_RX*2].dtd.next_td_ptr = QH_NEXT_TERMINATE;
619 qh_array[EP_TX*2+1].max_pkt_length = 512 << QH_MAX_PKT_LEN_POS; 729 qh_array[EP_TX*2+1].max_pkt_length = tx_packetsize << QH_MAX_PKT_LEN_POS | QH_ZLT_SEL;
620 qh_array[EP_TX*2+1].dtd.next_td_ptr = QH_NEXT_TERMINATE; 730 qh_array[EP_TX*2+1].dtd.next_td_ptr = QH_NEXT_TERMINATE;
621} 731}
622 732