aboutsummaryrefslogtreecommitdiff
path: root/drivers/mmc/mmc.c
diff options
context:
space:
mode:
authorLei Wen <leiwen@marvell.com>2011-05-02 16:26:26 +0000
committerAndy Fleming <afleming@freescale.com>2011-05-18 14:37:03 -0500
commitbc897b1d4d86597311430dbe7b3e6c807c8c53e5 (patch)
treedc5136100f1b0a873dd8bc90708286215335f559 /drivers/mmc/mmc.c
parentea6ebe21772568ee97fb5c23c01e993140f0e0e6 (diff)
downloadu-boot-bc897b1d4d86597311430dbe7b3e6c807c8c53e5.zip
u-boot-bc897b1d4d86597311430dbe7b3e6c807c8c53e5.tar.gz
u-boot-bc897b1d4d86597311430dbe7b3e6c807c8c53e5.tar.bz2
mmc: enable partition switch function for emmc
For emmc, it may have up to 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. Also for partition would be restore to user partition(part 0) when CMD0 is used, so change mmc_init routine to perform normal initialization only once for each slot, unless use the rescan command to force init again. Signed-off-by: Lei Wen <leiwen@marvell.com> Acked-by: Andy Fleming <afleming@freescale.com>
Diffstat (limited to 'drivers/mmc/mmc.c')
-rw-r--r--drivers/mmc/mmc.c30
1 files changed, 29 insertions, 1 deletions
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index cdf2713..1d089a7 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;
}
/*