1 // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
3 * Copyright (C) 2020, STMicroelectronics - All Rights Reserved
10 #include <dm/uclass.h>
11 #include <linux/list.h>
12 #include <linux/list_sort.h>
13 #include <linux/sizes.h>
15 #include "stm32prog.h"
17 #define OPT_SELECT BIT(0)
18 #define OPT_EMPTY BIT(1)
20 #define IS_SELECT(part) ((part)->option & OPT_SELECT)
21 #define IS_EMPTY(part) ((part)->option & OPT_EMPTY)
23 #define ALT_BUF_LEN SZ_1K
25 DECLARE_GLOBAL_DATA_PTR;
27 char *stm32prog_get_error(struct stm32prog_data *data)
29 static const char error_msg[] = "Unspecified";
31 if (strlen(data->error) == 0)
32 strcpy(data->error, error_msg);
37 static int parse_flash_layout(struct stm32prog_data *data,
44 static int __init part_cmp(void *priv, struct list_head *a, struct list_head *b)
46 struct stm32prog_part_t *parta, *partb;
48 parta = container_of(a, struct stm32prog_part_t, list);
49 partb = container_of(b, struct stm32prog_part_t, list);
51 return parta->addr > partb->addr ? 1 : -1;
54 static int init_device(struct stm32prog_data *data,
55 struct stm32prog_dev_t *dev)
57 struct blk_desc *block_dev = NULL;
59 u64 first_addr = 0, last_addr = 0;
60 struct stm32prog_part_t *part, *next_part;
62 switch (dev->target) {
64 stm32prog_err("unknown device type = %d", dev->target);
68 /* order partition list in offset order */
69 list_sort(NULL, &dev->part_list, &part_cmp);
71 pr_debug("id : Opt Phase Name target.n dev.n addr size part_off part_size\n");
72 list_for_each_entry(part, &dev->part_list, list) {
73 if (part->part_type == RAW_IMAGE) {
77 part->size = block_dev->lba * block_dev->blksz;
79 part->size = last_addr;
80 pr_debug("-- : %1d %02x %14s %02d %02d.%02d %08llx %08llx\n",
81 part->option, part->id, part->name,
82 part->part_type, part->target,
83 part->dev_id, part->addr, part->size);
87 part->part_id = part_id++;
89 /* last partition : size to the end of the device */
90 if (part->list.next != &dev->part_list) {
92 container_of(part->list.next,
93 struct stm32prog_part_t,
95 if (part->addr < next_part->addr) {
96 part->size = next_part->addr -
99 stm32prog_err("%s (0x%x): same address : 0x%llx == %s (0x%x): 0x%llx",
100 part->name, part->id,
108 if (part->addr <= last_addr) {
109 part->size = last_addr - part->addr;
111 stm32prog_err("%s (0x%x): invalid address 0x%llx (max=0x%llx)",
112 part->name, part->id,
113 part->addr, last_addr);
117 if (part->addr < first_addr) {
118 stm32prog_err("%s (0x%x): invalid address 0x%llx (min=0x%llx)",
119 part->name, part->id,
120 part->addr, first_addr);
124 pr_debug("%02d : %1d %02x %14s %02d %02d.%02d %08llx %08llx",
125 part->part_id, part->option, part->id, part->name,
126 part->part_type, part->target,
127 part->dev_id, part->addr, part->size);
132 static int treat_partition_list(struct stm32prog_data *data)
135 struct stm32prog_part_t *part;
137 for (j = 0; j < STM32PROG_MAX_DEV; j++) {
138 data->dev[j].target = STM32PROG_NONE;
139 INIT_LIST_HEAD(&data->dev[j].part_list);
142 for (i = 0; i < data->part_nb; i++) {
143 part = &data->part_array[i];
146 /* skip partition with IP="none" */
147 if (part->target == STM32PROG_NONE) {
148 if (IS_SELECT(part)) {
149 stm32prog_err("Layout: selected none phase = 0x%x",
156 if (part->id == PHASE_FLASHLAYOUT ||
157 part->id > PHASE_LAST_USER) {
158 stm32prog_err("Layout: invalid phase = 0x%x",
162 for (j = i + 1; j < data->part_nb; j++) {
163 if (part->id == data->part_array[j].id) {
164 stm32prog_err("Layout: duplicated phase 0x%x at line %d and %d",
169 for (j = 0; j < STM32PROG_MAX_DEV; j++) {
170 if (data->dev[j].target == STM32PROG_NONE) {
171 /* new device found */
172 data->dev[j].target = part->target;
173 data->dev[j].dev_id = part->dev_id;
176 } else if ((part->target == data->dev[j].target) &&
177 (part->dev_id == data->dev[j].dev_id)) {
181 if (j == STM32PROG_MAX_DEV) {
182 stm32prog_err("Layout: too many device");
185 part->dev = &data->dev[j];
186 list_add_tail(&part->list, &data->dev[j].part_list);
192 static int stm32prog_alt_add(struct stm32prog_data *data,
193 struct dfu_entity *dfu,
194 struct stm32prog_part_t *part)
200 char buf[ALT_BUF_LEN];
202 char multiplier, type;
204 /* max 3 digit for sector size */
205 if (part->size > SZ_1M) {
206 size = (u32)(part->size / SZ_1M);
208 } else if (part->size > SZ_1K) {
209 size = (u32)(part->size / SZ_1K);
212 size = (u32)part->size;
215 if (IS_SELECT(part) && !IS_EMPTY(part))
216 type = 'e'; /*Readable and Writeable*/
218 type = 'a';/*Readable*/
220 memset(buf, 0, sizeof(buf));
221 offset = snprintf(buf, ALT_BUF_LEN - offset,
222 "@%s/0x%02x/1*%d%c%c ",
223 part->name, part->id,
224 size, multiplier, type);
226 if (part->part_type == RAW_IMAGE) {
229 dfu_size = part->size;
230 offset += snprintf(buf + offset, ALT_BUF_LEN - offset,
231 "raw 0x0 0x%llx", dfu_size);
233 offset += snprintf(buf + offset,
234 ALT_BUF_LEN - offset,
236 offset += snprintf(buf + offset, ALT_BUF_LEN - offset,
237 " %d;", part->part_id);
239 switch (part->target) {
241 stm32prog_err("invalid target: %d", part->target);
244 pr_debug("dfu_alt_add(%s,%s,%s)\n", dfustr, devstr, buf);
245 ret = dfu_alt_add(dfu, dfustr, devstr, buf);
246 pr_debug("dfu_alt_add(%s,%s,%s) result %d\n",
247 dfustr, devstr, buf, ret);
252 static int stm32prog_alt_add_virt(struct dfu_entity *dfu,
253 char *name, int phase, int size)
257 char buf[ALT_BUF_LEN];
259 sprintf(devstr, "%d", phase);
260 sprintf(buf, "@%s/0x%02x/1*%dBe", name, phase, size);
261 ret = dfu_alt_add(dfu, "virt", devstr, buf);
262 pr_debug("dfu_alt_add(virt,%s,%s) result %d\n", devstr, buf, ret);
267 static int dfu_init_entities(struct stm32prog_data *data)
270 int phase, i, alt_id;
271 struct stm32prog_part_t *part;
272 struct dfu_entity *dfu;
275 alt_nb = 1; /* number of virtual = CMD */
276 if (data->part_nb == 0)
277 alt_nb++; /* +1 for FlashLayout */
279 for (i = 0; i < data->part_nb; i++) {
280 if (data->part_array[i].target != STM32PROG_NONE)
284 if (dfu_alt_init(alt_nb, &dfu))
287 puts("DFU alt info setting: ");
291 (phase <= PHASE_LAST_USER) &&
292 (alt_id < alt_nb) && !ret;
294 /* ordering alt setting by phase id */
296 for (i = 0; i < data->part_nb; i++) {
297 if (phase == data->part_array[i].id) {
298 part = &data->part_array[i];
304 if (part->target == STM32PROG_NONE)
306 part->alt_id = alt_id;
309 ret = stm32prog_alt_add(data, dfu, part);
312 char buf[ALT_BUF_LEN];
314 sprintf(buf, "@FlashLayout/0x%02x/1*256Ke ram %x 40000",
315 PHASE_FLASHLAYOUT, STM32_DDR_BASE);
316 ret = dfu_alt_add(dfu, "ram", NULL, buf);
317 pr_debug("dfu_alt_add(ram, NULL,%s) result %d\n", buf, ret);
321 ret = stm32prog_alt_add_virt(dfu, "virtual", PHASE_CMD, 512);
324 stm32prog_err("dfu init failed: %d", ret);
333 static void stm32prog_end_phase(struct stm32prog_data *data)
335 if (data->phase == PHASE_FLASHLAYOUT) {
336 if (parse_flash_layout(data, STM32_DDR_BASE, 0))
337 stm32prog_err("Layout: invalid FlashLayout");
345 void stm32prog_do_reset(struct stm32prog_data *data)
347 if (data->phase == PHASE_RESET) {
348 data->phase = PHASE_DO_RESET;
349 puts("Reset requested\n");
353 void stm32prog_next_phase(struct stm32prog_data *data)
356 struct stm32prog_part_t *part;
367 /* found next selected partition */
368 data->cur_part = NULL;
369 data->phase = PHASE_END;
373 if (phase > PHASE_LAST_USER)
375 for (i = 0; i < data->part_nb; i++) {
376 part = &data->part_array[i];
377 if (part->id == phase) {
378 if (IS_SELECT(part) && !IS_EMPTY(part)) {
379 data->cur_part = part;
388 if (data->phase == PHASE_END)
392 static void stm32prog_devices_init(struct stm32prog_data *data)
397 ret = treat_partition_list(data);
401 /* initialize the selected device */
402 for (i = 0; i < data->dev_nb; i++) {
403 ret = init_device(data, &data->dev[i]);
414 int stm32prog_dfu_init(struct stm32prog_data *data)
416 /* init device if no error */
418 stm32prog_devices_init(data);
421 stm32prog_next_phase(data);
423 /* prepare DFU for device read/write */
425 return dfu_init_entities(data);
428 int stm32prog_init(struct stm32prog_data *data, ulong addr, ulong size)
430 memset(data, 0x0, sizeof(*data));
431 data->phase = PHASE_FLASHLAYOUT;
433 return parse_flash_layout(data, addr, size);
436 void stm32prog_clean(struct stm32prog_data *data)
440 free(data->part_array);
441 free(data->header_data);
444 /* DFU callback: used after serial and direct DFU USB access */
445 void dfu_flush_callback(struct dfu_entity *dfu)
450 if (dfu->dev_type == DFU_DEV_RAM) {
452 stm32prog_data->phase == PHASE_FLASHLAYOUT) {
453 stm32prog_end_phase(stm32prog_data);
454 /* waiting DFU DETACH for reenumeration */
458 if (!stm32prog_data->cur_part)
461 if (dfu->alt == stm32prog_data->cur_part->alt_id) {
462 stm32prog_end_phase(stm32prog_data);
463 stm32prog_next_phase(stm32prog_data);
467 void dfu_initiated_callback(struct dfu_entity *dfu)
472 if (!stm32prog_data->cur_part)
475 /* force the saved offset for the current partition */
476 if (dfu->alt == stm32prog_data->cur_part->alt_id) {
477 dfu->offset = stm32prog_data->offset;
478 pr_debug("dfu offset = 0x%llx\n", dfu->offset);