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 <lei...@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

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to