summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/target/arm/imx233/sdmmc-imx233.c29
1 files changed, 27 insertions, 2 deletions
diff --git a/firmware/target/arm/imx233/sdmmc-imx233.c b/firmware/target/arm/imx233/sdmmc-imx233.c
index 9aafb5820a..5ebf0c7d3b 100644
--- a/firmware/target/arm/imx233/sdmmc-imx233.c
+++ b/firmware/target/arm/imx233/sdmmc-imx233.c
@@ -148,6 +148,7 @@ static uint8_t aligned_buffer[SDMMC_NUM_DRIVES][512] CACHEALIGN_ATTR;
148static tCardInfo sdmmc_card_info[SDMMC_NUM_DRIVES]; 148static tCardInfo sdmmc_card_info[SDMMC_NUM_DRIVES];
149static struct mutex mutex[SDMMC_NUM_DRIVES]; 149static struct mutex mutex[SDMMC_NUM_DRIVES];
150static int disk_last_activity[SDMMC_NUM_DRIVES]; 150static int disk_last_activity[SDMMC_NUM_DRIVES];
151static bool support_set_block_count[SDMMC_NUM_DRIVES];
151#define MIN_YIELD_PERIOD 5 152#define MIN_YIELD_PERIOD 5
152 153
153#define SDMMC_INFO(drive) sdmmc_card_info[drive] 154#define SDMMC_INFO(drive) sdmmc_card_info[drive]
@@ -400,6 +401,21 @@ static int init_sd_card(int drive)
400 /* Switch to 4-bit */ 401 /* Switch to 4-bit */
401 imx233_ssp_set_bus_width(ssp, 4); 402 imx233_ssp_set_bus_width(ssp, 4);
402 403
404 /* probe for CMD23 support */
405 support_set_block_count[drive] = false;
406 /* ACMD51, only transfer 8 bytes */
407 imx233_ssp_set_block_size(ssp, /*log2(8)*/3);
408 if(send_cmd(drive, SD_APP_CMD, SDMMC_RCA(drive), MCI_RESP, &resp))
409 {
410 if(imx233_ssp_sd_mmc_transfer(ssp, SD_SEND_SCR, 0, SSP_SHORT_RESP,
411 aligned_buffer[drive], 1, true, true, NULL) == SSP_SUCCESS)
412 {
413 if(aligned_buffer[drive][3] & 2)
414 support_set_block_count[drive] = true;
415 }
416 }
417 imx233_ssp_set_block_size(ssp, /*log2(512)*/9);
418
403 SDMMC_INFO(drive).initialized = 1; 419 SDMMC_INFO(drive).initialized = 1;
404 420
405 return 0; 421 return 0;
@@ -485,6 +501,10 @@ static int init_mmc_drive(int drive)
485 if(!send_cmd(drive, MMC_DESELECT_CARD, 0, MCI_NO_RESP, NULL)) 501 if(!send_cmd(drive, MMC_DESELECT_CARD, 0, MCI_NO_RESP, NULL))
486 return -13; 502 return -13;
487 503
504 /* MMC always support CMD23 */
505 support_set_block_count[drive] = false;
506 SDMMC_INFO(drive).initialized = 1;
507
488 return 0; 508 return 0;
489} 509}
490#endif 510#endif
@@ -497,6 +517,9 @@ static int __xfer_sectors(int drive, unsigned long start, int count, void *buf,
497 while(count != 0) 517 while(count != 0)
498 { 518 {
499 int this_count = MIN(count, IMX233_MAX_SINGLE_DMA_XFER_SIZE / 512); 519 int this_count = MIN(count, IMX233_MAX_SINGLE_DMA_XFER_SIZE / 512);
520 bool need_stop = true;
521 if(support_set_block_count[drive] && send_cmd(drive, 23, this_count, MCI_RESP, &resp))
522 need_stop = false;
500 /* Set bank_start to the correct unit (blocks or bytes). 523 /* Set bank_start to the correct unit (blocks or bytes).
501 * MMC drives use block addressing, SD cards bytes or blocks */ 524 * MMC drives use block addressing, SD cards bytes or blocks */
502 int bank_start = start; 525 int bank_start = start;
@@ -508,14 +531,16 @@ static int __xfer_sectors(int drive, unsigned long start, int count, void *buf,
508 read ? SD_READ_MULTIPLE_BLOCK : SD_WRITE_MULTIPLE_BLOCK, 531 read ? SD_READ_MULTIPLE_BLOCK : SD_WRITE_MULTIPLE_BLOCK,
509 bank_start, SSP_SHORT_RESP, buf, this_count, false, read, &resp); 532 bank_start, SSP_SHORT_RESP, buf, this_count, false, read, &resp);
510 if(ret != SSP_SUCCESS) 533 if(ret != SSP_SUCCESS)
511 break; 534 need_stop = true;
512 /* stop transmission 535 /* stop transmission
513 * NOTE: rely on SD_STOP_TRANSMISSION=MMC_STOP_TRANSMISSION */ 536 * NOTE: rely on SD_STOP_TRANSMISSION=MMC_STOP_TRANSMISSION */
514 if(!send_cmd(drive, SD_STOP_TRANSMISSION, 0, MCI_RESP|MCI_BUSY, &resp)) 537 if(need_stop && !send_cmd(drive, SD_STOP_TRANSMISSION, 0, MCI_RESP|MCI_BUSY, &resp))
515 { 538 {
516 ret = -15; 539 ret = -15;
517 break; 540 break;
518 } 541 }
542 if(ret != 0)
543 return ret;
519 count -= this_count; 544 count -= this_count;
520 start += this_count; 545 start += this_count;
521 buf += this_count * 512; 546 buf += this_count * 512;