diff options
author | Solomon Peachy <pizza@shaftnet.org> | 2020-08-24 23:34:34 -0400 |
---|---|---|
committer | Solomon Peachy <pizza@shaftnet.org> | 2020-08-25 12:16:33 +0000 |
commit | 63ef81de314a29b3289ff896a29a8844c6f1607f (patch) | |
tree | 754792070c10723413038e33493eabf29a153ec4 | |
parent | c06766bbeb13146c78c5aa1a4a3c4298de5d3f13 (diff) | |
download | rockbox-63ef81de314a29b3289ff896a29a8844c6f1607f.tar.gz rockbox-63ef81de314a29b3289ff896a29a8844c6f1607f.zip |
jz4760: Give each SD interface its own DMA channel, semaphore, and mutex
* Allows both SD interfaces to have requests in flight simultaneously
* Fixed a deadlock in the hotswap code
* Ensure TX DMA is idle before initiating a request (bug due to a typo)
Change-Id: I988fa29df5f8e41fc6bbdcc517db89842003b34d
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/ata-sd-jz4760.c | 251 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/system-jz4760.c | 6 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/system-target.h | 9 |
3 files changed, 175 insertions, 91 deletions
diff --git a/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4760.c b/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4760.c index 6862262045..0717f80b9d 100644 --- a/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4760.c +++ b/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4760.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "storage.h" | 30 | #include "storage.h" |
31 | #include "string.h" | 31 | #include "string.h" |
32 | 32 | ||
33 | #define SD_INTERRUPT 0 | ||
33 | #define SD_DMA_ENABLE 1 | 34 | #define SD_DMA_ENABLE 1 |
34 | #define SD_DMA_INTERRUPT 0 | 35 | #define SD_DMA_INTERRUPT 0 |
35 | 36 | ||
@@ -39,6 +40,7 @@ | |||
39 | 40 | ||
40 | static long last_disk_activity = -1; | 41 | static long last_disk_activity = -1; |
41 | static tCardInfo card[NUM_DRIVES]; | 42 | static tCardInfo card[NUM_DRIVES]; |
43 | static char active[NUM_DRIVES]; | ||
42 | 44 | ||
43 | #if defined(CONFIG_STORAGE_MULTI) || defined(HAVE_HOTSWAP) | 45 | #if defined(CONFIG_STORAGE_MULTI) || defined(HAVE_HOTSWAP) |
44 | static int sd_drive_nr = 0; | 46 | static int sd_drive_nr = 0; |
@@ -46,9 +48,9 @@ static int sd_drive_nr = 0; | |||
46 | #define sd_drive_nr 0 | 48 | #define sd_drive_nr 0 |
47 | #endif | 49 | #endif |
48 | 50 | ||
49 | static struct mutex sd_mtx; | 51 | static struct mutex sd_mtx[NUM_DRIVES]; |
50 | #if SD_DMA_INTERRUPT | 52 | #if SD_DMA_INTERRUPT || SD_INTERRUPT |
51 | static struct semaphore sd_wakeup; | 53 | static struct semaphore sd_wakeup[NUM_DRIVES]; |
52 | #endif | 54 | #endif |
53 | 55 | ||
54 | static int use_4bit[NUM_DRIVES]; | 56 | static int use_4bit[NUM_DRIVES]; |
@@ -382,6 +384,11 @@ static void jz_sd_get_response(const int drive, struct sd_request *request) | |||
382 | } | 384 | } |
383 | } | 385 | } |
384 | 386 | ||
387 | #if SD_DMA_ENABLE | ||
388 | static int jz_sd_transmit_data_dma(const int drive, struct sd_request *req); | ||
389 | static int jz_sd_receive_data_dma(const int drive, struct sd_request *req); | ||
390 | #endif | ||
391 | |||
385 | static int jz_sd_receive_data(const int drive, struct sd_request *req) | 392 | static int jz_sd_receive_data(const int drive, struct sd_request *req) |
386 | { | 393 | { |
387 | unsigned int nob = req->nob; | 394 | unsigned int nob = req->nob; |
@@ -391,6 +398,12 @@ static int jz_sd_receive_data(const int drive, struct sd_request *req) | |||
391 | unsigned int waligned = (((unsigned int) buf & 0x3) == 0); /* word aligned ? */ | 398 | unsigned int waligned = (((unsigned int) buf & 0x3) == 0); /* word aligned ? */ |
392 | unsigned int stat, data, cnt; | 399 | unsigned int stat, data, cnt; |
393 | 400 | ||
401 | #if SD_DMA_ENABLE | ||
402 | /* Use DMA if we can */ | ||
403 | if ((int)req->buffer & 0x3 == 0) | ||
404 | return jz_sd_receive_data_dma(drive, req); | ||
405 | #endif | ||
406 | |||
394 | for (; nob >= 1; nob--) | 407 | for (; nob >= 1; nob--) |
395 | { | 408 | { |
396 | long deadline = current_tick + (HZ * 65); | 409 | long deadline = current_tick + (HZ * 65); |
@@ -448,6 +461,12 @@ static int jz_sd_transmit_data(const int drive, struct sd_request *req) | |||
448 | unsigned int waligned = (((unsigned int) buf & 0x3) == 0); /* word aligned ? */ | 461 | unsigned int waligned = (((unsigned int) buf & 0x3) == 0); /* word aligned ? */ |
449 | unsigned int stat, data, cnt; | 462 | unsigned int stat, data, cnt; |
450 | 463 | ||
464 | #if SD_DMA_ENABLE | ||
465 | /* Use DMA if we can */ | ||
466 | if ((int)req->buffer & 0x3 == 0) | ||
467 | return jz_sd_transmit_data_dma(drive, req); | ||
468 | #endif | ||
469 | |||
451 | for (; nob >= 1; nob--) | 470 | for (; nob >= 1; nob--) |
452 | { | 471 | { |
453 | long deadline = current_tick + (HZ * 65); | 472 | long deadline = current_tick + (HZ * 65); |
@@ -498,123 +517,162 @@ static int jz_sd_transmit_data(const int drive, struct sd_request *req) | |||
498 | #if SD_DMA_ENABLE | 517 | #if SD_DMA_ENABLE |
499 | static int jz_sd_receive_data_dma(const int drive, struct sd_request *req) | 518 | static int jz_sd_receive_data_dma(const int drive, struct sd_request *req) |
500 | { | 519 | { |
501 | if ((unsigned int)req->buffer & 0x3) | ||
502 | return jz_sd_receive_data(drive, req); | ||
503 | |||
504 | /* flush dcache */ | ||
505 | dma_cache_wback_inv((unsigned long) req->buffer, req->cnt); | ||
506 | |||
507 | /* setup dma channel */ | 520 | /* setup dma channel */ |
508 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL) = 0; | 521 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(drive)) = 0; |
509 | REG_DMAC_DSAR(DMA_SD_RX_CHANNEL) = PHYSADDR(MSC_RXFIFO(MSC_CHN(drive))); /* DMA source addr */ | 522 | REG_DMAC_DSAR(DMA_SD_RX_CHANNEL(drive)) = PHYSADDR(MSC_RXFIFO(MSC_CHN(drive))); /* DMA source addr */ |
510 | REG_DMAC_DTAR(DMA_SD_RX_CHANNEL) = PHYSADDR((unsigned long)req->buffer); /* DMA dest addr */ | 523 | REG_DMAC_DTAR(DMA_SD_RX_CHANNEL(drive)) = PHYSADDR((unsigned long)req->buffer); /* DMA dest addr */ |
511 | REG_DMAC_DTCR(DMA_SD_RX_CHANNEL) = (req->cnt + 3) >> 2; /* DMA transfer count */ | 524 | REG_DMAC_DTCR(DMA_SD_RX_CHANNEL(drive)) = (req->cnt + 3) >> 2; /* DMA transfer count */ |
512 | REG_DMAC_DRSR(DMA_SD_RX_CHANNEL) = (drive == SD_SLOT_1) ? DMAC_DRSR_RS_MSC2IN : DMAC_DRSR_RS_MSC1IN; /* DMA request type */ | 525 | REG_DMAC_DRSR(DMA_SD_RX_CHANNEL(drive)) = (drive == SD_SLOT_1) ? DMAC_DRSR_RS_MSC2IN : DMAC_DRSR_RS_MSC1IN; /* DMA request type */ |
513 | 526 | ||
514 | REG_DMAC_DCMD(DMA_SD_RX_CHANNEL) = | 527 | REG_DMAC_DCMD(DMA_SD_RX_CHANNEL(drive)) = |
515 | #if SD_DMA_INTERRUPT | 528 | #if SD_DMA_INTERRUPT |
516 | DMAC_DCMD_TIE | /* Enable DMA interrupt */ | 529 | DMAC_DCMD_TIE | /* Enable DMA interrupt */ |
517 | #endif | 530 | #endif |
518 | DMAC_DCMD_DAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | | 531 | DMAC_DCMD_DAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | |
519 | DMAC_DCMD_DS_32BIT; | 532 | DMAC_DCMD_DS_32BIT; |
520 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL) = DMAC_DCCSR_EN | DMAC_DCCSR_NDES; | 533 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(drive)) = DMAC_DCCSR_EN | DMAC_DCCSR_NDES; |
521 | 534 | ||
522 | /* wait for dma completion */ | 535 | /* wait for dma completion */ |
523 | #if SD_DMA_INTERRUPT | 536 | #if SD_DMA_INTERRUPT |
524 | semaphore_wait(&sd_wakeup, TIMEOUT_BLOCK); | 537 | semaphore_wait(&sd_wakeup[drive], TIMEOUT_BLOCK); |
525 | #else | 538 | #else |
526 | while (REG_DMAC_DTCR(DMA_SD_RX_CHANNEL)) | 539 | while (REG_DMAC_DTCR(DMA_SD_RX_CHANNEL(drive))) |
527 | yield(); | 540 | yield(); |
528 | #endif | 541 | #endif |
529 | 542 | ||
530 | /* clear status and disable channel */ | 543 | /* clear status and disable channel */ |
531 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL) = 0; | 544 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(drive)) = 0; |
545 | |||
546 | /* flush dcache */ | ||
547 | dma_cache_wback_inv((unsigned long) req->buffer, req->cnt); | ||
532 | 548 | ||
533 | return SD_NO_ERROR; | 549 | return SD_NO_ERROR; |
534 | } | 550 | } |
535 | 551 | ||
536 | static int jz_sd_transmit_data_dma(const int drive, struct sd_request *req) | 552 | static int jz_sd_transmit_data_dma(const int drive, struct sd_request *req) |
537 | { | 553 | { |
538 | if ((unsigned int)req->buffer & 0x3) | ||
539 | return jz_sd_transmit_data(drive, req); | ||
540 | |||
541 | /* flush dcache */ | 554 | /* flush dcache */ |
542 | dma_cache_wback_inv((unsigned long) req->buffer, req->cnt); | 555 | dma_cache_wback_inv((unsigned long) req->buffer, req->cnt); |
543 | 556 | ||
544 | /* setup dma channel */ | 557 | /* setup dma channel */ |
545 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL) = 0; | 558 | REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(drive)) = 0; |
546 | REG_DMAC_DSAR(DMA_SD_TX_CHANNEL) = PHYSADDR((unsigned long) req->buffer); /* DMA source addr */ | 559 | REG_DMAC_DSAR(DMA_SD_TX_CHANNEL(drive)) = PHYSADDR((unsigned long) req->buffer); /* DMA source addr */ |
547 | REG_DMAC_DTAR(DMA_SD_TX_CHANNEL) = PHYSADDR(MSC_TXFIFO(MSC_CHN(drive))); /* DMA dest addr */ | 560 | REG_DMAC_DTAR(DMA_SD_TX_CHANNEL(drive)) = PHYSADDR(MSC_TXFIFO(MSC_CHN(drive))); /* DMA dest addr */ |
548 | REG_DMAC_DTCR(DMA_SD_TX_CHANNEL) = (req->cnt + 3) >> 2; /* DMA transfer count */ | 561 | REG_DMAC_DTCR(DMA_SD_TX_CHANNEL(drive)) = (req->cnt + 3) >> 2; /* DMA transfer count */ |
549 | REG_DMAC_DRSR(DMA_SD_TX_CHANNEL) = (drive == SD_SLOT_1) ? DMAC_DRSR_RS_MSC2OUT : DMAC_DRSR_RS_MSC1OUT; /* DMA request type */ | 562 | REG_DMAC_DRSR(DMA_SD_TX_CHANNEL(drive)) = (drive == SD_SLOT_1) ? DMAC_DRSR_RS_MSC2OUT : DMAC_DRSR_RS_MSC1OUT; /* DMA request type */ |
550 | 563 | ||
551 | REG_DMAC_DCMD(DMA_SD_TX_CHANNEL) = | 564 | REG_DMAC_DCMD(DMA_SD_TX_CHANNEL(drive)) = |
552 | #if SD_DMA_INTERRUPT | 565 | #if SD_DMA_INTERRUPT |
553 | DMAC_DCMD_TIE | /* Enable DMA interrupt */ | 566 | DMAC_DCMD_TIE | /* Enable DMA interrupt */ |
554 | #endif | 567 | #endif |
555 | DMAC_DCMD_SAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | | 568 | DMAC_DCMD_SAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | |
556 | DMAC_DCMD_DS_32BIT; | 569 | DMAC_DCMD_DS_32BIT; |
557 | REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL) = DMAC_DCCSR_EN | DMAC_DCCSR_NDES; | 570 | REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(drive)) = DMAC_DCCSR_EN | DMAC_DCCSR_NDES; |
558 | 571 | ||
559 | /* wait for dma completion */ | 572 | /* wait for dma completion */ |
560 | #if SD_DMA_INTERRUPT | 573 | #if SD_DMA_INTERRUPT |
561 | semaphore_wait(&sd_wakeup, TIMEOUT_BLOCK); | 574 | semaphore_wait(&sd_wakeup[drive], TIMEOUT_BLOCK); |
562 | #else | 575 | #else |
563 | while (REG_DMAC_DTCR(DMA_SD_TX_CHANNEL)) | 576 | while (REG_DMAC_DTCR(DMA_SD_TX_CHANNEL(drive))) |
564 | yield(); | 577 | yield(); |
565 | #endif | 578 | #endif |
566 | 579 | ||
567 | /* clear status and disable channel */ | 580 | /* clear status and disable channel */ |
568 | REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL) = 0; | 581 | REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(drive)) = 0; |
569 | 582 | ||
570 | return SD_NO_ERROR; | 583 | return SD_NO_ERROR; |
571 | } | 584 | } |
572 | 585 | ||
573 | #if SD_DMA_INTERRUPT | 586 | #if SD_DMA_INTERRUPT |
574 | void DMA_CALLBACK(DMA_SD_RX_CHANNEL)(void) | 587 | void DMA_CALLBACK(DMA_SD_RX_CHANNEL0)(void) |
575 | { | 588 | { |
576 | if (REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL) & DMAC_DCCSR_AR) | 589 | if (REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_1)) & DMAC_DCCSR_AR) |
577 | { | 590 | { |
578 | logf("SD RX DMA address error"); | 591 | logf("SD RX DMA address error"); |
579 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL) &= ~DMAC_DCCSR_AR; | 592 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_1)) &= ~DMAC_DCCSR_AR; |
580 | } | 593 | } |
581 | 594 | ||
582 | if (REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL) & DMAC_DCCSR_HLT) | 595 | if (REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_1)) & DMAC_DCCSR_HLT) |
583 | { | 596 | { |
584 | logf("SD RX DMA halt"); | 597 | logf("SD RX DMA halt"); |
585 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL) &= ~DMAC_DCCSR_HLT; | 598 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_1)) &= ~DMAC_DCCSR_HLT; |
586 | } | 599 | } |
587 | 600 | ||
588 | if (REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL) & DMAC_DCCSR_TT) | 601 | if (REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_1)) & DMAC_DCCSR_TT) |
589 | { | 602 | { |
590 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL) &= ~DMAC_DCCSR_TT; | 603 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_1)) &= ~DMAC_DCCSR_TT; |
591 | //sd_rx_dma_callback(); | 604 | //sd_rx_dma_callback(); |
592 | } | 605 | } |
593 | 606 | ||
594 | semaphore_release(&sd_wakeup); | 607 | semaphore_release(&sd_wakeup[SD_SLOT_1]); |
595 | } | 608 | } |
596 | 609 | ||
597 | void DMA_CALLBACK(DMA_SD_TX_CHANNEL)(void) | 610 | void DMA_CALLBACK(DMA_SD_RX_CHANNEL1)(void) |
598 | { | 611 | { |
599 | if (REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL) & DMAC_DCCSR_AR) | 612 | if (REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_2)) & DMAC_DCCSR_AR) |
613 | { | ||
614 | logf("SD RX DMA address error"); | ||
615 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_2)) &= ~DMAC_DCCSR_AR; | ||
616 | } | ||
617 | |||
618 | if (REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_2)) & DMAC_DCCSR_HLT) | ||
619 | { | ||
620 | logf("SD RX DMA halt"); | ||
621 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_2)) &= ~DMAC_DCCSR_HLT; | ||
622 | } | ||
623 | |||
624 | if (REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_2)) & DMAC_DCCSR_TT) | ||
625 | { | ||
626 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL(SD_SLOT_2)) &= ~DMAC_DCCSR_TT; | ||
627 | //sd_rx_dma_callback(); | ||
628 | } | ||
629 | |||
630 | semaphore_release(&sd_wakeup[SD_SLOT_2]); | ||
631 | } | ||
632 | |||
633 | void DMA_CALLBACK(DMA_SD_TX_CHANNEL0)(void) | ||
634 | { | ||
635 | if (REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_1)) & DMAC_DCCSR_AR) | ||
600 | { | 636 | { |
601 | logf("SD TX DMA address error: %x, %x, %x", var1, var2, var3); | 637 | logf("SD TX DMA address error: %x, %x, %x", var1, var2, var3); |
602 | REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL) &= ~DMAC_DCCSR_AR; | 638 | REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_1)) &= ~DMAC_DCCSR_AR; |
603 | } | 639 | } |
604 | 640 | ||
605 | if (REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL) & DMAC_DCCSR_HLT) | 641 | if (REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_1)) & DMAC_DCCSR_HLT) |
606 | { | 642 | { |
607 | logf("SD TX DMA halt"); | 643 | logf("SD TX DMA halt"); |
608 | REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL) &= ~DMAC_DCCSR_HLT; | 644 | REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_1)) &= ~DMAC_DCCSR_HLT; |
609 | } | 645 | } |
610 | 646 | ||
611 | if (REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL) & DMAC_DCCSR_TT) | 647 | if (REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_1)) & DMAC_DCCSR_TT) |
612 | { | 648 | { |
613 | REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL) &= ~DMAC_DCCSR_TT; | 649 | REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_1)) &= ~DMAC_DCCSR_TT; |
614 | //sd_tx_dma_callback(); | 650 | //sd_tx_dma_callback(); |
615 | } | 651 | } |
616 | 652 | ||
617 | semaphore_release(&sd_wakeup); | 653 | semaphore_release(&sd_wakeup[SD_SLOT_1]); |
654 | } | ||
655 | void DMA_CALLBACK(DMA_SD_TX_CHANNEL1)(void) | ||
656 | { | ||
657 | if (REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_2)) & DMAC_DCCSR_AR) | ||
658 | { | ||
659 | logf("SD TX DMA address error: %x, %x, %x", var1, var2, var3); | ||
660 | REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_2)) &= ~DMAC_DCCSR_AR; | ||
661 | } | ||
662 | |||
663 | if (REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_2)) & DMAC_DCCSR_HLT) | ||
664 | { | ||
665 | logf("SD TX DMA halt"); | ||
666 | REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_2)) &= ~DMAC_DCCSR_HLT; | ||
667 | } | ||
668 | |||
669 | if (REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_2)) & DMAC_DCCSR_TT) | ||
670 | { | ||
671 | REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL(SD_SLOT_2)) &= ~DMAC_DCCSR_TT; | ||
672 | //sd_tx_dma_callback(); | ||
673 | } | ||
674 | |||
675 | semaphore_release(&sd_wakeup[SD_SLOT_2]); | ||
618 | } | 676 | } |
619 | #endif /* SD_DMA_INTERRUPT */ | 677 | #endif /* SD_DMA_INTERRUPT */ |
620 | #endif /* SD_DMA_ENABLE */ | 678 | #endif /* SD_DMA_ENABLE */ |
@@ -678,7 +736,9 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request) | |||
678 | { | 736 | { |
679 | unsigned int cmdat = 0, events = 0; | 737 | unsigned int cmdat = 0, events = 0; |
680 | int retval; | 738 | int retval; |
739 | #if !SD_INTERRUPT | ||
681 | long deadline = current_tick + (HZ * 5); | 740 | long deadline = current_tick + (HZ * 5); |
741 | #endif | ||
682 | 742 | ||
683 | /* Indicate we have no result yet */ | 743 | /* Indicate we have no result yet */ |
684 | request->result = SD_NO_RESPONSE; | 744 | request->result = SD_NO_RESPONSE; |
@@ -702,8 +762,13 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request) | |||
702 | 762 | ||
703 | /* mask all interrupts and clear status */ | 763 | /* mask all interrupts and clear status */ |
704 | SD_IRQ_MASK(MSC_CHN(drive)); | 764 | SD_IRQ_MASK(MSC_CHN(drive)); |
705 | /*open interrupt */ | 765 | |
766 | /* open interrupt */ | ||
767 | #if SD_INTERRUPT | ||
768 | REG_MSC_IMASK(MSC_CHN(drive)) = ~(MSC_IMASK_DATA_TRAN_DONE | MSC_IMASK_PRG_DONE); | ||
769 | #else | ||
706 | REG_MSC_IMASK(MSC_CHN(drive)) = ~(MSC_IMASK_END_CMD_RES | MSC_IMASK_DATA_TRAN_DONE | MSC_IMASK_PRG_DONE); | 770 | REG_MSC_IMASK(MSC_CHN(drive)) = ~(MSC_IMASK_END_CMD_RES | MSC_IMASK_DATA_TRAN_DONE | MSC_IMASK_PRG_DONE); |
771 | #endif | ||
707 | 772 | ||
708 | /* Set command type and events */ | 773 | /* Set command type and events */ |
709 | switch (request->cmd) | 774 | switch (request->cmd) |
@@ -852,15 +917,16 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request) | |||
852 | jz_sd_start_clock(drive); | 917 | jz_sd_start_clock(drive); |
853 | 918 | ||
854 | /* Wait for command completion */ | 919 | /* Wait for command completion */ |
855 | //__intc_unmask_irq(IRQ_MSC); | 920 | #if SD_INTERRUPT |
856 | //semaphore_wait(&sd_wakeup, 100); | 921 | semaphore_wait(&sd_wakeup[drive], HZ * 5); |
922 | #else | ||
857 | while (!(REG_MSC_IREG(MSC_CHN(drive)) & MSC_IREG_END_CMD_RES)) | 923 | while (!(REG_MSC_IREG(MSC_CHN(drive)) & MSC_IREG_END_CMD_RES)) |
858 | { | 924 | { |
859 | if (TIME_AFTER(current_tick, deadline)) | 925 | if (TIME_AFTER(current_tick, deadline)) |
860 | return SD_ERROR_TIMEOUT; | 926 | return SD_ERROR_TIMEOUT; |
861 | yield(); | 927 | yield(); |
862 | } | 928 | } |
863 | 929 | #endif | |
864 | REG_MSC_IREG(MSC_CHN(drive)) = MSC_IREG_END_CMD_RES; /* clear flag */ | 930 | REG_MSC_IREG(MSC_CHN(drive)) = MSC_IREG_END_CMD_RES; /* clear flag */ |
865 | 931 | ||
866 | /* Check for status */ | 932 | /* Check for status */ |
@@ -880,41 +946,37 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request) | |||
880 | { | 946 | { |
881 | if (events & SD_EVENT_RX_DATA_DONE) | 947 | if (events & SD_EVENT_RX_DATA_DONE) |
882 | { | 948 | { |
883 | #if SD_DMA_ENABLE | ||
884 | retval = jz_sd_receive_data_dma(drive, request); | ||
885 | #else | ||
886 | retval = jz_sd_receive_data(drive, request); | 949 | retval = jz_sd_receive_data(drive, request); |
887 | #endif | ||
888 | } | 950 | } |
889 | if (retval) | 951 | if (retval) |
890 | return retval; | 952 | return retval; |
891 | 953 | ||
892 | if (events & SD_EVENT_TX_DATA_DONE) | 954 | if (events & SD_EVENT_TX_DATA_DONE) |
893 | { | 955 | { |
894 | #if SD_DMA_ENABLE | ||
895 | retval = jz_sd_transmit_data_dma(drive, request); | ||
896 | #else | ||
897 | retval = jz_sd_transmit_data(drive, request); | 956 | retval = jz_sd_transmit_data(drive, request); |
898 | #endif | ||
899 | } | 957 | } |
900 | if (retval) | 958 | if (retval) |
901 | return retval; | 959 | return retval; |
902 | 960 | ||
903 | //__intc_unmask_irq(IRQ_MSC); | 961 | #if SD_INTERRUPT |
904 | //semaphore_wait(&sd_wakeup, 100); | 962 | semaphore_wait(&sd_wakeup[drive], HZ * 5); |
963 | #else | ||
905 | /* Wait for Data Done */ | 964 | /* Wait for Data Done */ |
906 | while (!(REG_MSC_IREG(MSC_CHN(drive)) & MSC_IREG_DATA_TRAN_DONE)) | 965 | while (!(REG_MSC_IREG(MSC_CHN(drive)) & MSC_IREG_DATA_TRAN_DONE)) |
907 | yield(); | 966 | yield(); |
967 | #endif | ||
908 | REG_MSC_IREG(MSC_CHN(drive)) = MSC_IREG_DATA_TRAN_DONE; /* clear status */ | 968 | REG_MSC_IREG(MSC_CHN(drive)) = MSC_IREG_DATA_TRAN_DONE; /* clear status */ |
909 | } | 969 | } |
910 | 970 | ||
911 | /* Wait for Prog Done event */ | 971 | /* Wait for Prog Done event */ |
912 | if (events & SD_EVENT_PROG_DONE) | 972 | if (events & SD_EVENT_PROG_DONE) |
913 | { | 973 | { |
914 | //__intc_unmask_irq(IRQ_MSC); | 974 | #if SD_INTERRUPT |
915 | //semaphore_wait(&sd_wakeup, 100); | 975 | semaphore_wait(&sd_wakeup[drive], HZ * 5); |
976 | #else | ||
916 | while (!(REG_MSC_IREG(MSC_CHN(drive)) & MSC_IREG_PRG_DONE)) | 977 | while (!(REG_MSC_IREG(MSC_CHN(drive)) & MSC_IREG_PRG_DONE)) |
917 | yield(); | 978 | yield(); |
979 | #endif | ||
918 | REG_MSC_IREG(MSC_CHN(drive)) = MSC_IREG_PRG_DONE; /* clear status */ | 980 | REG_MSC_IREG(MSC_CHN(drive)) = MSC_IREG_PRG_DONE; /* clear status */ |
919 | } | 981 | } |
920 | 982 | ||
@@ -937,7 +999,12 @@ static int jz_sd_chkcard(const int drive) | |||
937 | /* MSC interrupt handler */ | 999 | /* MSC interrupt handler */ |
938 | void MSC(void) | 1000 | void MSC(void) |
939 | { | 1001 | { |
940 | //semaphore_release(&sd_wakeup); | 1002 | #if SD_INTERRUPT |
1003 | if (REG_MSC_IREG(MSC_CHN(SD_SLOT_1)) & MSC_IREG_DATA_TRAN_DONE) | ||
1004 | semaphore_release(&sd_wakeup[SD_SLOT_1]); | ||
1005 | else if (REG_MSC_IREG(MSC_CHN(SD_SLOT_2)) & MSC_IREG_DATA_TRAN_DONE) | ||
1006 | semaphore_release(&sd_wakeup[SD_SLOT_2]); | ||
1007 | #endif | ||
941 | logf("MSC interrupt"); | 1008 | logf("MSC interrupt"); |
942 | } | 1009 | } |
943 | 1010 | ||
@@ -1188,20 +1255,19 @@ static int sd_select_card(const int drive) | |||
1188 | return 0; | 1255 | return 0; |
1189 | } | 1256 | } |
1190 | 1257 | ||
1191 | static int sd_init_device(const int drive) | 1258 | static int __sd_init_device(const int drive) |
1192 | { | 1259 | { |
1193 | int retval = 0; | 1260 | int retval = 0; |
1194 | long deadline; | 1261 | long deadline; |
1195 | struct sd_request init_req; | 1262 | struct sd_request init_req; |
1196 | 1263 | ||
1197 | mutex_lock(&sd_mtx); | ||
1198 | |||
1199 | /* Initialise card data as blank */ | 1264 | /* Initialise card data as blank */ |
1200 | memset(&card[drive], 0, sizeof(tCardInfo)); | 1265 | memset(&card[drive], 0, sizeof(tCardInfo)); |
1201 | 1266 | ||
1202 | sd2_0[drive] = 0; | 1267 | sd2_0[drive] = 0; |
1203 | num_6[drive] = 0; | 1268 | num_6[drive] = 0; |
1204 | use_4bit[drive] = 0; | 1269 | use_4bit[drive] = 0; |
1270 | active[drive] = 0; | ||
1205 | 1271 | ||
1206 | /* reset mmc/sd controller */ | 1272 | /* reset mmc/sd controller */ |
1207 | jz_sd_hardware_init(drive); | 1273 | jz_sd_hardware_init(drive); |
@@ -1223,8 +1289,6 @@ static int sd_init_device(const int drive) | |||
1223 | else | 1289 | else |
1224 | __cpm_stop_msc1(); /* disable SD2 clock */ | 1290 | __cpm_stop_msc1(); /* disable SD2 clock */ |
1225 | 1291 | ||
1226 | mutex_unlock(&sd_mtx); | ||
1227 | |||
1228 | return retval; | 1292 | return retval; |
1229 | } | 1293 | } |
1230 | 1294 | ||
@@ -1235,28 +1299,37 @@ int sd_init(void) | |||
1235 | sd_init_gpio(); /* init GPIO */ | 1299 | sd_init_gpio(); /* init GPIO */ |
1236 | 1300 | ||
1237 | #if SD_DMA_ENABLE | 1301 | #if SD_DMA_ENABLE |
1238 | __dmac_channel_enable_clk(DMA_SD_RX_CHANNEL); | 1302 | __dmac_channel_enable_clk(DMA_SD_RX_CHANNEL(SD_SLOT_1)); |
1239 | __dmac_channel_enable_clk(DMA_SD_TX_CHANNEL); | 1303 | __dmac_channel_enable_clk(DMA_SD_RX_CHANNEL(SD_SLOT_2)); |
1304 | __dmac_channel_enable_clk(DMA_SD_TX_CHANNEL(SD_SLOT_1)); | ||
1305 | __dmac_channel_enable_clk(DMA_SD_TX_CHANNEL(SD_SLOT_2)); | ||
1240 | #endif | 1306 | #endif |
1241 | 1307 | ||
1242 | if(!inited) | 1308 | if(!inited) |
1243 | { | 1309 | { |
1244 | 1310 | ||
1245 | #if SD_DMA_INTERRUPT | 1311 | #if SD_DMA_INTERRUPT || SD_INTERRUPT |
1246 | semaphore_init(&sd_wakeup, 1, 0); | 1312 | semaphore_init(&sd_wakeup[SD_SLOT_1], 1, 0); |
1313 | semaphore_init(&sd_wakeup[SD_SLOT_2], 1, 0); | ||
1247 | #endif | 1314 | #endif |
1248 | mutex_init(&sd_mtx); | 1315 | mutex_init(&sd_mtx[SD_SLOT_1]); |
1316 | mutex_init(&sd_mtx[SD_SLOT_2]); | ||
1249 | 1317 | ||
1250 | #if SD_DMA_ENABLE && SD_DMA_INTERRUPT | 1318 | #if SD_DMA_ENABLE && SD_DMA_INTERRUPT |
1251 | system_enable_irq(DMA_IRQ(DMA_SD_RX_CHANNEL)); | 1319 | system_enable_irq(DMA_IRQ(DMA_SD_RX_CHANNEL(SD_SLOT_1))); |
1252 | system_enable_irq(DMA_IRQ(DMA_SD_TX_CHANNEL)); | 1320 | system_enable_irq(DMA_IRQ(DMA_SD_RX_CHANNEL(SD_SLOT_2))); |
1321 | system_enable_irq(DMA_IRQ(DMA_SD_TX_CHANNEL(SD_SLOT_1))); | ||
1322 | system_enable_irq(DMA_IRQ(DMA_SD_TX_CHANNEL(SD_SLOT_2))); | ||
1253 | #endif | 1323 | #endif |
1254 | 1324 | ||
1255 | inited = true; | 1325 | inited = true; |
1256 | } | 1326 | } |
1257 | 1327 | ||
1258 | for (int drive = 0; drive < NUM_DRIVES; drive++) | 1328 | for (int drive = 0; drive < NUM_DRIVES; drive++) { |
1259 | sd_init_device(drive); | 1329 | mutex_lock(&sd_mtx[drive]); |
1330 | __sd_init_device(drive); | ||
1331 | mutex_unlock(&sd_mtx[drive]); | ||
1332 | } | ||
1260 | 1333 | ||
1261 | return 0; | 1334 | return 0; |
1262 | } | 1335 | } |
@@ -1273,22 +1346,26 @@ tCardInfo* card_get_info_target(const int drive) | |||
1273 | 1346 | ||
1274 | static inline void sd_start_transfer(const int drive) | 1347 | static inline void sd_start_transfer(const int drive) |
1275 | { | 1348 | { |
1276 | mutex_lock(&sd_mtx); | 1349 | mutex_lock(&sd_mtx[drive]); |
1277 | if (drive == SD_SLOT_1) | 1350 | if (drive == SD_SLOT_1) |
1278 | __cpm_start_msc2(); | 1351 | __cpm_start_msc2(); |
1279 | else | 1352 | else |
1280 | __cpm_start_msc1(); | 1353 | __cpm_start_msc1(); |
1281 | led(true); | 1354 | |
1355 | active[drive] = 1; | ||
1356 | led(active[SD_SLOT_1] || active[SD_SLOT_2]); | ||
1282 | } | 1357 | } |
1283 | 1358 | ||
1284 | static inline void sd_stop_transfer(const int drive) | 1359 | static inline void sd_stop_transfer(const int drive) |
1285 | { | 1360 | { |
1286 | led(false); | 1361 | active[drive] = 0; |
1362 | led(active[SD_SLOT_1] || active[SD_SLOT_2]); | ||
1363 | |||
1287 | if (drive == SD_SLOT_1) | 1364 | if (drive == SD_SLOT_1) |
1288 | __cpm_stop_msc2(); | 1365 | __cpm_stop_msc2(); |
1289 | else | 1366 | else |
1290 | __cpm_stop_msc1(); | 1367 | __cpm_stop_msc1(); |
1291 | mutex_unlock(&sd_mtx); | 1368 | mutex_unlock(&sd_mtx[drive]); |
1292 | } | 1369 | } |
1293 | 1370 | ||
1294 | int sd_transfer_sectors(IF_MD(const int drive,) unsigned long start, int count, void* buf, bool write) | 1371 | int sd_transfer_sectors(IF_MD(const int drive,) unsigned long start, int count, void* buf, bool write) |
@@ -1305,7 +1382,7 @@ int sd_transfer_sectors(IF_MD(const int drive,) unsigned long start, int count, | |||
1305 | if (!card_detect_target(drive) || count < 1 || (start + count) > card[drive].numblocks) | 1382 | if (!card_detect_target(drive) || count < 1 || (start + count) > card[drive].numblocks) |
1306 | goto err; | 1383 | goto err; |
1307 | 1384 | ||
1308 | if(card[drive].initialized == 0 && !sd_init_device(drive)) | 1385 | if(card[drive].initialized == 0 && !__sd_init_device(drive)) |
1309 | goto err; | 1386 | goto err; |
1310 | 1387 | ||
1311 | sd_simple_cmd(drive, &request, SD_SEND_STATUS, card[drive].rca, RESPONSE_R1); | 1388 | sd_simple_cmd(drive, &request, SD_SEND_STATUS, card[drive].rca, RESPONSE_R1); |
@@ -1440,11 +1517,11 @@ int sd_event(long id, intptr_t data) | |||
1440 | case SYS_HOTSWAP_EXTRACTED: | 1517 | case SYS_HOTSWAP_EXTRACTED: |
1441 | /* Force card init for new card, re-init for re-inserted one or | 1518 | /* Force card init for new card, re-init for re-inserted one or |
1442 | * clear if the last attempt to init failed with an error. */ | 1519 | * clear if the last attempt to init failed with an error. */ |
1443 | mutex_lock(&sd_mtx); /* lock-out card activity */ | 1520 | mutex_lock(&sd_mtx[data]); /* lock-out card activity */ |
1444 | card[data].initialized = 0; | 1521 | card[data].initialized = 0; |
1445 | if (id == SYS_HOTSWAP_INSERTED) | 1522 | if (id == SYS_HOTSWAP_INSERTED) |
1446 | sd_init_device(data); | 1523 | __sd_init_device(data); |
1447 | mutex_unlock(&sd_mtx); | 1524 | mutex_unlock(&sd_mtx[data]); |
1448 | break; | 1525 | break; |
1449 | #endif /* HAVE_HOTSWAP */ | 1526 | #endif /* HAVE_HOTSWAP */ |
1450 | default: | 1527 | default: |
diff --git a/firmware/target/mips/ingenic_jz47xx/system-jz4760.c b/firmware/target/mips/ingenic_jz47xx/system-jz4760.c index 3d4015c465..eb20985b97 100644 --- a/firmware/target/mips/ingenic_jz47xx/system-jz4760.c +++ b/firmware/target/mips/ingenic_jz47xx/system-jz4760.c | |||
@@ -664,8 +664,10 @@ void dma_preinit(void) | |||
664 | REG_MDMAC_DMACKES = 0x1; | 664 | REG_MDMAC_DMACKES = 0x1; |
665 | 665 | ||
666 | REG_DMAC_DMACR(DMA_AIC_TX_CHANNEL) = DMAC_DMACR_DMAE | DMAC_DMACR_FAIC; | 666 | REG_DMAC_DMACR(DMA_AIC_TX_CHANNEL) = DMAC_DMACR_DMAE | DMAC_DMACR_FAIC; |
667 | REG_DMAC_DMACR(DMA_SD_RX_CHANNEL) = DMAC_DMACR_DMAE | DMAC_DMACR_FMSC; | 667 | REG_DMAC_DMACR(DMA_SD_RX_CHANNEL(0)) = DMAC_DMACR_DMAE | DMAC_DMACR_FMSC; |
668 | REG_DMAC_DMACR(DMA_SD_TX_CHANNEL) = DMAC_DMACR_DMAE | DMAC_DMACR_FMSC; | 668 | REG_DMAC_DMACR(DMA_SD_RX_CHANNEL(1)) = DMAC_DMACR_DMAE | DMAC_DMACR_FMSC; |
669 | REG_DMAC_DMACR(DMA_SD_TX_CHANNEL(0)) = DMAC_DMACR_DMAE | DMAC_DMACR_FMSC; | ||
670 | REG_DMAC_DMACR(DMA_SD_TX_CHANNEL(1)) = DMAC_DMACR_DMAE | DMAC_DMACR_FMSC; | ||
669 | } | 671 | } |
670 | 672 | ||
671 | /* Gets called *before* main */ | 673 | /* Gets called *before* main */ |
diff --git a/firmware/target/mips/ingenic_jz47xx/system-target.h b/firmware/target/mips/ingenic_jz47xx/system-target.h index 9720d3a80c..b6e779ea53 100644 --- a/firmware/target/mips/ingenic_jz47xx/system-target.h +++ b/firmware/target/mips/ingenic_jz47xx/system-target.h | |||
@@ -97,8 +97,13 @@ void dma_disable(void); | |||
97 | #define DMA_AIC_TX_CHANNEL 0 | 97 | #define DMA_AIC_TX_CHANNEL 0 |
98 | #define DMA_NAND_CHANNEL 1 | 98 | #define DMA_NAND_CHANNEL 1 |
99 | #define DMA_USB_CHANNEL 2 | 99 | #define DMA_USB_CHANNEL 2 |
100 | #define DMA_SD_RX_CHANNEL 3 | 100 | #define DMA_SD_RX_CHANNEL0 3 |
101 | #define DMA_SD_TX_CHANNEL 4 | 101 | #define DMA_SD_RX_CHANNEL1 4 |
102 | // Note: channel 5 and 11 cannot be used! | ||
103 | #define DMA_SD_TX_CHANNEL0 6 | ||
104 | #define DMA_SD_TX_CHANNEL1 7 | ||
105 | #define DMA_SD_RX_CHANNEL(n) 3+n | ||
106 | #define DMA_SD_TX_CHANNEL(n) 6+n | ||
102 | #endif | 107 | #endif |
103 | 108 | ||
104 | #define XDMA_CALLBACK(n) DMA ## n | 109 | #define XDMA_CALLBACK(n) DMA ## n |