[U-Boot] [U-BOOT] [PATCH] mmc: enable switch partition function

Lei Wen leiwen at marvell.com
Mon Jan 31 09:47:45 CET 2011


For emmc, it may has upto 7 partitions: two boot partitions, one
user partition, one RPMB partition and four general purpose partitions.
(Refer to JESD84-A44.pdf/page 154)

As bootloader may need to read out or reflashing images on those
different partitions, it is better to enable the partition switch with
console command support.

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 common/cmd_mmc.c  |   24 +++++++++++++++++++++++-
 drivers/mmc/mmc.c |   16 ++++++++++++++++
 include/mmc.h     |    5 +++++
 3 files changed, 44 insertions(+), 1 deletions(-)

diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c
index 4323f76..2181e04 100644
--- a/common/cmd_mmc.c
+++ b/common/cmd_mmc.c
@@ -177,7 +177,6 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
 	case 0:
 	case 1:
-	case 4:
 		return cmd_usage(cmdtp);
 
 	case 2:
@@ -233,6 +232,28 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 			printf("%d blocks written: %s\n",
 				n, (n == cnt) ? "OK" : "ERROR");
 			return (n == cnt) ? 0 : 1;
+		} else if (strcmp(argv[1], "sw_part") == 0) {
+			int dev = simple_strtoul(argv[2], NULL, 10);
+			struct mmc *mmc = find_mmc_device(dev);
+			int num = simple_strtoul(argv[3], NULL, 10);
+			int ret;
+
+			if (num > PART_ACCESS_MASK) {
+				printf("#part_num shouldn't be larger than %d\n",
+					PART_ACCESS_MASK);
+				return 1;
+			}
+
+			mmc_init(mmc);
+			if (mmc->part_config == MMCPART_NOAVAILABLE) {
+				printf("Card doesn't support part_switch\n");
+				return 1;
+			}
+
+			ret = mmc_switch_part(dev, num);
+			printf("switch to partions #%d, %s\n",
+					num, (!ret) ? "OK" : "ERROR");
+			return (!ret) ? 0 : 1;
 		} else
 			rc = cmd_usage(cmdtp);
 
@@ -247,5 +268,6 @@ U_BOOT_CMD(
 	"mmc write <device num> addr blk# cnt\n"
 	"mmc rescan <device num>\n"
 	"mmc part <device num> - lists available partition on mmc\n"
+	"mmc sw_part <device num> <part_num> - switch part support for emmc\n"
 	"mmc list - lists available devices");
 #endif
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 6805b33..f42b3fb 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -428,6 +428,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;
@@ -725,6 +737,7 @@ int mmc_startup(struct mmc *mmc)
 	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);
@@ -733,6 +746,9 @@ 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] & 0x1)
+			mmc->part_config = ext_csd[179];
 	}
 
 	if (IS_SD(mmc))
diff --git a/include/mmc.h b/include/mmc.h
index 74c0b1d..10dfafd 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -128,6 +128,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 */
@@ -169,6 +170,8 @@
 #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)
 
 struct mmc_cid {
 	unsigned long psn;
@@ -265,6 +268,7 @@ struct mmc {
 	uint csd[4];
 	uint cid[4];
 	ushort rca;
+	char part_config;
 	uint tran_speed;
 	uint read_bl_len;
 	uint write_bl_len;
@@ -285,6 +289,7 @@ struct mmc *find_mmc_device(int dev_num);
 int mmc_set_dev(int dev_num);
 void print_mmc_devices(char separator);
 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);
-- 
1.7.0.4



More information about the U-Boot mailing list