summaryrefslogtreecommitdiff
path: root/drivers/mmc/mmc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/mmc.c')
-rw-r--r--drivers/mmc/mmc.c151
1 files changed, 143 insertions, 8 deletions
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index e6a296a..73f7195 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -254,7 +254,7 @@ err_out:
}
static unsigned long
-mmc_berase(int dev_num, unsigned long start, lbaint_t blkcnt)
+mmc_berase(int dev_num, lbaint_t start, lbaint_t blkcnt)
{
int err = 0;
struct mmc *mmc = find_mmc_device(dev_num);
@@ -266,7 +266,8 @@ mmc_berase(int dev_num, unsigned long start, lbaint_t blkcnt)
if ((start % mmc->erase_grp_size) || (blkcnt % mmc->erase_grp_size))
printf("\n\nCaution! Your devices Erase group is 0x%x\n"
- "The erase range would be change to 0x%lx~0x%lx\n\n",
+ "The erase range would be change to "
+ "0x" LBAF "~0x" LBAF "\n\n",
mmc->erase_grp_size, start & ~(mmc->erase_grp_size - 1),
((start + blkcnt + mmc->erase_grp_size)
& ~(mmc->erase_grp_size - 1)) - 1);
@@ -289,14 +290,14 @@ mmc_berase(int dev_num, unsigned long start, lbaint_t blkcnt)
}
static ulong
-mmc_write_blocks(struct mmc *mmc, ulong start, lbaint_t blkcnt, const void*src)
+mmc_write_blocks(struct mmc *mmc, lbaint_t start, lbaint_t blkcnt, const void*src)
{
struct mmc_cmd cmd;
struct mmc_data data;
int timeout = 1000;
if ((start + blkcnt) > mmc->block_dev.lba) {
- printf("MMC: block number 0x%lx exceeds max(0x%lx)\n",
+ printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
start + blkcnt, mmc->block_dev.lba);
return 0;
}
@@ -346,7 +347,7 @@ mmc_write_blocks(struct mmc *mmc, ulong start, lbaint_t blkcnt, const void*src)
}
static ulong
-mmc_bwrite(int dev_num, ulong start, lbaint_t blkcnt, const void*src)
+mmc_bwrite(int dev_num, lbaint_t start, lbaint_t blkcnt, const void*src)
{
lbaint_t cur, blocks_todo = blkcnt;
@@ -369,7 +370,7 @@ mmc_bwrite(int dev_num, ulong start, lbaint_t blkcnt, const void*src)
return blkcnt;
}
-static int mmc_read_blocks(struct mmc *mmc, void *dst, ulong start,
+static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
lbaint_t blkcnt)
{
struct mmc_cmd cmd;
@@ -408,7 +409,7 @@ static int mmc_read_blocks(struct mmc *mmc, void *dst, ulong start,
return blkcnt;
}
-static ulong mmc_bread(int dev_num, ulong start, lbaint_t blkcnt, void *dst)
+static ulong mmc_bread(int dev_num, lbaint_t start, lbaint_t blkcnt, void *dst)
{
lbaint_t cur, blocks_todo = blkcnt;
@@ -420,7 +421,7 @@ static ulong mmc_bread(int dev_num, ulong start, lbaint_t blkcnt, void *dst)
return 0;
if ((start + blkcnt) > mmc->block_dev.lba) {
- printf("MMC: block number 0x%lx exceeds max(0x%lx)\n",
+ printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
start + blkcnt, mmc->block_dev.lba);
return 0;
}
@@ -1503,3 +1504,137 @@ int mmc_initialize(bd_t *bis)
do_preinit();
return 0;
}
+
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+/*
+ * This function changes the size of boot partition and the size of rpmb
+ * partition present on EMMC devices.
+ *
+ * Input Parameters:
+ * struct *mmc: pointer for the mmc device strcuture
+ * bootsize: size of boot partition
+ * rpmbsize: size of rpmb partition
+ *
+ * Returns 0 on success.
+ */
+
+int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize,
+ unsigned long rpmbsize)
+{
+ int err;
+ struct mmc_cmd cmd;
+
+ /* Only use this command for raw EMMC moviNAND. Enter backdoor mode */
+ cmd.cmdidx = MMC_CMD_RES_MAN;
+ cmd.resp_type = MMC_RSP_R1b;
+ cmd.cmdarg = MMC_CMD62_ARG1;
+
+ err = mmc_send_cmd(mmc, &cmd, NULL);
+ if (err) {
+ debug("mmc_boot_partition_size_change: Error1 = %d\n", err);
+ return err;
+ }
+
+ /* Boot partition changing mode */
+ cmd.cmdidx = MMC_CMD_RES_MAN;
+ cmd.resp_type = MMC_RSP_R1b;
+ cmd.cmdarg = MMC_CMD62_ARG2;
+
+ err = mmc_send_cmd(mmc, &cmd, NULL);
+ if (err) {
+ debug("mmc_boot_partition_size_change: Error2 = %d\n", err);
+ return err;
+ }
+ /* boot partition size is multiple of 128KB */
+ bootsize = (bootsize * 1024) / 128;
+
+ /* Arg: boot partition size */
+ cmd.cmdidx = MMC_CMD_RES_MAN;
+ cmd.resp_type = MMC_RSP_R1b;
+ cmd.cmdarg = bootsize;
+
+ err = mmc_send_cmd(mmc, &cmd, NULL);
+ if (err) {
+ debug("mmc_boot_partition_size_change: Error3 = %d\n", err);
+ return err;
+ }
+ /* RPMB partition size is multiple of 128KB */
+ rpmbsize = (rpmbsize * 1024) / 128;
+ /* Arg: RPMB partition size */
+ cmd.cmdidx = MMC_CMD_RES_MAN;
+ cmd.resp_type = MMC_RSP_R1b;
+ cmd.cmdarg = rpmbsize;
+
+ err = mmc_send_cmd(mmc, &cmd, NULL);
+ if (err) {
+ debug("mmc_boot_partition_size_change: Error4 = %d\n", err);
+ return err;
+ }
+ return 0;
+}
+
+/*
+ * This function shall form and send the commands to open / close the
+ * boot partition specified by user.
+ *
+ * Input Parameters:
+ * ack: 0x0 - No boot acknowledge sent (default)
+ * 0x1 - Boot acknowledge sent during boot operation
+ * part_num: User selects boot data that will be sent to master
+ * 0x0 - Device not boot enabled (default)
+ * 0x1 - Boot partition 1 enabled for boot
+ * 0x2 - Boot partition 2 enabled for boot
+ * access: User selects partitions to access
+ * 0x0 : No access to boot partition (default)
+ * 0x1 : R/W boot partition 1
+ * 0x2 : R/W boot partition 2
+ * 0x3 : R/W Replay Protected Memory Block (RPMB)
+ *
+ * Returns 0 on success.
+ */
+int mmc_boot_part_access(struct mmc *mmc, u8 ack, u8 part_num, u8 access)
+{
+ int err;
+ struct mmc_cmd cmd;
+
+ /* Boot ack enable, boot partition enable , boot partition access */
+ cmd.cmdidx = MMC_CMD_SWITCH;
+ cmd.resp_type = MMC_RSP_R1b;
+
+ cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
+ (EXT_CSD_PART_CONF << 16) |
+ ((EXT_CSD_BOOT_ACK(ack) |
+ EXT_CSD_BOOT_PART_NUM(part_num) |
+ EXT_CSD_PARTITION_ACCESS(access)) << 8);
+
+ err = mmc_send_cmd(mmc, &cmd, NULL);
+ if (err) {
+ if (access) {
+ debug("mmc boot partition#%d open fail:Error1 = %d\n",
+ part_num, err);
+ } else {
+ debug("mmc boot partition#%d close fail:Error = %d\n",
+ part_num, err);
+ }
+ return err;
+ }
+
+ if (access) {
+ /* 4bit transfer mode at booting time. */
+ cmd.cmdidx = MMC_CMD_SWITCH;
+ cmd.resp_type = MMC_RSP_R1b;
+
+ cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
+ (EXT_CSD_BOOT_BUS_WIDTH << 16) |
+ ((1 << 0) << 8);
+
+ err = mmc_send_cmd(mmc, &cmd, NULL);
+ if (err) {
+ debug("mmc boot partition#%d open fail:Error2 = %d\n",
+ part_num, err);
+ return err;
+ }
+ }
+ return 0;
+}
+#endif