Merge changes I85a87dc9,If75df769,I55b0c910 into integration

* changes:
  feat(plat/st): add STM32MP_EMMC_BOOT option
  feat(drivers/st): manage boot part in io_mmc
  feat(drivers/mmc): boot partition read support
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index e288d47..c327e71 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -105,6 +105,36 @@
 	return MMC_GET_STATE(resp_data[0]);
 }
 
+static int mmc_send_part_switch_cmd(unsigned int part_config)
+{
+	int ret;
+	unsigned int part_time = 0;
+
+	ret = mmc_send_cmd(MMC_CMD(6),
+			   EXTCSD_WRITE_BYTES |
+			   EXTCSD_CMD(CMD_EXTCSD_PARTITION_CONFIG) |
+			   EXTCSD_VALUE(part_config) |
+			   EXTCSD_CMD_SET_NORMAL,
+			   MMC_RESPONSE_R1B, NULL);
+	if (ret != 0) {
+		return ret;
+	}
+
+	/* Partition switch timing is in 10ms units */
+	part_time = mmc_ext_csd[CMD_EXTCSD_PART_SWITCH_TIME] * 10;
+
+	mdelay(part_time);
+
+	do {
+		ret = mmc_device_state();
+		if (ret < 0) {
+			return ret;
+		}
+	} while (ret == MMC_STATE_PRG);
+
+	return 0;
+}
+
 static int mmc_set_ext_csd(unsigned int ext_cmd, unsigned int value)
 {
 	int ret;
@@ -668,7 +698,7 @@
 {
 	mmc_set_ext_csd(CMD_EXTCSD_PARTITION_CONFIG,
 			PART_CFG_BOOT_PARTITION1_ENABLE |
-			PART_CFG_PARTITION1_ACCESS);
+			PART_CFG_BOOT_PARTITION1_ACCESS);
 }
 
 static inline void mmc_rpmb_disable(void)
@@ -710,6 +740,50 @@
 	return size_erased;
 }
 
+static int mmc_part_switch(unsigned int part_type)
+{
+	uint8_t part_config = mmc_ext_csd[CMD_EXTCSD_PARTITION_CONFIG];
+
+	part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK;
+	part_config |= part_type;
+
+	return mmc_send_part_switch_cmd(part_config);
+}
+
+static unsigned char mmc_current_boot_part(void)
+{
+	return PART_CFG_CURRENT_BOOT_PARTITION(mmc_ext_csd[CMD_EXTCSD_PARTITION_CONFIG]);
+}
+
+size_t mmc_boot_part_read_blocks(int lba, uintptr_t buf, size_t size)
+{
+	size_t size_read;
+	int ret;
+	unsigned char current_boot_part = mmc_current_boot_part();
+
+	if (current_boot_part != 1U &&
+	    current_boot_part != 2U) {
+		ERROR("Got unexpected value for active boot partition, %u\n", current_boot_part);
+		return 0;
+	}
+
+	ret = mmc_part_switch(current_boot_part);
+	if (ret < 0) {
+		ERROR("Failed to switch to boot partition, %d\n", ret);
+		return 0;
+	}
+
+	size_read = mmc_read_blocks(lba, buf, size);
+
+	ret = mmc_part_switch(0);
+	if (ret < 0) {
+		ERROR("Failed to switch back to user partition, %d\n", ret);
+		return 0;
+	}
+
+	return size_read;
+}
+
 int mmc_init(const struct mmc_ops *ops_ptr, unsigned int clk,
 	     unsigned int width, unsigned int flags,
 	     struct mmc_device_info *device_info)
diff --git a/drivers/st/io/io_mmc.c b/drivers/st/io/io_mmc.c
index 0ed7154..2bf88e6 100644
--- a/drivers/st/io/io_mmc.c
+++ b/drivers/st/io/io_mmc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -29,6 +29,7 @@
 static io_type_t device_type_mmc(void);
 
 static signed long long seek_offset;
