stm32mp1: Add support for SPI-NOR boot device

STM32MP1 platform is able to boot from SPI-NOR devices.
These modifications add this support using the new
SPI-NOR framework.

Change-Id: I75ff9eba4661f9fb87ce24ced2bacbf8558ebe44
Signed-off-by: Lionel Debieve <lionel.debieve@st.com>
diff --git a/plat/st/common/bl2_io_storage.c b/plat/st/common/bl2_io_storage.c
index d0bc605..3ec7d40 100644
--- a/plat/st/common/bl2_io_storage.c
+++ b/plat/st/common/bl2_io_storage.c
@@ -20,6 +20,7 @@
 #include <drivers/partition/partition.h>
 #include <drivers/raw_nand.h>
 #include <drivers/spi_nand.h>
+#include <drivers/spi_nor.h>
 #include <drivers/st/io_mmc.h>
 #include <drivers/st/io_stm32image.h>
 #include <drivers/st/stm32_fmc2_nand.h>
@@ -61,6 +62,15 @@
 static const io_dev_connector_t *mmc_dev_con;
 #endif /* STM32MP_SDMMC || STM32MP_EMMC */
 
+#if STM32MP_SPI_NOR
+static io_mtd_dev_spec_t spi_nor_dev_spec = {
+	.ops = {
+		.init = spi_nor_init,
+		.read = spi_nor_read,
+	},
+};
+#endif
+
 #if STM32MP_RAW_NAND
 static io_mtd_dev_spec_t nand_dev_spec = {
 	.ops = {
@@ -79,7 +89,9 @@
 		.read = nand_read,
 	},
 };
+#endif
 
+#if STM32MP_SPI_NAND || STM32MP_SPI_NOR
 static const io_dev_connector_t *spi_dev_con;
 #endif
 
@@ -236,6 +248,9 @@
 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
 		INFO("Using EMMC\n");
 		break;
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
+		INFO("Using QSPI NOR\n");
+		break;
 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
 		INFO("Using FMC NAND\n");
 		break;
@@ -345,6 +360,59 @@
 }
 #endif /* STM32MP_SDMMC || STM32MP_EMMC */
 
+#if STM32MP_SPI_NOR
+static void boot_spi_nor(boot_api_context_t *boot_context)
+{
+	int io_result __unused;
+	uint8_t idx;
+	struct stm32image_part_info *part;
+
+	io_result = stm32_qspi_init();
+	assert(io_result == 0);
+
+	io_result = register_io_dev_mtd(&spi_dev_con);
+	assert(io_result == 0);
+
+	/* Open connections to device */
+	io_result = io_dev_open(spi_dev_con,
+				(uintptr_t)&spi_nor_dev_spec,
+				&storage_dev_handle);
+	assert(io_result == 0);
+
+	stm32image_dev_info_spec.device_size = spi_nor_dev_spec.device_size;
+
+	idx = IMG_IDX_BL33;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NOR_BL33_OFFSET;
+	part->bkp_offset = 0U;
+
+#ifdef AARCH32_SP_OPTEE
+	idx = IMG_IDX_OPTEE_HEADER;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NOR_TEEH_OFFSET;
+	part->bkp_offset = 0U;
+
+	idx = IMG_IDX_OPTEE_PAGED;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NOR_TEED_OFFSET;
+	part->bkp_offset = 0U;
+
+	idx = IMG_IDX_OPTEE_PAGER;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NOR_TEEX_OFFSET;
+	part->bkp_offset = 0U;
+#endif
+
+	io_result = register_io_dev_stm32image(&stm32image_dev_con);
+	assert(io_result == 0);
+
+	io_result = io_dev_open(stm32image_dev_con,
+				(uintptr_t)&stm32image_dev_info_spec,
+				&image_dev_handle);
+	assert(io_result == 0);
+}
+#endif /* STM32MP_SPI_NOR */
+
 #if STM32MP_RAW_NAND
 static void boot_fmc2_nand(boot_api_context_t *boot_context)
 {
@@ -486,6 +554,12 @@
 		boot_mmc(MMC_IS_EMMC, boot_context->boot_interface_instance);
 		break;
 #endif
+#if STM32MP_SPI_NOR
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
+		dmbsy();
+		boot_spi_nor(boot_context);
+		break;
+#endif
 #if STM32MP_RAW_NAND
 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
 		dmbsy();
diff --git a/plat/st/stm32mp1/include/boot_api.h b/plat/st/stm32mp1/include/boot_api.h
index 1f05d0b..c16639a 100644
--- a/plat/st/stm32mp1/include/boot_api.h
+++ b/plat/st/stm32mp1/include/boot_api.h
@@ -36,6 +36,9 @@
 /* Boot occurred on FMC */
 #define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC		0x3U
 
+/* Boot occurred on QSPI NOR */
+#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI		0x4U
+
 /* Boot occurred on QSPI NAND */
 #define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI		0x7U
 
diff --git a/plat/st/stm32mp1/include/stm32mp1_boot_device.h b/plat/st/stm32mp1/include/stm32mp1_boot_device.h
index db80f93..a745983 100644
--- a/plat/st/stm32mp1/include/stm32mp1_boot_device.h
+++ b/plat/st/stm32mp1/include/stm32mp1_boot_device.h
@@ -9,8 +9,10 @@
 
 #include <drivers/raw_nand.h>
 #include <drivers/spi_nand.h>
+#include <drivers/spi_nor.h>
 
 int plat_get_raw_nand_data(struct rawnand_device *device);
 int plat_get_spi_nand_data(struct spinand_device *device);
+int plat_get_nor_data(struct nor_device *device);
 
 #endif /* STM32MP1_BOOT_DEVICE_H */
diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk
index d25f3b3..b86287b 100644
--- a/plat/st/stm32mp1/platform.mk
+++ b/plat/st/stm32mp1/platform.mk
@@ -29,9 +29,10 @@
 STM32MP_SDMMC		?=	0
 STM32MP_RAW_NAND	?=	0
 STM32MP_SPI_NAND	?=	0
+STM32MP_SPI_NOR		?=	0
 
 ifeq ($(filter 1,${STM32MP_EMMC} ${STM32MP_SDMMC} ${STM32MP_RAW_NAND} \
-	${STM32MP_SPI_NAND}),)
+	${STM32MP_SPI_NAND} ${STM32MP_SPI_NOR}),)
 $(error "No boot device driver is enabled")
 endif
 
