diff mbox series

[09/18] stm32mp: stm32prog: add MTD devices support

Message ID 20200318082503.8025-10-patrick.delaunay@st.com
State Accepted
Commit eb845d6f8b72c5c12ecc8a455418e0dd7b8b79a1
Headers show
Series stm32mp1: add command stm32prog | expand

Commit Message

Patrick Delaunay March 18, 2020, 8:24 a.m. UTC
Add support of MTD device (DFU_MTD backend) for
NOR, NAND or SPI-NAND target.

Signed-off-by: Patrick Delaunay <patrick.delaunay at st.com>
---

 arch/arm/mach-stm32mp/Kconfig                 |   2 +
 .../mach-stm32mp/cmd_stm32prog/stm32prog.c    | 114 +++++++++++++++++-
 .../mach-stm32mp/cmd_stm32prog/stm32prog.h    |   4 +
 configs/stm32mp15_basic_defconfig             |   2 -
 configs/stm32mp15_trusted_defconfig           |   2 -
 5 files changed, 117 insertions(+), 7 deletions(-)
diff mbox series

Patch

diff --git a/arch/arm/mach-stm32mp/Kconfig b/arch/arm/mach-stm32mp/Kconfig
index 39504e8540..af16393152 100644
--- a/arch/arm/mach-stm32mp/Kconfig
+++ b/arch/arm/mach-stm32mp/Kconfig
@@ -121,7 +121,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;
@@ -521,6 +564,29 @@  static int init_device(struct stm32prog_data *data,
 			 first_addr, last_addr);
 		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);
@@ -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,
@@ -914,6 +1014,14 @@  static int stm32prog_alt_add(struct stm32prog_data *data,
 		sprintf(dfustr, "mmc");
 		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);
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;
diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig
index 2e7d8bc990..7837cbe9c7 100644
--- a/configs/stm32mp15_basic_defconfig
+++ b/configs/stm32mp15_basic_defconfig
@@ -37,7 +37,6 @@  CONFIG_CMD_FUSE=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
-CONFIG_CMD_MTD=y
 CONFIG_CMD_REMOTEPROC=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
@@ -67,7 +66,6 @@  CONFIG_ENV_UBI_VOLUME="uboot_config"
 CONFIG_ENV_UBI_VOLUME_REDUND="uboot_config_r"
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_STM32_ADC=y
-CONFIG_DFU_MTD=y
 CONFIG_SET_DFU_ALT_INFO=y
 CONFIG_USB_FUNCTION_FASTBOOT=y
 CONFIG_FASTBOOT_BUF_ADDR=0xC0000000
diff --git a/configs/stm32mp15_trusted_defconfig b/configs/stm32mp15_trusted_defconfig
index 6f6c909da0..e5b1ab5d04 100644
--- a/configs/stm32mp15_trusted_defconfig
+++ b/configs/stm32mp15_trusted_defconfig
@@ -25,7 +25,6 @@  CONFIG_CMD_FUSE=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
-CONFIG_CMD_MTD=y
 CONFIG_CMD_REMOTEPROC=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
@@ -53,7 +52,6 @@  CONFIG_ENV_UBI_VOLUME="uboot_config"
 CONFIG_ENV_UBI_VOLUME_REDUND="uboot_config_r"
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_STM32_ADC=y
-CONFIG_DFU_MTD=y
 CONFIG_SET_DFU_ALT_INFO=y
 CONFIG_USB_FUNCTION_FASTBOOT=y
 CONFIG_FASTBOOT_BUF_ADDR=0xC0000000