|
@@ -159,7 +159,7 @@ int mmc_set_blocklen(struct mmc *mmc, int len)
|
|
{
|
|
{
|
|
struct mmc_cmd cmd;
|
|
struct mmc_cmd cmd;
|
|
|
|
|
|
- if (mmc->card_caps & MMC_MODE_DDR_52MHz)
|
|
|
|
|
|
+ if (mmc->ddr_mode)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
cmd.cmdidx = MMC_CMD_SET_BLOCKLEN;
|
|
cmd.cmdidx = MMC_CMD_SET_BLOCKLEN;
|
|
@@ -486,7 +486,7 @@ static int mmc_change_freq(struct mmc *mmc)
|
|
char cardtype;
|
|
char cardtype;
|
|
int err;
|
|
int err;
|
|
|
|
|
|
- mmc->card_caps = 0;
|
|
|
|
|
|
+ mmc->card_caps = MMC_MODE_4BIT | MMC_MODE_8BIT;
|
|
|
|
|
|
if (mmc_host_is_spi(mmc))
|
|
if (mmc_host_is_spi(mmc))
|
|
return 0;
|
|
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 */
|
|
/* High Speed is set, there are two types: 52MHz and 26MHz */
|
|
if (cardtype & EXT_CSD_CARD_TYPE_52) {
|
|
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_DDR_52MHz;
|
|
mmc->card_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
|
|
mmc->card_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
|
|
} else {
|
|
} else {
|
|
@@ -1001,6 +1001,9 @@ static int mmc_startup(struct mmc *mmc)
|
|
case 6:
|
|
case 6:
|
|
mmc->version = MMC_VERSION_4_5;
|
|
mmc->version = MMC_VERSION_4_5;
|
|
break;
|
|
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 =
|
|
mmc->erase_grp_size =
|
|
ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] *
|
|
ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] *
|
|
MMC_MAX_BLOCK_LEN * 1024;
|
|
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 {
|
|
} else {
|
|
/* Calculate the group size from the csd value. */
|
|
/* Calculate the group size from the csd value. */
|
|
int erase_gsz, erase_gmul;
|
|
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 */
|
|
/* An array to map CSD bus widths to host cap bits */
|
|
static unsigned ext_to_hostcaps[] = {
|
|
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_4] = MMC_MODE_4BIT,
|
|
[EXT_CSD_BUS_WIDTH_8] = MMC_MODE_8BIT,
|
|
[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++) {
|
|
for (idx=0; idx < ARRAY_SIZE(ext_csd_bits); idx++) {
|
|
unsigned int extw = 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;
|
|
continue;
|
|
|
|
|
|
err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
|
|
err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
|
|
@@ -1131,26 +1151,33 @@ static int mmc_startup(struct mmc *mmc)
|
|
if (err)
|
|
if (err)
|
|
continue;
|
|
continue;
|
|
|
|
|
|
|
|
+ mmc->ddr_mode = (caps & MMC_MODE_DDR_52MHz) ? 1 : 0;
|
|
mmc_set_bus_width(mmc, widths[idx]);
|
|
mmc_set_bus_width(mmc, widths[idx]);
|
|
|
|
|
|
err = mmc_send_ext_csd(mmc, test_csd);
|
|
err = mmc_send_ext_csd(mmc, test_csd);
|
|
|
|
+
|
|
|
|
+ if (err)
|
|
|
|
+ continue;
|
|
|
|
+
|
|
/* Only compare read only fields */
|
|
/* 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;
|
|
break;
|
|
- }
|
|
|
|
|
|
+ else
|
|
|
|
+ err = SWITCH_ERR;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (err)
|
|
|
|
+ return err;
|
|
|
|
+
|
|
if (mmc->card_caps & MMC_MODE_HS) {
|
|
if (mmc->card_caps & MMC_MODE_HS) {
|
|
if (mmc->card_caps & MMC_MODE_HS_52MHz)
|
|
if (mmc->card_caps & MMC_MODE_HS_52MHz)
|
|
mmc->tran_speed = 52000000;
|
|
mmc->tran_speed = 52000000;
|
|
@@ -1161,6 +1188,12 @@ static int mmc_startup(struct mmc *mmc)
|
|
|
|
|
|
mmc_set_clock(mmc, mmc->tran_speed);
|
|
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 */
|
|
/* fill in device description */
|
|
mmc->block_dev.lun = 0;
|
|
mmc->block_dev.lun = 0;
|
|
mmc->block_dev.type = 0;
|
|
mmc->block_dev.type = 0;
|
|
@@ -1306,6 +1339,7 @@ int mmc_start_init(struct mmc *mmc)
|
|
if (err)
|
|
if (err)
|
|
return err;
|
|
return err;
|
|
|
|
|
|
|
|
+ mmc->ddr_mode = 0;
|
|
mmc_set_bus_width(mmc, 1);
|
|
mmc_set_bus_width(mmc, 1);
|
|
mmc_set_clock(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);
|
|
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");
|
|
printf("\n");
|