Newer
Older
cmd.cmdidx = SD_CMD_SEND_RELATIVE_ADDR;
cmd.cmdarg = mmc->rca << 16;
cmd.resp_type = MMC_RSP_R6;
if (IS_SD(mmc))
mmc->rca = (cmd.response[0] >> 16) & 0xffff;
}
/* Get the Card-Specific Data */
cmd.cmdidx = MMC_CMD_SEND_CSD;
cmd.resp_type = MMC_RSP_R2;
cmd.cmdarg = mmc->rca << 16;
err = mmc_send_cmd(mmc, &cmd, NULL);
/* Waiting for the ready status */
mmc_send_status(mmc, timeout);
mmc->csd[0] = cmd.response[0];
mmc->csd[1] = cmd.response[1];
mmc->csd[2] = cmd.response[2];
mmc->csd[3] = cmd.response[3];
int version = (cmd.response[0] >> 26) & 0xf;
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
switch (version) {
case 0:
mmc->version = MMC_VERSION_1_2;
break;
case 1:
mmc->version = MMC_VERSION_1_4;
break;
case 2:
mmc->version = MMC_VERSION_2_2;
break;
case 3:
mmc->version = MMC_VERSION_3;
break;
case 4:
mmc->version = MMC_VERSION_4;
break;
default:
mmc->version = MMC_VERSION_1_2;
break;
}
}
/* divide frequency by 10, since the mults are 10x bigger */
freq = fbase[(cmd.response[0] & 0x7)];
mult = multipliers[((cmd.response[0] >> 3) & 0xf)];
mmc->read_bl_len = 1 << ((cmd.response[1] >> 16) & 0xf);
if (IS_SD(mmc))
mmc->write_bl_len = mmc->read_bl_len;
else
mmc->write_bl_len = 1 << ((cmd.response[3] >> 22) & 0xf);
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
if (mmc->high_capacity) {
csize = (mmc->csd[1] & 0x3f) << 16
| (mmc->csd[2] & 0xffff0000) >> 16;
cmult = 8;
} else {
csize = (mmc->csd[1] & 0x3ff) << 2
| (mmc->csd[2] & 0xc0000000) >> 30;
cmult = (mmc->csd[2] & 0x00038000) >> 15;
}
mmc->capacity = (csize + 1) << (cmult + 2);
mmc->capacity *= mmc->read_bl_len;
if (mmc->read_bl_len > 512)
mmc->read_bl_len = 512;
if (mmc->write_bl_len > 512)
mmc->write_bl_len = 512;
/* Select the card, and put it into Transfer Mode */
if (!mmc_host_is_spi(mmc)) { /* cmd not supported in spi */
cmd.cmdidx = MMC_CMD_SELECT_CARD;
cmd.cmdarg = mmc->rca << 16;
err = mmc_send_cmd(mmc, &cmd, NULL);
/*
* For SD, its erase group is always one sector
*/
mmc->erase_grp_size = 1;
mmc->part_config = MMCPART_NOAVAILABLE;
if (!IS_SD(mmc) && (mmc->version >= MMC_VERSION_4)) {
/* check ext_csd version and capacity */
err = mmc_send_ext_csd(mmc, ext_csd);
if (!err & (ext_csd[EXT_CSD_REV] >= 2)) {
/*
* According to the JEDEC Standard, the value of
* ext_csd's capacity is valid if the value is more
* than 2GB
*/
capacity = ext_csd[EXT_CSD_SEC_CNT] << 0
| ext_csd[EXT_CSD_SEC_CNT + 1] << 8
| ext_csd[EXT_CSD_SEC_CNT + 2] << 16
| ext_csd[EXT_CSD_SEC_CNT + 3] << 24;
if ((capacity >> 20) > 2 * 1024)
/*
* Check whether GROUP_DEF is set, if yes, read out
* group size from ext_csd directly, or calculate
* the group size from the csd value.
*/
if (ext_csd[EXT_CSD_ERASE_GROUP_DEF])
mmc->erase_grp_size =
ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] * 512 * 1024;
else {
int erase_gsz, erase_gmul;
erase_gsz = (mmc->csd[2] & 0x00007c00) >> 10;
erase_gmul = (mmc->csd[2] & 0x000003e0) >> 5;
mmc->erase_grp_size = (erase_gsz + 1)
* (erase_gmul + 1);
}
/* store the partition info of emmc */
if (ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & PART_SUPPORT)
mmc->part_config = ext_csd[EXT_CSD_PART_CONF];
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
if (IS_SD(mmc))
err = sd_change_freq(mmc);
else
err = mmc_change_freq(mmc);
if (err)
return err;
/* Restrict card's capabilities by what the host can do */
mmc->card_caps &= mmc->host_caps;
if (IS_SD(mmc)) {
if (mmc->card_caps & MMC_MODE_4BIT) {
cmd.cmdidx = MMC_CMD_APP_CMD;
cmd.resp_type = MMC_RSP_R1;
cmd.cmdarg = mmc->rca << 16;
err = mmc_send_cmd(mmc, &cmd, NULL);
if (err)
return err;
cmd.cmdidx = SD_CMD_APP_SET_BUS_WIDTH;
cmd.resp_type = MMC_RSP_R1;
cmd.cmdarg = 2;
err = mmc_send_cmd(mmc, &cmd, NULL);
if (err)
return err;
mmc_set_bus_width(mmc, 4);
}
if (mmc->card_caps & MMC_MODE_HS)
mmc->tran_speed = 50000000;
mmc->tran_speed = 25000000;
width = ((mmc->host_caps & MMC_MODE_MASK_WIDTH_BITS) >>
MMC_MODE_WIDTH_BITS_SHIFT);
for (; width >= 0; width--) {
/* Set the card to use 4 bit*/
err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
if (!width) {
mmc_set_bus_width(mmc, 1);
break;
} else
mmc_set_bus_width(mmc, 4 * width);
err = mmc_send_ext_csd(mmc, test_csd);
if (!err && ext_csd[EXT_CSD_PARTITIONING_SUPPORT] \
== test_csd[EXT_CSD_PARTITIONING_SUPPORT]
&& ext_csd[EXT_CSD_ERASE_GROUP_DEF] \
== test_csd[EXT_CSD_ERASE_GROUP_DEF] \
&& 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 |= width;
break;
}
}
if (mmc->card_caps & MMC_MODE_HS) {
if (mmc->card_caps & MMC_MODE_HS_52MHz)
mmc->tran_speed = 52000000;
mmc->tran_speed = 26000000;
}
mmc_set_clock(mmc, mmc->tran_speed);
/* fill in device description */
mmc->block_dev.lun = 0;
mmc->block_dev.type = 0;
mmc->block_dev.blksz = mmc->read_bl_len;
mmc->block_dev.lba = lldiv(mmc->capacity, mmc->read_bl_len);
sprintf(mmc->block_dev.vendor, "Man %06x Snr %08x", mmc->cid[0] >> 8,
(mmc->cid[2] << 8) | (mmc->cid[3] >> 24));
sprintf(mmc->block_dev.product, "%c%c%c%c%c", mmc->cid[0] & 0xff,
(mmc->cid[1] >> 24), (mmc->cid[1] >> 16) & 0xff,
(mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff);
sprintf(mmc->block_dev.revision, "%d.%d", mmc->cid[2] >> 28,
(mmc->cid[2] >> 24) & 0xf);
init_part(&mmc->block_dev);
return 0;
}
int mmc_send_if_cond(struct mmc *mmc)
{
struct mmc_cmd cmd;
int err;
cmd.cmdidx = SD_CMD_SEND_IF_COND;
/* We set the bit if the host supports voltages between 2.7 and 3.6 V */
cmd.cmdarg = ((mmc->voltages & 0xff8000) != 0) << 8 | 0xaa;
cmd.resp_type = MMC_RSP_R7;
err = mmc_send_cmd(mmc, &cmd, NULL);
if (err)
return err;
return UNUSABLE_ERR;
else
mmc->version = SD_VERSION_2;
return 0;
}
int mmc_register(struct mmc *mmc)
{
/* Setup the universal parts of the block interface just once */
mmc->block_dev.if_type = IF_TYPE_MMC;
mmc->block_dev.dev = cur_dev_num++;
mmc->block_dev.removable = 1;
mmc->block_dev.block_read = mmc_bread;
mmc->block_dev.block_write = mmc_bwrite;
mmc->block_dev.block_erase = mmc_berase;
if (!mmc->b_max)
mmc->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
INIT_LIST_HEAD (&mmc->link);
list_add_tail (&mmc->link, &mmc_devices);
return 0;
}
block_dev_desc_t *mmc_get_dev(int dev)
{
struct mmc *mmc = find_mmc_device(dev);
if (!mmc)
return NULL;
mmc_init(mmc);
return &mmc->block_dev;
int err;
if (mmc_getcd(mmc) == 0) {
mmc->has_init = 0;
printf("MMC: no card present\n");
return NO_CARD_ERR;
}
if (mmc->has_init)
return 0;
err = mmc->init(mmc);
if (err)
return err;
mmc_set_bus_width(mmc, 1);
mmc_set_clock(mmc, 1);
/* Reset the Card */
err = mmc_go_idle(mmc);
if (err)
return err;
/* The internal partition reset to user partition(0) at every CMD0*/
mmc->part_num = 0;
err = mmc_send_if_cond(mmc);
/* Now try to get the SD card's operating condition */
err = sd_send_op_cond(mmc);
/* If the command timed out, we check for an MMC card */
if (err == TIMEOUT) {
err = mmc_send_op_cond(mmc);
if (err) {
printf("Card did not respond to voltage select!\n");
return UNUSABLE_ERR;
}
}
err = mmc_startup(mmc);
if (err)
mmc->has_init = 0;
else
mmc->has_init = 1;
return err;
}
/*
* CPU and board-specific MMC initializations. Aliased function
* signals caller to move on
*/
static int __def_mmc_init(bd_t *bis)
{
return -1;
}
int cpu_mmc_init(bd_t *bis) __attribute__((weak, alias("__def_mmc_init")));
int board_mmc_init(bd_t *bis) __attribute__((weak, alias("__def_mmc_init")));
void print_mmc_devices(char separator)
{
struct mmc *m;
struct list_head *entry;
list_for_each(entry, &mmc_devices) {
m = list_entry(entry, struct mmc, link);
printf("%s: %d", m->name, m->block_dev.dev);
if (entry->next != &mmc_devices)
printf("%c ", separator);
}
printf("\n");
}
int get_mmc_num(void)
{
return cur_dev_num;
}