+static size_t (*_read_blocks)(int lba, uintptr_t buf, size_t size);
 
 static const io_dev_connector_t mmc_dev_connector = {
 	.dev_open = mmc_dev_open
@@ -60,9 +61,15 @@
 /* Open a connection to the mmc device */
 static int mmc_dev_open(const uintptr_t init_params, io_dev_info_t **dev_info)
 {
+	struct io_mmc_dev_spec *device_spec =
+		(struct io_mmc_dev_spec *)init_params;
+
 	assert(dev_info != NULL);
 	*dev_info = (io_dev_info_t *)&mmc_dev_info;
 
+	_read_blocks = !device_spec->use_boot_part ?
+		mmc_read_blocks : mmc_boot_part_read_blocks;
+
 	return 0;
 }
 
@@ -100,8 +107,8 @@
 	uint8_t retries;
 
 	for (retries = 0U; retries < 3U; retries++) {
-		*length_read = mmc_read_blocks(seek_offset / MMC_BLOCK_SIZE,
-					       buffer, length);
+		*length_read = _read_blocks(seek_offset / MMC_BLOCK_SIZE,
+					    buffer, length);
 
 		if (*length_read == length) {
 			return 0;
diff --git a/include/drivers/mmc.h b/include/drivers/mmc.h
index 7611f01..834a80f 100644
--- a/include/drivers/mmc.h
+++ b/include/drivers/mmc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -60,10 +60,16 @@
 #define CMD_EXTCSD_PARTITION_CONFIG	179
 #define CMD_EXTCSD_BUS_WIDTH		183
 #define CMD_EXTCSD_HS_TIMING		185
+#define CMD_EXTCSD_PART_SWITCH_TIME	199
 #define CMD_EXTCSD_SEC_CNT		212
 
+#define EXT_CSD_PART_CONFIG_ACC_MASK	GENMASK(2, 0)
 #define PART_CFG_BOOT_PARTITION1_ENABLE	(U(1) << 3)
-#define PART_CFG_PARTITION1_ACCESS	(U(1) << 0)
+#define PART_CFG_BOOT_PARTITION1_ACCESS (U(1) << 0)
+#define PART_CFG_BOOT_PART_EN_MASK		GENMASK(5, 3)
+#define PART_CFG_BOOT_PART_EN_SHIFT		3
+#define PART_CFG_CURRENT_BOOT_PARTITION(x)	(((x) & PART_CFG_BOOT_PART_EN_MASK) >> \
+	PART_CFG_BOOT_PART_EN_SHIFT)
 
 /* Values in EXT CSD register */
 #define MMC_BUS_WIDTH_1			U(0)
@@ -230,6 +236,7 @@
 size_t mmc_rpmb_read_blocks(int lba, uintptr_t buf, size_t size);
 size_t mmc_rpmb_write_blocks(int lba, const uintptr_t buf, size_t size);
 size_t mmc_rpmb_erase_blocks(int lba, size_t size);
+size_t mmc_boot_part_read_blocks(int lba, uintptr_t buf, size_t size);
 int mmc_init(const struct mmc_ops *ops_ptr, unsigned int clk,
 	     unsigned int width, unsigned int flags,
 	     struct mmc_device_info *device_info);
diff --git a/include/drivers/st/io_mmc.h b/include/drivers/st/io_mmc.h
index b35b4b5..6179e89 100644
--- a/include/drivers/st/io_mmc.h
+++ b/include/drivers/st/io_mmc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,6 +9,10 @@
 
 #include <drivers/io/io_driver.h>
 
+struct io_mmc_dev_spec {
+	bool use_boot_part;
+};
+
 int register_io_dev_mmc(const io_dev_connector_t **dev_con);
 
 #endif /* IO_MMC_H */
diff --git a/plat/st/common/bl2_io_storage.c b/plat/st/common/bl2_io_storage.c
index a25643b..0a18d99 100644
--- a/plat/st/common/bl2_io_storage.c
+++ b/plat/st/common/bl2_io_storage.c
@@ -62,6 +62,30 @@
 	.block_size = MMC_BLOCK_SIZE,
 };
 
+#if STM32MP_EMMC_BOOT
+static io_block_spec_t emmc_boot_ssbl_block_spec = {
+	.offset = PLAT_EMMC_BOOT_SSBL_OFFSET,
+	.length = MMC_BLOCK_SIZE, /* We are interested only in first 4 bytes */
+};
+
+static const io_block_dev_spec_t mmc_block_dev_boot_part_spec = {
+	/* It's used as temp buffer in block driver */
+	.buffer = {
+		.offset = (size_t)&block_buffer,
+		.length = MMC_BLOCK_SIZE,
+	},
+	.ops = {
+		.read = mmc_boot_part_read_blocks,
+		.write = NULL,
+	},
+	.block_size = MMC_BLOCK_SIZE,
+};
+#endif
+
+static struct io_mmc_dev_spec mmc_device_spec = {
+	.use_boot_part = false,
+};
+
 static const io_dev_connector_t *mmc_dev_con;
 #endif /* STM32MP_SDMMC || STM32MP_EMMC */
 
@@ -236,6 +260,38 @@
 	return io_dev_init(storage_dev_handle, 0);
 }
 
