|
|
|
@ -159,7 +159,7 @@ int mmc_set_blocklen(struct mmc *mmc, int len) |
|
|
|
|
{ |
|
|
|
|
struct mmc_cmd cmd; |
|
|
|
|
|
|
|
|
|
if (mmc->card_caps & MMC_MODE_DDR_52MHz) |
|
|
|
|
if (mmc->ddr_mode) |
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
cmd.cmdidx = MMC_CMD_SET_BLOCKLEN; |
|
|
|
@ -486,7 +486,7 @@ static int mmc_change_freq(struct mmc *mmc) |
|
|
|
|
char cardtype; |
|
|
|
|
int err; |
|
|
|
|
|
|
|
|
|
mmc->card_caps = 0; |
|
|
|
|
mmc->card_caps = MMC_MODE_4BIT | MMC_MODE_8BIT; |
|
|
|
|
|
|
|
|
|
if (mmc_host_is_spi(mmc)) |
|
|
|
|
return 0; |
|
|
|
@ -519,7 +519,7 @@ static int mmc_change_freq(struct mmc *mmc) |
|
|
|
|
|
|
|
|
|
/* High Speed is set, there are two types: 52MHz and 26MHz */ |
|
|
|
|
if (cardtype & EXT_CSD_CARD_TYPE_52) { |
|
|
|
|
if (cardtype & EXT_CSD_CARD_TYPE_DDR_52) |
|
|
|
|
if (cardtype & EXT_CSD_CARD_TYPE_DDR_1_8V) |
|
|
|
|
mmc->card_caps |= MMC_MODE_DDR_52MHz; |
|
|
|
|
mmc->card_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; |
|
|
|
|
} else { |
|
|
|
@ -1001,6 +1001,9 @@ static int mmc_startup(struct mmc *mmc) |
|
|
|
|
case 6: |
|
|
|
|
mmc->version = MMC_VERSION_4_5; |
|
|
|
|
break; |
|
|
|
|
case 7: |
|
|
|
|
mmc->version = MMC_VERSION_5_0; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -1022,6 +1025,21 @@ static int mmc_startup(struct mmc *mmc) |
|
|
|
|
mmc->erase_grp_size = |
|
|
|
|
ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] * |
|
|
|
|
MMC_MAX_BLOCK_LEN * 1024; |
|
|
|
|
/*
|
|
|
|
|
* if high capacity and partition setting completed |
|
|
|
|
* SEC_COUNT is valid even if it is smaller than 2 GiB |
|
|
|
|
* JEDEC Standard JESD84-B45, 6.2.4 |
|
|
|
|
*/ |
|
|
|
|
if (mmc->high_capacity && |
|
|
|
|
(ext_csd[EXT_CSD_PARTITION_SETTING] & |
|
|
|
|
EXT_CSD_PARTITION_SETTING_COMPLETED)) { |
|
|
|
|
capacity = (ext_csd[EXT_CSD_SEC_CNT]) | |
|
|
|
|
(ext_csd[EXT_CSD_SEC_CNT + 1] << 8) | |
|
|
|
|
(ext_csd[EXT_CSD_SEC_CNT + 2] << 16) | |
|
|
|
|
(ext_csd[EXT_CSD_SEC_CNT + 3] << 24); |
|
|
|
|
capacity *= MMC_MAX_BLOCK_LEN; |
|
|
|
|
mmc->capacity_user = capacity; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
/* Calculate the group size from the csd value. */ |
|
|
|
|
int erase_gsz, erase_gmul; |
|
|
|
@ -1103,8 +1121,10 @@ static int mmc_startup(struct mmc *mmc) |
|
|
|
|
|
|
|
|
|
/* An array to map CSD bus widths to host cap bits */ |
|
|
|
|
static unsigned ext_to_hostcaps[] = { |
|
|
|
|
[EXT_CSD_DDR_BUS_WIDTH_4] = MMC_MODE_DDR_52MHz, |
|
|
|
|
[EXT_CSD_DDR_BUS_WIDTH_8] = MMC_MODE_DDR_52MHz, |
|
|
|
|
[EXT_CSD_DDR_BUS_WIDTH_4] = |
|
|
|
|
MMC_MODE_DDR_52MHz | MMC_MODE_4BIT, |
|
|
|
|
[EXT_CSD_DDR_BUS_WIDTH_8] = |
|
|
|
|
MMC_MODE_DDR_52MHz | MMC_MODE_8BIT, |
|
|
|
|
[EXT_CSD_BUS_WIDTH_4] = MMC_MODE_4BIT, |
|
|
|
|
[EXT_CSD_BUS_WIDTH_8] = MMC_MODE_8BIT, |
|
|
|
|
}; |
|
|
|
@ -1116,13 +1136,13 @@ static int mmc_startup(struct mmc *mmc) |
|
|
|
|
|
|
|
|
|
for (idx=0; idx < ARRAY_SIZE(ext_csd_bits); idx++) { |
|
|
|
|
unsigned int extw = ext_csd_bits[idx]; |
|
|
|
|
unsigned int caps = ext_to_hostcaps[extw]; |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Check to make sure the controller supports |
|
|
|
|
* this bus width, if it's more than 1 |
|
|
|
|
* Check to make sure the card and controller support |
|
|
|
|
* these capabilities |
|
|
|
|
*/ |
|
|
|
|
if (extw != EXT_CSD_BUS_WIDTH_1 && |
|
|
|
|
!(mmc->cfg->host_caps & ext_to_hostcaps[extw])) |
|
|
|
|
if ((mmc->card_caps & caps) != caps) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, |
|
|
|
@ -1131,26 +1151,33 @@ static int mmc_startup(struct mmc *mmc) |
|
|
|
|
if (err) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
mmc->ddr_mode = (caps & MMC_MODE_DDR_52MHz) ? 1 : 0; |
|
|
|
|
mmc_set_bus_width(mmc, widths[idx]); |
|
|
|
|
|
|
|
|
|
err = mmc_send_ext_csd(mmc, test_csd); |
|
|
|
|
|
|
|
|
|
if (err) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
/* Only compare read only fields */ |
|
|
|
|
if (!err && ext_csd[EXT_CSD_PARTITIONING_SUPPORT] \
|
|
|
|
|
== test_csd[EXT_CSD_PARTITIONING_SUPPORT] |
|
|
|
|
&& ext_csd[EXT_CSD_HC_WP_GRP_SIZE] \
|
|
|
|
|
== test_csd[EXT_CSD_HC_WP_GRP_SIZE] \
|
|
|
|
|
&& ext_csd[EXT_CSD_REV] \
|
|
|
|
|
== test_csd[EXT_CSD_REV] |
|
|
|
|
&& ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] \
|
|
|
|
|
== test_csd[EXT_CSD_HC_ERASE_GRP_SIZE] |
|
|
|
|
&& memcmp(&ext_csd[EXT_CSD_SEC_CNT], \
|
|
|
|
|
&test_csd[EXT_CSD_SEC_CNT], 4) == 0) { |
|
|
|
|
|
|
|
|
|
mmc->card_caps |= ext_to_hostcaps[extw]; |
|
|
|
|
if (ext_csd[EXT_CSD_PARTITIONING_SUPPORT] |
|
|
|
|
== test_csd[EXT_CSD_PARTITIONING_SUPPORT] && |
|
|
|
|
ext_csd[EXT_CSD_HC_WP_GRP_SIZE] |
|
|
|
|
== test_csd[EXT_CSD_HC_WP_GRP_SIZE] && |
|
|
|
|
ext_csd[EXT_CSD_REV] |
|
|
|
|
== test_csd[EXT_CSD_REV] && |
|
|
|
|
ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] |
|
|
|
|
== test_csd[EXT_CSD_HC_ERASE_GRP_SIZE] && |
|
|
|
|
memcmp(&ext_csd[EXT_CSD_SEC_CNT], |
|
|
|
|
&test_csd[EXT_CSD_SEC_CNT], 4) == 0) |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
err = SWITCH_ERR; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (err) |
|
|
|
|
return err; |
|
|
|
|
|
|
|
|
|
if (mmc->card_caps & MMC_MODE_HS) { |
|
|
|
|
if (mmc->card_caps & MMC_MODE_HS_52MHz) |
|
|
|
|
mmc->tran_speed = 52000000; |
|
|
|
@ -1161,6 +1188,12 @@ static int mmc_startup(struct mmc *mmc) |
|
|
|
|
|
|
|
|
|
mmc_set_clock(mmc, mmc->tran_speed); |
|
|
|
|
|
|
|
|
|
/* Fix the block length for DDR mode */ |
|
|
|
|
if (mmc->ddr_mode) { |
|
|
|
|
mmc->read_bl_len = MMC_MAX_BLOCK_LEN; |
|
|
|
|
mmc->write_bl_len = MMC_MAX_BLOCK_LEN; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* fill in device description */ |
|
|
|
|
mmc->block_dev.lun = 0; |
|
|
|
|
mmc->block_dev.type = 0; |
|
|
|
@ -1306,6 +1339,7 @@ int mmc_start_init(struct mmc *mmc) |
|
|
|
|
if (err) |
|
|
|
|
return err; |
|
|
|
|
|
|
|
|
|
mmc->ddr_mode = 0; |
|
|
|
|
mmc_set_bus_width(mmc, 1); |
|
|
|
|
mmc_set_clock(mmc, 1); |
|
|
|
|
|
|
|
|
@ -1408,8 +1442,11 @@ void print_mmc_devices(char separator) |
|
|
|
|
|
|
|
|
|
printf("%s: %d", m->cfg->name, m->block_dev.dev); |
|
|
|
|
|
|
|
|
|
if (entry->next != &mmc_devices) |
|
|
|
|
printf("%c ", separator); |
|
|
|
|
if (entry->next != &mmc_devices) { |
|
|
|
|
printf("%c", separator); |
|
|
|
|
if (separator != '\n') |
|
|
|
|
puts (" "); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
printf("\n"); |
|
|
|
|