stm32mp: stm32prog: add MTD devices support
authorPatrick Delaunay <patrick.delaunay@st.com>
Wed, 18 Mar 2020 08:24:54 +0000 (09:24 +0100)
committerPatrick Delaunay <patrick.delaunay@st.com>
Thu, 14 May 2020 07:02:12 +0000 (09:02 +0200)
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>
arch/arm/mach-stm32mp/Kconfig
arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c
arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h
configs/stm32mp15_basic_defconfig
configs/stm32mp15_trusted_defconfig

index bf573acff37ec779cbe28fe54921e4ca1b1d09df..6fed2c622c67c2a5213e3dddaaa1c3d0c671049a 100644 (file)
@@ -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,
index 787bcdef7da2aa2e6ddfb6c83af62c3fbb1632f4..93ee6a55a1b1e63e080a720b48792e9c593ac97b 100644 (file)
@@ -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);
index ea88459896f7f2f9a8f1850398237ac4c495ff7e..8e635da3a4979a5045c1aa393347f54bdf0099ca 100644 (file)
@@ -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;
index c902f10491ab501fe376847fd209320910570ae1..cdcf591c955f2d7dfcaa02860ae6027345aed925 100644 (file)
@@ -36,7 +36,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
@@ -66,7 +65,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
index f01bfa555dab9fd6e0d268cda4921cbf755c223e..695fca02ac0116747486d31e2789ddab680fe63f 100644 (file)
@@ -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