1
0
Fork 0
forked from len0rd/rockbox

imx233: add support for CMD23 in sd/mmc

This allows tells the card the number of blocks that will be
transfered. This is usually faster than continuous read/write.
It is mandatory for MMC and on SD cards, support is probed.

Change-Id: Ide3f97c26c2b714390884c69e05b00c2caa552f8
This commit is contained in:
Amaury Pouly 2013-08-21 11:07:51 +02:00
parent 9a58721974
commit e90a5efe54

View file

@ -148,6 +148,7 @@ static uint8_t aligned_buffer[SDMMC_NUM_DRIVES][512] CACHEALIGN_ATTR;
static tCardInfo sdmmc_card_info[SDMMC_NUM_DRIVES];
static struct mutex mutex[SDMMC_NUM_DRIVES];
static int disk_last_activity[SDMMC_NUM_DRIVES];
static bool support_set_block_count[SDMMC_NUM_DRIVES];
#define MIN_YIELD_PERIOD 5
#define SDMMC_INFO(drive) sdmmc_card_info[drive]
@ -400,6 +401,21 @@ static int init_sd_card(int drive)
/* Switch to 4-bit */
imx233_ssp_set_bus_width(ssp, 4);
/* probe for CMD23 support */
support_set_block_count[drive] = false;
/* ACMD51, only transfer 8 bytes */
imx233_ssp_set_block_size(ssp, /*log2(8)*/3);
if(send_cmd(drive, SD_APP_CMD, SDMMC_RCA(drive), MCI_RESP, &resp))
{
if(imx233_ssp_sd_mmc_transfer(ssp, SD_SEND_SCR, 0, SSP_SHORT_RESP,
aligned_buffer[drive], 1, true, true, NULL) == SSP_SUCCESS)
{
if(aligned_buffer[drive][3] & 2)
support_set_block_count[drive] = true;
}
}
imx233_ssp_set_block_size(ssp, /*log2(512)*/9);
SDMMC_INFO(drive).initialized = 1;
return 0;
@ -485,6 +501,10 @@ static int init_mmc_drive(int drive)
if(!send_cmd(drive, MMC_DESELECT_CARD, 0, MCI_NO_RESP, NULL))
return -13;
/* MMC always support CMD23 */
support_set_block_count[drive] = false;
SDMMC_INFO(drive).initialized = 1;
return 0;
}
#endif
@ -497,6 +517,9 @@ static int __xfer_sectors(int drive, unsigned long start, int count, void *buf,
while(count != 0)
{
int this_count = MIN(count, IMX233_MAX_SINGLE_DMA_XFER_SIZE / 512);
bool need_stop = true;
if(support_set_block_count[drive] && send_cmd(drive, 23, this_count, MCI_RESP, &resp))
need_stop = false;
/* Set bank_start to the correct unit (blocks or bytes).
* MMC drives use block addressing, SD cards bytes or blocks */
int bank_start = start;
@ -508,14 +531,16 @@ static int __xfer_sectors(int drive, unsigned long start, int count, void *buf,
read ? SD_READ_MULTIPLE_BLOCK : SD_WRITE_MULTIPLE_BLOCK,
bank_start, SSP_SHORT_RESP, buf, this_count, false, read, &resp);
if(ret != SSP_SUCCESS)
break;
need_stop = true;
/* stop transmission
* NOTE: rely on SD_STOP_TRANSMISSION=MMC_STOP_TRANSMISSION */
if(!send_cmd(drive, SD_STOP_TRANSMISSION, 0, MCI_RESP|MCI_BUSY, &resp))
if(need_stop && !send_cmd(drive, SD_STOP_TRANSMISSION, 0, MCI_RESP|MCI_BUSY, &resp))
{
ret = -15;
break;
}
if(ret != 0)
return ret;
count -= this_count;
start += this_count;
buf += this_count * 512;