summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/target/arm/as3525/ata_sd_as3525.c26
1 files changed, 14 insertions, 12 deletions
diff --git a/firmware/target/arm/as3525/ata_sd_as3525.c b/firmware/target/arm/as3525/ata_sd_as3525.c
index ae3d466abf..d959b89e7d 100644
--- a/firmware/target/arm/as3525/ata_sd_as3525.c
+++ b/firmware/target/arm/as3525/ata_sd_as3525.c
@@ -121,7 +121,8 @@ static bool sd_enabled = false;
121#endif 121#endif
122 122
123static struct wakeup transfer_completion_signal; 123static struct wakeup transfer_completion_signal;
124static volatile bool retry; 124static volatile unsigned int transfer_error[NUM_VOLUMES];
125#define PL180_MAX_TRANSFER_ERRORS 10
125 126
126#define UNALIGNED_NUM_SECTORS 10 127#define UNALIGNED_NUM_SECTORS 10
127static unsigned char aligned_buffer[UNALIGNED_NUM_SECTORS* SECTOR_SIZE] __attribute__((aligned(32))); /* align on cache line size */ 128static unsigned char aligned_buffer[UNALIGNED_NUM_SECTORS* SECTOR_SIZE] __attribute__((aligned(32))); /* align on cache line size */
@@ -161,8 +162,7 @@ void INT_NAND(void)
161{ 162{
162 const int status = MCI_STATUS(INTERNAL_AS3525); 163 const int status = MCI_STATUS(INTERNAL_AS3525);
163 164
164 if(status & MCI_ERROR) 165 transfer_error[INTERNAL_AS3525] = status & MCI_ERROR;
165 retry = true;
166 166
167 wakeup_signal(&transfer_completion_signal); 167 wakeup_signal(&transfer_completion_signal);
168 MCI_CLEAR(INTERNAL_AS3525) = status; 168 MCI_CLEAR(INTERNAL_AS3525) = status;
@@ -173,8 +173,7 @@ void INT_MCI0(void)
173{ 173{
174 const int status = MCI_STATUS(SD_SLOT_AS3525); 174 const int status = MCI_STATUS(SD_SLOT_AS3525);
175 175
176 if(status & MCI_ERROR) 176 transfer_error[SD_SLOT_AS3525] = status & MCI_ERROR;
177 retry = true;
178 177
179 wakeup_signal(&transfer_completion_signal); 178 wakeup_signal(&transfer_completion_signal);
180 MCI_CLEAR(SD_SLOT_AS3525) = status; 179 MCI_CLEAR(SD_SLOT_AS3525) = status;
@@ -558,10 +557,12 @@ static int sd_wait_for_state(const int drive, unsigned int state)
558static int sd_select_bank(signed char bank) 557static int sd_select_bank(signed char bank)
559{ 558{
560 int ret; 559 int ret;
560 unsigned loops = 0;
561 561
562 do { 562 do {
563 /* The ISR will set this to true if an error occurred */ 563 if(loops++ > PL180_MAX_TRANSFER_ERRORS)
564 retry = false; 564 panicf("SD bank %d error : 0x%x", bank,
565 transfer_error[INTERNAL_AS3525]);
565 566
566 ret = sd_wait_for_state(INTERNAL_AS3525, SD_TRAN); 567 ret = sd_wait_for_state(INTERNAL_AS3525, SD_TRAN);
567 if (ret < 0) 568 if (ret < 0)
@@ -610,7 +611,7 @@ static int sd_select_bank(signed char bank)
610 ret = sd_wait_for_state(INTERNAL_AS3525, SD_TRAN); 611 ret = sd_wait_for_state(INTERNAL_AS3525, SD_TRAN);
611 if (ret < 0) 612 if (ret < 0)
612 return ret - 4; 613 return ret - 4;
613 } while(retry); 614 } while(transfer_error[INTERNAL_AS3525]);
614 615
615 card_info[INTERNAL_AS3525].current_bank = (bank == -1) ? 0 : bank; 616 card_info[INTERNAL_AS3525].current_bank = (bank == -1) ? 0 : bank;
616 617
@@ -624,6 +625,7 @@ static int sd_transfer_sectors(IF_MV2(int drive,) unsigned long start,
624 const int drive = 0; 625 const int drive = 0;
625#endif 626#endif
626 int ret = 0; 627 int ret = 0;
628 unsigned loops = 0;
627 629
628 /* skip SanDisk OF */ 630 /* skip SanDisk OF */
629 if (drive == INTERNAL_AS3525) 631 if (drive == INTERNAL_AS3525)
@@ -663,9 +665,6 @@ static int sd_transfer_sectors(IF_MV2(int drive,) unsigned long start,
663 write ? SD_WRITE_MULTIPLE_BLOCK : SD_READ_MULTIPLE_BLOCK; 665 write ? SD_WRITE_MULTIPLE_BLOCK : SD_READ_MULTIPLE_BLOCK;
664 unsigned long bank_start = start; 666 unsigned long bank_start = start;
665 667
666 /* The ISR will set this to true if an error occurred */
667 retry = false;
668
669 /* Only switch banks for internal storage */ 668 /* Only switch banks for internal storage */
670 if(drive == INTERNAL_AS3525) 669 if(drive == INTERNAL_AS3525)
671 { 670 {
@@ -728,14 +727,17 @@ static int sd_transfer_sectors(IF_MV2(int drive,) unsigned long start,
728 727
729 728
730 wakeup_wait(&transfer_completion_signal, TIMEOUT_BLOCK); 729 wakeup_wait(&transfer_completion_signal, TIMEOUT_BLOCK);
731 if(!retry) 730 if(!transfer_error[drive])
732 { 731 {
733 if(!write) 732 if(!write)
734 memcpy(buf, uncached_buffer, transfer * SECTOR_SIZE); 733 memcpy(buf, uncached_buffer, transfer * SECTOR_SIZE);
735 buf += transfer * SECTOR_SIZE; 734 buf += transfer * SECTOR_SIZE;
736 start += transfer; 735 start += transfer;
737 count -= transfer; 736 count -= transfer;
737 loops = 0; /* reset errors counter */
738 } 738 }
739 else if(loops++ > PL180_MAX_TRANSFER_ERRORS)
740 panicf("SD transfer error : 0x%x", transfer_error[drive]);
739 741
740 last_disk_activity = current_tick; 742 last_disk_activity = current_tick;
741 743