dfu: mmc: Provide support for eMMC boot partition access

Before this patch it was only possible to access the default eMMC HW
partition. By partition selection I mean the access to eMMC via the
ext_csd[179] register programming.

It sometimes happens that it is necessary to write to other partitions.
This patch adds extra attribute to "raw" sub type of the dfu_alt_info
environment variable (e.g. boot-mmc.bin raw 0x0 0x200 mmcpart 1;)

It saves the original boot value and restores it after storing the file.

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
master
Lukasz Majewski 10 years ago committed by Marek Vasut
parent 584b55b072
commit c8151b4a5d
  1. 46
      drivers/dfu/dfu_mmc.c
  2. 3
      include/dfu.h

@ -18,11 +18,29 @@ static unsigned char __aligned(CONFIG_SYS_CACHELINE_SIZE)
dfu_file_buf[CONFIG_SYS_DFU_MAX_FILE_SIZE];
static long dfu_file_buf_len;
static int mmc_access_part(struct dfu_entity *dfu, struct mmc *mmc, int part)
{
int ret;
if (part == mmc->part_num)
return 0;
ret = mmc_switch_part(dfu->dev_num, part);
if (ret) {
error("Cannot switch to partition %d\n", part);
return ret;
}
mmc->part_num = part;
return 0;
}
static int mmc_block_op(enum dfu_op op, struct dfu_entity *dfu,
u64 offset, void *buf, long *len)
{
struct mmc *mmc = find_mmc_device(dfu->dev_num);
u32 blk_start, blk_count, n = 0;
int ret, part_num_bkp = 0;
/*
* We must ensure that we work in lba_blk_size chunks, so ALIGN
@ -39,6 +57,13 @@ static int mmc_block_op(enum dfu_op op, struct dfu_entity *dfu,
return -EINVAL;
}
if (dfu->data.mmc.hw_partition >= 0) {
part_num_bkp = mmc->part_num;
ret = mmc_access_part(dfu, mmc, dfu->data.mmc.hw_partition);
if (ret)
return ret;
}
debug("%s: %s dev: %d start: %d cnt: %d buf: 0x%p\n", __func__,
op == DFU_OP_READ ? "MMC READ" : "MMC WRITE", dfu->dev_num,
blk_start, blk_count, buf);
@ -57,9 +82,17 @@ static int mmc_block_op(enum dfu_op op, struct dfu_entity *dfu,
if (n != blk_count) {
error("MMC operation failed");
if (dfu->data.mmc.hw_partition >= 0)
mmc_access_part(dfu, mmc, part_num_bkp);
return -EIO;
}
if (dfu->data.mmc.hw_partition >= 0) {
ret = mmc_access_part(dfu, mmc, part_num_bkp);
if (ret)
return ret;
}
return 0;
}
@ -194,6 +227,8 @@ int dfu_read_medium_mmc(struct dfu_entity *dfu, u64 offset, void *buf,
* 2nd and 3rd:
* lba_start and lba_size, for raw write
* mmc_dev and mmc_part, for filesystems and part
* 4th (optional):
* mmcpart <num> (access to HW eMMC partitions)
*/
int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *s)
{
@ -233,11 +268,22 @@ int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *s)
return -ENODEV;
}
dfu->data.mmc.hw_partition = -EINVAL;
if (!strcmp(entity_type, "raw")) {
dfu->layout = DFU_RAW_ADDR;
dfu->data.mmc.lba_start = second_arg;
dfu->data.mmc.lba_size = third_arg;
dfu->data.mmc.lba_blk_size = mmc->read_bl_len;
/*
* Check for an extra entry at dfu_alt_info env variable
* specifying the mmc HW defined partition number
*/
if (s)
if (!strcmp(strsep(&s, " "), "mmcpart"))
dfu->data.mmc.hw_partition =
simple_strtoul(s, NULL, 0);
} else if (!strcmp(entity_type, "part")) {
disk_partition_t partinfo;
block_dev_desc_t *blk_dev = &mmc->block_dev;

@ -43,6 +43,9 @@ struct mmc_internal_data {
unsigned int lba_size;
unsigned int lba_blk_size;
/* eMMC HW partition access */
int hw_partition;
/* FAT/EXT */
unsigned int dev;
unsigned int part;

Loading…
Cancel
Save