summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/target/arm/as3525/ata_sd_as3525.c66
1 files changed, 36 insertions, 30 deletions
diff --git a/firmware/target/arm/as3525/ata_sd_as3525.c b/firmware/target/arm/as3525/ata_sd_as3525.c
index 03a6a8bd02..a0b9b13c0c 100644
--- a/firmware/target/arm/as3525/ata_sd_as3525.c
+++ b/firmware/target/arm/as3525/ata_sd_as3525.c
@@ -142,8 +142,8 @@ void INT_GPIOA(void)
142 GPIOA_IC = (1<<2); 142 GPIOA_IC = (1<<2);
143 timeout_register(&sd1_oneshot, sd1_oneshot_callback, (3*HZ/10), 0); 143 timeout_register(&sd1_oneshot, sd1_oneshot_callback, (3*HZ/10), 0);
144} 144}
145#endif 145#endif /* defined(SANSA_E200V2) || defined(SANSA_FUZE) */
146#endif 146#endif /* HAVE_HOTSWAP */
147 147
148void INT_NAND(void) 148void INT_NAND(void)
149{ 149{
@@ -211,7 +211,7 @@ static bool send_cmd(const int drive, const int cmd, const int arg,
211 { /* resp received */ 211 { /* resp received */
212 if(flags & MCI_LONG_RESP) 212 if(flags & MCI_LONG_RESP)
213 { 213 {
214 /* store the response in little endian order for the words */ 214 /* store the response in reverse words order */
215 response[0] = MCI_RESP3(drive); 215 response[0] = MCI_RESP3(drive);
216 response[1] = MCI_RESP2(drive); 216 response[1] = MCI_RESP2(drive);
217 response[2] = MCI_RESP1(drive); 217 response[2] = MCI_RESP1(drive);
@@ -322,7 +322,7 @@ static int sd_init_card(const int drive)
322 322
323 card_info[drive].initialized = 1; 323 card_info[drive].initialized = 1;
324 324
325 MCI_CLOCK(drive) |= MCI_CLOCK_BYPASS; /* full speed */ 325 MCI_CLOCK(drive) |= MCI_CLOCK_BYPASS; /* full speed for controller clock */
326 mci_delay(); 326 mci_delay();
327 327
328 /* 328 /*
@@ -626,7 +626,6 @@ static int sd_transfer_sectors(IF_MV2(int drive,) unsigned long start,
626 const int drive = 0; 626 const int drive = 0;
627#endif 627#endif
628 int ret = 0; 628 int ret = 0;
629 int bank;
630 bool unaligned_transfer = (int)buf & 3; 629 bool unaligned_transfer = (int)buf & 3;
631 630
632 /* skip SanDisk OF */ 631 /* skip SanDisk OF */
@@ -647,29 +646,10 @@ static int sd_transfer_sectors(IF_MV2(int drive,) unsigned long start,
647 646
648 last_disk_activity = current_tick; 647 last_disk_activity = current_tick;
649 648
650 /* Only switch banks for internal storage */
651 if(drive == INTERNAL_AS3525)
652 {
653 bank = start / BLOCKS_PER_BANK;
654
655 if(card_info[INTERNAL_AS3525].current_bank != bank)
656 {
657 ret = sd_select_bank(bank);
658 if (ret < 0)
659 {
660 ret -= 20;
661 goto sd_transfer_error;
662 }
663 }
664
665 start -= bank * BLOCKS_PER_BANK;
666 }
667
668
669 ret = sd_wait_for_state(drive, SD_TRAN); 649 ret = sd_wait_for_state(drive, SD_TRAN);
670 if (ret < 0) 650 if (ret < 0)
671 { 651 {
672 ret -= 2*20; 652 ret -= 20;
673 goto sd_transfer_error; 653 goto sd_transfer_error;
674 } 654 }
675 655
@@ -683,13 +663,35 @@ static int sd_transfer_sectors(IF_MV2(int drive,) unsigned long start,
683 void *dma_buf; 663 void *dma_buf;
684 const int cmd = 664 const int cmd =
685 write ? SD_WRITE_MULTIPLE_BLOCK : SD_READ_MULTIPLE_BLOCK; 665 write ? SD_WRITE_MULTIPLE_BLOCK : SD_READ_MULTIPLE_BLOCK;
686 int arg = start; 666 unsigned long bank_start = start;
687 if(!(card_info[drive].ocr & (1<<30))) /* not SDHC */
688 arg *= BLOCK_SIZE;
689 667
690 /* Interrupt handler might set this to true during transfer */ 668 /* Interrupt handler might set this to true during transfer */
691 retry = false; 669 retry = false;
692 670
671 /* Only switch banks for internal storage */
672 if(drive == INTERNAL_AS3525)
673 {
674 int bank = start / BLOCKS_PER_BANK; /* Current bank */
675
676 /* Switch bank if needed */
677 if(card_info[INTERNAL_AS3525].current_bank != bank)
678 {
679 ret = sd_select_bank(bank);
680 if (ret < 0)
681 {
682 ret -= 2*20;
683 goto sd_transfer_error;
684 }
685 }
686
687 /* Adjust start block in current bank */
688 bank_start -= bank * BLOCKS_PER_BANK;
689
690 /* Do not cross a bank boundary in a single transfer loop */
691 if((transfer + bank_start) >= BLOCKS_PER_BANK)
692 transfer = BLOCKS_PER_BANK - bank_start;
693 }
694
693 if(unaligned_transfer) 695 if(unaligned_transfer)
694 { 696 {
695 dma_buf = aligned_buffer; 697 dma_buf = aligned_buffer;
@@ -698,10 +700,14 @@ static int sd_transfer_sectors(IF_MV2(int drive,) unsigned long start,
698 if(write) 700 if(write)
699 memcpy(aligned_buffer, buf, transfer * SECTOR_SIZE); 701 memcpy(aligned_buffer, buf, transfer * SECTOR_SIZE);
700 } 702 }
701 else 703 else /* Aligned transfers are faster : no memcpy */
702 dma_buf = buf; 704 dma_buf = buf;
703 705
704 if(!send_cmd(drive, cmd, arg, MCI_ARG, NULL)) 706 /* Set bank_start to the correct unit (blocks or bytes) */
707 if(!(card_info[drive].ocr & (1<<30))) /* not SDHC */
708 bank_start *= BLOCK_SIZE;
709
710 if(!send_cmd(drive, cmd, bank_start, MCI_ARG, NULL))
705 { 711 {
706 ret -= 3*20; 712 ret -= 3*20;
707 goto sd_transfer_error; 713 goto sd_transfer_error;