@@ -39,10 +40,12 @@
 $(eval $(call assert_boolean,STM32MP_SDMMC))
 $(eval $(call assert_boolean,STM32MP_RAW_NAND))
 $(eval $(call assert_boolean,STM32MP_SPI_NAND))
+$(eval $(call assert_boolean,STM32MP_SPI_NOR))
 $(eval $(call add_define,STM32MP_EMMC))
 $(eval $(call add_define,STM32MP_SDMMC))
 $(eval $(call add_define,STM32MP_RAW_NAND))
 $(eval $(call add_define,STM32MP_SPI_NAND))
+$(eval $(call add_define,STM32MP_SPI_NOR))
 
 PLAT_INCLUDES		:=	-Iplat/st/common/include/
 PLAT_INCLUDES		+=	-Iplat/st/stm32mp1/include/
@@ -116,14 +119,21 @@
 BL2_SOURCES		+=	drivers/mtd/nand/spi_nand.c
 endif
 
-ifeq (${STM32MP_SPI_NAND},1)
+ifeq (${STM32MP_SPI_NOR},1)
+BL2_SOURCES		+=	drivers/mtd/nor/spi_nor.c
+endif
+
+ifneq ($(filter 1,${STM32MP_SPI_NAND} ${STM32MP_SPI_NOR}),)
 BL2_SOURCES		+=	drivers/mtd/spi-mem/spi_mem.c				\
 				drivers/st/spi/stm32_qspi.c
 endif
 
 ifneq ($(filter 1,${STM32MP_RAW_NAND} ${STM32MP_SPI_NAND}),)
-BL2_SOURCES		+=	drivers/mtd/nand/core.c					\
-				plat/st/stm32mp1/stm32mp1_boot_device.c
+BL2_SOURCES		+=	drivers/mtd/nand/core.c
+endif
+
+ifneq ($(filter 1,${STM32MP_RAW_NAND} ${STM32MP_SPI_NAND} ${STM32MP_SPI_NOR}),)
+BL2_SOURCES		+=	plat/st/stm32mp1/stm32mp1_boot_device.c
 endif
 
 BL2_SOURCES		+=	drivers/st/ddr/stm32mp1_ddr.c				\
diff --git a/plat/st/stm32mp1/stm32mp1_boot_device.c b/plat/st/stm32mp1/stm32mp1_boot_device.c
index fa352f3..2d8eccf 100644
--- a/plat/st/stm32mp1/stm32mp1_boot_device.c
+++ b/plat/st/stm32mp1/stm32mp1_boot_device.c
@@ -11,6 +11,7 @@
 #include <plat/common/platform.h>
 
 #define SZ_512		0x200U
+#define SZ_64M		0x4000000U
 
 #if STM32MP_RAW_NAND || STM32MP_SPI_NAND
 static int get_data_from_otp(struct nand_device *nand_dev, bool is_slc)
@@ -149,3 +150,21 @@
 }
 #endif
 
+#if STM32MP_SPI_NOR
+int plat_get_nor_data(struct nor_device *device)
+{
+	device->size = SZ_64M;
+
+	zeromem(&device->read_op, sizeof(struct spi_mem_op));
+	device->read_op.cmd.opcode = SPI_NOR_OP_READ_1_1_4;
+	device->read_op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
+	device->read_op.addr.nbytes = 3U;
+	device->read_op.addr.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
+	device->read_op.dummy.nbytes = 1U;
+	device->read_op.dummy.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
+	device->read_op.data.buswidth = SPI_MEM_BUSWIDTH_4_LINE;
+	device->read_op.data.dir = SPI_MEM_DATA_IN;
+
+	return 0;
+}
+#endif
diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h
index a427dcf..11b01ab 100644
--- a/plat/st/stm32mp1/stm32mp1_def.h
+++ b/plat/st/stm32mp1/stm32mp1_def.h
@@ -151,6 +151,13 @@
 /*******************************************************************************
  * STM32MP1 RAW partition offset for MTD devices
  ******************************************************************************/
+#define STM32MP_NOR_BL33_OFFSET		U(0x00080000)
+#ifdef AARCH32_SP_OPTEE
+#define STM32MP_NOR_TEEH_OFFSET		U(0x00280000)
+#define STM32MP_NOR_TEED_OFFSET		U(0x002C0000)
+#define STM32MP_NOR_TEEX_OFFSET		U(0x00300000)
+#endif
+
 #define STM32MP_NAND_BL33_OFFSET	U(0x00200000)
 #ifdef AARCH32_SP_OPTEE
 #define STM32MP_NAND_TEEH_OFFSET	U(0x00600000)