aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPer Forlin <per.forlin@linaro.org>2011-08-26 12:21:52 +0200
committerMathieu J. Poirier <mathieu.poirier@linaro.org>2011-11-07 10:21:42 -0700
commit9bb9295fc2cbbe1cc315fd48056ca509e5436d94 (patch)
treec72ef463c97d09e4a9c7d625aed860905a169843
parent20f0eb7e02cf16ebb7f3fdcd0ba8dc6089d86a5b (diff)
snowball: override copy port of generic mmc-fixes from igloo.
TODO: remove this patch and use pl180_mmci driver Signed-off-by: Per Forlin <per.forlin@linaro.org>
-rw-r--r--common/cmd_mmc.c393
-rw-r--r--drivers/mmc/mmc.c778
-rw-r--r--include/mmc.h197
3 files changed, 698 insertions, 670 deletions
diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c
index 176646d46..ceafdda12 100644
--- a/common/cmd_mmc.c
+++ b/common/cmd_mmc.c
@@ -25,14 +25,17 @@
#include <command.h>
#include <mmc.h>
-static int curr_device = -1;
#ifndef CONFIG_GENERIC_MMC
-int do_mmc (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+static int curr_device = -1;
+
+int do_mmc (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
int dev;
- if (argc < 2)
- return cmd_usage(cmdtp);
+ if (argc < 2) {
+ cmd_usage(cmdtp);
+ return 1;
+ }
if (strcmp(argv[1], "init") == 0) {
if (argc == 2) {
@@ -43,7 +46,8 @@ int do_mmc (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
} else if (argc == 3) {
dev = (int)simple_strtoul(argv[2], NULL, 10);
} else {
- return cmd_usage(cmdtp);
+ cmd_usage(cmdtp);
+ return 1;
}
if (mmc_legacy_init(dev) != 0) {
@@ -68,12 +72,14 @@ int do_mmc (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
#endif
curr_device = dev;
} else {
- return cmd_usage(cmdtp);
+ cmd_usage(cmdtp);
+ return 1;
}
printf("mmc%d is current device\n", curr_device);
} else {
- return cmd_usage(cmdtp);
+ cmd_usage(cmdtp);
+ return 1;
}
return 0;
@@ -103,202 +109,281 @@ static void print_mmcinfo(struct mmc *mmc)
(mmc->version >> 4) & 0xf, mmc->version & 0xf);
printf("High Capacity: %s\n", mmc->high_capacity ? "Yes" : "No");
- puts("Capacity: ");
- print_size(mmc->capacity, "\n");
+ printf("Capacity: %lld\n", mmc->capacity);
printf("Bus Width: %d-bit\n", mmc->bus_width);
}
-int do_mmcinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+static void print_csd(struct mmc *mmc)
+{
+ printf("mmc->csd[0] = 0x%08X\n", mmc->csd[0]);
+ printf("mmc->csd[1] = 0x%08X\n", mmc->csd[1]);
+ printf("mmc->csd[2] = 0x%08X\n", mmc->csd[2]);
+ printf("mmc->csd[3] = 0x%08X\n", mmc->csd[3]);
+
+ printf("csd->csd_structure = 0x%02X\n", CSD_STRUCTURE(mmc->csd));
+ printf("csd->spec_vers = 0x%02X\n", CSD_SPEC_VERS(mmc->csd));
+ printf("csd->taac = 0x%02X\n", CSD_TAAC(mmc->csd));
+ printf("csd->nsac = 0x%02X\n", CSD_NSAC(mmc->csd));
+ printf("csd->tran_speed = 0x%02X\n", CSD_TRAN_SPEED(mmc->csd));
+ printf("csd->ccc = 0x%04X\n", CSD_CCC(mmc->csd));
+ printf("csd->read_bl_len = 0x%02X\n", CSD_READ_BL_LEN(mmc->csd));
+ printf("csd->read_bl_partial = 0x%02X\n",
+ CSD_READ_BL_PARTIAL(mmc->csd));
+ printf("csd->write_blk_misalign = 0x%02X\n",
+ CSD_WRITE_BLK_MISALIGN(mmc->csd));
+ printf("csd->read_blk_misalign = 0x%02X\n",
+ CSD_READ_BLK_MISALIGN(mmc->csd));
+ printf("csd->dsr_imp = 0x%02X\n", CSD_DSR_IMP(mmc->csd));
+ printf("csd->c_size = 0x%04X\n", CSD_C_SIZE(mmc->csd));
+ printf("csd->vdd_r_curr_min = 0x%04X\n", CSD_VDD_R_CURR_MIN(mmc->csd));
+ printf("csd->vdd_r_curr_max = 0x%04X\n", CSD_VDD_R_CURR_MAX(mmc->csd));
+ printf("csd->vdd_w_curr_min = 0x%04X\n", CSD_VDD_W_CURR_MIN(mmc->csd));
+ printf("csd->vdd_w_curr_max = 0x%04X\n", CSD_VDD_W_CURR_MAX(mmc->csd));
+ printf("csd->c_size_mult = 0x%04X\n", CSD_C_SIZE_MULT(mmc->csd));
+ printf("csd->erase_grp_size = 0x%04X\n", CSD_ERASE_GRP_SIZE(mmc->csd));
+ printf("csd->erase_grp_mult = 0x%04X\n", CSD_ERASE_GRP_MULT(mmc->csd));
+ printf("csd->wp_grp_size = 0x%04X\n", CSD_WP_GRP_SIZE(mmc->csd));
+ printf("csd->wp_grp_enable = 0x%02X\n", CSD_WP_GRP_ENABLE(mmc->csd));
+ printf("csd->default_ecc = 0x%02X\n", CSD_DEFAULT_ECC(mmc->csd));
+ printf("csd->r2w_factor = 0x%04X\n", CSD_R2W_FACTOR(mmc->csd));
+ printf("csd->write_bl_len = 0x%04X\n", CSD_WRITE_BL_LEN(mmc->csd));
+ printf("csd->write_bl_partial = 0x%02X\n",
+ CSD_WRITE_BL_PARTIAL(mmc->csd));
+ printf("csd->file_format_grp = 0x%02X\n",
+ CSD_FILE_FORMAT_GRP(mmc->csd));
+ printf("csd->copy = 0x%02X\n", CSD_COPY(mmc->csd));
+ printf("csd->perm_write_protect = 0x%02X\n",
+ CSD_PERM_WRITE_PROTECT(mmc->csd));
+ printf("csd->tmp_write_protect = 0x%02X\n",
+ CSD_TMP_WRITE_PROTECT(mmc->csd));
+ printf("csd->ecc = 0x%02X\n", CSD_ECC(mmc->csd));
+ printf("csd->crc = 0x%02X\n", CSD_CRC(mmc->csd));
+ printf("csd->one = 0x%02X\n", CSD_ONE(mmc->csd));
+}
+
+static void print_ext_csd(char *ext_csd)
+{
+ printf("ext_csd->s_cmd_set = 0x%02X\n", ext_csd[504]);
+ printf("ext_csd->hpl_features = 0x%02X\n", ext_csd[503]);
+ printf("ext_csd->bkops_support = 0x%02X\n", ext_csd[502]);
+ printf("ext_csd->bkops_status = 0x%02X\n", ext_csd[246]);
+ printf("ext_csd->correctly_prg_sectors_num = 0x%08X\n",
+ ext_csd[245] * (1 << 24) | ext_csd[244] * (1 << 16) |
+ ext_csd[243] * (1 << 8) | ext_csd[242]);
+ printf("ext_csd->ini_timeout_ap = 0x%02X\n", ext_csd[241]);
+ printf("ext_csd->pwr_cl_ddr_52_360 = 0x%02X\n", ext_csd[239]);
+ printf("ext_csd->pwr_cl_ddr_52_195 = 0x%02X\n", ext_csd[238]);
+ printf("ext_csd->min_perf_ddr_w_8_52 = 0x%02X\n", ext_csd[235]);
+ printf("ext_csd->min_perf_ddr_r_8_52 = 0x%02X\n", ext_csd[234]);
+ printf("ext_csd->trim_mult = 0x%02X\n", ext_csd[232]);
+ printf("ext_csd->sec_feature_support = 0x%02X\n", ext_csd[231]);
+ printf("ext_csd->sec_erase_mult = 0x%02X\n", ext_csd[230]);
+ printf("ext_csd->sec_trim_mult = 0x%02X\n", ext_csd[229]);
+ printf("ext_csd->boot_info = 0x%02X\n", ext_csd[228]);
+ printf("ext_csd->boot_size_mult = 0x%02X\n", ext_csd[226]);
+ printf("ext_csd->acc_size = 0x%02X\n", ext_csd[225]);
+ printf("ext_csd->hc_erase_gp_size = 0x%02X\n", ext_csd[224]);
+ printf("ext_csd->erase_timeout_mult = 0x%02X\n", ext_csd[223]);
+ printf("ext_csd->rel_wr_sec_c = 0x%02X\n", ext_csd[222]);
+ printf("ext_csd->hc_wp_grp_size = 0x%02X\n", ext_csd[221]);
+ printf("ext_csd->s_c_vcc = 0x%02X\n", ext_csd[220]);
+ printf("ext_csd->s_c_vccq = 0x%02X\n", ext_csd[219]);
+ printf("ext_csd->s_a_timeout = 0x%02X\n", ext_csd[217]);
+ printf("ext_csd->sec_count = 0x%08X\n", ext_csd[215] * (1 << 24) |
+ ext_csd[214] * (1 << 16)|ext_csd[213]*(1 << 8)|ext_csd[212]);
+ printf("ext_csd->min_perf_w_8_52 = 0x%02X\n", ext_csd[210]);
+ printf("ext_csd->min_perf_r_8_52 = 0x%02X\n", ext_csd[209]);
+ printf("ext_csd->min_perf_w_8_26_4_52 = 0x%02X\n", ext_csd[208]);
+ printf("ext_csd->min_perf_r_8_26_4_52 = 0x%02X\n", ext_csd[207]);
+ printf("ext_csd->min_perf_w_4_26 = 0x%02X\n", ext_csd[206]);
+ printf("ext_csd->min_perf_r_4_26 = 0x%02X\n", ext_csd[205]);
+ printf("ext_csd->pwr_cl_26_360 = 0x%02X\n", ext_csd[203]);
+ printf("ext_csd->pwr_cl_52_360 = 0x%02X\n", ext_csd[202]);
+ printf("ext_csd->pwr_cl_26_195 = 0x%02X\n", ext_csd[201]);
+ printf("ext_csd->pwr_cl_52_195 = 0x%02X\n", ext_csd[200]);
+ printf("ext_csd->partition_switch_time = 0x%02X\n", ext_csd[199]);
+ printf("ext_csd->out_of_interrupt_time = 0x%02X\n", ext_csd[198]);
+ printf("ext_csd->card_type = 0x%02X\n", ext_csd[196]);
+ printf("ext_csd->csd_structure = 0x%02X\n", ext_csd[194]);
+ printf("ext_csd->ext_csd_rev = 0x%02X\n", ext_csd[192]);
+ printf("ext_csd->cmd_set = 0x%02X\n", ext_csd[191]);
+ printf("ext_csd->cmd_set_rev = 0x%02X\n", ext_csd[189]);
+ printf("ext_csd->power_class = 0x%02X\n", ext_csd[187]);
+ printf("ext_csd->hs_timing = 0x%02X\n", ext_csd[185]);
+ printf("ext_csd->bus_width = 0x%02X\n", ext_csd[183]);
+ printf("ext_csd->erased_mem_cont = 0x%02X\n", ext_csd[181]);
+ printf("ext_csd->partition_config = 0x%02X\n", ext_csd[179]);
+ printf("ext_csd->boot_config_prot = 0x%02X\n", ext_csd[178]);
+ printf("ext_csd->boot_bus_width = 0x%02X\n", ext_csd[177]);
+ printf("ext_csd->erase_group_def = 0x%02X\n", ext_csd[175]);
+ printf("ext_csd->boot_wp = 0x%02X\n", ext_csd[173]);
+ printf("ext_csd->user_wp = 0x%02X\n", ext_csd[171]);
+ printf("ext_csd->fw_config = 0x%02X\n", ext_csd[169]);
+ printf("ext_csd->rpmb_size_mult = 0x%02X\n", ext_csd[168]);
+ printf("ext_csd->wr_rel_set = 0x%02X\n", ext_csd[167]);
+ printf("ext_csd->wr_rel_param = 0x%02X\n", ext_csd[166]);
+ printf("ext_csd->bkops_start = 0x%02X\n", ext_csd[164]);
+ printf("ext_csd->bkops_en = 0x%02X\n", ext_csd[163]);
+ printf("ext_csd->rst_n_function = 0x%02X\n", ext_csd[162]);
+ printf("ext_csd->hpi_mgmt = 0x%02X\n", ext_csd[161]);
+ printf("ext_csd->partitioning_support = 0x%02X\n", ext_csd[160]);
+ printf("ext_csd->max_en_size_mult = 0x%08X\n", ext_csd[159] * (1 << 16)
+ | ext_csd[158] * (1 << 8) | ext_csd[157]);
+ printf("ext_csd->partitions_attribute = 0x%02X\n", ext_csd[156]);
+ printf("ext_csd->partition_setting_completed = 0x%02X\n", ext_csd[155]);
+ printf("ext_csd->gp_size_mult = 0x%08X\n", ext_csd[146] * (1 << 24) |
+ ext_csd[145] * (1 << 16) | ext_csd[144] * (1 << 8) |
+ ext_csd[143]);
+ printf("ext_csd->enh_size_mult = 0x%08X\n", ext_csd[142] * (1 << 16) |
+ ext_csd[141]*(1 << 8) | ext_csd[140]);
+ printf("ext_csd->enh_start_addr = 0x%08X\n", ext_csd[139] * (1 << 24) |
+ ext_csd[138] * (1 << 16) | ext_csd[137] * (1 << 8) |
+ ext_csd[136]);
+ printf("ext_csd->sec_bad_blk_mgmnt = 0x%02X\n", ext_csd[134]);
+}
+
+int do_mmcinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
struct mmc *mmc;
+ int dev_num;
- if (curr_device < 0) {
- if (get_mmc_num() > 0)
- curr_device = 0;
- else {
- puts("No MMC device available\n");
- return 1;
- }
- }
+ if (argc < 2)
+ dev_num = 0;
+ else
+ dev_num = simple_strtoul(argv[1], NULL, 0);
- mmc = find_mmc_device(curr_device);
+ mmc = find_mmc_device(dev_num);
if (mmc) {
mmc_init(mmc);
print_mmcinfo(mmc);
- return 0;
- } else {
- printf("no mmc device at slot %x\n", curr_device);
- return 1;
+
+ if ((argc > 2) && (strcmp(argv[2], "csd") == 0))
+ print_csd(mmc);
+
+ /* Print Ext CSD */
+ if ((argc > 2) && (strcmp(argv[2], "ext_csd") == 0)) {
+ char ext_csd[512];
+ struct mmc_cmd cmd;
+ struct mmc_data data;
+
+ /* Get the Card Status Register */
+ cmd.cmdidx = MMC_CMD_SEND_EXT_CSD;
+ cmd.resp_type = MMC_RSP_R1;
+ cmd.cmdarg = 0;
+ cmd.flags = 0;
+
+ data.dest = ext_csd;
+ data.blocks = 1;
+ data.blocksize = 512;
+ data.flags = MMC_DATA_READ;
+
+ if (!mmc->send_cmd(mmc, &cmd, &data))
+ print_ext_csd(ext_csd);
+ }
}
+
+ return 0;
}
-U_BOOT_CMD(
- mmcinfo, 1, 0, do_mmcinfo,
- "display MMC info",
- " - device number of the device to dislay info of\n"
+U_BOOT_CMD(mmcinfo, 3, 0, do_mmcinfo,
+ "mmcinfo <dev num> [csd | ext_csd] -- display MMC info\n",
""
);
-int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
- if (argc < 2)
- return cmd_usage(cmdtp);
-
- if (curr_device < 0) {
- if (get_mmc_num() > 0)
- curr_device = 0;
- else {
- puts("No MMC device available\n");
- return 1;
- }
- }
+ int rc = 0;
- if (strcmp(argv[1], "rescan") == 0) {
- struct mmc *mmc = find_mmc_device(curr_device);
+ switch (argc) {
+ case 3:
+ if (strcmp(argv[1], "rescan") == 0) {
+ int dev = simple_strtoul(argv[2], NULL, 10);
+ struct mmc *mmc = find_mmc_device(dev);
- if (!mmc) {
- printf("no mmc device at slot %x\n", curr_device);
- return 1;
- }
-
- mmc->has_init = 0;
- mmc_init(mmc);
+ if (!mmc)
+ return 1;
- return 0;
- } else if (strncmp(argv[1], "part", 4) == 0) {
- block_dev_desc_t *mmc_dev;
- struct mmc *mmc = find_mmc_device(curr_device);
+ mmc_init(mmc);
- if (!mmc) {
- printf("no mmc device at slot %x\n", curr_device);
- return 1;
- }
- mmc_init(mmc);
- mmc_dev = mmc_get_dev(curr_device);
- if (mmc_dev != NULL &&
- mmc_dev->type != DEV_TYPE_UNKNOWN) {
- print_part(mmc_dev);
return 0;
}
- puts("get mmc type error!\n");
+ case 0:
+ case 1:
+ case 4:
+ printf("Usage:\n%s\n", cmdtp->usage);
return 1;
- } else if (strcmp(argv[1], "list") == 0) {
- print_mmc_devices('\n');
- return 0;
- } else if (strcmp(argv[1], "dev") == 0) {
- int dev, part = -1;
- struct mmc *mmc;
-
- if (argc == 2)
- dev = curr_device;
- else if (argc == 3)
- dev = simple_strtoul(argv[2], NULL, 10);
- else if (argc == 4) {
- dev = (int)simple_strtoul(argv[2], NULL, 10);
- part = (int)simple_strtoul(argv[3], NULL, 10);
- if (part > PART_ACCESS_MASK) {
- printf("#part_num shouldn't be larger"
- " than %d\n", PART_ACCESS_MASK);
- return 1;
- }
- } else
- return cmd_usage(cmdtp);
- mmc = find_mmc_device(dev);
- if (!mmc) {
- printf("no mmc device at slot %x\n", dev);
- return 1;
+ case 2:
+ if (!strcmp(argv[1], "list")) {
+ print_mmc_devices('\n');
+ return 0;
}
-
- mmc_init(mmc);
- if (part != -1) {
- int ret;
- if (mmc->part_config == MMCPART_NOAVAILABLE) {
- printf("Card doesn't support part_switch\n");
+ return 1;
+ default: /* at least 5 args */
+ if (strcmp(argv[1], "read") == 0) {
+ int dev = simple_strtoul(argv[2], NULL, 10);
+ void *addr = (void *)simple_strtoul(argv[3], NULL, 16);
+ u32 cnt = simple_strtoul(argv[5], NULL, 16);
+ u32 n;
+ u32 blk = simple_strtoul(argv[4], NULL, 16);
+ struct mmc *mmc = find_mmc_device(dev);
+
+ if (!mmc)
return 1;
- }
- if (part != mmc->part_num) {
- ret = mmc_switch_part(dev, part);
- if (!ret)
- mmc->part_num = part;
+ printf("\nMMC read: dev # %d, block # %d, count %d\n",
+ dev, blk, cnt);
- printf("switch to partions #%d, %s\n",
- part, (!ret) ? "OK" : "ERROR");
- }
- }
- curr_device = dev;
- if (mmc->part_config == MMCPART_NOAVAILABLE)
- printf("mmc%d is current device\n", curr_device);
- else
- printf("mmc%d(part %d) is current device\n",
- curr_device, mmc->part_num);
-
- return 0;
- } else if (strcmp(argv[1], "read") == 0) {
- void *addr = (void *)simple_strtoul(argv[2], NULL, 16);
- u32 cnt = simple_strtoul(argv[4], NULL, 16);
- u32 n;
- u32 blk = simple_strtoul(argv[3], NULL, 16);
- struct mmc *mmc = find_mmc_device(curr_device);
-
- if (!mmc) {
- printf("no mmc device at slot %x\n", curr_device);
- return 1;
- }
-
- printf("\nMMC read: dev # %d, block # %d, count %d ... ",
- curr_device, blk, cnt);
-
- mmc_init(mmc);
+ mmc_init(mmc);
- n = mmc->block_dev.block_read(curr_device, blk, cnt, addr);
+ n = mmc->block_dev.block_read(dev, blk, cnt, addr);
- /* flush cache after read */
- flush_cache((ulong)addr, cnt * 512); /* FIXME */
+ /* flush cache after read */
+ flush_cache((ulong)addr, cnt * 512); /* FIXME */
- printf("%d blocks read: %s\n",
+ printf("%d blocks read: %s\n",
n, (n==cnt) ? "OK" : "ERROR");
- return (n == cnt) ? 0 : 1;
- } else if (strcmp(argv[1], "write") == 0) {
- void *addr = (void *)simple_strtoul(argv[2], NULL, 16);
- u32 cnt = simple_strtoul(argv[4], NULL, 16);
- u32 n;
- struct mmc *mmc = find_mmc_device(curr_device);
+ return (n == cnt) ? 0 : 1;
+ } else if (strcmp(argv[1], "write") == 0) {
+ int dev = simple_strtoul(argv[2], NULL, 10);
+ void *addr = (void *)simple_strtoul(argv[3], NULL, 16);
+ u32 cnt = simple_strtoul(argv[5], NULL, 16);
+ u32 n;
+ struct mmc *mmc = find_mmc_device(dev);
- int blk = simple_strtoul(argv[3], NULL, 16);
+ int blk = simple_strtoul(argv[4], NULL, 16);
- if (!mmc) {
- printf("no mmc device at slot %x\n", curr_device);
- return 1;
- }
+ if (!mmc)
+ return 1;
- printf("\nMMC write: dev # %d, block # %d, count %d ... ",
- curr_device, blk, cnt);
+ printf("\nMMC write: dev # %d, block # %d, count %d\n",
+ dev, blk, cnt);
- mmc_init(mmc);
+ mmc_init(mmc);
- n = mmc->block_dev.block_write(curr_device, blk, cnt, addr);
+ n = mmc->block_dev.block_write(dev, blk, cnt, addr);
- printf("%d blocks written: %s\n",
+ printf("%d blocks written: %s\n",
n, (n == cnt) ? "OK" : "ERROR");
- return (n == cnt) ? 0 : 1;
- }
+ return (n == cnt) ? 0 : 1;
+ } else {
+ printf("Usage:\n%s\n", cmdtp->usage);
+ rc = 1;
+ }
- return cmd_usage(cmdtp);
+ return rc;
+ }
}
U_BOOT_CMD(
mmc, 6, 1, do_mmcops,
"MMC sub system",
- "read addr blk# cnt\n"
- "mmc write addr blk# cnt\n"
- "mmc rescan\n"
- "mmc part - lists available partition on current mmc device\n"
- "mmc dev [dev] [part] - show or set current mmc device [partition]\n"
+ "read <device num> addr blk# cnt\n"
+ "mmc write <device num> addr blk# cnt\n"
+ "mmc rescan <device num>\n"
"mmc list - lists available devices");
#endif
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 21aedbaa3..89f78ffa3 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -32,126 +32,37 @@
#include <linux/list.h>
#include <div64.h>
-/* Set block count limit because of 16 bit register limit on some hardware*/
-#ifndef CONFIG_SYS_MMC_MAX_BLK_COUNT
-#define CONFIG_SYS_MMC_MAX_BLK_COUNT 65535
-#endif
-
static struct list_head mmc_devices;
static int cur_dev_num = -1;
-int __board_mmc_getcd(u8 *cd, struct mmc *mmc) {
- return -1;
-}
-
-int board_mmc_getcd(u8 *cd, struct mmc *mmc)__attribute__((weak,
- alias("__board_mmc_getcd")));
-
-int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
+static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
+ struct mmc_data *data)
{
-#ifdef CONFIG_MMC_TRACE
- int ret;
- int i;
- u8 *ptr;
-
- printf("CMD_SEND:%d\n", cmd->cmdidx);
- printf("\t\tARG\t\t\t 0x%08X\n", cmd->cmdarg);
- printf("\t\tFLAG\t\t\t %d\n", cmd->flags);
- ret = mmc->send_cmd(mmc, cmd, data);
- switch (cmd->resp_type) {
- case MMC_RSP_NONE:
- printf("\t\tMMC_RSP_NONE\n");
- break;
- case MMC_RSP_R1:
- printf("\t\tMMC_RSP_R1,5,6,7 \t 0x%08X \n",
- cmd->response[0]);
- break;
- case MMC_RSP_R1b:
- printf("\t\tMMC_RSP_R1b\t\t 0x%08X \n",
- cmd->response[0]);
- break;
- case MMC_RSP_R2:
- printf("\t\tMMC_RSP_R2\t\t 0x%08X \n",
- cmd->response[0]);
- printf("\t\t \t\t 0x%08X \n",
- cmd->response[1]);
- printf("\t\t \t\t 0x%08X \n",
- cmd->response[2]);
- printf("\t\t \t\t 0x%08X \n",
- cmd->response[3]);
- printf("\n");
- printf("\t\t\t\t\tDUMPING DATA\n");
- for (i = 0; i < 4; i++) {
- int j;
- printf("\t\t\t\t\t%03d - ", i*4);
- ptr = &cmd->response[i];
- ptr += 3;
- for (j = 0; j < 4; j++)
- printf("%02X ", *ptr--);
- printf("\n");
- }
- break;
- case MMC_RSP_R3:
- printf("\t\tMMC_RSP_R3,4\t\t 0x%08X \n",
- cmd->response[0]);
- break;
- default:
- printf("\t\tERROR MMC rsp not supported\n");
- break;
- }
- return ret;
-#else
return mmc->send_cmd(mmc, cmd, data);
-#endif
}
-int mmc_send_status(struct mmc *mmc, int timeout)
+static int mmc_set_blocklen(struct mmc *mmc, uint len)
{
struct mmc_cmd cmd;
- int err;
-#ifdef CONFIG_MMC_TRACE
- int status;
-#endif
- cmd.cmdidx = MMC_CMD_SEND_STATUS;
+ cmd.cmdidx = MMC_CMD_SET_BLOCKLEN;
cmd.resp_type = MMC_RSP_R1;
- cmd.cmdarg = 0;
+ cmd.cmdarg = len;
cmd.flags = 0;
- do {
- err = mmc_send_cmd(mmc, &cmd, NULL);
- if (err)
- return err;
- else if (cmd.response[0] & MMC_STATUS_RDY_FOR_DATA)
- break;
-
- udelay(1000);
-
- if (cmd.response[0] & MMC_STATUS_MASK) {
- printf("Status Error: 0x%08X\n", cmd.response[0]);
- return COMM_ERR;
- }
- } while (timeout--);
-
-#ifdef CONFIG_MMC_TRACE
- status = (cmd.response[0] & MMC_STATUS_CURR_STATE) >> 9;
- printf("CURR STATE:%d\n", status);
-#endif
- if (!timeout) {
- printf("Timeout waiting card ready\n");
- return TIMEOUT;
- }
-
- return 0;
+ return mmc_send_cmd(mmc, &cmd, NULL);
}
-int mmc_set_blocklen(struct mmc *mmc, int len)
+static int mmc_set_block_count(struct mmc *mmc, uint blkcnt)
{
struct mmc_cmd cmd;
- cmd.cmdidx = MMC_CMD_SET_BLOCKLEN;
+ cmd.cmdidx = MMC_CMD_SET_BLOCK_COUNT;
cmd.resp_type = MMC_RSP_R1;
- cmd.cmdarg = len;
+ if (mmc->card_caps & MMC_MODE_REL_WR)
+ cmd.cmdarg = 0x80000000 | blkcnt;
+ else
+ cmd.cmdarg = blkcnt;
cmd.flags = 0;
return mmc_send_cmd(mmc, &cmd, NULL);
@@ -174,163 +85,249 @@ struct mmc *find_mmc_device(int dev_num)
return NULL;
}
-static ulong
-mmc_write_blocks(struct mmc *mmc, ulong start, lbaint_t blkcnt, const void*src)
+static unsigned long
+mmc_bwrite_multi(struct mmc *mmc, ulong start, ulong blkcnt, const void *src)
{
struct mmc_cmd cmd;
struct mmc_data data;
- int timeout = 1000;
+ int err;
+ ulong blkwritecnt;
+ ulong blkleftcnt = blkcnt;
+ void *src_p = (void *) src;
+ uint max_block_cnt = 0xffff;
- if ((start + blkcnt) > mmc->block_dev.lba) {
- printf("MMC: block number 0x%lx exceeds max(0x%lx)\n",
- start + blkcnt, mmc->block_dev.lba);
- return 0;
- }
+ /*
+ * Each mmc host controller has a size limit in it's register, used
+ * when initializing a new data transfer. Thus we need to wrap larger
+ * bulk of requests. At the moment the limit is hardcoded to 0xFFFF
+ * blocks. This should maybe be configurable by each host driver
+ * instead.
+ */
+
+ if ((mmc->card_caps & MMC_MODE_REL_WR) &&
+ !(mmc->wr_rel_param & EXT_CSD_WR_REL_PARAM_EN_REL_WR))
+ max_block_cnt = mmc->rel_wr_sec_c;
+
+ while (blkleftcnt > 0) {
+
+ if (blkleftcnt > max_block_cnt)
+ blkwritecnt = max_block_cnt;
+ else
+ blkwritecnt = blkleftcnt;
+
+ if (mmc->high_capacity)
+ cmd.cmdarg = start;
+ else
+ cmd.cmdarg = start * mmc->write_bl_len;
+
+ if (mmc->card_caps & MMC_MODE_REL_WR) {
+ err = mmc_set_block_count(mmc, blkwritecnt);
+ if (err) {
+ printf("MMC set block count failed, err=%d\n",
+ err);
+ return 0;
+ }
+ }
- if (blkcnt > 1)
cmd.cmdidx = MMC_CMD_WRITE_MULTIPLE_BLOCK;
- else
- cmd.cmdidx = MMC_CMD_WRITE_SINGLE_BLOCK;
+ cmd.resp_type = MMC_RSP_R1;
+ cmd.flags = 0;
+
+ data.blocksize = mmc->write_bl_len;
+ data.flags = MMC_DATA_WRITE;
+ data.src = src_p;
+ data.blocks = blkwritecnt;
+
+ err = mmc_send_cmd(mmc, &cmd, &data);
+ if (err) {
+ printf("MMC write multi failed, err=%d\n", err);
+ return 0;
+ }
+
+ if (!(mmc->card_caps & MMC_MODE_REL_WR) ||
+ (max_block_cnt != mmc->rel_wr_sec_c)) {
+ cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
+ cmd.cmdarg = 0;
+ cmd.resp_type = MMC_RSP_R1b;
+ cmd.flags = 0;
+
+ err = mmc_send_cmd(mmc, &cmd, NULL);
+ if (err) {
+ printf("MMC write - stop cmd failed, err=%d\n",
+ err);
+ return 0;
+ }
+ }
+
+ blkleftcnt -= blkwritecnt;
+ start += blkwritecnt;
+ src_p += blkwritecnt * mmc->write_bl_len;
+ }
+
+ return blkcnt;
+}
+
+static unsigned long
+mmc_bwrite_single(struct mmc *mmc, ulong start, const void *src)
+{
+ struct mmc_cmd cmd;
+ struct mmc_data data;
+ int err;
+
+ cmd.cmdidx = MMC_CMD_WRITE_SINGLE_BLOCK;
+ cmd.resp_type = MMC_RSP_R1;
+ cmd.flags = 0;
if (mmc->high_capacity)
cmd.cmdarg = start;
else
cmd.cmdarg = start * mmc->write_bl_len;
- cmd.resp_type = MMC_RSP_R1;
- cmd.flags = 0;
-
data.src = src;
- data.blocks = blkcnt;
+ data.blocks = 1;
data.blocksize = mmc->write_bl_len;
data.flags = MMC_DATA_WRITE;
- if (mmc_send_cmd(mmc, &cmd, &data)) {
- printf("mmc write failed\n");
+ err = mmc_send_cmd(mmc, &cmd, &data);
+ if (err) {
+ printf("MMC write single failed, err=%d\n", err);
return 0;
}
- /* SPI multiblock writes terminate using a special
- * token, not a STOP_TRANSMISSION request.
- */
- if (!mmc_host_is_spi(mmc) && blkcnt > 1) {
- cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
- cmd.cmdarg = 0;
- cmd.resp_type = MMC_RSP_R1b;
- cmd.flags = 0;
- if (mmc_send_cmd(mmc, &cmd, NULL)) {
- printf("mmc fail to send stop cmd\n");
- return 0;
- }
-
- /* Waiting for the ready status */
- mmc_send_status(mmc, timeout);
- }
-
- return blkcnt;
+ return 1;
}
-static ulong
-mmc_bwrite(int dev_num, ulong start, lbaint_t blkcnt, const void*src)
+static unsigned long
+mmc_bwrite(int dev_num, unsigned long start, lbaint_t blkcnt, const void *src)
{
- lbaint_t cur, blocks_todo = blkcnt;
-
+ int err;
struct mmc *mmc = find_mmc_device(dev_num);
- if (!mmc)
- return 0;
- if (mmc_set_blocklen(mmc, mmc->write_bl_len))
+ if (!mmc) {
+ printf("MMC Device %d not found\n", dev_num);
return 0;
+ }
- do {
- cur = (blocks_todo > mmc->b_max) ? mmc->b_max : blocks_todo;
- if(mmc_write_blocks(mmc, start, cur, src) != cur)
- return 0;
- blocks_todo -= cur;
- start += cur;
- src += cur * mmc->write_bl_len;
- } while (blocks_todo > 0);
+ if (blkcnt > 1)
+ return mmc_bwrite_multi(mmc, start, blkcnt, src);
+ else if (blkcnt == 1)
+ return mmc_bwrite_single(mmc, start, src);
- return blkcnt;
+ return 0;
}
-int mmc_read_blocks(struct mmc *mmc, void *dst, ulong start, lbaint_t blkcnt)
+static unsigned long
+mmc_bread_multi(struct mmc *mmc, ulong start, ulong blkcnt, void *dst)
{
struct mmc_cmd cmd;
struct mmc_data data;
- int timeout = 1000;
+ int err;
+ ulong blkreadcnt;
+ ulong blkleftcnt = blkcnt;
- if (blkcnt > 1)
- cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
- else
- cmd.cmdidx = MMC_CMD_READ_SINGLE_BLOCK;
+ /*
+ * Each mmc host controller has a size limit in it's register, used
+ * when initializing a new data transfer. Thus we need to wrap larger
+ * bulk of requests. At the moment the limit is hardcoded to 0xFFFF
+ * blocks. This should maybe be configurable by each host driver
+ * instead.
+ */
- if (mmc->high_capacity)
- cmd.cmdarg = start;
- else
- cmd.cmdarg = start * mmc->read_bl_len;
+ while (blkleftcnt > 0) {
+ if (blkleftcnt > 0xffff)
+ blkreadcnt = 0xffff;
+ else
+ blkreadcnt = blkleftcnt;
- cmd.resp_type = MMC_RSP_R1;
- cmd.flags = 0;
+ if (mmc->high_capacity)
+ cmd.cmdarg = start;
+ else
+ cmd.cmdarg = start * mmc->read_bl_len;
- data.dest = dst;
- data.blocks = blkcnt;
- data.blocksize = mmc->read_bl_len;
- data.flags = MMC_DATA_READ;
+ cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK;
+ cmd.resp_type = MMC_RSP_R1;
+ cmd.flags = 0;
- if (mmc_send_cmd(mmc, &cmd, &data))
- return 0;
+ data.blocksize = mmc->read_bl_len;
+ data.flags = MMC_DATA_READ;
+ data.dest = dst;
+ data.blocks = blkreadcnt;
+
+ err = mmc_send_cmd(mmc, &cmd, &data);
+ if (err) {
+ printf("MMC read multi failed, err=%d\n", err);
+ return 0;
+ }
- if (blkcnt > 1) {
cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
cmd.cmdarg = 0;
cmd.resp_type = MMC_RSP_R1b;
cmd.flags = 0;
- if (mmc_send_cmd(mmc, &cmd, NULL)) {
- printf("mmc fail to send stop cmd\n");
+
+ err = mmc_send_cmd(mmc, &cmd, NULL);
+ if (err) {
+ printf("MMC read - stop cmd failed, err=%d\n", err);
return 0;
}
- /* Waiting for the ready status */
- mmc_send_status(mmc, timeout);
+ blkleftcnt -= blkreadcnt;
+ start += blkreadcnt;
+ dst += blkreadcnt * mmc->read_bl_len;
}
return blkcnt;
}
-static ulong mmc_bread(int dev_num, ulong start, lbaint_t blkcnt, void *dst)
+static unsigned long
+mmc_bread_single(struct mmc *mmc, ulong start, void *dst)
{
- lbaint_t cur, blocks_todo = blkcnt;
+ struct mmc_cmd cmd;
+ struct mmc_data data;
+ int err;
- if (blkcnt == 0)
- return 0;
+ cmd.cmdidx = MMC_CMD_READ_SINGLE_BLOCK;
+ cmd.resp_type = MMC_RSP_R1;
+ cmd.flags = 0;
- struct mmc *mmc = find_mmc_device(dev_num);
- if (!mmc)
- return 0;
+ if (mmc->high_capacity)
+ cmd.cmdarg = start;
+ else
+ cmd.cmdarg = start * mmc->read_bl_len;
+
+ data.dest = dst;
+ data.blocks = 1;
+ data.blocksize = mmc->read_bl_len;
+ data.flags = MMC_DATA_READ;
- if ((start + blkcnt) > mmc->block_dev.lba) {
- printf("MMC: block number 0x%lx exceeds max(0x%lx)\n",
- start + blkcnt, mmc->block_dev.lba);
+ err = mmc_send_cmd(mmc, &cmd, &data);
+ if (err) {
+ printf("MMC read single failed, err=%d\n", err);
return 0;
}
- if (mmc_set_blocklen(mmc, mmc->read_bl_len))
+ return 1;
+}
+
+static unsigned long
+mmc_bread(int dev_num, unsigned long start, lbaint_t blkcnt, void *dst)
+{
+ int err;
+ struct mmc *mmc = find_mmc_device(dev_num);
+
+ if (!mmc) {
+ printf("MMC Device %d not found\n", dev_num);
return 0;
+ }
- do {
- cur = (blocks_todo > mmc->b_max) ? mmc->b_max : blocks_todo;
- if(mmc_read_blocks(mmc, dst, start, cur) != cur)
- return 0;
- blocks_todo -= cur;
- start += cur;
- dst += cur * mmc->read_bl_len;
- } while (blocks_todo > 0);
+ if (blkcnt > 1)
+ return mmc_bread_multi(mmc, start, blkcnt, dst);
+ else if (blkcnt == 1)
+ return mmc_bread_single(mmc, start, dst);
- return blkcnt;
+ return 0;
}
-int mmc_go_idle(struct mmc* mmc)
+static int mmc_go_idle(struct mmc *mmc)
{
struct mmc_cmd cmd;
int err;
@@ -352,7 +349,7 @@ int mmc_go_idle(struct mmc* mmc)
return 0;
}
-int
+static int
sd_send_op_cond(struct mmc *mmc)
{
int timeout = 1000;
@@ -372,16 +369,7 @@ sd_send_op_cond(struct mmc *mmc)
cmd.cmdidx = SD_CMD_APP_SEND_OP_COND;
cmd.resp_type = MMC_RSP_R3;
-
- /*
- * Most cards do not answer if some reserved bits
- * in the ocr are set. However, Some controller
- * can set bit 7 (reserved for low voltages), but
- * how to manage low voltages SD card is not yet
- * specified.
- */
- cmd.cmdarg = mmc_host_is_spi(mmc) ? 0 :
- (mmc->voltages & 0xff8000);
+ cmd.cmdarg = mmc->voltages;
if (mmc->version == SD_VERSION_2)
cmd.cmdarg |= OCR_HCS;
@@ -397,58 +385,31 @@ sd_send_op_cond(struct mmc *mmc)
if (timeout <= 0)
return UNUSABLE_ERR;
- if (mmc->version != SD_VERSION_2)
+ if (mmc->version != SD_VERSION_2) {
mmc->version = SD_VERSION_1_0;
-
- if (mmc_host_is_spi(mmc)) { /* read OCR for spi */
- cmd.cmdidx = MMC_CMD_SPI_READ_OCR;
- cmd.resp_type = MMC_RSP_R3;
- cmd.cmdarg = 0;
- cmd.flags = 0;
-
- err = mmc_send_cmd(mmc, &cmd, NULL);
-
- if (err)
- return err;
+ mmc->high_capacity = 0;
+ } else {
+ mmc->ocr = cmd.response[0];
+ mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS);
}
-
- mmc->ocr = cmd.response[0];
-
- mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS);
mmc->rca = 0;
return 0;
}
-int mmc_send_op_cond(struct mmc *mmc)
+static int mmc_send_op_cond(struct mmc *mmc)
{
- int timeout = 10000;
+ int timeout = 1000;
struct mmc_cmd cmd;
int err;
/* Some cards seem to need this */
mmc_go_idle(mmc);
- /* Asking to the card its capabilities */
- cmd.cmdidx = MMC_CMD_SEND_OP_COND;
- cmd.resp_type = MMC_RSP_R3;
- cmd.cmdarg = 0;
- cmd.flags = 0;
-
- err = mmc_send_cmd(mmc, &cmd, NULL);
-
- if (err)
- return err;
-
- udelay(1000);
-
do {
cmd.cmdidx = MMC_CMD_SEND_OP_COND;
cmd.resp_type = MMC_RSP_R3;
- cmd.cmdarg = (mmc_host_is_spi(mmc) ? 0 :
- (mmc->voltages &
- (cmd.response[0] & OCR_VOLTAGE_MASK)) |
- (cmd.response[0] & OCR_ACCESS_MODE));
+ cmd.cmdarg = OCR_HCS | mmc->voltages;
cmd.flags = 0;
err = mmc_send_cmd(mmc, &cmd, NULL);
@@ -462,18 +423,6 @@ int mmc_send_op_cond(struct mmc *mmc)
if (timeout <= 0)
return UNUSABLE_ERR;
- if (mmc_host_is_spi(mmc)) { /* read OCR for spi */
- cmd.cmdidx = MMC_CMD_SPI_READ_OCR;
- cmd.resp_type = MMC_RSP_R3;
- cmd.cmdarg = 0;
- cmd.flags = 0;
-
- err = mmc_send_cmd(mmc, &cmd, NULL);
-
- if (err)
- return err;
- }
-
mmc->version = MMC_VERSION_UNKNOWN;
mmc->ocr = cmd.response[0];
@@ -483,12 +432,10 @@ int mmc_send_op_cond(struct mmc *mmc)
return 0;
}
-
-int mmc_send_ext_csd(struct mmc *mmc, char *ext_csd)
+static int mmc_send_ext_csd(struct mmc *mmc, char *ext_csd)
{
struct mmc_cmd cmd;
struct mmc_data data;
- int err;
/* Get the Card Status Register */
cmd.cmdidx = MMC_CMD_SEND_EXT_CSD;
@@ -501,35 +448,24 @@ int mmc_send_ext_csd(struct mmc *mmc, char *ext_csd)
data.blocksize = 512;
data.flags = MMC_DATA_READ;
- err = mmc_send_cmd(mmc, &cmd, &data);
-
- return err;
+ return mmc_send_cmd(mmc, &cmd, &data);
}
-
-int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
+static int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
{
struct mmc_cmd cmd;
- int timeout = 1000;
- int ret;
cmd.cmdidx = MMC_CMD_SWITCH;
cmd.resp_type = MMC_RSP_R1b;
cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
- (index << 16) |
- (value << 8);
+ (index << 16) |
+ (value << 8);
cmd.flags = 0;
- ret = mmc_send_cmd(mmc, &cmd, NULL);
-
- /* Waiting for the ready status */
- mmc_send_status(mmc, timeout);
-
- return ret;
-
+ return mmc_send_cmd(mmc, &cmd, NULL);
}
-int mmc_change_freq(struct mmc *mmc)
+static int mmc_change_freq(struct mmc *mmc)
{
char ext_csd[512];
char cardtype;
@@ -537,59 +473,68 @@ int mmc_change_freq(struct mmc *mmc)
mmc->card_caps = 0;
- if (mmc_host_is_spi(mmc))
- return 0;
+ /*
+ * Instead of probing according to the bus testing procedure,
+ * the buswitdh that is supported from the MMC device is hardcoded
+ * to both 8 and/or 4 bit. It is up to the host driver to set
+ * other limitations. This also applies to DDR mode.
+ */
+ mmc->card_caps = MMC_MODE_4BIT | MMC_MODE_8BIT | MMC_MODE_DDR |
+ MMC_MODE_REL_WR;
/* Only version 4 supports high-speed */
if (mmc->version < MMC_VERSION_4)
return 0;
- mmc->card_caps |= MMC_MODE_4BIT;
-
err = mmc_send_ext_csd(mmc, ext_csd);
if (err)
return err;
- cardtype = ext_csd[196] & 0xf;
+ if (mmc->high_capacity)
+ mmc->capacity = (u64)(ext_csd[EXT_CSD_SEC_CNT + 0] << 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) *
+ mmc->read_bl_len;
- err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, 1);
+ mmc->wr_rel_param = ext_csd[EXT_CSD_WR_REL_PARAM];
+ mmc->rel_wr_sec_c = ext_csd[EXT_CSD_REL_WR_SEC_C];
+ if (mmc->rel_wr_sec_c == 1)
+ mmc->card_caps &= ~MMC_MODE_REL_WR;
+
+ err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, 1);
if (err)
return err;
/* Now check to see that it worked */
err = mmc_send_ext_csd(mmc, ext_csd);
-
if (err)
return err;
/* No high-speed support */
- if (!ext_csd[185])
+ if (!ext_csd[EXT_CSD_HS_TIMING])
return 0;
- /* High Speed is set, there are two types: 52MHz and 26MHz */
+ /*
+ * High Speed mode is set, two types: SDR 52MHz or SDR 26MHz
+ * DDR mode is not supported yet.
+ */
+ cardtype = ext_csd[EXT_CSD_CARD_TYPE];
if (cardtype & MMC_HS_52MHZ)
mmc->card_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
else
mmc->card_caps |= MMC_MODE_HS;
- return 0;
-}
-
-int mmc_switch_part(int dev_num, unsigned int part_num)
-{
- struct mmc *mmc = find_mmc_device(dev_num);
-
- if (!mmc)
- return -1;
+ if (mmc->wr_rel_param & EXT_CSD_WR_REL_PARAM_HS_CTRL_REL)
+ err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_WR_REL_SET, 1);
- return mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
- (mmc->part_config & ~PART_ACCESS_MASK)
- | (part_num & PART_ACCESS_MASK));
+ return 0;
}
-int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp)
+static int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp)
{
struct mmc_cmd cmd;
struct mmc_data data;
@@ -610,8 +555,7 @@ int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp)
return mmc_send_cmd(mmc, &cmd, &data);
}
-
-int sd_change_freq(struct mmc *mmc)
+static int sd_change_freq(struct mmc *mmc)
{
int err;
struct mmc_cmd cmd;
@@ -622,9 +566,6 @@ int sd_change_freq(struct mmc *mmc)
mmc->card_caps = 0;
- if (mmc_host_is_spi(mmc))
- return 0;
-
/* Read the SCR to find out if this card supports higher speeds */
cmd.cmdidx = MMC_CMD_APP_CMD;
cmd.resp_type = MMC_RSP_R1;
@@ -643,20 +584,15 @@ int sd_change_freq(struct mmc *mmc)
timeout = 3;
-retry_scr:
- data.dest = (char *)&scr;
- data.blocksize = 8;
- data.blocks = 1;
- data.flags = MMC_DATA_READ;
-
- err = mmc_send_cmd(mmc, &cmd, &data);
-
- if (err) {
- if (timeout--)
- goto retry_scr;
-
+ do {
+ data.dest = (char *)&scr;
+ data.blocksize = 8;
+ data.blocks = 1;
+ data.flags = MMC_DATA_READ;
+ err = mmc_send_cmd(mmc, &cmd, &data);
+ } while (err && timeout--);
+ if (!timeout)
return err;
- }
mmc->scr[0] = __be32_to_cpu(scr[0]);
mmc->scr[1] = __be32_to_cpu(scr[1]);
@@ -676,9 +612,6 @@ retry_scr:
break;
}
- if (mmc->scr[0] & SD_DATA_4BIT)
- mmc->card_caps |= MMC_MODE_4BIT;
-
/* Version 1.0 doesn't support switching */
if (mmc->version == SD_VERSION_1_0)
return 0;
@@ -696,6 +629,9 @@ retry_scr:
break;
}
+ if (mmc->scr[0] & SD_DATA_4BIT)
+ mmc->card_caps |= MMC_MODE_4BIT;
+
/* If high-speed isn't supported, we return */
if (!(__be32_to_cpu(switch_status[3]) & SD_HIGHSPEED_SUPPORTED))
return 0;
@@ -711,19 +647,22 @@ retry_scr:
return 0;
}
-/* frequency bases */
-/* divided by 10 to be nice to platforms without floating point */
-static const int fbase[] = {
+/*
+ * frequency bases
+ * divided by 10 to be nice to platforms without floating point
+ */
+static int fbase[] = {
10000,
100000,
1000000,
10000000,
};
-/* Multiplier values for TRAN_SPEED. Multiplied by 10 to be nice
+/*
+ * Multiplier values for TRAN_SPEED. Multiplied by 10 to be nice
* to platforms without floating point.
*/
-static const int multipliers[] = {
+static int multipliers[] = {
0, /* reserved */
10,
12,
@@ -742,12 +681,12 @@ static const int multipliers[] = {
80,
};
-void mmc_set_ios(struct mmc *mmc)
+static void mmc_set_ios(struct mmc *mmc)
{
mmc->set_ios(mmc);
}
-void mmc_set_clock(struct mmc *mmc, uint clock)
+static void mmc_set_clock(struct mmc *mmc, uint clock)
{
if (clock > mmc->f_max)
clock = mmc->f_max;
@@ -760,38 +699,22 @@ void mmc_set_clock(struct mmc *mmc, uint clock)
mmc_set_ios(mmc);
}
-void mmc_set_bus_width(struct mmc *mmc, uint width)
+static void mmc_set_bus_width(struct mmc *mmc, uint width)
{
mmc->bus_width = width;
mmc_set_ios(mmc);
}
-int mmc_startup(struct mmc *mmc)
+static int mmc_startup(struct mmc *mmc)
{
int err;
uint mult, freq;
u64 cmult, csize;
struct mmc_cmd cmd;
- char ext_csd[512];
- int timeout = 1000;
-
-#ifdef CONFIG_MMC_SPI_CRC_ON
- if (mmc_host_is_spi(mmc)) { /* enable CRC check for spi */
- cmd.cmdidx = MMC_CMD_SPI_CRC_ON_OFF;
- cmd.resp_type = MMC_RSP_R1;
- cmd.cmdarg = 1;
- cmd.flags = 0;
- err = mmc_send_cmd(mmc, &cmd, NULL);
-
- if (err)
- return err;
- }
-#endif
/* Put the Card in Identify Mode */
- cmd.cmdidx = mmc_host_is_spi(mmc) ? MMC_CMD_SEND_CID :
- MMC_CMD_ALL_SEND_CID; /* cmd not supported in spi */
+ cmd.cmdidx = MMC_CMD_ALL_SEND_CID;
cmd.resp_type = MMC_RSP_R2;
cmd.cmdarg = 0;
cmd.flags = 0;
@@ -808,20 +731,18 @@ int mmc_startup(struct mmc *mmc)
* For SD cards, get the Relatvie Address.
* This also puts the cards into Standby State
*/
- if (!mmc_host_is_spi(mmc)) { /* cmd not supported in spi */
- cmd.cmdidx = SD_CMD_SEND_RELATIVE_ADDR;
- cmd.cmdarg = mmc->rca << 16;
- cmd.resp_type = MMC_RSP_R6;
- cmd.flags = 0;
+ cmd.cmdidx = SD_CMD_SEND_RELATIVE_ADDR;
+ cmd.cmdarg = mmc->rca << 16;
+ cmd.resp_type = MMC_RSP_R6;
+ cmd.flags = 0;
- err = mmc_send_cmd(mmc, &cmd, NULL);
+ err = mmc_send_cmd(mmc, &cmd, NULL);
- if (err)
- return err;
+ if (err)
+ return err;
- if (IS_SD(mmc))
- mmc->rca = (cmd.response[0] >> 16) & 0xffff;
- }
+ if (IS_SD(mmc))
+ mmc->rca = (cmd.response[0] >> 16) & 0xffff;
/* Get the Card-Specific Data */
cmd.cmdidx = MMC_CMD_SEND_CSD;
@@ -831,9 +752,6 @@ int mmc_startup(struct mmc *mmc)
err = mmc_send_cmd(mmc, &cmd, NULL);
- /* Waiting for the ready status */
- mmc_send_status(mmc, timeout);
-
if (err)
return err;
@@ -880,16 +798,21 @@ int mmc_startup(struct mmc *mmc)
else
mmc->write_bl_len = 1 << ((cmd.response[3] >> 22) & 0xf);
+ /* This is not correct for MMC cards bigger than 2GB.
+ * C_SIZE=0xFFF and C_SIZE_MULT=0x7 for bigger than 2GB.
+ * READ_BL_LEN < 12 (2k sectors) to do the calculation.
+ * High capasity cards: Use EXT_CSD instead.
+ * Check for SD!
+ */
if (mmc->high_capacity) {
- csize = (mmc->csd[1] & 0x3f) << 16
- | (mmc->csd[2] & 0xffff0000) >> 16;
+ csize = CSD_HC_SIZE(mmc->csd);
cmult = 8;
} else {
- csize = (mmc->csd[1] & 0x3ff) << 2
- | (mmc->csd[2] & 0xc0000000) >> 30;
- cmult = (mmc->csd[2] & 0x00038000) >> 15;
+ csize = CSD_C_SIZE(mmc->csd);
+ cmult = CSD_C_SIZE_MULT(mmc->csd);
}
+ /* This is only correct for MMC cards up to 2GB. SD? */
mmc->capacity = (csize + 1) << (cmult + 2);
mmc->capacity *= mmc->read_bl_len;
@@ -900,41 +823,31 @@ int mmc_startup(struct mmc *mmc)
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.resp_type = MMC_RSP_R1b;
- cmd.cmdarg = mmc->rca << 16;
- cmd.flags = 0;
- err = mmc_send_cmd(mmc, &cmd, NULL);
-
- if (err)
- return err;
- }
-
- 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[192] >= 2)) {
- mmc->capacity = ext_csd[212] << 0 | ext_csd[213] << 8 |
- ext_csd[214] << 16 | ext_csd[215] << 24;
- mmc->capacity *= 512;
- }
+ cmd.cmdidx = MMC_CMD_SELECT_CARD;
+ cmd.resp_type = MMC_RSP_R1b;
+ cmd.cmdarg = mmc->rca << 16;
+ cmd.flags = 0;
+ err = mmc_send_cmd(mmc, &cmd, NULL);
- /* store the partition info of emmc */
- if (ext_csd[160] & PART_SUPPORT)
- mmc->part_config = ext_csd[179];
- }
+ if (err)
+ return err;
- if (IS_SD(mmc))
+ if (IS_SD(mmc)) {
err = sd_change_freq(mmc);
- else
+ debug("sd_change_freq returns %d\n", err);
+ } else {
err = mmc_change_freq(mmc);
+ debug("mmc_change_freq returns %d\n", err);
+ }
if (err)
return err;
- /* Restrict card's capabilities by what the host can do */
+ /*
+ * Restrict card capabilities by the host capabilities.
+ * FIXME: Host caps are ignored when setting high speed in
+ * mmc_change_freq and sd_change_freq.
+ */
mmc->card_caps &= mmc->host_caps;
if (IS_SD(mmc)) {
@@ -964,15 +877,39 @@ int mmc_startup(struct mmc *mmc)
else
mmc_set_clock(mmc, 25000000);
} else {
- if (mmc->card_caps & MMC_MODE_4BIT) {
- /* Set the card to use 4 bit*/
+ if ((mmc->card_caps & MMC_MODE_DDR_8BIT) == MMC_MODE_DDR_8BIT) {
+ /* Set the card to use 8 bit*/
+ printf("EXT_CSD_BUS_WIDTH_DDR_8\n");
err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_BUS_WIDTH,
- EXT_CSD_BUS_WIDTH_4);
+ EXT_CSD_BUS_WIDTH_DDR_8);
+ if (err)
+ return err;
+ err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_POWER_CLASS,
+ 0xAA);
+ if (err)
+ return err;
+ printf("EXT_CSD_BUS_WIDTH_DDR_8\n");
+ mmc->ddr_en = 1;
+ mmc_set_bus_width(mmc, 8);
+ } else if ((mmc->card_caps & MMC_MODE_DDR_4BIT) ==
+ MMC_MODE_DDR_4BIT) {
+ /* Set the card to use 4 bit*/
+ err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_BUS_WIDTH,
+ EXT_CSD_BUS_WIDTH_DDR_4);
if (err)
return err;
+ err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_POWER_CLASS,
+ 0xAA);
+ if (err)
+ return err;
+ printf("EXT_CSD_BUS_WIDTH_DDR_4\n");
+ mmc->ddr_en = 1;
mmc_set_bus_width(mmc, 4);
} else if (mmc->card_caps & MMC_MODE_8BIT) {
/* Set the card to use 8 bit*/
@@ -984,6 +921,16 @@ int mmc_startup(struct mmc *mmc)
return err;
mmc_set_bus_width(mmc, 8);
+ } else if (mmc->card_caps & MMC_MODE_4BIT) {
+ /* Set the card to use 4 bit*/
+ err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_BUS_WIDTH,
+ EXT_CSD_BUS_WIDTH_4);
+
+ if (err)
+ return err;
+
+ mmc_set_bus_width(mmc, 4);
}
if (mmc->card_caps & MMC_MODE_HS) {
@@ -993,6 +940,15 @@ int mmc_startup(struct mmc *mmc)
mmc_set_clock(mmc, 26000000);
} else
mmc_set_clock(mmc, 20000000);
+
+ if (mmc->card_caps & MMC_MODE_REL_WR) {
+ err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_WR_REL_SET,
+ 0x1F);
+
+ if (err)
+ return err;
+ }
}
/* fill in device description */
@@ -1012,7 +968,7 @@ int mmc_startup(struct mmc *mmc)
return 0;
}
-int mmc_send_if_cond(struct mmc *mmc)
+static int mmc_send_if_cond(struct mmc *mmc)
{
struct mmc_cmd cmd;
int err;
@@ -1044,8 +1000,6 @@ int mmc_register(struct mmc *mmc)
mmc->block_dev.removable = 1;
mmc->block_dev.block_read = mmc_bread;
mmc->block_dev.block_write = mmc_bwrite;
- if (!mmc->b_max)
- mmc->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
INIT_LIST_HEAD (&mmc->link);
@@ -1065,9 +1019,6 @@ int mmc_init(struct mmc *mmc)
{
int err;
- if (mmc->has_init)
- return 0;
-
err = mmc->init(mmc);
if (err)
@@ -1082,19 +1033,18 @@ int mmc_init(struct mmc *mmc)
if (err)
return err;
- /* The internal partition reset to user partition(0) at every CMD0*/
- mmc->part_num = 0;
-
/* Test for SD version 2 */
err = mmc_send_if_cond(mmc);
+ debug("mmc_send_if_cond returns %d\n", err);
/* Now try to get the SD card's operating condition */
err = sd_send_op_cond(mmc);
+ debug("sd_send_op_cond returns %d\n", err);
/* If the command timed out, we check for an MMC card */
if (err == TIMEOUT) {
err = mmc_send_op_cond(mmc);
-
+ debug("mmc_send_op_cond returns %d\n", err);
if (err) {
printf("Card did not respond to voltage select!\n");
return UNUSABLE_ERR;
@@ -1102,10 +1052,14 @@ int mmc_init(struct mmc *mmc)
}
err = mmc_startup(mmc);
- if (err)
- mmc->has_init = 0;
- else
- mmc->has_init = 1;
+
+ if (!err) {
+ err = mmc_set_blocklen(mmc, 512);
+ if (err)
+ printf("MMC set write bl len failed, err=%d\n", err);
+ }
+
+ debug("mmc_startup returns %d\n", err);
return err;
}
@@ -1119,7 +1073,12 @@ static int __def_mmc_init(bd_t *bis)
}
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")));
+/*
+ * It seems attribute 'weak' does not work as intended. With gcc 4.4.1 and
+ * optimization O2 it always links in the weak function. Declare board_mmc_init
+ * as external.
+ */
+extern int board_mmc_init(bd_t *bis);
void print_mmc_devices(char separator)
{
@@ -1138,11 +1097,6 @@ void print_mmc_devices(char separator)
printf("\n");
}
-int get_mmc_num(void)
-{
- return cur_dev_num;
-}
-
int mmc_initialize(bd_t *bis)
{
INIT_LIST_HEAD (&mmc_devices);
diff --git a/include/mmc.h b/include/mmc.h
index aeacdee30..57338fe11 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008,2010 Freescale Semiconductor, Inc
+ * Copyright 2008, Freescale Semiconductor, Inc
* Andy Fleming
*
* Based (loosely) on the Linux code
@@ -14,7 +14,7 @@
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
@@ -42,9 +42,13 @@
#define MMC_MODE_HS 0x001
#define MMC_MODE_HS_52MHz 0x010
+#define MMC_MODE_1BIT 0x000
#define MMC_MODE_4BIT 0x100
#define MMC_MODE_8BIT 0x200
-#define MMC_MODE_SPI 0x400
+#define MMC_MODE_DDR 0x400
+#define MMC_MODE_DDR_4BIT (MMC_MODE_4BIT | MMC_MODE_DDR)
+#define MMC_MODE_DDR_8BIT (MMC_MODE_8BIT | MMC_MODE_DDR)
+#define MMC_MODE_REL_WR 0x800
#define SD_DATA_4BIT 0x00040000
@@ -73,11 +77,10 @@
#define MMC_CMD_SET_BLOCKLEN 16
#define MMC_CMD_READ_SINGLE_BLOCK 17
#define MMC_CMD_READ_MULTIPLE_BLOCK 18
+#define MMC_CMD_SET_BLOCK_COUNT 23
#define MMC_CMD_WRITE_SINGLE_BLOCK 24
#define MMC_CMD_WRITE_MULTIPLE_BLOCK 25
#define MMC_CMD_APP_CMD 55
-#define MMC_CMD_SPI_READ_OCR 58
-#define MMC_CMD_SPI_CRC_ON_OFF 59
#define SD_CMD_SEND_RELATIVE_ADDR 3
#define SD_CMD_SWITCH_FUNC 6
@@ -94,15 +97,8 @@
#define MMC_HS_TIMING 0x00000100
#define MMC_HS_52MHZ 0x2
-#define OCR_BUSY 0x80000000
-#define OCR_HCS 0x40000000
-#define OCR_VOLTAGE_MASK 0x007FFF80
-#define OCR_ACCESS_MODE 0x60000000
-
-#define MMC_STATUS_MASK (~0x0206BF7F)
-#define MMC_STATUS_RDY_FOR_DATA (1 << 8)
-#define MMC_STATUS_CURR_STATE (0xf << 9)
-#define MMC_STATUS_ERROR (1 << 19)
+#define OCR_BUSY 0x80000000
+#define OCR_HCS 0x40000000
#define MMC_VDD_165_195 0x00000080 /* VDD voltage 1.65 - 1.95 */
#define MMC_VDD_20_21 0x00000100 /* VDD voltage 2.0 ~ 2.1 */
@@ -138,51 +134,61 @@
* EXT_CSD fields
*/
-#define EXT_CSD_PART_CONF 179 /* R/W */
-#define EXT_CSD_BUS_WIDTH 183 /* R/W */
-#define EXT_CSD_HS_TIMING 185 /* R/W */
-#define EXT_CSD_CARD_TYPE 196 /* RO */
-#define EXT_CSD_REV 192 /* RO */
-#define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */
+#define EXT_CSD_WR_REL_PARAM 166 /* R */
+#define EXT_CSD_WR_REL_SET 167 /* R/W */
+#define EXT_CSD_BUS_WIDTH 183 /* R/W */
+#define EXT_CSD_HS_TIMING 185 /* R/W */
+#define EXT_CSD_POWER_CLASS 187 /* R/W */
+#define EXT_CSD_REV 192 /* RO */
+#define EXT_CSD_CARD_TYPE 196 /* RO */
+#define EXT_CSD_OUT_OF_INT_TIME 198 /* RO */
+#define EXT_CSD_MIN_PERF_R_8_52 209 /* RO */
+#define EXT_CSD_MIN_PERF_W_8_52 210 /* RO */
+#define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */
+#define EXT_CSD_REL_WR_SEC_C 222 /* RO */
+#define EXT_CSD_PWR_CL_DDR_52_195 238 /* RO */
+#define EXT_CSD_PWR_CL_DDR_52_360 239 /* RO */
/*
* EXT_CSD field definitions
*/
-#define EXT_CSD_CMD_SET_NORMAL (1 << 0)
-#define EXT_CSD_CMD_SET_SECURE (1 << 1)
-#define EXT_CSD_CMD_SET_CPSECURE (1 << 2)
+#define EXT_CSD_CMD_SET_NORMAL (1<<0)
+#define EXT_CSD_CMD_SET_SECURE (1<<1)
+#define EXT_CSD_CMD_SET_CPSECURE (1<<2)
-#define EXT_CSD_CARD_TYPE_26 (1 << 0) /* Card can run at 26MHz */
-#define EXT_CSD_CARD_TYPE_52 (1 << 1) /* Card can run at 52MHz */
+#define EXT_CSD_CARD_TYPE_26 (1<<0) /* Card can run at 26MHz */
+#define EXT_CSD_CARD_TYPE_52 (1<<1) /* Card can run at 52MHz */
#define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */
#define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */
#define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */
+#define EXT_CSD_BUS_WIDTH_DDR_4 5 /* Card is in 4 bit ddr mode */
+#define EXT_CSD_BUS_WIDTH_DDR_8 6 /* Card is in 8 bit ddr mode */
+
+#define EXT_CSD_WR_REL_PARAM_HS_CTRL_REL (1 << 0)
+#define EXT_CSD_WR_REL_PARAM_EN_REL_WR (1 << 2)
#define R1_ILLEGAL_COMMAND (1 << 22)
#define R1_APP_CMD (1 << 5)
#define MMC_RSP_PRESENT (1 << 0)
-#define MMC_RSP_136 (1 << 1) /* 136 bit response */
-#define MMC_RSP_CRC (1 << 2) /* expect valid crc */
-#define MMC_RSP_BUSY (1 << 3) /* card may send busy */
-#define MMC_RSP_OPCODE (1 << 4) /* response contains opcode */
+#define MMC_RSP_136 (1 << 1) /* 136 bit response */
+#define MMC_RSP_CRC (1 << 2) /* expect valid crc */
+#define MMC_RSP_BUSY (1 << 3) /* card may send busy */
+#define MMC_RSP_OPCODE (1 << 4) /* response contains opcode */
-#define MMC_RSP_NONE (0)
-#define MMC_RSP_R1 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
+#define MMC_RSP_NONE (0)
+#define MMC_RSP_R1 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
#define MMC_RSP_R1b (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE| \
MMC_RSP_BUSY)
-#define MMC_RSP_R2 (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC)
-#define MMC_RSP_R3 (MMC_RSP_PRESENT)
-#define MMC_RSP_R4 (MMC_RSP_PRESENT)
-#define MMC_RSP_R5 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
-#define MMC_RSP_R6 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
-#define MMC_RSP_R7 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
+#define MMC_RSP_R2 (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC)
+#define MMC_RSP_R3 (MMC_RSP_PRESENT)
+#define MMC_RSP_R4 (MMC_RSP_PRESENT)
+#define MMC_RSP_R5 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
+#define MMC_RSP_R6 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
+#define MMC_RSP_R7 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
-#define MMCPART_NOAVAILABLE (0xff)
-#define PART_ACCESS_MASK (0x7)
-#define PART_SUPPORT (0x1)
struct mmc_cid {
unsigned long psn;
@@ -194,54 +200,48 @@ struct mmc_cid {
};
/*
- * WARNING!
- *
- * This structure is used by atmel_mci.c only.
- * It works for the AVR32 architecture but NOT
- * for ARM/AT91 architectures.
- * Its use is highly depreciated.
- * After the atmel_mci.c driver for AVR32 has
- * been replaced this structure will be removed.
+ * CSD_EXTRACT can be used as is for all CSD members except for c_size
+ * because c_size spans over a 32-bit boundary and must be expressed by a
+ * combination.
*/
-struct mmc_csd
-{
- u8 csd_structure:2,
- spec_vers:4,
- rsvd1:2;
- u8 taac;
- u8 nsac;
- u8 tran_speed;
- u16 ccc:12,
- read_bl_len:4;
- u64 read_bl_partial:1,
- write_blk_misalign:1,
- read_blk_misalign:1,
- dsr_imp:1,
- rsvd2:2,
- c_size:12,
- vdd_r_curr_min:3,
- vdd_r_curr_max:3,
- vdd_w_curr_min:3,
- vdd_w_curr_max:3,
- c_size_mult:3,
- sector_size:5,
- erase_grp_size:5,
- wp_grp_size:5,
- wp_grp_enable:1,
- default_ecc:2,
- r2w_factor:3,
- write_bl_len:4,
- write_bl_partial:1,
- rsvd3:5;
- u8 file_format_grp:1,
- copy:1,
- perm_write_protect:1,
- tmp_write_protect:1,
- file_format:2,
- ecc:2;
- u8 crc:7;
- u8 one:1;
-};
+#define CSD_EXTRACT(csd, bit, width) ((csd[3-(bit/32)] & \
+ (((1 << width) - 1) << (bit - (bit/32) * 32))) >> (bit - (bit/32) * 32))
+
+#define CSD_STRUCTURE(csd) CSD_EXTRACT(csd, 126, 2)
+#define CSD_SPEC_VERS(csd) CSD_EXTRACT(csd, 122, 4)
+#define CSD_TAAC(csd) CSD_EXTRACT(csd, 112, 8)
+#define CSD_NSAC(csd) CSD_EXTRACT(csd, 104, 8)
+#define CSD_TRAN_SPEED(csd) CSD_EXTRACT(csd, 96, 8)
+#define CSD_CCC(csd) CSD_EXTRACT(csd, 4, 12)
+#define CSD_READ_BL_LEN(csd) CSD_EXTRACT(csd, 80, 1)
+#define CSD_READ_BL_PARTIAL(csd) CSD_EXTRACT(csd, 79, 1)
+#define CSD_WRITE_BLK_MISALIGN(csd) CSD_EXTRACT(csd, 78, 1)
+#define CSD_READ_BLK_MISALIGN(csd) CSD_EXTRACT(csd, 77, 1)
+#define CSD_DSR_IMP(csd) CSD_EXTRACT(csd, 76, 1)
+#define CSD_C_SIZE(csd) (CSD_EXTRACT(csd, 64, 10) << 2 | \
+ CSD_EXTRACT(csd, 62, 2))
+#define CSD_HC_SIZE(csd) (CSD_EXTRACT(csd, 64, 8) << 16 | \
+ CSD_EXTRACT(csd, 48, 16))
+#define CSD_VDD_R_CURR_MIN(csd) CSD_EXTRACT(csd, 59, 3)
+#define CSD_VDD_R_CURR_MAX(csd) CSD_EXTRACT(csd, 56, 3)
+#define CSD_VDD_W_CURR_MIN(csd) CSD_EXTRACT(csd, 53, 3)
+#define CSD_VDD_W_CURR_MAX(csd) CSD_EXTRACT(csd, 50, 3)
+#define CSD_C_SIZE_MULT(csd) CSD_EXTRACT(csd, 47, 3)
+#define CSD_ERASE_GRP_SIZE(csd) CSD_EXTRACT(csd, 42, 5)
+#define CSD_ERASE_GRP_MULT(csd) CSD_EXTRACT(csd, 37, 5)
+#define CSD_WP_GRP_SIZE(csd) CSD_EXTRACT(csd, 32, 5)
+#define CSD_WP_GRP_ENABLE(csd) CSD_EXTRACT(csd, 31, 1)
+#define CSD_DEFAULT_ECC(csd) CSD_EXTRACT(csd, 29, 2)
+#define CSD_R2W_FACTOR(csd) CSD_EXTRACT(csd, 26, 3)
+#define CSD_WRITE_BL_LEN(csd) CSD_EXTRACT(csd, 22, 4)
+#define CSD_WRITE_BL_PARTIAL(csd) CSD_EXTRACT(csd, 21, 1)
+#define CSD_FILE_FORMAT_GRP(csd) CSD_EXTRACT(csd, 15, 1)
+#define CSD_COPY(csd) CSD_EXTRACT(csd, 14, 1)
+#define CSD_PERM_WRITE_PROTECT(csd) CSD_EXTRACT(csd, 13, 1)
+#define CSD_TMP_WRITE_PROTECT(csd) CSD_EXTRACT(csd, 12, 1)
+#define CSD_ECC(csd) CSD_EXTRACT(csd, 8, 2)
+#define CSD_CRC(csd) CSD_EXTRACT(csd, 1, 2)
+#define CSD_ONE(csd) CSD_EXTRACT(csd, 0, 1)
struct mmc_cmd {
ushort cmdidx;
@@ -267,7 +267,6 @@ struct mmc {
void *priv;
uint voltages;
uint version;
- uint has_init;
uint f_min;
uint f_max;
int high_capacity;
@@ -280,38 +279,28 @@ struct mmc {
uint csd[4];
uint cid[4];
ushort rca;
- char part_config;
- char part_num;
uint tran_speed;
uint read_bl_len;
uint write_bl_len;
+ uint data_timeout;
+ uint wr_rel_param;
+ uint rel_wr_sec_c;
+ u8 ddr_en;
u64 capacity;
block_dev_desc_t block_dev;
int (*send_cmd)(struct mmc *mmc,
struct mmc_cmd *cmd, struct mmc_data *data);
void (*set_ios)(struct mmc *mmc);
int (*init)(struct mmc *mmc);
- uint b_max;
};
int mmc_register(struct mmc *mmc);
int mmc_initialize(bd_t *bis);
int mmc_init(struct mmc *mmc);
-int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size);
-void mmc_set_clock(struct mmc *mmc, uint clock);
struct mmc *find_mmc_device(int dev_num);
-int mmc_set_dev(int dev_num);
void print_mmc_devices(char separator);
-int get_mmc_num(void);
-int board_mmc_getcd(u8 *cd, struct mmc *mmc);
-int mmc_switch_part(int dev_num, unsigned int part_num);
-
-#ifdef CONFIG_GENERIC_MMC
-int atmel_mci_init(void *regs);
-#define mmc_host_is_spi(mmc) ((mmc)->host_caps & MMC_MODE_SPI)
-struct mmc *mmc_spi_init(uint bus, uint cs, uint speed, uint mode);
-#else
+
+#ifndef CONFIG_GENERIC_MMC
int mmc_legacy_init(int verbose);
#endif
-
#endif /* _MMC_H_ */