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 <patrick.delaunay@st.com>
Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
This commit is contained in:
Patrick Delaunay 2020-03-18 09:24:52 +01:00
parent aff4c5dd82
commit 878f7542f1
2 changed files with 90 additions and 36 deletions

View file

@ -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)

View file

@ -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;