summaryrefslogtreecommitdiff
path: root/arch/arm
diff options
context:
space:
mode:
authorPatrick Delaunay <patrick.delaunay@st.com>2020-03-18 11:24:54 +0300
committerPatrick Delaunay <patrick.delaunay@st.com>2020-05-14 10:02:12 +0300
commiteb845d6f8b72c5c12ecc8a455418e0dd7b8b79a1 (patch)
tree06ef52f3ef015b8a585e2617c7f5cbd9f60ff42b /arch/arm
parentffc405e63b945de77dca51364cd5c6335f11d5c4 (diff)
downloadu-boot-eb845d6f8b72c5c12ecc8a455418e0dd7b8b79a1.tar.xz
stm32mp: stm32prog: add MTD devices support
Add support of MTD device (DFU_MTD backend) for NOR, NAND or SPI-NAND target. Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com> Reviewed-by: Patrice Chotard <patrice.chotard@st.com>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mach-stm32mp/Kconfig2
-rw-r--r--arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c114
-rw-r--r--arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h4
3 files changed, 117 insertions, 3 deletions
diff --git a/arch/arm/mach-stm32mp/Kconfig b/arch/arm/mach-stm32mp/Kconfig
index bf573acff3..6fed2c622c 100644
--- a/arch/arm/mach-stm32mp/Kconfig
+++ b/arch/arm/mach-stm32mp/Kconfig
@@ -114,7 +114,9 @@ config CMD_STM32PROG
select DFU_VIRT
select PARTITION_TYPE_GUID
imply CMD_GPT if MMC
+ imply CMD_MTD if MTD
imply DFU_MMC if MMC
+ imply DFU_MTD if MTD
help
activate a specific command stm32prog for STM32MP soc family
witch update the device with the tools STM32CubeProgrammer,
diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c
index 787bcdef7d..93ee6a55a1 100644
--- a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c
+++ b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c
@@ -8,9 +8,12 @@
#include <dfu.h>
#include <malloc.h>
#include <mmc.h>
+#include <part.h>
#include <dm/uclass.h>
+#include <jffs2/load_kernel.h>
#include <linux/list.h>
#include <linux/list_sort.h>
+#include <linux/mtd/mtd.h>
#include <linux/sizes.h>
#include "stm32prog.h"
@@ -65,6 +68,11 @@ enum stm32prog_col_t {
COL_NB_STM32
};
+/* partition handling routines : CONFIG_CMD_MTDPARTS */
+int mtdparts_init(void);
+int find_dev_and_part(const char *id, struct mtd_device **dev,
+ u8 *part_num, struct part_info **part);
+
char *stm32prog_get_error(struct stm32prog_data *data)
{
static const char error_msg[] = "Unspecified";
@@ -233,6 +241,15 @@ static int parse_ip(struct stm32prog_data *data,
} else if (!strncmp(p, "mmc", 3)) {
part->target = STM32PROG_MMC;
len = 3;
+ } else if (!strncmp(p, "nor", 3)) {
+ part->target = STM32PROG_NOR;
+ len = 3;
+ } else if (!strncmp(p, "nand", 4)) {
+ part->target = STM32PROG_NAND;
+ len = 4;
+ } else if (!strncmp(p, "spi-nand", 8)) {
+ part->target = STM32PROG_SPI_NAND;
+ len = 8;
} else {
result = -EINVAL;
}
@@ -475,11 +492,37 @@ static int __init part_cmp(void *priv, struct list_head *a, struct list_head *b)
return parta->addr > partb->addr ? 1 : -1;
}
+static void get_mtd_by_target(char *string, enum stm32prog_target target,
+ int dev_id)
+{
+ const char *dev_str;
+
+ switch (target) {
+ case STM32PROG_NOR:
+ dev_str = "nor";
+ break;
+ case STM32PROG_NAND:
+ dev_str = "nand";
+ break;
+ case STM32PROG_SPI_NAND:
+ dev_str = "spi-nand";
+ break;
+ default:
+ dev_str = "invalid";
+ break;
+ }
+ sprintf(string, "%s%d", dev_str, dev_id);
+}
+
static int init_device(struct stm32prog_data *data,
struct stm32prog_dev_t *dev)
{
struct mmc *mmc = NULL;
struct blk_desc *block_dev = NULL;
+#ifdef CONFIG_MTD
+ struct mtd_info *mtd = NULL;
+ char mtd_id[16];
+#endif
int part_id;
int ret;
u64 first_addr = 0, last_addr = 0;
@@ -522,6 +565,29 @@ static int init_device(struct stm32prog_data *data,
pr_debug(" full_update = %d\n", dev->full_update);
break;
#endif
+#ifdef CONFIG_MTD
+ case STM32PROG_NOR:
+ case STM32PROG_NAND:
+ case STM32PROG_SPI_NAND:
+ get_mtd_by_target(mtd_id, dev->target, dev->dev_id);
+ pr_debug("%s\n", mtd_id);
+
+ mtdparts_init();
+ mtd = get_mtd_device_nm(mtd_id);
+ if (IS_ERR(mtd)) {
+ stm32prog_err("MTD device %s not found", mtd_id);
+ return -ENODEV;
+ }
+ first_addr = 0;
+ last_addr = mtd->size;
+ dev->erase_size = mtd->erasesize;
+ pr_debug("MTD device %s: size=%lld erasesize=%d\n",
+ mtd_id, mtd->size, mtd->erasesize);
+ pr_debug(" available address = 0x%llx..0x%llx\n",
+ first_addr, last_addr);
+ dev->mtd = mtd;
+ break;
+#endif
default:
stm32prog_err("unknown device type = %d", dev->target);
return -ENODEV;
@@ -637,6 +703,29 @@ static int init_device(struct stm32prog_data *data,
part_found = true;
}
+#ifdef CONFIG_MTD
+ if (mtd) {
+ char mtd_part_id[32];
+ struct part_info *mtd_part;
+ struct mtd_device *mtd_dev;
+ u8 part_num;
+
+ sprintf(mtd_part_id, "%s,%d", mtd_id,
+ part->part_id - 1);
+ ret = find_dev_and_part(mtd_part_id, &mtd_dev,
+ &part_num, &mtd_part);
+ if (ret != 0) {
+ stm32prog_err("%s (0x%x): Invalid MTD partition %s",
+ part->name, part->id,
+ mtd_part_id);
+ return -ENODEV;
+ }
+ part_addr = mtd_part->offset;
+ part_size = mtd_part->size;
+ part_name = mtd_part->name;
+ part_found = true;
+ }
+#endif
if (!part_found) {
stm32prog_err("%s (0x%x): Invalid partition",
part->name, part->id);
@@ -840,6 +929,9 @@ static int create_partitions(struct stm32prog_data *data)
}
puts("done\n");
+#ifdef DEBUG
+ run_command("mtd list", 0);
+#endif
free(buf);
#endif
@@ -898,9 +990,17 @@ static int stm32prog_alt_add(struct stm32prog_data *data,
offset += snprintf(buf + offset, ALT_BUF_LEN - offset,
" mmcpart %d;", -(part->part_id));
} else {
- offset += snprintf(buf + offset,
- ALT_BUF_LEN - offset,
- "part");
+ if (part->part_type == PART_SYSTEM &&
+ (part->target == STM32PROG_NAND ||
+ part->target == STM32PROG_NOR ||
+ part->target == STM32PROG_SPI_NAND))
+ offset += snprintf(buf + offset,
+ ALT_BUF_LEN - offset,
+ "partubi");
+ else
+ offset += snprintf(buf + offset,
+ ALT_BUF_LEN - offset,
+ "part");
/* dev_id requested by DFU MMC */
if (part->target == STM32PROG_MMC)
offset += snprintf(buf + offset, ALT_BUF_LEN - offset,
@@ -915,6 +1015,14 @@ static int stm32prog_alt_add(struct stm32prog_data *data,
sprintf(devstr, "%d", part->dev_id);
break;
#endif
+#ifdef CONFIG_MTD
+ case STM32PROG_NAND:
+ case STM32PROG_NOR:
+ case STM32PROG_SPI_NAND:
+ sprintf(dfustr, "mtd");
+ get_mtd_by_target(devstr, part->target, part->dev_id);
+ break;
+#endif
default:
stm32prog_err("invalid target: %d", part->target);
return -ENODEV;
diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h
index ea88459896..8e635da3a4 100644
--- a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h
+++ b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h
@@ -20,6 +20,9 @@
enum stm32prog_target {
STM32PROG_NONE,
STM32PROG_MMC,
+ STM32PROG_NAND,
+ STM32PROG_NOR,
+ STM32PROG_SPI_NAND
};
enum stm32prog_link_t {
@@ -67,6 +70,7 @@ struct stm32prog_dev_t {
char dev_id;
u32 erase_size;
struct mmc *mmc;
+ struct mtd_info *mtd;
/* list of partition for this device / ordered in offset */
struct list_head part_list;
bool full_update;