Introduce STMicroelectronics STM32MP1 platform

STM32MP1 is a microprocessor designed by STMicroelectronics,
based on a dual Arm Cortex-A7.
It is an Armv7-A platform, using dedicated code from TF-A.

STM32MP1 uses BL2 compiled with BL2_AT_EL3.

Signed-off-by: Yann Gautier <yann.gautier@st.com>
Signed-off-by: Mathieu Belou <mathieu.belou@st.com>
Signed-off-by: Etienne Carriere <etienne.carriere@st.com>
Signed-off-by: Lionel Debieve <lionel.debieve@st.com>
Signed-off-by: Nicolas Le Bayon <nicolas.le.bayon@st.com>
Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com>
Signed-off-by: Pascal Paillet <p.paillet@st.com>
diff --git a/plat/st/stm32mp1/bl2_io_storage.c b/plat/st/stm32mp1/bl2_io_storage.c
new file mode 100644
index 0000000..7346c0c
--- /dev/null
+++ b/plat/st/stm32mp1/bl2_io_storage.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <boot_api.h>
+#include <debug.h>
+#include <io_driver.h>
+#include <io_dummy.h>
+#include <io_storage.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <stm32mp1_private.h>
+#include <stm32mp1_rcc.h>
+#include <string.h>
+#include <utils.h>
+
+/* IO devices */
+static const io_dev_connector_t *dummy_dev_con;
+static uintptr_t dummy_dev_handle;
+static uintptr_t dummy_dev_spec;
+
+static const io_block_spec_t bl32_block_spec = {
+	.offset = BL32_BASE,
+	.length = STM32MP1_BL32_SIZE
+};
+
+static const io_block_spec_t bl2_block_spec = {
+	.offset = BL2_BASE,
+	.length = STM32MP1_BL2_SIZE,
+};
+
+static int open_dummy(const uintptr_t spec);
+
+struct plat_io_policy {
+	uintptr_t *dev_handle;
+	uintptr_t image_spec;
+	int (*check)(const uintptr_t spec);
+};
+
+static const struct plat_io_policy policies[] = {
+	[BL2_IMAGE_ID] = {
+		.dev_handle = &dummy_dev_handle,
+		.image_spec = (uintptr_t)&bl2_block_spec,
+		.check = open_dummy
+	},
+	[BL32_IMAGE_ID] = {
+		.dev_handle = &dummy_dev_handle,
+		.image_spec = (uintptr_t)&bl32_block_spec,
+		.check = open_dummy
+	},
+};
+
+static int open_dummy(const uintptr_t spec)
+{
+	return io_dev_init(dummy_dev_handle, 0);
+}
+
+static void print_boot_device(boot_api_context_t *boot_context)
+{
+	switch (boot_context->boot_interface_selected) {
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
+		INFO("Using SDMMC\n");
+		break;
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
+		INFO("Using EMMC\n");
+		break;
+	default:
+		ERROR("Boot interface not found\n");
+		panic();
+		break;
+	}
+
+	if (boot_context->boot_interface_instance != 0U) {
+		INFO("  Instance %d\n", boot_context->boot_interface_instance);
+	}
+}
+
+static void print_reset_reason(void)
+{
+	uint32_t rstsr = mmio_read_32(RCC_BASE + RCC_MP_RSTSCLRR);
+
+	if (rstsr == 0U) {
+		WARN("Reset reason unknown\n");
+		return;
+	}
+
+	INFO("Reset reason (0x%x):\n", rstsr);
+
+	if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) == 0U) {
+		if ((rstsr & RCC_MP_RSTSCLRR_STDBYRSTF) != 0U) {
+			INFO("System exits from STANDBY\n");
+			return;
+		}
+
+		if ((rstsr & RCC_MP_RSTSCLRR_CSTDBYRSTF) != 0U) {
+			INFO("MPU exits from CSTANDBY\n");
+			return;
+		}
+	}
+
+	if ((rstsr & RCC_MP_RSTSCLRR_PORRSTF) != 0U) {
+		INFO("  Power-on Reset (rst_por)\n");
+		return;
+	}
+
+	if ((rstsr & RCC_MP_RSTSCLRR_BORRSTF) != 0U) {
+		INFO("  Brownout Reset (rst_bor)\n");
+		return;
+	}
+
+	if ((rstsr & RCC_MP_RSTSCLRR_MPSYSRSTF) != 0U) {
+		INFO("  System reset generated by MPU (MPSYSRST)\n");
+		return;
+	}
+
+	if ((rstsr & RCC_MP_RSTSCLRR_HCSSRSTF) != 0U) {
+		INFO("  Reset due to a clock failure on HSE\n");
+		return;
+	}
+
+	if ((rstsr & RCC_MP_RSTSCLRR_IWDG1RSTF) != 0U) {
+		INFO("  IWDG1 Reset (rst_iwdg1)\n");
+		return;
+	}
+
+	if ((rstsr & RCC_MP_RSTSCLRR_IWDG2RSTF) != 0U) {
+		INFO("  IWDG2 Reset (rst_iwdg2)\n");
+		return;
+	}
+
+	if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) != 0U) {
+		INFO("  Pad Reset from NRST\n");
+		return;
+	}
+
+	if ((rstsr & RCC_MP_RSTSCLRR_VCORERSTF) != 0U) {
+		INFO("  Reset due to a failure of VDD_CORE\n");
+		return;
+	}
+
+	ERROR("  Unidentified reset reason\n");
+}
+
+void stm32mp1_io_setup(void)
+{
+	int io_result __unused;
+	boot_api_context_t *boot_context =
+		(boot_api_context_t *)stm32mp1_get_boot_ctx_address();
+
+	print_reset_reason();
+
+	print_boot_device(boot_context);
+
+	if ((boot_context->boot_partition_used_toboot == 1U) ||
+	    (boot_context->boot_partition_used_toboot == 2U)) {
+		INFO("Boot used partition fsbl%d\n",
+		     boot_context->boot_partition_used_toboot);
+	}
+
+	io_result = register_io_dev_dummy(&dummy_dev_con);
+	assert(io_result == 0);
+
+	io_result = io_dev_open(dummy_dev_con, dummy_dev_spec,
+				&dummy_dev_handle);
+	assert(io_result == 0);
+}
+
+/*
+ * Return an IO device handle and specification which can be used to access
+ * an image. Use this to enforce platform load policy.
+ */
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+			  uintptr_t *image_spec)
+{
+	int rc;
+	const struct plat_io_policy *policy;
+
+	assert(image_id < ARRAY_SIZE(policies));
+
+	policy = &policies[image_id];
+	rc = policy->check(policy->image_spec);
+	if (rc == 0) {
+		*image_spec = policy->image_spec;
+		*dev_handle = *(policy->dev_handle);
+	}
+
+	return rc;
+}