diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c
index e266d4fa43ffc047134b58ce56ec07ea87ff65db..176646d4627bfa18e5b627d28956629ce78246ef 100644
--- a/common/cmd_mmc.c
+++ b/common/cmd_mmc.c
@@ -164,6 +164,7 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 			return 1;
 		}
 
+		mmc->has_init = 0;
 		mmc_init(mmc);
 
 		return 0;
@@ -189,14 +190,22 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 		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);
@@ -205,8 +214,29 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 			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) {
@@ -269,6 +299,6 @@ U_BOOT_CMD(
 	"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
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index cdf2713bad402de98f3a8313e216642eb5d1d158..1d089a7d11e2c3bfa3079e6e83a775e6b3b32e4b 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -577,6 +577,18 @@ int mmc_change_freq(struct mmc *mmc)
 	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;
@@ -899,6 +911,7 @@ int mmc_startup(struct mmc *mmc)
 			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);
@@ -907,6 +920,10 @@ int mmc_startup(struct mmc *mmc)
 					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))
@@ -1048,6 +1065,9 @@ int mmc_init(struct mmc *mmc)
 {
 	int err;
 
+	if (mmc->has_init)
+		return 0;
+
 	err = mmc->init(mmc);
 
 	if (err)
@@ -1062,6 +1082,9 @@ 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);
 
@@ -1078,7 +1101,12 @@ int mmc_init(struct mmc *mmc)
 		}
 	}
 
-	return mmc_startup(mmc);
+	err = mmc_startup(mmc);
+	if (err)
+		mmc->has_init = 0;
+	else
+		mmc->has_init = 1;
+	return err;
 }
 
 /*
diff --git a/include/mmc.h b/include/mmc.h
index 5501f5547a47c58e8fe42cc0aa6c7210cc5b0a65..aeacdee3095d8a5356b791b11944ea54587800dd 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -138,6 +138,7 @@
  * 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 */
@@ -179,6 +180,9 @@
 #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;
@@ -263,6 +267,7 @@ struct mmc {
 	void *priv;
 	uint voltages;
 	uint version;
+	uint has_init;
 	uint f_min;
 	uint f_max;
 	int high_capacity;
@@ -275,6 +280,8 @@ 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;
@@ -297,6 +304,7 @@ 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);