return 1;
}
+ mmc->has_init = 0;
mmc_init(mmc);
return 0;
print_mmc_devices('\n');
return 0;
} else if (strcmp(argv[1], "dev") == 0) {
- int dev;
+ 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
+ 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);
return 1;
}
+ mmc_init(mmc);
+ if (part != -1) {
+ int ret;
+ if (mmc->part_config == MMCPART_NOAVAILABLE) {
+ printf("Card doesn't support part_switch\n");
+ return 1;
+ }
+
+ if (part != mmc->part_num) {
+ ret = mmc_switch_part(dev, part);
+ if (!ret)
+ mmc->part_num = part;
+
+ printf("switch to partions #%d, %s\n",
+ part, (!ret) ? "OK" : "ERROR");
+ }
+ }
curr_device = dev;
- printf("mmc%d is current device\n", curr_device);
+ 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) {
"mmc write addr blk# cnt\n"
"mmc rescan\n"
"mmc part - lists available partition on current mmc device\n"
- "mmc dev [dev] - show or set current mmc device\n"
+ "mmc dev [dev] [part] - show or set current mmc device [partition]\n"
"mmc list - lists available devices");
#endif
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;
+
+ return mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
+ (mmc->part_config & ~PART_ACCESS_MASK)
+ | (part_num & PART_ACCESS_MASK));
+}
+
int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp)
{
struct mmc_cmd cmd;
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);
ext_csd[214] << 16 | ext_csd[215] << 24;
mmc->capacity *= 512;
}
+
+ /* store the partition info of emmc */
+ if (ext_csd[160] & PART_SUPPORT)
+ mmc->part_config = ext_csd[179];
}
if (IS_SD(mmc))
{
int err;
+ if (mmc->has_init)
+ return 0;
+
err = mmc->init(mmc);
if (err)
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);
}
}
- return mmc_startup(mmc);
+ err = mmc_startup(mmc);
+ if (err)
+ mmc->has_init = 0;
+ else
+ mmc->has_init = 1;
+ return err;
}
/*
* 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 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;
void *priv;
uint voltages;
uint version;
+ uint has_init;
uint f_min;
uint f_max;
int high_capacity;
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;
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);