+#if STM32MP_EMMC_BOOT
+static uint32_t get_boot_part_ssbl_header(void)
+{
+	uint32_t magic = 0;
+	int io_result;
+	size_t bytes_read;
+
+	io_result = register_io_dev_block(&mmc_dev_con);
+	if (io_result != 0) {
+		panic();
+	}
+
+	io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_block_dev_boot_part_spec,
+				&storage_dev_handle);
+	assert(io_result == 0);
+
+	io_result = io_open(storage_dev_handle, (uintptr_t) &emmc_boot_ssbl_block_spec,
+			    &image_dev_handle);
+	assert(io_result == 0);
+
+	io_result = io_read(image_dev_handle, (uintptr_t) &magic, sizeof(magic),
+			    &bytes_read);
+	assert(io_result == 0);
+	assert(bytes_read == sizeof(magic));
+
+	io_result = io_dev_close(storage_dev_handle);
+	assert(io_result == 0);
+
+	return magic;
+}
+#endif
+
 static void print_boot_device(boot_api_context_t *boot_context)
 {
 	switch (boot_context->boot_interface_selected) {
@@ -273,7 +329,8 @@
 	uint8_t idx;
 	struct stm32image_part_info *part;
 	struct stm32_sdmmc2_params params;
-	const partition_entry_t *entry;
+	const partition_entry_t *entry __unused;
+	uint32_t magic __unused;
 
 	zeromem(&params, sizeof(struct stm32_sdmmc2_params));
 
@@ -305,6 +362,26 @@
 		panic();
 	}
 
+	stm32image_dev_info_spec.device_size =
+		stm32_sdmmc2_mmc_get_device_size();
+
+#if STM32MP_EMMC_BOOT
+	magic = get_boot_part_ssbl_header();
+
+	if (magic == BOOT_API_IMAGE_HEADER_MAGIC_NB) {
+		VERBOSE("%s, header found, jump to emmc load\n", __func__);
+		idx = IMG_IDX_BL33;
+		part = &stm32image_dev_info_spec.part_info[idx];
+		part->part_offset = PLAT_EMMC_BOOT_SSBL_OFFSET;
+		part->bkp_offset = 0U;
+		mmc_device_spec.use_boot_part = true;
+
+		goto emmc_boot;
+	} else {
+		WARN("%s: Can't find STM32 header on a boot partition\n", __func__);
+	}
+#endif
+
 	/* Open MMC as a block device to read GPT table */
 	io_result = register_io_dev_block(&mmc_dev_con);
 	if (io_result != 0) {
@@ -320,9 +397,6 @@
 	io_result = io_dev_close(storage_dev_handle);
 	assert(io_result == 0);
 
-	stm32image_dev_info_spec.device_size =
-		stm32_sdmmc2_mmc_get_device_size();
-
 	for (idx = 0U; idx < IMG_IDX_NUM; idx++) {
 		part = &stm32image_dev_info_spec.part_info[idx];
 		entry = get_partition_entry(part->name);
@@ -335,6 +409,9 @@
 		part->bkp_offset = 0U;
 	}
 
+#if STM32MP_EMMC_BOOT
+emmc_boot:
+#endif
 	/*
 	 * Re-open MMC with io_mmc, for better perfs compared to
 	 * io_block.
@@ -342,7 +419,8 @@
 	io_result = register_io_dev_mmc(&mmc_dev_con);
 	assert(io_result == 0);
 
-	io_result = io_dev_open(mmc_dev_con, 0, &storage_dev_handle);
+	io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_device_spec,
+				&storage_dev_handle);
 	assert(io_result == 0);
 
 	io_result = register_io_dev_stm32image(&stm32image_dev_con);
diff --git a/plat/st/stm32mp1/include/platform_def.h b/plat/st/stm32mp1/include/platform_def.h
index 9a2f54a..2d7d369 100644
--- a/plat/st/stm32mp1/include/platform_def.h
+++ b/plat/st/stm32mp1/include/platform_def.h
@@ -88,6 +88,12 @@
  */
 #define PLAT_STM32MP_NS_IMAGE_OFFSET	BL33_BASE
 
+/*
+ * SSBL offset in case it's stored in eMMC boot partition.
+ * We can fix it to 256K because TF-A size can't be bigger than SRAM
+ */
+#define PLAT_EMMC_BOOT_SSBL_OFFSET		U(0x40000)
+
 /*******************************************************************************
  * DTB specific defines.
  ******************************************************************************/
diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk
index 50fb1b7..128dbc4 100644
--- a/plat/st/stm32mp1/platform.mk
+++ b/plat/st/stm32mp1/platform.mk
@@ -42,6 +42,7 @@
 STM32MP_RAW_NAND	?=	0
 STM32MP_SPI_NAND	?=	0
 STM32MP_SPI_NOR		?=	0
+STM32MP_EMMC_BOOT	?=	0
 
 ifeq ($(filter 1,${STM32MP_EMMC} ${STM32MP_SDMMC} ${STM32MP_RAW_NAND} \
 	${STM32MP_SPI_NAND} ${STM32MP_SPI_NOR}),)
@@ -77,6 +78,7 @@
 		STM32MP_RAW_NAND \
 		STM32MP_SPI_NAND \
 		STM32MP_SPI_NOR \
+		STM32MP_EMMC_BOOT \
 		PLAT_XLAT_TABLES_DYNAMIC \
 )))
 
@@ -93,6 +95,7 @@
 		STM32MP_RAW_NAND \
 		STM32MP_SPI_NAND \
 		STM32MP_SPI_NOR \
+		STM32MP_EMMC_BOOT \
 		PLAT_XLAT_TABLES_DYNAMIC \
 		STM32_TF_A_COPIES \
 		PLAT_PARTITION_MAX_ENTRIES \