From 878f7542f1880a73e703223de695c43d0f45e2bf Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Wed, 18 Mar 2020 09:24:52 +0100 Subject: [PATCH] stm32mp: stm32prog: add support of boot partition for eMMC device Add support of eMMC device boot partition with part_id = -1 for offset="boot1" or = -2 for offset="boot2" The stm32prog command configures the MMC DFU backend with "mmcpart" and configure the eMMC (command "mmc bootbus" and "mmc partconf") when the update is done. Signed-off-by: Patrick Delaunay Reviewed-by: Patrice Chotard --- .../mach-stm32mp/cmd_stm32prog/stm32prog.c | 124 +++++++++++++----- .../mach-stm32mp/cmd_stm32prog/stm32prog.h | 2 +- 2 files changed, 90 insertions(+), 36 deletions(-) diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c index feb83670b5..f63036606e 100644 --- a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c +++ b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c @@ -259,12 +259,30 @@ static int parse_offset(struct stm32prog_data *data, char *tail; part->part_id = 0; + part->addr = 0; part->size = 0; - part->addr = simple_strtoull(p, &tail, 0); - if (tail == p || *tail != '\0') { - stm32prog_err("Layout line %d: invalid offset '%s'", - i, p); - result = -EINVAL; + /* eMMC boot parttion */ + if (!strncmp(p, "boot", 4)) { + if (strlen(p) != 5) { + result = -EINVAL; + } else { + if (p[4] == '1') + part->part_id = -1; + else if (p[4] == '2') + part->part_id = -2; + else + result = -EINVAL; + } + if (result) + stm32prog_err("Layout line %d: invalid part '%s'", + i, p); + } else { + part->addr = simple_strtoull(p, &tail, 0); + if (tail == p || *tail != '\0') { + stm32prog_err("Layout line %d: invalid offset '%s'", + i, p); + result = -EINVAL; + } } return result; @@ -451,7 +469,10 @@ static int __init part_cmp(void *priv, struct list_head *a, struct list_head *b) parta = container_of(a, struct stm32prog_part_t, list); partb = container_of(b, struct stm32prog_part_t, list); - return parta->addr > partb->addr ? 1 : -1; + if (parta->part_id != partb->part_id) + return parta->part_id - partb->part_id; + else + return parta->addr > partb->addr ? 1 : -1; } static int init_device(struct stm32prog_data *data, @@ -520,44 +541,53 @@ static int init_device(struct stm32prog_data *data, part->dev_id, part->addr, part->size); continue; } - - part->part_id = part_id++; - - /* last partition : size to the end of the device */ - if (part->list.next != &dev->part_list) { - next_part = - container_of(part->list.next, - struct stm32prog_part_t, - list); - if (part->addr < next_part->addr) { - part->size = next_part->addr - - part->addr; + if (part->part_id < 0) { /* boot hw partition for eMMC */ + if (mmc) { + part->size = mmc->capacity_boot; } else { - stm32prog_err("%s (0x%x): same address : 0x%llx == %s (0x%x): 0x%llx", + stm32prog_err("%s (0x%x): hw partition not expected : %d", part->name, part->id, - part->addr, - next_part->name, - next_part->id, - next_part->addr); - return -EINVAL; + part->part_id); + return -ENODEV; } } else { - if (part->addr <= last_addr) { - part->size = last_addr - part->addr; + part->part_id = part_id++; + + /* last partition : size to the end of the device */ + if (part->list.next != &dev->part_list) { + next_part = + container_of(part->list.next, + struct stm32prog_part_t, + list); + if (part->addr < next_part->addr) { + part->size = next_part->addr - + part->addr; + } else { + stm32prog_err("%s (0x%x): same address : 0x%llx == %s (0x%x): 0x%llx", + part->name, part->id, + part->addr, + next_part->name, + next_part->id, + next_part->addr); + return -EINVAL; + } } else { - stm32prog_err("%s (0x%x): invalid address 0x%llx (max=0x%llx)", + if (part->addr <= last_addr) { + part->size = last_addr - part->addr; + } else { + stm32prog_err("%s (0x%x): invalid address 0x%llx (max=0x%llx)", + part->name, part->id, + part->addr, last_addr); + return -EINVAL; + } + } + if (part->addr < first_addr) { + stm32prog_err("%s (0x%x): invalid address 0x%llx (min=0x%llx)", part->name, part->id, - part->addr, last_addr); + part->addr, first_addr); return -EINVAL; } } - if (part->addr < first_addr) { - stm32prog_err("%s (0x%x): invalid address 0x%llx (min=0x%llx)", - part->name, part->id, - part->addr, first_addr); - return -EINVAL; - } - if ((part->addr & ((u64)part->dev->erase_size - 1)) != 0) { stm32prog_err("%s (0x%x): not aligned address : 0x%llx on erase size 0x%x", part->name, part->id, part->addr, @@ -657,6 +687,9 @@ static int create_partitions(struct stm32prog_data *data) memset(buf, 0, buflen); list_for_each_entry(part, &data->dev[i].part_list, list) { + /* skip eMMC boot partitions */ + if (part->part_id < 0) + continue; /* skip Raw Image */ if (part->part_type == RAW_IMAGE) continue; @@ -787,6 +820,14 @@ static int stm32prog_alt_add(struct stm32prog_data *data, dfu_size = part->size; offset += snprintf(buf + offset, ALT_BUF_LEN - offset, "raw 0x0 0x%llx", dfu_size); + } else if (part->part_id < 0) { + u64 nb_blk = part->size / part->dev->mmc->read_bl_len; + + offset += snprintf(buf + offset, ALT_BUF_LEN - offset, + "raw 0x%llx 0x%llx", + part->addr, nb_blk); + offset += snprintf(buf + offset, ALT_BUF_LEN - offset, + " mmcpart %d;", -(part->part_id)); } else { offset += snprintf(buf + offset, ALT_BUF_LEN - offset, @@ -908,6 +949,19 @@ static void stm32prog_end_phase(struct stm32prog_data *data) if (!data->cur_part) return; + + if (CONFIG_IS_ENABLED(MMC) && + data->cur_part->part_id < 0) { + char cmdbuf[60]; + + sprintf(cmdbuf, "mmc bootbus %d 0 0 0; mmc partconf %d 1 %d 0", + data->cur_part->dev_id, data->cur_part->dev_id, + -(data->cur_part->part_id)); + if (run_command(cmdbuf, 0)) { + stm32prog_err("commands '%s' failed", cmdbuf); + return; + } + } } void stm32prog_do_reset(struct stm32prog_data *data) diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h index 228a25d37f..6c3ad56a38 100644 --- a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h +++ b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h @@ -89,7 +89,7 @@ struct stm32prog_part_t { /* information on associated device */ struct stm32prog_dev_t *dev; /* pointer to device */ - u16 part_id; /* partition id in device */ + s16 part_id; /* partition id in device */ int alt_id; /* alt id in usb/dfu */ struct list_head list; -- 2.39.5