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>
This commit is contained in:
parent
584b55b072
commit
c8151b4a5d
2 changed files with 49 additions and 0 deletions
|
@ -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…
Reference in a new issue