summaryrefslogtreecommitdiffstats
path: root/plat/st/stm32mp1
diff options
context:
space:
mode:
Diffstat (limited to 'plat/st/stm32mp1')
-rw-r--r--plat/st/stm32mp1/bl2_plat_setup.c562
-rw-r--r--plat/st/stm32mp1/cert_create_tbbr.mk19
-rw-r--r--plat/st/stm32mp1/include/boot_api.h409
-rw-r--r--plat/st/stm32mp1/include/plat_def_fip_uuid.h14
-rw-r--r--plat/st/stm32mp1/include/plat_tbbr_img_def.h40
-rw-r--r--plat/st/stm32mp1/include/platform_def.h218
-rw-r--r--plat/st/stm32mp1/include/stm32mp1_dbgmcu.h16
-rw-r--r--plat/st/stm32mp1/include/stm32mp1_mbedtls_config.h119
-rw-r--r--plat/st/stm32mp1/include/stm32mp1_private.h38
-rw-r--r--plat/st/stm32mp1/include/stm32mp1_shared_resources.h38
-rw-r--r--plat/st/stm32mp1/include/stm32mp1_smc.h67
-rw-r--r--plat/st/stm32mp1/include/tbbr/stm32mp1_tbb_cert.h19
-rw-r--r--plat/st/stm32mp1/plat_bl2_mem_params_desc.c134
-rw-r--r--plat/st/stm32mp1/plat_def_uuid_config.c18
-rw-r--r--plat/st/stm32mp1/plat_fiptool.mk25
-rw-r--r--plat/st/stm32mp1/plat_image_load.c36
-rw-r--r--plat/st/stm32mp1/platform.mk553
-rw-r--r--plat/st/stm32mp1/services/bsec_svc.c60
-rw-r--r--plat/st/stm32mp1/services/bsec_svc.h19
-rw-r--r--plat/st/stm32mp1/services/stm32mp1_svc_setup.c100
-rw-r--r--plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk53
-rw-r--r--plat/st/stm32mp1/sp_min/sp_min_setup.c197
-rw-r--r--plat/st/stm32mp1/stm32mp1.S11
-rw-r--r--plat/st/stm32mp1/stm32mp1.ld.S71
-rw-r--r--plat/st/stm32mp1/stm32mp1_boot_device.c209
-rw-r--r--plat/st/stm32mp1/stm32mp1_dbgmcu.c74
-rw-r--r--plat/st/stm32mp1/stm32mp1_def.h669
-rw-r--r--plat/st/stm32mp1/stm32mp1_fconf_firewall.c128
-rw-r--r--plat/st/stm32mp1/stm32mp1_fip_def.h138
-rw-r--r--plat/st/stm32mp1/stm32mp1_gic.c92
-rw-r--r--plat/st/stm32mp1/stm32mp1_helper.S336
-rw-r--r--plat/st/stm32mp1/stm32mp1_pm.c243
-rw-r--r--plat/st/stm32mp1/stm32mp1_private.c788
-rw-r--r--plat/st/stm32mp1/stm32mp1_scmi.c479
-rw-r--r--plat/st/stm32mp1/stm32mp1_shared_resources.c596
-rw-r--r--plat/st/stm32mp1/stm32mp1_stack_protector.c22
-rw-r--r--plat/st/stm32mp1/stm32mp1_syscfg.c411
-rw-r--r--plat/st/stm32mp1/stm32mp1_tbb_cert.c37
-rw-r--r--plat/st/stm32mp1/stm32mp1_topology.c57
-rw-r--r--plat/st/stm32mp1/stm32mp1_usb_dfu.c423
40 files changed, 7538 insertions, 0 deletions
diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c
new file mode 100644
index 0000000..4f04a6f
--- /dev/null
+++ b/plat/st/stm32mp1/bl2_plat_setup.c
@@ -0,0 +1,562 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/generic_delay_timer.h>
+#include <drivers/mmc.h>
+#include <drivers/st/bsec.h>
+#include <drivers/st/regulator_fixed.h>
+#include <drivers/st/stm32_iwdg.h>
+#include <drivers/st/stm32_rng.h>
+#include <drivers/st/stm32_uart.h>
+#include <drivers/st/stm32mp1_clk.h>
+#include <drivers/st/stm32mp1_pwr.h>
+#include <drivers/st/stm32mp1_ram.h>
+#include <drivers/st/stm32mp_pmic.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+#include <lib/mmio.h>
+#include <lib/optee_utils.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+
+#include <platform_def.h>
+#include <stm32mp_common.h>
+#include <stm32mp1_dbgmcu.h>
+
+#if DEBUG
+static const char debug_msg[] = {
+ "***************************************************\n"
+ "** DEBUG ACCESS PORT IS OPEN! **\n"
+ "** This boot image is only for debugging purpose **\n"
+ "** and is unsafe for production use. **\n"
+ "** **\n"
+ "** If you see this message and you are not **\n"
+ "** debugging report this immediately to your **\n"
+ "** vendor! **\n"
+ "***************************************************\n"
+};
+#endif
+
+static void print_reset_reason(void)
+{
+ uint32_t rstsr = mmio_read_32(stm32mp_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 STM32MP15
+ if ((rstsr & RCC_MP_RSTSCLRR_MCSYSRSTF) != 0U) {
+ if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) != 0U) {
+ INFO(" System reset generated by MCU (MCSYSRST)\n");
+ } else {
+ INFO(" Local reset generated by MCU (MCSYSRST)\n");
+ }
+ return;
+ }
+#endif
+
+ 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_MPUP0RSTF) != 0U) {
+ INFO(" MPU Processor 0 Reset\n");
+ return;
+ }
+
+#if STM32MP15
+ if ((rstsr & RCC_MP_RSTSCLRR_MPUP1RSTF) != 0U) {
+ INFO(" MPU Processor 1 Reset\n");
+ return;
+ }
+#endif
+
+ 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 bl2_el3_early_platform_setup(u_register_t arg0,
+ u_register_t arg1 __unused,
+ u_register_t arg2 __unused,
+ u_register_t arg3 __unused)
+{
+ stm32mp_setup_early_console();
+
+ stm32mp_save_boot_ctx_address(arg0);
+}
+
+void bl2_platform_setup(void)
+{
+ int ret;
+
+ ret = stm32mp1_ddr_probe();
+ if (ret < 0) {
+ ERROR("Invalid DDR init: error %d\n", ret);
+ panic();
+ }
+
+ /* Map DDR for binary load, now with cacheable attribute */
+ ret = mmap_add_dynamic_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE,
+ STM32MP_DDR_MAX_SIZE, MT_MEMORY | MT_RW | MT_SECURE);
+ if (ret < 0) {
+ ERROR("DDR mapping: error %d\n", ret);
+ panic();
+ }
+}
+
+#if STM32MP15
+static void update_monotonic_counter(void)
+{
+ uint32_t version;
+ uint32_t otp;
+
+ CASSERT(STM32_TF_VERSION <= MAX_MONOTONIC_VALUE,
+ assert_stm32mp1_monotonic_counter_reach_max);
+
+ /* Check if monotonic counter needs to be incremented */
+ if (stm32_get_otp_index(MONOTONIC_OTP, &otp, NULL) != 0) {
+ panic();
+ }
+
+ if (stm32_get_otp_value_from_idx(otp, &version) != 0) {
+ panic();
+ }
+
+ if ((version + 1U) < BIT(STM32_TF_VERSION)) {
+ uint32_t result;
+
+ /* Need to increment the monotonic counter. */
+ version = BIT(STM32_TF_VERSION) - 1U;
+
+ result = bsec_program_otp(version, otp);
+ if (result != BSEC_OK) {
+ ERROR("BSEC: MONOTONIC_OTP program Error %u\n",
+ result);
+ panic();
+ }
+ INFO("Monotonic counter has been incremented (value 0x%x)\n",
+ version);
+ }
+}
+#endif
+
+void bl2_el3_plat_arch_setup(void)
+{
+ const char *board_model;
+ boot_api_context_t *boot_context =
+ (boot_api_context_t *)stm32mp_get_boot_ctx_address();
+ uintptr_t pwr_base;
+ uintptr_t rcc_base;
+
+ if (bsec_probe() != 0U) {
+ panic();
+ }
+
+ mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
+ BL_CODE_END - BL_CODE_BASE,
+ MT_CODE | MT_SECURE);
+
+ /* Prevent corruption of preloaded Device Tree */
+ mmap_add_region(DTB_BASE, DTB_BASE,
+ DTB_LIMIT - DTB_BASE,
+ MT_RO_DATA | MT_SECURE);
+
+ configure_mmu();
+
+ if (dt_open_and_check(STM32MP_DTB_BASE) < 0) {
+ panic();
+ }
+
+ pwr_base = stm32mp_pwr_base();
+ rcc_base = stm32mp_rcc_base();
+
+ /*
+ * Disable the backup domain write protection.
+ * The protection is enable at each reset by hardware
+ * and must be disabled by software.
+ */
+ mmio_setbits_32(pwr_base + PWR_CR1, PWR_CR1_DBP);
+
+ while ((mmio_read_32(pwr_base + PWR_CR1) & PWR_CR1_DBP) == 0U) {
+ ;
+ }
+
+ /* Reset backup domain on cold boot cases */
+ if ((mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_RTCSRC_MASK) == 0U) {
+ mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_VSWRST);
+
+ while ((mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_VSWRST) ==
+ 0U) {
+ ;
+ }
+
+ mmio_clrbits_32(rcc_base + RCC_BDCR, RCC_BDCR_VSWRST);
+ }
+
+#if STM32MP15
+ /* Disable MCKPROT */
+ mmio_clrbits_32(rcc_base + RCC_TZCR, RCC_TZCR_MCKPROT);
+#endif
+
+ /*
+ * Set minimum reset pulse duration to 31ms for discrete power
+ * supplied boards.
+ */
+ if (dt_pmic_status() <= 0) {
+ mmio_clrsetbits_32(rcc_base + RCC_RDLSICR,
+ RCC_RDLSICR_MRD_MASK,
+ 31U << RCC_RDLSICR_MRD_SHIFT);
+ }
+
+ generic_delay_timer_init();
+
+#if STM32MP_UART_PROGRAMMER
+ /* Disable programmer UART before changing clock tree */
+ if (boot_context->boot_interface_selected ==
+ BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART) {
+ uintptr_t uart_prog_addr =
+ get_uart_address(boot_context->boot_interface_instance);
+
+ stm32_uart_stop(uart_prog_addr);
+ }
+#endif
+ if (stm32mp1_clk_probe() < 0) {
+ panic();
+ }
+
+ if (stm32mp1_clk_init() < 0) {
+ panic();
+ }
+
+ stm32_save_boot_interface(boot_context->boot_interface_selected,
+ boot_context->boot_interface_instance);
+ stm32_save_boot_auth(boot_context->auth_status,
+ boot_context->boot_partition_used_toboot);
+
+#if STM32MP_USB_PROGRAMMER && STM32MP15
+ /* Deconfigure all UART RX pins configured by ROM code */
+ stm32mp1_deconfigure_uart_pins();
+#endif
+
+ if (stm32mp_uart_console_setup() != 0) {
+ goto skip_console_init;
+ }
+
+ stm32mp_print_cpuinfo();
+
+ board_model = dt_get_board_model();
+ if (board_model != NULL) {
+ NOTICE("Model: %s\n", board_model);
+ }
+
+ stm32mp_print_boardinfo();
+
+ if (boot_context->auth_status != BOOT_API_CTX_AUTH_NO) {
+ NOTICE("Bootrom authentication %s\n",
+ (boot_context->auth_status == BOOT_API_CTX_AUTH_FAILED) ?
+ "failed" : "succeeded");
+ }
+
+skip_console_init:
+#if !TRUSTED_BOARD_BOOT
+ if (stm32mp_is_closed_device()) {
+ /* Closed chip mandates authentication */
+ ERROR("Secure chip: TRUSTED_BOARD_BOOT must be enabled\n");
+ panic();
+ }
+#endif
+
+ if (fixed_regulator_register() != 0) {
+ panic();
+ }
+
+ if (dt_pmic_status() > 0) {
+ initialize_pmic();
+ if (pmic_voltages_init() != 0) {
+ ERROR("PMIC voltages init failed\n");
+ panic();
+ }
+ print_pmic_info_and_debug();
+ }
+
+ stm32mp1_syscfg_init();
+
+ if (stm32_iwdg_init() < 0) {
+ panic();
+ }
+
+ stm32_iwdg_refresh();
+
+ if (bsec_read_debug_conf() != 0U) {
+ if (stm32mp_is_closed_device()) {
+#if DEBUG
+ WARN("\n%s", debug_msg);
+#else
+ ERROR("***Debug opened on closed chip***\n");
+#endif
+ }
+ }
+
+#if STM32MP13
+ if (stm32_rng_init() != 0) {
+ panic();
+ }
+#endif
+
+ stm32mp1_arch_security_setup();
+
+ print_reset_reason();
+
+#if STM32MP15
+ update_monotonic_counter();
+#endif
+
+ stm32mp1_syscfg_enable_io_compensation_finish();
+
+ fconf_populate("TB_FW", STM32MP_DTB_BASE);
+
+ stm32mp_io_setup();
+}
+
+/*******************************************************************************
+ * This function can be used by the platforms to update/use image
+ * information for given `image_id`.
+ ******************************************************************************/
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+ int err = 0;
+ bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+ bl_mem_params_node_t *bl32_mem_params;
+ bl_mem_params_node_t *pager_mem_params __unused;
+ bl_mem_params_node_t *paged_mem_params __unused;
+ const struct dyn_cfg_dtb_info_t *config_info;
+ bl_mem_params_node_t *tos_fw_mem_params;
+ unsigned int i;
+ unsigned int idx;
+ unsigned long long ddr_top __unused;
+ const unsigned int image_ids[] = {
+ BL32_IMAGE_ID,
+ BL33_IMAGE_ID,
+ HW_CONFIG_ID,
+ TOS_FW_CONFIG_ID,
+ };
+
+ assert(bl_mem_params != NULL);
+
+ switch (image_id) {
+ case FW_CONFIG_ID:
+ /* Set global DTB info for fixed fw_config information */
+ set_config_info(STM32MP_FW_CONFIG_BASE, ~0UL, STM32MP_FW_CONFIG_MAX_SIZE,
+ FW_CONFIG_ID);
+ fconf_populate("FW_CONFIG", STM32MP_FW_CONFIG_BASE);
+
+ idx = dyn_cfg_dtb_info_get_index(TOS_FW_CONFIG_ID);
+
+ /* Iterate through all the fw config IDs */
+ for (i = 0U; i < ARRAY_SIZE(image_ids); i++) {
+ if ((image_ids[i] == TOS_FW_CONFIG_ID) && (idx == FCONF_INVALID_IDX)) {
+ continue;
+ }
+
+ bl_mem_params = get_bl_mem_params_node(image_ids[i]);
+ assert(bl_mem_params != NULL);
+
+ config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, image_ids[i]);
+ if (config_info == NULL) {
+ continue;
+ }
+
+ bl_mem_params->image_info.image_base = config_info->config_addr;
+ bl_mem_params->image_info.image_max_size = config_info->config_max_size;
+
+ bl_mem_params->image_info.h.attr &= ~IMAGE_ATTRIB_SKIP_LOADING;
+
+ switch (image_ids[i]) {
+ case BL32_IMAGE_ID:
+ bl_mem_params->ep_info.pc = config_info->config_addr;
+
+ /* In case of OPTEE, initialize address space with tos_fw addr */
+ pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
+ assert(pager_mem_params != NULL);
+ pager_mem_params->image_info.image_base = config_info->config_addr;
+ pager_mem_params->image_info.image_max_size =
+ config_info->config_max_size;
+
+ /* Init base and size for pager if exist */
+ paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
+ if (paged_mem_params != NULL) {
+ paged_mem_params->image_info.image_base = STM32MP_DDR_BASE +
+ (dt_get_ddr_size() - STM32MP_DDR_S_SIZE -
+ STM32MP_DDR_SHMEM_SIZE);
+ paged_mem_params->image_info.image_max_size =
+ STM32MP_DDR_S_SIZE;
+ }
+ break;
+
+ case BL33_IMAGE_ID:
+ bl_mem_params->ep_info.pc = config_info->config_addr;
+ break;
+
+ case HW_CONFIG_ID:
+ case TOS_FW_CONFIG_ID:
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ }
+ break;
+
+ case BL32_IMAGE_ID:
+ if (optee_header_is_valid(bl_mem_params->image_info.image_base)) {
+ image_info_t *paged_image_info = NULL;
+
+ /* BL32 is OP-TEE header */
+ bl_mem_params->ep_info.pc = bl_mem_params->image_info.image_base;
+ pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
+ assert(pager_mem_params != NULL);
+
+ paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
+ if (paged_mem_params != NULL) {
+ paged_image_info = &paged_mem_params->image_info;
+ }
+
+ err = parse_optee_header(&bl_mem_params->ep_info,
+ &pager_mem_params->image_info,
+ paged_image_info);
+ if (err != 0) {
+ ERROR("OPTEE header parse error.\n");
+ panic();
+ }
+
+ /* Set optee boot info from parsed header data */
+ if (paged_mem_params != NULL) {
+ bl_mem_params->ep_info.args.arg0 =
+ paged_mem_params->image_info.image_base;
+ } else {
+ bl_mem_params->ep_info.args.arg0 = 0U;
+ }
+
+ bl_mem_params->ep_info.args.arg1 = 0U; /* Unused */
+ bl_mem_params->ep_info.args.arg2 = 0U; /* No DT supported */
+ } else {
+ bl_mem_params->ep_info.pc = bl_mem_params->image_info.image_base;
+ tos_fw_mem_params = get_bl_mem_params_node(TOS_FW_CONFIG_ID);
+ assert(tos_fw_mem_params != NULL);
+ bl_mem_params->image_info.image_max_size +=
+ tos_fw_mem_params->image_info.image_max_size;
+ bl_mem_params->ep_info.args.arg0 = 0;
+ }
+ break;
+
+ case BL33_IMAGE_ID:
+ bl32_mem_params = get_bl_mem_params_node(BL32_IMAGE_ID);
+ assert(bl32_mem_params != NULL);
+ bl32_mem_params->ep_info.lr_svc = bl_mem_params->ep_info.pc;
+#if PSA_FWU_SUPPORT
+ stm32mp1_fwu_set_boot_idx();
+#endif /* PSA_FWU_SUPPORT */
+ break;
+
+ default:
+ /* Do nothing in default case */
+ break;
+ }
+
+#if STM32MP_SDMMC || STM32MP_EMMC
+ /*
+ * Invalidate remaining data read from MMC but not flushed by load_image_flush().
+ * We take the worst case which is 2 MMC blocks.
+ */
+ if ((image_id != FW_CONFIG_ID) &&
+ ((bl_mem_params->image_info.h.attr & IMAGE_ATTRIB_SKIP_LOADING) == 0U)) {
+ inv_dcache_range(bl_mem_params->image_info.image_base +
+ bl_mem_params->image_info.image_size,
+ 2U * MMC_BLOCK_SIZE);
+ }
+#endif /* STM32MP_SDMMC || STM32MP_EMMC */
+
+ return err;
+}
+
+void bl2_el3_plat_prepare_exit(void)
+{
+ uint16_t boot_itf = stm32mp_get_boot_itf_selected();
+
+ switch (boot_itf) {
+#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART:
+ case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
+ /* Invalidate the downloaded buffer used with io_memmap */
+ inv_dcache_range(DWL_BUFFER_BASE, DWL_BUFFER_SIZE);
+ break;
+#endif /* STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER */
+ default:
+ /* Do nothing in default case */
+ break;
+ }
+
+ stm32mp1_security_setup();
+}
diff --git a/plat/st/stm32mp1/cert_create_tbbr.mk b/plat/st/stm32mp1/cert_create_tbbr.mk
new file mode 100644
index 0000000..5b1a3ed
--- /dev/null
+++ b/plat/st/stm32mp1/cert_create_tbbr.mk
@@ -0,0 +1,19 @@
+#
+# Copyright (c) 2022, STMicroelectronics - All Rights Reserved
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Override TBBR Cert to update generic certificate
+
+$(eval $(call add_define,PDEF_CERTS))
+
+PLAT_INCLUDE += -I${PLAT_DIR}include
+
+src/stm32mp1_tbb_cert.o: ${PLAT_DIR}stm32mp1_tbb_cert.c
+ ${Q}${HOSTCC} -c ${HOSTCCFLAGS} ${INC_DIR} $< -o $@
+
+PLAT_OBJECTS = src/stm32mp1_tbb_cert.o
+
+OBJECTS += $(PLAT_OBJECTS)
+
diff --git a/plat/st/stm32mp1/include/boot_api.h b/plat/st/stm32mp1/include/boot_api.h
new file mode 100644
index 0000000..1054609
--- /dev/null
+++ b/plat/st/stm32mp1/include/boot_api.h
@@ -0,0 +1,409 @@
+/*
+ * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BOOT_API_H
+#define BOOT_API_H
+
+#include <stdint.h>
+#include <stdio.h>
+
+/*
+ * Possible value of boot context field 'auth_status'
+ */
+#if STM32MP13
+ /* No authentication done */
+#define BOOT_API_CTX_AUTH_NO 0x7CFDD351U
+ /* Authentication done and failed */
+#define BOOT_API_CTX_AUTH_FAILED 0x51330884U
+ /* Authentication done and success */
+#define BOOT_API_CTX_AUTH_SUCCESS 0x67E8CAE1U
+#endif
+#if STM32MP15
+/* No authentication done */
+#define BOOT_API_CTX_AUTH_NO 0x0U
+/* Authentication done and failed */
+#define BOOT_API_CTX_AUTH_FAILED 0x1U
+/* Authentication done and succeeded */
+#define BOOT_API_CTX_AUTH_SUCCESS 0x2U
+#endif
+
+/*
+ * Possible value of boot context field 'boot_interface_sel'
+ */
+
+/* Value of field 'boot_interface_sel' when no boot occurred */
+#define BOOT_API_CTX_BOOT_INTERFACE_SEL_NO 0x0U
+
+/* Boot occurred on SD */
+#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD 0x1U
+
+/* Boot occurred on EMMC */
+#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC 0x2U
+
+/* 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 UART */
+#define BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART 0x5U
+
+/* Boot occurred on USB */
+#define BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB 0x6U
+
+/* Boot occurred on QSPI NAND */
+#define BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI 0x7U
+
+/**
+ * @brief Possible value of boot context field 'EmmcXferStatus'
+ */
+/*
+ * Possible value of boot context field 'emmc_xfer_status'
+ */
+#define BOOT_API_CTX_EMMC_XFER_STATUS_NOT_STARTED 0x0U
+#define BOOT_API_CTX_EMMC_XFER_STATUS_DATAEND_DETECTED 0x1U
+#define BOOT_API_CTX_EMMC_XFER_STATUS_XFER_OVERALL_TIMEOUT_DETECTED 0x2U
+#define BOOT_API_CTX_EMMC_XFER_STATUS_XFER_DATA_TIMEOUT 0x3U
+
+/*
+ * Possible value of boot context field 'emmc_error_status'
+ */
+#define BOOT_API_CTX_EMMC_ERROR_STATUS_NONE 0x0U
+#define BOOT_API_CTX_EMMC_ERROR_STATUS_CMD_TIMEOUT 0x1U
+#define BOOT_API_CTX_EMMC_ERROR_STATUS_ACK_TIMEOUT 0x2U
+#define BOOT_API_CTX_EMMC_ERROR_STATUS_DATA_CRC_FAIL 0x3U
+#define BOOT_API_CTX_EMMC_ERROR_STATUS_NOT_ENOUGH_BOOT_DATA_RX 0x4U
+#define BOOT_API_CTX_EMMC_ERROR_STATUS_HEADER_NOT_FOUND 0x5U
+#define BOOT_API_CTX_EMMC_ERROR_STATUS_HEADER_SIZE_ZERO 0x6U
+#define BOOT_API_CTX_EMMC_ERROR_STATUS_IMAGE_NOT_COMPLETE 0x7U
+#define BOOT_API_CTX_EMMC_ERROR_STATUS_ACK_ERROR 0x8U
+
+/* Image Header related definitions */
+
+/* Definition of header version */
+#if STM32MP13
+#define BOOT_API_HEADER_VERSION 0x00020000U
+#endif
+#if STM32MP15
+#define BOOT_API_HEADER_VERSION 0x00010000U
+#endif
+
+/*
+ * Magic number used to detect header in memory
+ * Its value must be 'S' 'T' 'M' 0x32, i.e 0x324D5453 as field
+ * 'bootapi_image_header_t.magic'
+ * This identifies the start of a boot image.
+ */
+#define BOOT_API_IMAGE_HEADER_MAGIC_NB 0x324D5453U
+
+/* Definitions related to Authentication used in image header structure */
+#define BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES 64
+#define BOOT_API_ECDSA_SIGNATURE_LEN_IN_BYTES 64
+#define BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES 32
+
+/* Possible values of the field 'boot_api_image_header_t.ecc_algo_type' */
+#define BOOT_API_ECDSA_ALGO_TYPE_P256NIST 1
+#define BOOT_API_ECDSA_ALGO_TYPE_BRAINPOOL256 2
+
+/*
+ * Extension headers related definitions
+ */
+/* 'bootapi_image_header_t.extension_flag' used for authentication feature */
+#define BOOT_API_AUTHENTICATION_EXTENSION_BIT BIT(0)
+/* 'bootapi_image_header_t.extension_flag' used for FSBL decryption feature */
+#define BOOT_API_FSBL_DECRYPTION_EXTENSION_BIT BIT(1)
+/* 'bootapi_image_header_t.extension_flag' used for padding header feature */
+#define BOOT_API_PADDING_EXTENSION_BIT BIT(31)
+/*
+ * mask of bits of field 'bootapi_image_header_t.extension_flag'
+ * used for extension headers
+ */
+#define BOOT_API_ALL_EXTENSIONS_MASK \
+ (BOOT_API_AUTHENTICATION_EXTENSION_BIT | \
+ BOOT_API_FSBL_DECRYPTION_EXTENSION_BIT | \
+ BOOT_API_PADDING_EXTENSION_BIT)
+/*
+ * Magic number of FSBL decryption extension header
+ * The value shall gives the four bytes 'S','T',0x00,0x01 in memory
+ */
+#define BOOT_API_FSBL_DECRYPTION_HEADER_MAGIC_NB 0x01005453U
+
+/*
+ * Magic number of PKH revocation extension header
+ * The value shall gives the four bytes 'S','T',0x00,0x02 in memory
+ */
+#define BOOT_API_AUTHENTICATION_HEADER_MAGIC_NB 0x02005453U
+
+/* Max number of ECDSA public key hash in table */
+#define BOOT_API_AUTHENTICATION_NB_PKH_MAX 8U
+
+/* ECDSA public key hash table size in bytes */
+#define BOOT_API_AUTHENTICATION_TABLE_SIZE_BYTES \
+ (BOOT_API_AUTHENTICATION_NB_PKH_MAX * \
+ BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES)
+
+/*
+ * Magic number of padding extension header
+ * The value shall gives the four bytes 'S','T',0xFF,0xFF in memory
+ */
+#define BOOT_API_PADDING_HEADER_MAGIC_NB 0xFFFF5453U
+
+/*
+ * Cores secure magic numbers
+ * Constant to be stored in bakcup register
+ * BOOT_API_MAGIC_NUMBER_TAMP_BCK_REG_IDX
+ */
+#define BOOT_API_A7_CORE0_MAGIC_NUMBER 0xCA7FACE0U
+#define BOOT_API_A7_CORE1_MAGIC_NUMBER 0xCA7FACE1U
+
+/*
+ * TAMP_BCK4R register index
+ * This register is used to write a Magic Number in order to restart
+ * Cortex A7 Core 1 and make it execute @ branch address from TAMP_BCK5R
+ */
+#define BOOT_API_CORE1_MAGIC_NUMBER_TAMP_BCK_REG_IDX 4U
+
+/*
+ * TAMP_BCK5R register index
+ * This register is used to contain the branch address of
+ * Cortex A7 Core 1 when restarted by a TAMP_BCK4R magic number writing
+ */
+#define BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX 5U
+
+/*
+ * Possible value of boot context field 'hse_clock_value_in_hz'
+ */
+#define BOOT_API_CTX_HSE_CLOCK_VALUE_UNDEFINED 0U
+#define BOOT_API_CTX_HSE_CLOCK_VALUE_24_MHZ 24000000U
+#define BOOT_API_CTX_HSE_CLOCK_VALUE_25_MHZ 25000000U
+#define BOOT_API_CTX_HSE_CLOCK_VALUE_26_MHZ 26000000U
+
+/*
+ * Possible value of boot context field 'boot_partition_used_toboot'
+ */
+#define BOOT_API_CTX_BOOT_PARTITION_UNDEFINED 0U
+
+/* Used FSBL1 to boot */
+#define BOOT_API_CTX_BOOT_PARTITION_FSBL1 1U
+
+/* Used FSBL2 to boot */
+#define BOOT_API_CTX_BOOT_PARTITION_FSBL2 2U
+
+/* OTP_CFG0 */
+#define BOOT_API_OTP_MODE_WORD_NB 0
+/* Closed = OTP_CFG0[6] */
+#define BOOT_API_OTP_MODE_CLOSED_BIT_POS 6
+
+#define BOOT_API_RETURN_OK 0x77U
+
+/*
+ * Boot Context related definitions
+ */
+
+/*
+ * Boot core boot configuration structure
+ * Specifies all items of the cold boot configuration
+ * Memory and peripheral part.
+ */
+typedef struct {
+ /*
+ * Boot interface used to boot : take values from defines
+ * BOOT_API_CTX_BOOT_INTERFACE_SEL_XXX above
+ */
+ uint16_t boot_interface_selected;
+ uint16_t boot_interface_instance;
+#if STM32MP13
+ uint32_t reserved1[12];
+#endif
+#if STM32MP15
+ uint32_t reserved1[13];
+#endif
+ uint32_t otp_afmux_values[3];
+ uint32_t reserved[3];
+#if STM32MP15
+ uint32_t reserved2[2];
+#endif
+ uint32_t auth_status;
+
+#if STM32MP15
+ /*
+ * Pointers to bootROM External Secure Services
+ * - ECDSA verify signature
+ */
+ uint32_t reserved3;
+ uint32_t (*bootrom_ecdsa_verify_signature)(uint8_t *hash_in,
+ uint8_t *pubkey_in,
+ uint8_t *signature,
+ uint32_t ecc_algo);
+ uint32_t reserved4;
+#endif
+ /*
+ * Information specific to an SD boot
+ * Updated each time an SD boot is at least attempted,
+ * even if not successful
+ * Note : This is useful to understand why an SD boot failed
+ * in particular
+ */
+ uint32_t sd_err_internal_timeout_cnt;
+ uint32_t sd_err_dcrc_fail_cnt;
+ uint32_t sd_err_dtimeout_cnt;
+ uint32_t sd_err_ctimeout_cnt;
+ uint32_t sd_err_ccrc_fail_cnt;
+ uint32_t sd_overall_retry_cnt;
+ /*
+ * Information specific to an eMMC boot
+ * Updated each time an eMMC boot is at least attempted,
+ * even if not successful
+ * Note : This is useful to understand why an eMMC boot failed
+ * in particular
+ */
+ uint32_t emmc_xfer_status;
+ uint32_t emmc_error_status;
+ uint32_t emmc_nbbytes_rxcopied_tosysram_download_area;
+ uint32_t hse_clock_value_in_hz;
+ /*
+ * Boot partition :
+ * ie FSBL partition on which the boot was successful
+ */
+ uint32_t boot_partition_used_toboot;
+
+} __packed boot_api_context_t;
+
+/*
+ * Image Header related definitions
+ */
+
+/*
+ * Structure used to define the common Header format used for FSBL, xloader,
+ * ... and in particular used by bootROM for FSBL header readout.
+ * FSBL header size is 256 Bytes = 0x100
+ */
+typedef struct {
+ /* BOOT_API_IMAGE_HEADER_MAGIC_NB */
+ uint32_t magic;
+ uint8_t image_signature[BOOT_API_ECDSA_SIGNATURE_LEN_IN_BYTES];
+ /*
+ * Checksum of payload
+ * 32-bit sum all payload bytes considered as 8 bit unsigned
+ * numbers, discarding any overflow bits.
+ * Use to check UART/USB downloaded image integrity when signature
+ * is not used
+ */
+ uint32_t payload_checksum;
+ /* Image header version : should have value BOOT_API_HEADER_VERSION */
+ uint32_t header_version;
+ /* Image length in bytes */
+ uint32_t image_length;
+ /*
+ * Image Entry point address : should be in the SYSRAM area
+ * and at least within the download area range
+ */
+ uint32_t image_entry_point;
+ /* Reserved */
+ uint32_t reserved1;
+ /*
+ * Image load address : not used by bootROM but to be consistent
+ * with header format for other packages (xloader, ...)
+ */
+ uint32_t load_address;
+ /* Reserved */
+ uint32_t reserved2;
+ /* Image version to be compared by bootROM with monotonic
+ * counter value in OTP_CFG4 prior executing the downloaded image
+ */
+ uint32_t image_version;
+
+#if STM32MP13
+ /*
+ * Extension flags :
+ *
+ * Bit 0 : Authentication extension header
+ * value 0 : No signature check request
+ * Bit 1 : Encryption extension header
+ * Bit 2 : Padding extension header
+ */
+ uint32_t extension_flags;
+ /* Length in bytes of all extension headers */
+ uint32_t extension_headers_length;
+ /* Add binary type information */
+ uint32_t binary_type;
+ /* Pad up to 128 byte total size */
+ uint8_t pad[16];
+ /* Followed by extension header */
+ uint8_t ext_header[];
+#endif
+#if STM32MP15
+ /*
+ * Option flags:
+ * Bit 0 : No signature check request : 'No_sig_check'
+ * value 1 : for No signature check request
+ * value 0 : No request to bypass the signature check
+ * Note : No signature check is never allowed on a Secured chip
+ */
+ uint32_t option_flags;
+ /*
+ * Type of ECC algorithm to use :
+ * value 1 : for P-256 NIST algorithm
+ * value 2 : for Brainpool 256 algorithm
+ * See definitions 'BOOT_API_ECDSA_ALGO_TYPE_XXX' above.
+ */
+ uint32_t ecc_algo_type;
+ /*
+ * OEM ECC Public Key (aka Root pubk) provided in header on 512 bits.
+ * The SHA-256 hash of the OEM ECC pubk must match the one stored
+ * in OTP cells.
+ */
+ uint8_t ecc_pubk[BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES];
+ /* Pad up to 256 byte total size */
+ uint8_t pad[83];
+ /* Add binary type information */
+ uint8_t binary_type;
+#endif
+} __packed boot_api_image_header_t;
+
+typedef uint8_t boot_api_sha256_t[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES];
+
+typedef struct {
+ /* Extension header type:
+ * BOOT_API_FSBL_DECRYPTION_HEADER_MAGIC_NB or
+ * BOOT_API_AUTHENTICATION_HEADER_MAGIC_NB
+ * BOOT_API_PADDING_HEADER_MAGIC_NB
+ */
+ uint32_t type;
+ /* Extension header len in byte */
+ uint32_t len;
+ /* parameters of this extension */
+ uint8_t params[];
+} __packed boot_extension_header_t;
+
+typedef struct {
+ /* Idx of ECDSA public key to be used in table */
+ uint32_t pk_idx;
+ /* Number of ECDSA public key in table */
+ uint32_t nb_pk;
+ /*
+ * Type of ECC algorithm to use :
+ * value 1 : for P-256 NIST algorithm
+ * value 2 : for Brainpool 256 algorithm
+ * See definitions 'BOOT_API_ECDSA_ALGO_TYPE_XXX' above.
+ */
+ uint32_t ecc_algo_type;
+ /* ECDSA public key to be used to check signature. */
+ uint8_t ecc_pubk[BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES];
+ /* table of Hash of Algo+ECDSA public key */
+ boot_api_sha256_t pk_hashes[];
+} __packed boot_ext_header_params_authentication_t;
+
+typedef struct {
+ /* Size of encryption key (128 or 256) */
+ uint32_t key_size;
+ uint32_t derivation_cont;
+ /* 128 msb bits of plain payload SHA256 */
+ uint32_t hash[4];
+} __packed boot_ext_header_params_encrypted_fsbl_t;
+
+#endif /* BOOT_API_H */
diff --git a/plat/st/stm32mp1/include/plat_def_fip_uuid.h b/plat/st/stm32mp1/include/plat_def_fip_uuid.h
new file mode 100644
index 0000000..e5fbc2d
--- /dev/null
+++ b/plat/st/stm32mp1/include/plat_def_fip_uuid.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_DEF_FIP_UUID_H
+#define PLAT_DEF_FIP_UUID_H
+
+#define UUID_STM32MP_CONFIG_CERT \
+ {{0x50, 0x1d, 0x8d, 0xd2}, {0x8b, 0xce}, {0x49, 0xa5}, 0x84, 0xeb, \
+ {0x55, 0x9a, 0x9f, 0x2e, 0xae, 0xaf} }
+#endif /* PLAT_DEF_FIP_UUID_H */
+
diff --git a/plat/st/stm32mp1/include/plat_tbbr_img_def.h b/plat/st/stm32mp1/include/plat_tbbr_img_def.h
new file mode 100644
index 0000000..984aae8
--- /dev/null
+++ b/plat/st/stm32mp1/include/plat_tbbr_img_def.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef STM32MP1_IMG_DEF_H
+#define STM32MP1_IMG_DEF_H
+
+#include <export/common/tbbr/tbbr_img_def_exp.h>
+
+/* Undef the existing values */
+#undef BL32_EXTRA1_IMAGE_ID
+#undef BL32_EXTRA2_IMAGE_ID
+#undef TOS_FW_CONFIG_ID
+#undef TRUSTED_BOOT_FW_CERT_ID
+#undef FWU_METADATA_IMAGE_ID
+#undef BKUP_FWU_METADATA_IMAGE_ID
+#undef FW_CONFIG_ID
+#undef HW_CONFIG_ID
+#undef GPT_IMAGE_ID
+#undef ENC_IMAGE_ID
+
+/* Define the STM32MP1 used ID */
+#define FW_CONFIG_ID U(1)
+#define HW_CONFIG_ID U(2)
+#define GPT_IMAGE_ID U(3)
+#define ENC_IMAGE_ID U(6)
+#define BL32_EXTRA1_IMAGE_ID U(8)
+#define BL32_EXTRA2_IMAGE_ID U(9)
+#define FWU_METADATA_IMAGE_ID U(12)
+#define BKUP_FWU_METADATA_IMAGE_ID U(13)
+#define TOS_FW_CONFIG_ID U(16)
+#define STM32MP_CONFIG_CERT_ID U(17)
+
+/* Increase the MAX_NUMBER_IDS to match the authentication pool required */
+#define MAX_NUMBER_IDS U(19)
+
+#endif /* STM32MP1_IMG_DEF_H */
diff --git a/plat/st/stm32mp1/include/platform_def.h b/plat/st/stm32mp1/include/platform_def.h
new file mode 100644
index 0000000..61b847f
--- /dev/null
+++ b/plat/st/stm32mp1/include/platform_def.h
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include <drivers/arm/gic_common.h>
+#include <lib/utils_def.h>
+#include <plat/common/common_def.h>
+
+#include "../stm32mp1_def.h"
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* Size of cacheable stacks */
+#if defined(IMAGE_BL32)
+#define PLATFORM_STACK_SIZE 0x600
+#else
+#define PLATFORM_STACK_SIZE 0xC00
+#endif
+
+#define FIP_IMAGE_NAME "fip"
+#define METADATA_PART_1 "metadata1"
+#define METADATA_PART_2 "metadata2"
+
+#define STM32MP_PRIMARY_CPU U(0x0)
+#define STM32MP_SECONDARY_CPU U(0x1)
+
+#define PLATFORM_CLUSTER_COUNT U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT U(2)
+#define PLATFORM_CLUSTER1_CORE_COUNT U(0)
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \
+ PLATFORM_CLUSTER0_CORE_COUNT)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER 2
+
+#define MAX_IO_DEVICES U(4)
+#define MAX_IO_HANDLES U(4)
+#define MAX_IO_BLOCK_DEVICES U(1)
+#define MAX_IO_MTD_DEVICES U(1)
+
+/*******************************************************************************
+ * BL2 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL2 just below BL3-1. BL2_BASE is calculated using the current BL2 debug
+ * size plus a little space for growth.
+ */
+#define BL2_BASE STM32MP_BL2_BASE
+#define BL2_LIMIT (STM32MP_BL2_BASE + \
+ STM32MP_BL2_SIZE)
+
+#define BL2_RO_BASE STM32MP_BL2_RO_BASE
+#define BL2_RO_LIMIT (STM32MP_BL2_RO_BASE + \
+ STM32MP_BL2_RO_SIZE)
+
+#define BL2_RW_BASE STM32MP_BL2_RW_BASE
+#define BL2_RW_LIMIT (STM32MP_BL2_RW_BASE + \
+ STM32MP_BL2_RW_SIZE)
+/*******************************************************************************
+ * BL32 specific defines.
+ ******************************************************************************/
+#if defined(IMAGE_BL32)
+#if ENABLE_PIE
+#define BL32_BASE 0
+#define BL32_LIMIT STM32MP_BL32_SIZE
+#else
+#define BL32_BASE STM32MP_BL32_BASE
+#define BL32_LIMIT (STM32MP_BL32_BASE + \
+ STM32MP_BL32_SIZE)
+#endif
+#endif /* defined(IMAGE_BL32) */
+
+/*******************************************************************************
+ * BL33 specific defines.
+ ******************************************************************************/
+#define BL33_BASE STM32MP_BL33_BASE
+
+/*
+ * Load address of BL33 for this platform port
+ */
+#define PLAT_STM32MP_NS_IMAGE_OFFSET BL33_BASE
+
+/* Needed by STM32CubeProgrammer support */
+#define DWL_BUFFER_SIZE U(0x01000000)
+
+/*
+ * 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.
+ ******************************************************************************/
+#define DTB_BASE STM32MP_DTB_BASE
+#define DTB_LIMIT (STM32MP_DTB_BASE + \
+ STM32MP_DTB_SIZE)
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32)
+
+/*******************************************************************************
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * aligned on the biggest cache line size in the platform. This is known only
+ * to the platform as it might have a combination of integrated and external
+ * caches. Such alignment ensures that two maiboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT 6
+#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT)
+
+/*
+ * Secure Interrupt: based on the standard ARM mapping
+ */
+#define ARM_IRQ_SEC_PHY_TIMER U(29)
+
+#define ARM_IRQ_SEC_SGI_0 U(8)
+#define ARM_IRQ_SEC_SGI_1 U(9)
+#define ARM_IRQ_SEC_SGI_2 U(10)
+#define ARM_IRQ_SEC_SGI_3 U(11)
+#define ARM_IRQ_SEC_SGI_4 U(12)
+#define ARM_IRQ_SEC_SGI_5 U(13)
+#define ARM_IRQ_SEC_SGI_6 U(14)
+#define ARM_IRQ_SEC_SGI_7 U(15)
+
+#define STM32MP1_IRQ_TZC400 U(36)
+#define STM32MP1_IRQ_TAMPSERRS U(229)
+#define STM32MP1_IRQ_AXIERRIRQ U(244)
+
+/*
+ * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLATFORM_G1S_PROPS(grp) \
+ INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, \
+ GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(STM32MP1_IRQ_AXIERRIRQ, \
+ GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(STM32MP1_IRQ_TZC400, \
+ GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, \
+ GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, \
+ GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, \
+ GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, \
+ GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, \
+ GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, \
+ GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_EDGE)
+
+#define PLATFORM_G0_PROPS(grp) \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_0, \
+ GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, \
+ GIC_HIGHEST_SEC_PRIORITY, \
+ grp, GIC_INTR_CFG_EDGE)
+
+/*
+ * Power
+ */
+#define PLAT_MAX_PWR_LVL U(1)
+
+/* Local power state for power domains in Run state. */
+#define ARM_LOCAL_STATE_RUN U(0)
+/* Local power state for retention. Valid only for CPU power domains */
+#define ARM_LOCAL_STATE_RET U(1)
+/* Local power state for power-down. Valid for CPU and cluster power domains */
+#define ARM_LOCAL_STATE_OFF U(2)
+/*
+ * This macro defines the deepest retention state possible.
+ * A higher state id will represent an invalid or a power down state.
+ */
+#define PLAT_MAX_RET_STATE ARM_LOCAL_STATE_RET
+/*
+ * This macro defines the deepest power down states possible. Any state ID
+ * higher than this is invalid.
+ */
+#define PLAT_MAX_OFF_STATE ARM_LOCAL_STATE_OFF
+
+/*******************************************************************************
+ * Size of the per-cpu data in bytes that should be reserved in the generic
+ * per-cpu data structure for the FVP port.
+ ******************************************************************************/
+#define PLAT_PCPU_DATA_SIZE 2
+
+/*******************************************************************************
+ * Number of parallel entry slots in SMT SCMI server entry context. For this
+ * platform, SCMI server is reached through SMC only, hence the number of
+ * entry slots.
+ ******************************************************************************/
+#define PLAT_SMT_ENTRY_COUNT PLATFORM_CORE_COUNT
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h b/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h
new file mode 100644
index 0000000..3663bce
--- /dev/null
+++ b/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2015-2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP1_DBGMCU_H
+#define STM32MP1_DBGMCU_H
+
+#include <stdint.h>
+
+/* Get chip version and ID from DBGMCU registers */
+int stm32mp1_dbgmcu_get_chip_version(uint32_t *chip_version);
+int stm32mp1_dbgmcu_get_chip_dev_id(uint32_t *chip_dev_id);
+
+#endif /* STM32MP1_DBGMCU_H */
diff --git a/plat/st/stm32mp1/include/stm32mp1_mbedtls_config.h b/plat/st/stm32mp1/include/stm32mp1_mbedtls_config.h
new file mode 100644
index 0000000..2f07621
--- /dev/null
+++ b/plat/st/stm32mp1/include/stm32mp1_mbedtls_config.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef MBEDTLS_CONFIG_H
+#define MBEDTLS_CONFIG_H
+
+/*
+ * Key algorithms currently supported on mbed TLS libraries
+ */
+#define TF_MBEDTLS_USE_RSA 0
+#define TF_MBEDTLS_USE_ECDSA 1
+
+/*
+ * Hash algorithms currently supported on mbed TLS libraries
+ */
+#define TF_MBEDTLS_SHA256 1
+#define TF_MBEDTLS_SHA384 2
+#define TF_MBEDTLS_SHA512 3
+
+/*
+ * Configuration file to build mbed TLS with the required features for
+ * Trusted Boot
+ */
+
+#define MBEDTLS_PLATFORM_MEMORY
+#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
+/* Prevent mbed TLS from using snprintf so that it can use tf_snprintf. */
+#define MBEDTLS_PLATFORM_SNPRINTF_ALT
+
+#define MBEDTLS_PKCS1_V21
+
+#define MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
+#define MBEDTLS_X509_CHECK_KEY_USAGE
+#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE
+
+#define MBEDTLS_ASN1_PARSE_C
+#define MBEDTLS_ASN1_WRITE_C
+
+#define MBEDTLS_BASE64_C
+#define MBEDTLS_BIGNUM_C
+
+#define MBEDTLS_ERROR_C
+#define MBEDTLS_MD_C
+
+#define MBEDTLS_MEMORY_BUFFER_ALLOC_C
+#define MBEDTLS_OID_C
+
+#define MBEDTLS_PK_C
+#define MBEDTLS_PK_PARSE_C
+#define MBEDTLS_PK_WRITE_C
+
+#define MBEDTLS_PLATFORM_C
+
+#if TF_MBEDTLS_USE_ECDSA
+#define MBEDTLS_ECDSA_C
+#define MBEDTLS_ECP_C
+#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
+#define MBEDTLS_ECP_NO_INTERNAL_RNG
+#endif
+#if TF_MBEDTLS_USE_RSA
+#define MBEDTLS_RSA_C
+#define MBEDTLS_X509_RSASSA_PSS_SUPPORT
+#endif
+
+#define MBEDTLS_SHA256_C
+#if (TF_MBEDTLS_HASH_ALG_ID != TF_MBEDTLS_SHA256)
+#define MBEDTLS_SHA512_C
+#endif
+
+#define MBEDTLS_VERSION_C
+
+#define MBEDTLS_X509_USE_C
+#define MBEDTLS_X509_CRT_PARSE_C
+
+#if TF_MBEDTLS_USE_AES_GCM
+#define MBEDTLS_AES_C
+#define MBEDTLS_CIPHER_C
+#define MBEDTLS_GCM_C
+#endif
+
+/* MPI / BIGNUM options */
+#define MBEDTLS_MPI_WINDOW_SIZE 2
+
+#if TF_MBEDTLS_USE_RSA
+#if TF_MBEDTLS_KEY_SIZE <= 2048
+#define MBEDTLS_MPI_MAX_SIZE 256
+#else
+#define MBEDTLS_MPI_MAX_SIZE 512
+#endif
+#else
+#define MBEDTLS_MPI_MAX_SIZE 256
+#endif
+
+/* Memory buffer allocator options */
+#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 8
+
+/*
+ * Prevent the use of 128-bit division which
+ * creates dependency on external libraries.
+ */
+#define MBEDTLS_NO_UDBL_DIVISION
+
+#ifndef __ASSEMBLER__
+/* System headers required to build mbed TLS with the current configuration */
+#include <stdlib.h>
+#include <mbedtls/check_config.h>
+#endif
+
+/*
+ * Mbed TLS heap size is smal as we only use the asn1
+ * parsing functions
+ * digest, signature and crypto algorithm are done by
+ * other library.
+ */
+
+#define TF_MBEDTLS_HEAP_SIZE U(5120)
+#endif /* MBEDTLS_CONFIG_H */
diff --git a/plat/st/stm32mp1/include/stm32mp1_private.h b/plat/st/stm32mp1/include/stm32mp1_private.h
new file mode 100644
index 0000000..21ef60d
--- /dev/null
+++ b/plat/st/stm32mp1/include/stm32mp1_private.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP1_PRIVATE_H
+#define STM32MP1_PRIVATE_H
+
+#include <stdint.h>
+
+void configure_mmu(void);
+
+void stm32mp1_arch_security_setup(void);
+void stm32mp1_security_setup(void);
+
+void stm32mp1_gic_pcpu_init(void);
+void stm32mp1_gic_init(void);
+
+void stm32mp1_syscfg_init(void);
+void stm32mp1_syscfg_enable_io_compensation_start(void);
+void stm32mp1_syscfg_enable_io_compensation_finish(void);
+void stm32mp1_syscfg_disable_io_compensation(void);
+uint32_t stm32mp1_syscfg_get_chip_version(void);
+uint32_t stm32mp1_syscfg_get_chip_dev_id(void);
+#if STM32MP13
+void stm32mp1_syscfg_boot_mode_enable(void);
+void stm32mp1_syscfg_boot_mode_disable(void);
+#endif
+#if STM32MP15
+static inline void stm32mp1_syscfg_boot_mode_enable(void){}
+static inline void stm32mp1_syscfg_boot_mode_disable(void){}
+#endif
+
+void stm32mp1_deconfigure_uart_pins(void);
+
+void stm32mp1_init_scmi_server(void);
+#endif /* STM32MP1_PRIVATE_H */
diff --git a/plat/st/stm32mp1/include/stm32mp1_shared_resources.h b/plat/st/stm32mp1/include/stm32mp1_shared_resources.h
new file mode 100644
index 0000000..3f6367e
--- /dev/null
+++ b/plat/st/stm32mp1/include/stm32mp1_shared_resources.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP1_SHARED_RESOURCES_H
+#define STM32MP1_SHARED_RESOURCES_H
+
+#include <stm32mp_shared_resources.h>
+
+#define STM32MP1_SHRES_GPIOZ(i) (STM32MP1_SHRES_GPIOZ_0 + (i))
+
+enum stm32mp_shres {
+ STM32MP1_SHRES_CRYP1,
+ STM32MP1_SHRES_GPIOZ_0,
+ STM32MP1_SHRES_GPIOZ_1,
+ STM32MP1_SHRES_GPIOZ_2,
+ STM32MP1_SHRES_GPIOZ_3,
+ STM32MP1_SHRES_GPIOZ_4,
+ STM32MP1_SHRES_GPIOZ_5,
+ STM32MP1_SHRES_GPIOZ_6,
+ STM32MP1_SHRES_GPIOZ_7,
+ STM32MP1_SHRES_HASH1,
+ STM32MP1_SHRES_I2C4,
+ STM32MP1_SHRES_I2C6,
+ STM32MP1_SHRES_IWDG1,
+ STM32MP1_SHRES_MCU,
+ STM32MP1_SHRES_MDMA,
+ STM32MP1_SHRES_PLL3,
+ STM32MP1_SHRES_RNG1,
+ STM32MP1_SHRES_RTC,
+ STM32MP1_SHRES_SPI6,
+ STM32MP1_SHRES_USART1,
+
+ STM32MP1_SHRES_COUNT
+};
+#endif /* STM32MP1_SHARED_RESOURCES_H */
diff --git a/plat/st/stm32mp1/include/stm32mp1_smc.h b/plat/st/stm32mp1/include/stm32mp1_smc.h
new file mode 100644
index 0000000..52088de
--- /dev/null
+++ b/plat/st/stm32mp1/include/stm32mp1_smc.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2016-2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP1_SMC_H
+#define STM32MP1_SMC_H
+
+/*
+ * SMC function IDs for STM32 Service queries
+ * STM32 SMC services use the space between 0x82000000 and 0x8200FFFF
+ * like this is defined in SMC calling Convention by ARM
+ * for SiP (silicon Partner)
+ * https://developer.arm.com/docs/den0028/latest
+ */
+
+/* Secure Service access from Non-secure */
+
+/*
+ * STM32_SMC_BSEC call API
+ *
+ * Argument a0: (input) SMCC ID
+ * (output) status return code
+ * Argument a1: (input) Service ID (STM32_SMC_BSEC_xxx)
+ * Argument a2: (input) OTP index
+ * (output) OTP read value, if applicable
+ * Argument a3: (input) OTP value if applicable
+ */
+#define STM32_SMC_BSEC 0x82001003
+
+/*
+ * STM32_SIP_SMC_SCMI_AGENT0
+ * STM32_SIP_SMC_SCMI_AGENT1
+ * Process SCMI message pending in SCMI shared memory buffer.
+ *
+ * Argument a0: (input) SMCC ID
+ */
+#define STM32_SIP_SMC_SCMI_AGENT0 0x82002000
+#define STM32_SIP_SMC_SCMI_AGENT1 0x82002001
+
+/* SMC function IDs for SiP Service queries */
+#define STM32_SIP_SVC_CALL_COUNT 0x8200ff00
+#define STM32_SIP_SVC_UID 0x8200ff01
+/* 0x8200ff02 is reserved */
+#define STM32_SIP_SVC_VERSION 0x8200ff03
+
+/* STM32 SiP Service Calls version numbers */
+#define STM32_SIP_SVC_VERSION_MAJOR 0x0
+#define STM32_SIP_SVC_VERSION_MINOR 0x1
+
+/* Number of STM32 SiP Calls implemented */
+#define STM32_COMMON_SIP_NUM_CALLS 3
+
+/* Service for BSEC */
+#define STM32_SMC_READ_SHADOW 0x01
+#define STM32_SMC_PROG_OTP 0x02
+#define STM32_SMC_WRITE_SHADOW 0x03
+#define STM32_SMC_READ_OTP 0x04
+
+/* SMC error codes */
+#define STM32_SMC_OK 0x00000000U
+#define STM32_SMC_NOT_SUPPORTED 0xFFFFFFFFU
+#define STM32_SMC_FAILED 0xFFFFFFFEU
+#define STM32_SMC_INVALID_PARAMS 0xFFFFFFFDU
+
+#endif /* STM32MP1_SMC_H */
diff --git a/plat/st/stm32mp1/include/tbbr/stm32mp1_tbb_cert.h b/plat/st/stm32mp1/include/tbbr/stm32mp1_tbb_cert.h
new file mode 100644
index 0000000..2cc1e19
--- /dev/null
+++ b/plat/st/stm32mp1/include/tbbr/stm32mp1_tbb_cert.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP1_TBB_CERT_H
+#define STM32MP1_TBB_CERT_H
+
+#include <tbbr/tbb_cert.h>
+
+/*
+ * Enumerate the certificates that are used to establish the chain of trust
+ */
+enum {
+ STM32MP_CONFIG_CERT = FWU_CERT + 1
+};
+
+#endif /* STM32MP1_TBB_CERT_H */
diff --git a/plat/st/stm32mp1/plat_bl2_mem_params_desc.c b/plat/st/stm32mp1/plat_bl2_mem_params_desc.c
new file mode 100644
index 0000000..9ca0930
--- /dev/null
+++ b/plat/st/stm32mp1/plat_bl2_mem_params_desc.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <plat/common/platform.h>
+
+#include <platform_def.h>
+
+/*******************************************************************************
+ * Following descriptor provides BL image/ep information that gets used
+ * by BL2 to load the images and also subset of this information is
+ * passed to next BL image. The image loading sequence is managed by
+ * populating the images in required loading order. The image execution
+ * sequence is managed by populating the `next_handoff_image_id` with
+ * the next executable image id.
+ ******************************************************************************/
+static bl_mem_params_node_t bl2_mem_params_descs[] = {
+ /* Fill FW_CONFIG related information if it exists */
+ {
+ .image_id = FW_CONFIG_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+ VERSION_2, entry_point_info_t,
+ SECURE | NON_EXECUTABLE),
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_PLAT_SETUP),
+
+ .image_info.image_base = STM32MP_FW_CONFIG_BASE,
+ .image_info.image_max_size = STM32MP_FW_CONFIG_MAX_SIZE,
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+
+ /* Fill BL32 related information */
+ {
+ .image_id = BL32_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | EXECUTABLE | EP_FIRST_EXE),
+
+ .ep_info.spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM,
+ SPSR_E_LITTLE,
+ DISABLE_ALL_EXCEPTIONS),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_SKIP_LOADING),
+
+ .next_handoff_image_id = BL33_IMAGE_ID,
+ },
+
+ /* Fill BL32 external 1 image related information */
+ {
+ .image_id = BL32_EXTRA1_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_SKIP_LOADING),
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+#if STM32MP15
+ /* Fill BL32 external 2 image related information */
+ {
+ .image_id = BL32_EXTRA2_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ SECURE | NON_EXECUTABLE),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_SKIP_LOADING),
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+#endif
+
+ /* Fill HW_CONFIG related information if it exists */
+ {
+ .image_id = HW_CONFIG_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+ VERSION_2, entry_point_info_t,
+ NON_SECURE | NON_EXECUTABLE),
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_SKIP_LOADING),
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+
+ /* Fill TOS_FW_CONFIG related information if it exists */
+ {
+ .image_id = TOS_FW_CONFIG_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+ VERSION_2, entry_point_info_t,
+ SECURE | NON_EXECUTABLE),
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_SKIP_LOADING),
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
+
+ /* Fill BL33 related information */
+ {
+ .image_id = BL33_IMAGE_ID,
+
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+ VERSION_2, entry_point_info_t,
+ NON_SECURE | EXECUTABLE),
+
+ .ep_info.spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM,
+ SPSR_E_LITTLE,
+ DISABLE_ALL_EXCEPTIONS),
+
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_SKIP_LOADING),
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ }
+};
+
+REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
diff --git a/plat/st/stm32mp1/plat_def_uuid_config.c b/plat/st/stm32mp1/plat_def_uuid_config.c
new file mode 100644
index 0000000..efaf567
--- /dev/null
+++ b/plat/st/stm32mp1/plat_def_uuid_config.c
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <firmware_image_package.h>
+
+#include "tbbr_config.h"
+
+toc_entry_t plat_def_toc_entries[] = {
+ {
+ .name = "STM32MP CONFIG CERT",
+ .uuid = UUID_STM32MP_CONFIG_CERT,
+ .cmdline_name = "stm32mp-cfg-cert"
+ }
+};
+
diff --git a/plat/st/stm32mp1/plat_fiptool.mk b/plat/st/stm32mp1/plat_fiptool.mk
new file mode 100644
index 0000000..00570c2
--- /dev/null
+++ b/plat/st/stm32mp1/plat_fiptool.mk
@@ -0,0 +1,25 @@
+#
+# Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Name of the platform defined source file name,
+# which contains platform defined UUID entries populated
+# in the plat_def_toc_entries[].
+PLAT_DEF_UUID_FILE_NAME := plat_def_uuid_config
+
+INCLUDE_PATHS += -I${PLAT_DIR}/include -I./
+
+PLAT_DEF_UUID := yes
+
+ifeq (${PLAT_DEF_UUID},yes)
+HOSTCCFLAGS += -DPLAT_DEF_FIP_UUID
+
+${PLAT_DEF_UUID_FILE_NAME}.o: ${PLAT_DIR}${PLAT_DEF_UUID_FILE_NAME}.c
+ ${HOSTCC} -c ${CPPFLAGS} ${HOSTCCFLAGS} ${INCLUDE_PATHS} $< -o $@
+
+PLAT_OBJECTS += ${PLAT_DEF_UUID_FILE_NAME}.o
+endif
+
+OBJECTS += ${PLAT_OBJECTS}
diff --git a/plat/st/stm32mp1/plat_image_load.c b/plat/st/stm32mp1/plat_image_load.c
new file mode 100644
index 0000000..c4048fc
--- /dev/null
+++ b/plat/st/stm32mp1/plat_image_load.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/desc_image_load.h>
+
+/*******************************************************************************
+ * This function flushes the data structures so that they are visible
+ * in memory for the next BL image.
+ ******************************************************************************/
+void plat_flush_next_bl_params(void)
+{
+ flush_bl_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of loadable images.
+ ******************************************************************************/
+bl_load_info_t *plat_get_bl_image_load_info(void)
+{
+ return get_bl_load_info_from_mem_params_desc();
+}
+
+/*******************************************************************************
+ * This function returns the list of executable images.
+ ******************************************************************************/
+bl_params_t *plat_get_next_bl_params(void)
+{
+ bl_params_t *bl_params = get_next_bl_params_from_mem_params_desc();
+
+ populate_next_bl_params_config(bl_params);
+
+ return bl_params;
+}
diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk
new file mode 100644
index 0000000..7eecf30
--- /dev/null
+++ b/plat/st/stm32mp1/platform.mk
@@ -0,0 +1,553 @@
+#
+# Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+ARM_CORTEX_A7 := yes
+ARM_WITH_NEON := yes
+BL2_AT_EL3 := 1
+USE_COHERENT_MEM := 0
+
+STM32MP_EARLY_CONSOLE ?= 0
+STM32MP_RECONFIGURE_CONSOLE ?= 0
+STM32MP_UART_BAUDRATE ?= 115200
+
+TRUSTED_BOARD_BOOT ?= 0
+STM32MP_USE_EXTERNAL_HEAP ?= 0
+
+# Use secure library from the ROM code for authentication
+STM32MP_CRYPTO_ROM_LIB ?= 0
+
+# Please don't increment this value without good understanding of
+# the monotonic counter
+STM32_TF_VERSION ?= 0
+
+# Enable dynamic memory mapping
+PLAT_XLAT_TABLES_DYNAMIC := 1
+
+# Default Device tree
+DTB_FILE_NAME ?= stm32mp157c-ev1.dtb
+
+STM32MP13 ?= 0
+STM32MP15 ?= 0
+
+ifeq ($(STM32MP13),1)
+ifeq ($(STM32MP15),1)
+$(error Cannot enable both flags STM32MP13 and STM32MP15)
+endif
+STM32MP13 := 1
+STM32MP15 := 0
+else ifeq ($(STM32MP15),1)
+STM32MP13 := 0
+STM32MP15 := 1
+else ifneq ($(findstring stm32mp13,$(DTB_FILE_NAME)),)
+STM32MP13 := 1
+STM32MP15 := 0
+else ifneq ($(findstring stm32mp15,$(DTB_FILE_NAME)),)
+STM32MP13 := 0
+STM32MP15 := 1
+endif
+
+ifeq ($(STM32MP13),1)
+# Will use SRAM2 as mbedtls heap
+STM32MP_USE_EXTERNAL_HEAP := 1
+
+# DDR controller with single AXI port and 16-bit interface
+STM32MP_DDR_DUAL_AXI_PORT:= 0
+STM32MP_DDR_32BIT_INTERFACE:= 0
+
+ifeq (${TRUSTED_BOARD_BOOT},1)
+# PKA algo to include
+PKA_USE_NIST_P256 := 1
+PKA_USE_BRAINPOOL_P256T1:= 1
+endif
+
+# STM32 image header version v2.0
+STM32_HEADER_VERSION_MAJOR:= 2
+STM32_HEADER_VERSION_MINOR:= 0
+endif
+
+ifeq ($(STM32MP15),1)
+# DDR controller with dual AXI port and 32-bit interface
+STM32MP_DDR_DUAL_AXI_PORT:= 1
+STM32MP_DDR_32BIT_INTERFACE:= 1
+
+# STM32 image header version v1.0
+STM32_HEADER_VERSION_MAJOR:= 1
+STM32_HEADER_VERSION_MINOR:= 0
+
+# Add OP-TEE reserved shared memory area in mapping
+STM32MP15_OPTEE_RSV_SHM := 1
+$(eval $(call add_defines,STM32MP15_OPTEE_RSV_SHM))
+
+STM32MP_CRYPTO_ROM_LIB := 1
+
+# Decryption support
+ifneq ($(DECRYPTION_SUPPORT),none)
+$(error "DECRYPTION_SUPPORT not supported on STM32MP15")
+endif
+endif
+
+# STM32 image header binary type for BL2
+STM32_HEADER_BL2_BINARY_TYPE:= 0x10
+
+ifeq ($(AARCH32_SP),sp_min)
+# Disable Neon support: sp_min runtime may conflict with non-secure world
+TF_CFLAGS += -mfloat-abi=soft
+endif
+
+TF_CFLAGS += -Wsign-compare
+TF_CFLAGS += -Wformat-signedness
+
+# Not needed for Cortex-A7
+WORKAROUND_CVE_2017_5715:= 0
+WORKAROUND_CVE_2022_23960:= 0
+
+# Number of TF-A copies in the device
+STM32_TF_A_COPIES := 2
+
+# PLAT_PARTITION_MAX_ENTRIES must take care of STM32_TF-A_COPIES and other partitions
+# such as metadata (2) to find all the FIP partitions (default is 2).
+PLAT_PARTITION_MAX_ENTRIES := $(shell echo $$(($(STM32_TF_A_COPIES) + 4)))
+
+ifeq (${PSA_FWU_SUPPORT},1)
+# Number of banks of updatable firmware
+NR_OF_FW_BANKS := 2
+NR_OF_IMAGES_IN_FW_BANK := 1
+
+FWU_MAX_PART = $(shell echo $$(($(STM32_TF_A_COPIES) + 2 + $(NR_OF_FW_BANKS))))
+ifeq ($(shell test $(FWU_MAX_PART) -gt $(PLAT_PARTITION_MAX_ENTRIES); echo $$?),0)
+$(error "Required partition number is $(FWU_MAX_PART) where PLAT_PARTITION_MAX_ENTRIES is only \
+$(PLAT_PARTITION_MAX_ENTRIES)")
+endif
+endif
+
+ifeq ($(STM32MP13),1)
+STM32_HASH_VER := 4
+STM32_RNG_VER := 4
+else # Assuming STM32MP15
+STM32_HASH_VER := 2
+STM32_RNG_VER := 2
+endif
+
+# Boot devices
+STM32MP_EMMC ?= 0
+STM32MP_SDMMC ?= 0
+STM32MP_RAW_NAND ?= 0
+STM32MP_SPI_NAND ?= 0
+STM32MP_SPI_NOR ?= 0
+STM32MP_EMMC_BOOT ?= 0
+
+# Serial boot devices
+STM32MP_USB_PROGRAMMER ?= 0
+STM32MP_UART_PROGRAMMER ?= 0
+
+# Download load address for serial boot devices
+DWL_BUFFER_BASE ?= 0xC7000000
+
+# Device tree
+ifeq ($(STM32MP13),1)
+BL2_DTSI := stm32mp13-bl2.dtsi
+FDT_SOURCES := $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl2.dts,$(DTB_FILE_NAME)))
+else
+BL2_DTSI := stm32mp15-bl2.dtsi
+FDT_SOURCES := $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl2.dts,$(DTB_FILE_NAME)))
+ifeq ($(AARCH32_SP),sp_min)
+BL32_DTSI := stm32mp15-bl32.dtsi
+FDT_SOURCES += $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl32.dts,$(DTB_FILE_NAME)))
+endif
+endif
+
+$(eval DTC_V = $(shell $(DTC) -v | awk '{print $$NF}'))
+$(eval DTC_VERSION = $(shell printf "%d" $(shell echo ${DTC_V} | cut -d- -f1 | sed "s/\./0/g" | grep -o "[0-9]*")))
+DTC_CPPFLAGS += ${INCLUDES}
+DTC_FLAGS += -Wno-unit_address_vs_reg
+ifeq ($(shell test $(DTC_VERSION) -ge 10601; echo $$?),0)
+DTC_FLAGS += -Wno-interrupt_provider
+endif
+
+# Macros and rules to build TF binary
+STM32_TF_ELF_LDFLAGS := --hash-style=gnu --as-needed
+STM32_TF_STM32 := $(addprefix ${BUILD_PLAT}/tf-a-, $(patsubst %.dtb,%.stm32,$(DTB_FILE_NAME)))
+STM32_TF_LINKERFILE := ${BUILD_PLAT}/stm32mp1.ld
+
+ASFLAGS += -DBL2_BIN_PATH=\"${BUILD_PLAT}/bl2.bin\"
+ifeq ($(AARCH32_SP),sp_min)
+# BL32 is built only if using SP_MIN
+BL32_DEP := bl32
+ASFLAGS += -DBL32_BIN_PATH=\"${BUILD_PLAT}/bl32.bin\"
+endif
+
+# Variables for use with stm32image
+STM32IMAGEPATH ?= tools/stm32image
+STM32IMAGE ?= ${STM32IMAGEPATH}/stm32image${BIN_EXT}
+STM32IMAGE_SRC := ${STM32IMAGEPATH}/stm32image.c
+
+FIP_DEPS += dtbs
+STM32MP_HW_CONFIG := ${BL33_CFG}
+STM32MP_FW_CONFIG_NAME := $(patsubst %.dtb,%-fw-config.dtb,$(DTB_FILE_NAME))
+STM32MP_FW_CONFIG := ${BUILD_PLAT}/fdts/$(STM32MP_FW_CONFIG_NAME)
+ifneq (${AARCH32_SP},none)
+FDT_SOURCES += $(addprefix fdts/, $(patsubst %.dtb,%.dts,$(STM32MP_FW_CONFIG_NAME)))
+endif
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_FW_CONFIG},--fw-config))
+# Add the HW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_HW_CONFIG},--hw-config))
+ifeq ($(GENERATE_COT),1)
+STM32MP_CFG_CERT := $(BUILD_PLAT)/stm32mp_cfg_cert.crt
+# Add the STM32MP_CFG_CERT to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_CFG_CERT},--stm32mp-cfg-cert))
+endif
+ifeq ($(AARCH32_SP),sp_min)
+STM32MP_TOS_FW_CONFIG := $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl32.dtb,$(DTB_FILE_NAME)))
+$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_TOS_FW_CONFIG},--tos-fw-config))
+else
+# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images
+# in the FIP if the platform requires.
+ifneq ($(BL32_EXTRA1),)
+$(eval $(call TOOL_ADD_IMG,BL32_EXTRA1,--tos-fw-extra1,,$(ENCRYPT_BL32)))
+endif
+ifneq ($(BL32_EXTRA2),)
+$(eval $(call TOOL_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2,,$(ENCRYPT_BL32)))
+endif
+endif
+
+# Enable flags for C files
+$(eval $(call assert_booleans,\
+ $(sort \
+ PKA_USE_BRAINPOOL_P256T1 \
+ PKA_USE_NIST_P256 \
+ PLAT_TBBR_IMG_DEF \
+ PLAT_XLAT_TABLES_DYNAMIC \
+ STM32MP_CRYPTO_ROM_LIB \
+ STM32MP_DDR_32BIT_INTERFACE \
+ STM32MP_DDR_DUAL_AXI_PORT \
+ STM32MP_EARLY_CONSOLE \
+ STM32MP_EMMC \
+ STM32MP_EMMC_BOOT \
+ STM32MP_RAW_NAND \
+ STM32MP_RECONFIGURE_CONSOLE \
+ STM32MP_SDMMC \
+ STM32MP_SPI_NAND \
+ STM32MP_SPI_NOR \
+ STM32MP_UART_PROGRAMMER \
+ STM32MP_USB_PROGRAMMER \
+ STM32MP_USE_EXTERNAL_HEAP \
+ STM32MP13 \
+ STM32MP15 \
+)))
+
+$(eval $(call assert_numerics,\
+ $(sort \
+ PLAT_PARTITION_MAX_ENTRIES \
+ STM32_HASH_VER \
+ STM32_HEADER_VERSION_MAJOR \
+ STM32_RNG_VER \
+ STM32_TF_A_COPIES \
+ STM32_TF_VERSION \
+ STM32MP_UART_BAUDRATE \
+)))
+
+$(eval $(call add_defines,\
+ $(sort \
+ DWL_BUFFER_BASE \
+ PKA_USE_BRAINPOOL_P256T1 \
+ PKA_USE_NIST_P256 \
+ PLAT_PARTITION_MAX_ENTRIES \
+ PLAT_TBBR_IMG_DEF \
+ PLAT_XLAT_TABLES_DYNAMIC \
+ STM32_HASH_VER \
+ STM32_HEADER_VERSION_MAJOR \
+ STM32_RNG_VER \
+ STM32_TF_A_COPIES \
+ STM32_TF_VERSION \
+ STM32MP_CRYPTO_ROM_LIB \
+ STM32MP_DDR_32BIT_INTERFACE \
+ STM32MP_DDR_DUAL_AXI_PORT \
+ STM32MP_EARLY_CONSOLE \
+ STM32MP_EMMC \
+ STM32MP_EMMC_BOOT \
+ STM32MP_RAW_NAND \
+ STM32MP_RECONFIGURE_CONSOLE \
+ STM32MP_SDMMC \
+ STM32MP_SPI_NAND \
+ STM32MP_SPI_NOR \
+ STM32MP_UART_BAUDRATE \
+ STM32MP_UART_PROGRAMMER \
+ STM32MP_USB_PROGRAMMER \
+ STM32MP_USE_EXTERNAL_HEAP \
+ STM32MP13 \
+ STM32MP15 \
+)))
+
+# Include paths and source files
+PLAT_INCLUDES := -Iplat/st/common/include/
+PLAT_INCLUDES += -Iplat/st/stm32mp1/include/
+
+include lib/fconf/fconf.mk
+include lib/libfdt/libfdt.mk
+
+PLAT_BL_COMMON_SOURCES := common/uuid.c \
+ plat/st/common/stm32mp_common.c \
+ plat/st/stm32mp1/stm32mp1_private.c
+
+PLAT_BL_COMMON_SOURCES += drivers/st/uart/aarch32/stm32_console.S
+
+ifneq (${ENABLE_STACK_PROTECTOR},0)
+PLAT_BL_COMMON_SOURCES += plat/st/stm32mp1/stm32mp1_stack_protector.c
+endif
+
+include lib/xlat_tables_v2/xlat_tables.mk
+PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS}
+
+PLAT_BL_COMMON_SOURCES += lib/cpus/aarch32/cortex_a7.S
+
+PLAT_BL_COMMON_SOURCES += drivers/arm/tzc/tzc400.c \
+ drivers/clk/clk.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ drivers/st/bsec/bsec2.c \
+ drivers/st/clk/stm32mp_clkfunc.c \
+ drivers/st/ddr/stm32mp_ddr.c \
+ drivers/st/ddr/stm32mp1_ddr_helpers.c \
+ drivers/st/gpio/stm32_gpio.c \
+ drivers/st/i2c/stm32_i2c.c \
+ drivers/st/iwdg/stm32_iwdg.c \
+ drivers/st/pmic/stm32mp_pmic.c \
+ drivers/st/pmic/stpmic1.c \
+ drivers/st/regulator/regulator_core.c \
+ drivers/st/regulator/regulator_fixed.c \
+ drivers/st/reset/stm32mp1_reset.c \
+ plat/st/common/stm32mp_dt.c \
+ plat/st/stm32mp1/stm32mp1_dbgmcu.c \
+ plat/st/stm32mp1/stm32mp1_helper.S \
+ plat/st/stm32mp1/stm32mp1_syscfg.c
+
+ifeq ($(STM32MP13),1)
+PLAT_BL_COMMON_SOURCES += drivers/st/clk/clk-stm32-core.c \
+ drivers/st/clk/clk-stm32mp13.c \
+ drivers/st/crypto/stm32_rng.c
+else
+PLAT_BL_COMMON_SOURCES += drivers/st/clk/stm32mp1_clk.c
+endif
+
+BL2_SOURCES += ${FCONF_SOURCES} ${FCONF_DYN_SOURCES}
+
+BL2_SOURCES += drivers/io/io_fip.c \
+ plat/st/common/bl2_io_storage.c \
+ plat/st/common/stm32mp_fconf_io.c \
+ plat/st/stm32mp1/plat_bl2_mem_params_desc.c \
+ plat/st/stm32mp1/stm32mp1_fconf_firewall.c
+
+include lib/zlib/zlib.mk
+
+ifeq (${PSA_FWU_SUPPORT},1)
+include drivers/fwu/fwu.mk
+endif
+
+
+BL2_SOURCES += $(ZLIB_SOURCES)
+
+BL2_SOURCES += drivers/io/io_block.c \
+ drivers/io/io_mtd.c \
+ drivers/io/io_storage.c \
+ drivers/st/crypto/stm32_hash.c \
+ plat/st/stm32mp1/bl2_plat_setup.c
+
+ifneq (${DECRYPTION_SUPPORT},none)
+BL2_SOURCES += drivers/io/io_encrypted.c
+endif
+
+ifeq (${TRUSTED_BOARD_BOOT},1)
+AUTH_SOURCES := drivers/auth/auth_mod.c \
+ drivers/auth/crypto_mod.c \
+ drivers/auth/img_parser_mod.c
+
+ifeq (${GENERATE_COT},1)
+TFW_NVCTR_VAL := 0
+NTFW_NVCTR_VAL := 0
+KEY_SIZE :=
+KEY_ALG := ecdsa
+HASH_ALG := sha256
+
+ifeq (${SAVE_KEYS},1)
+TRUSTED_WORLD_KEY ?= ${BUILD_PLAT}/trusted.pem
+NON_TRUSTED_WORLD_KEY ?= ${BUILD_PLAT}/non-trusted.pem
+BL32_KEY ?= ${BUILD_PLAT}/trusted_os.pem
+BL33_KEY ?= ${BUILD_PLAT}/non-trusted_os.pem
+endif
+
+endif
+TF_MBEDTLS_KEY_ALG := ecdsa
+MBEDTLS_CONFIG_FILE ?= "<stm32mp1_mbedtls_config.h>"
+
+include drivers/auth/mbedtls/mbedtls_x509.mk
+
+COT_DESC_IN_DTB := 1
+AUTH_SOURCES += lib/fconf/fconf_cot_getter.c \
+ lib/fconf/fconf_tbbr_getter.c \
+ plat/st/common/stm32mp_crypto_lib.c
+
+ifeq ($(STM32MP13),1)
+AUTH_SOURCES += drivers/st/crypto/stm32_pka.c
+AUTH_SOURCES += drivers/st/crypto/stm32_saes.c
+endif
+
+BL2_SOURCES += $(AUTH_SOURCES) \
+ plat/st/common/stm32mp_trusted_boot.c
+endif
+
+ifneq ($(filter 1,${STM32MP_EMMC} ${STM32MP_SDMMC}),)
+BL2_SOURCES += drivers/mmc/mmc.c \
+ drivers/partition/gpt.c \
+ drivers/partition/partition.c \
+ drivers/st/io/io_mmc.c \
+ drivers/st/mmc/stm32_sdmmc2.c
+endif
+
+ifeq (${STM32MP_RAW_NAND},1)
+$(eval $(call add_define_val,NAND_ONFI_DETECT,1))
+BL2_SOURCES += drivers/mtd/nand/raw_nand.c \
+ drivers/st/fmc/stm32_fmc2_nand.c
+endif
+
+ifeq (${STM32MP_SPI_NAND},1)
+BL2_SOURCES += drivers/mtd/nand/spi_nand.c
+endif
+
+ifeq (${STM32MP_SPI_NOR},1)
+ifneq (${STM32MP_FORCE_MTD_START_OFFSET},)
+$(eval $(call add_define_val,STM32MP_NOR_FIP_OFFSET,${STM32MP_FORCE_MTD_START_OFFSET}))
+endif
+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}),)
+ifneq (${STM32MP_FORCE_MTD_START_OFFSET},)
+$(eval $(call add_define_val,STM32MP_NAND_FIP_OFFSET,${STM32MP_FORCE_MTD_START_OFFSET}))
+endif
+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
+
+ifneq ($(filter 1,${STM32MP_UART_PROGRAMMER} ${STM32MP_USB_PROGRAMMER}),)
+BL2_SOURCES += drivers/io/io_memmap.c
+endif
+
+ifeq (${STM32MP_UART_PROGRAMMER},1)
+BL2_SOURCES += drivers/st/uart/stm32_uart.c \
+ plat/st/common/stm32cubeprogrammer_uart.c
+endif
+
+ifeq (${STM32MP_USB_PROGRAMMER},1)
+#The DFU stack uses only one end point, reduce the USB stack footprint
+$(eval $(call add_define_val,CONFIG_USBD_EP_NB,1U))
+BL2_SOURCES += drivers/st/usb/stm32mp1_usb.c \
+ drivers/usb/usb_device.c \
+ plat/st/common/stm32cubeprogrammer_usb.c \
+ plat/st/common/usb_dfu.c \
+ plat/st/stm32mp1/stm32mp1_usb_dfu.c
+endif
+
+BL2_SOURCES += drivers/st/ddr/stm32mp_ddr_test.c \
+ drivers/st/ddr/stm32mp_ram.c \
+ drivers/st/ddr/stm32mp1_ddr.c \
+ drivers/st/ddr/stm32mp1_ram.c
+
+BL2_SOURCES += common/desc_image_load.c \
+ plat/st/stm32mp1/plat_image_load.c
+
+BL2_SOURCES += lib/optee/optee_utils.c
+
+# Compilation rules
+.PHONY: check_dtc_version stm32image clean_stm32image check_boot_device
+.SUFFIXES:
+
+all: check_dtc_version stm32image ${STM32_TF_STM32}
+
+distclean realclean clean: clean_stm32image
+
+bl2: check_boot_device
+
+check_boot_device:
+ @if [ ${STM32MP_EMMC} != 1 ] && \
+ [ ${STM32MP_SDMMC} != 1 ] && \
+ [ ${STM32MP_RAW_NAND} != 1 ] && \
+ [ ${STM32MP_SPI_NAND} != 1 ] && \
+ [ ${STM32MP_SPI_NOR} != 1 ] && \
+ [ ${STM32MP_UART_PROGRAMMER} != 1 ] && \
+ [ ${STM32MP_USB_PROGRAMMER} != 1 ]; then \
+ echo "No boot device driver is enabled"; \
+ false; \
+ fi
+
+stm32image: ${STM32IMAGE}
+
+${STM32IMAGE}: ${STM32IMAGE_SRC}
+ ${Q}${MAKE} CPPFLAGS="" --no-print-directory -C ${STM32IMAGEPATH}
+
+clean_stm32image:
+ ${Q}${MAKE} --no-print-directory -C ${STM32IMAGEPATH} clean
+
+check_dtc_version:
+ @if [ ${DTC_VERSION} -lt 10404 ]; then \
+ echo "dtc version too old (${DTC_V}), you need at least version 1.4.4"; \
+ false; \
+ fi
+
+# Create DTB file for BL2
+${BUILD_PLAT}/fdts/%-bl2.dts: fdts/%.dts fdts/${BL2_DTSI} | ${BUILD_PLAT} fdt_dirs
+ @echo '#include "$(patsubst fdts/%,%,$<)"' > $@
+ @echo '#include "${BL2_DTSI}"' >> $@
+
+${BUILD_PLAT}/fdts/%-bl2.dtb: ${BUILD_PLAT}/fdts/%-bl2.dts
+
+ifeq ($(AARCH32_SP),sp_min)
+# Create DTB file for BL32
+${BUILD_PLAT}/fdts/%-bl32.dts: fdts/%.dts fdts/${BL32_DTSI} | ${BUILD_PLAT} fdt_dirs
+ @echo '#include "$(patsubst fdts/%,%,$<)"' > $@
+ @echo '#include "${BL32_DTSI}"' >> $@
+
+${BUILD_PLAT}/fdts/%-bl32.dtb: ${BUILD_PLAT}/fdts/%-bl32.dts
+endif
+
+${BUILD_PLAT}/stm32mp1-%.o: ${BUILD_PLAT}/fdts/%-bl2.dtb plat/st/stm32mp1/stm32mp1.S bl2
+ @echo " AS stm32mp1.S"
+ ${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} \
+ -DDTB_BIN_PATH=\"$<\" \
+ -c plat/st/stm32mp1/stm32mp1.S -o $@
+
+$(eval $(call MAKE_LD,${STM32_TF_LINKERFILE},plat/st/stm32mp1/stm32mp1.ld.S,bl2))
+
+tf-a-%.elf: stm32mp1-%.o ${STM32_TF_LINKERFILE}
+ @echo " LDS $<"
+ ${Q}${LD} -o $@ ${STM32_TF_ELF_LDFLAGS} -Map=$(@:.elf=.map) --script ${STM32_TF_LINKERFILE} $<
+
+tf-a-%.bin: tf-a-%.elf
+ ${Q}${OC} -O binary $< $@
+ @echo
+ @echo "Built $@ successfully"
+ @echo
+
+tf-a-%.stm32: ${STM32IMAGE} tf-a-%.bin
+ @echo
+ @echo "Generate $@"
+ $(eval LOADADDR = $(shell cat $(@:.stm32=.map) | grep RAM | awk '{print $$2}'))
+ $(eval ENTRY = $(shell cat $(@:.stm32=.map) | grep "__BL2_IMAGE_START" | awk '{print $$1}'))
+ ${Q}${STM32IMAGE} -s $(word 2,$^) -d $@ \
+ -l $(LOADADDR) -e ${ENTRY} \
+ -v ${STM32_TF_VERSION} \
+ -m ${STM32_HEADER_VERSION_MAJOR} \
+ -n ${STM32_HEADER_VERSION_MINOR} \
+ -b ${STM32_HEADER_BL2_BINARY_TYPE}
+ @echo
diff --git a/plat/st/stm32mp1/services/bsec_svc.c b/plat/st/stm32mp1/services/bsec_svc.c
new file mode 100644
index 0000000..1fb44b4
--- /dev/null
+++ b/plat/st/stm32mp1/services/bsec_svc.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2016-2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <drivers/st/bsec.h>
+#include <drivers/st/bsec2_reg.h>
+
+#include <stm32mp1_smc.h>
+
+#include "bsec_svc.h"
+
+uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3,
+ uint32_t *ret_otp_value)
+{
+ uint32_t result;
+ uint32_t tmp_data = 0U;
+
+ switch (x1) {
+ case STM32_SMC_READ_SHADOW:
+ result = bsec_read_otp(ret_otp_value, x2);
+ break;
+ case STM32_SMC_PROG_OTP:
+ *ret_otp_value = 0U;
+ result = bsec_program_otp(x3, x2);
+ break;
+ case STM32_SMC_WRITE_SHADOW:
+ *ret_otp_value = 0U;
+ result = bsec_write_otp(x3, x2);
+ break;
+ case STM32_SMC_READ_OTP:
+ *ret_otp_value = 0U;
+ result = bsec_read_otp(&tmp_data, x2);
+ if (result != BSEC_OK) {
+ break;
+ }
+
+ result = bsec_shadow_register(x2);
+ if (result != BSEC_OK) {
+ break;
+ }
+
+ result = bsec_read_otp(ret_otp_value, x2);
+ if (result != BSEC_OK) {
+ break;
+ }
+
+ result = bsec_write_otp(tmp_data, x2);
+ break;
+
+ default:
+ return STM32_SMC_INVALID_PARAMS;
+ }
+
+ return (result == BSEC_OK) ? STM32_SMC_OK : STM32_SMC_FAILED;
+}
diff --git a/plat/st/stm32mp1/services/bsec_svc.h b/plat/st/stm32mp1/services/bsec_svc.h
new file mode 100644
index 0000000..06752ef
--- /dev/null
+++ b/plat/st/stm32mp1/services/bsec_svc.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BSEC_SVC_H
+#define BSEC_SVC_H
+
+#include <stdint.h>
+
+/* version of this service */
+/* must be increase at each structure modification */
+#define BSEC_SERVICE_VERSION 0x01U
+
+uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3,
+ uint32_t *ret_otp_value);
+
+#endif /* BSEC_SVC_H */
diff --git a/plat/st/stm32mp1/services/stm32mp1_svc_setup.c b/plat/st/stm32mp1/services/stm32mp1_svc_setup.c
new file mode 100644
index 0000000..ed8a448
--- /dev/null
+++ b/plat/st/stm32mp1/services/stm32mp1_svc_setup.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2014-2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <drivers/scmi-msg.h>
+#include <lib/psci/psci.h>
+#include <tools_share/uuid.h>
+
+#include <stm32mp1_smc.h>
+
+#include "bsec_svc.h"
+
+/* STM32 SiP Service UUID */
+DEFINE_SVC_UUID2(stm32_sip_svc_uid,
+ 0xa778aa50, 0xf49b, 0x144a, 0x8a, 0x5e,
+ 0x26, 0x4d, 0x59, 0x94, 0xc2, 0x14);
+
+/* Setup STM32MP1 Standard Services */
+static int32_t stm32mp1_svc_setup(void)
+{
+ /*
+ * PSCI is the only specification implemented as a Standard Service.
+ * Invoke PSCI setup from here.
+ */
+ return 0;
+}
+
+/*
+ * Top-level Standard Service SMC handler. This handler will in turn dispatch
+ * calls to PSCI SMC handler.
+ */
+static uintptr_t stm32mp1_svc_smc_handler(uint32_t smc_fid, u_register_t x1,
+ u_register_t x2, u_register_t x3,
+ u_register_t x4, void *cookie,
+ void *handle, u_register_t flags)
+{
+ uint32_t ret1 = 0U, ret2 = 0U;
+ bool ret_uid = false, ret2_enabled = false;
+
+ switch (smc_fid) {
+ case STM32_SIP_SVC_CALL_COUNT:
+ ret1 = STM32_COMMON_SIP_NUM_CALLS;
+ break;
+
+ case STM32_SIP_SVC_UID:
+ /* Return UUID to the caller */
+ ret_uid = true;
+ break;
+
+ case STM32_SIP_SVC_VERSION:
+ /* Return the version of current implementation */
+ ret1 = STM32_SIP_SVC_VERSION_MAJOR;
+ ret2 = STM32_SIP_SVC_VERSION_MINOR;
+ ret2_enabled = true;
+ break;
+
+ case STM32_SMC_BSEC:
+ ret1 = bsec_main(x1, x2, x3, &ret2);
+ ret2_enabled = true;
+ break;
+
+ case STM32_SIP_SMC_SCMI_AGENT0:
+ scmi_smt_fastcall_smc_entry(0);
+ break;
+ case STM32_SIP_SMC_SCMI_AGENT1:
+ scmi_smt_fastcall_smc_entry(1);
+ break;
+
+ default:
+ WARN("Unimplemented STM32MP1 Service Call: 0x%x\n", smc_fid);
+ ret1 = STM32_SMC_NOT_SUPPORTED;
+ break;
+ }
+
+ if (ret_uid) {
+ SMC_UUID_RET(handle, stm32_sip_svc_uid);
+ }
+
+ if (ret2_enabled) {
+ SMC_RET2(handle, ret1, ret2);
+ }
+
+ SMC_RET1(handle, ret1);
+}
+
+/* Register Standard Service Calls as runtime service */
+DECLARE_RT_SVC(stm32mp1_sip_svc,
+ OEN_SIP_START,
+ OEN_SIP_END,
+ SMC_TYPE_FAST,
+ stm32mp1_svc_setup,
+ stm32mp1_svc_smc_handler
+);
diff --git a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
new file mode 100644
index 0000000..1d754d9
--- /dev/null
+++ b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
@@ -0,0 +1,53 @@
+#
+# Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+ifeq ($(STM32MP13),1)
+$(error "SP_min is not supported on STM32MP13 platform")
+endif
+
+SP_MIN_WITH_SECURE_FIQ := 1
+
+override ENABLE_PIE := 1
+BL32_CFLAGS += -fpie -DENABLE_PIE
+BL32_LDFLAGS += $(PIE_LDFLAGS)
+
+BL32_CFLAGS += -DSTM32MP_SHARED_RESOURCES
+
+BL32_SOURCES += drivers/st/etzpc/etzpc.c \
+ plat/common/aarch32/platform_mp_stack.S \
+ plat/st/stm32mp1/sp_min/sp_min_setup.c \
+ plat/st/stm32mp1/stm32mp1_pm.c \
+ plat/st/stm32mp1/stm32mp1_shared_resources.c \
+ plat/st/stm32mp1/stm32mp1_topology.c
+
+# FDT wrappers
+include common/fdt_wrappers.mk
+BL32_SOURCES += ${FDT_WRAPPERS_SOURCES}
+
+# Generic GIC v2
+include drivers/arm/gic/v2/gicv2.mk
+
+BL32_SOURCES += ${GICV2_SOURCES} \
+ plat/common/plat_gicv2.c \
+ plat/st/stm32mp1/stm32mp1_gic.c
+
+# Generic PSCI
+BL32_SOURCES += plat/common/plat_psci_common.c
+
+# SCMI server drivers
+BL32_SOURCES += drivers/scmi-msg/base.c \
+ drivers/scmi-msg/clock.c \
+ drivers/scmi-msg/entry.c \
+ drivers/scmi-msg/reset_domain.c \
+ drivers/scmi-msg/smt.c
+
+# stm32mp1 specific services
+BL32_SOURCES += plat/st/stm32mp1/services/bsec_svc.c \
+ plat/st/stm32mp1/services/stm32mp1_svc_setup.c \
+ plat/st/stm32mp1/stm32mp1_scmi.c
+
+# Arm Archtecture services
+BL32_SOURCES += services/arm_arch_svc/arm_arch_svc_setup.c
diff --git a/plat/st/stm32mp1/sp_min/sp_min_setup.c b/plat/st/stm32mp1/sp_min/sp_min_setup.c
new file mode 100644
index 0000000..50b0794
--- /dev/null
+++ b/plat/st/stm32mp1/sp_min/sp_min_setup.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <context.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/arm/tzc400.h>
+#include <drivers/generic_delay_timer.h>
+#include <drivers/st/bsec.h>
+#include <drivers/st/etzpc.h>
+#include <drivers/st/stm32_gpio.h>
+#include <drivers/st/stm32_iwdg.h>
+#include <drivers/st/stm32mp1_clk.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+
+#include <platform_sp_min.h>
+
+/******************************************************************************
+ * Placeholder variables for copying the arguments that have been passed to
+ * BL32 from BL2.
+ ******************************************************************************/
+static entry_point_info_t bl33_image_ep_info;
+
+/*******************************************************************************
+ * Interrupt handler for FIQ (secure IRQ)
+ ******************************************************************************/
+void sp_min_plat_fiq_handler(uint32_t id)
+{
+ (void)plat_crash_console_init();
+
+ switch (id & INT_ID_MASK) {
+ case STM32MP1_IRQ_TZC400:
+ tzc400_init(STM32MP1_TZC_BASE);
+ (void)tzc400_it_handler();
+ panic();
+ break;
+ case STM32MP1_IRQ_AXIERRIRQ:
+ ERROR("STM32MP1_IRQ_AXIERRIRQ generated\n");
+ panic();
+ break;
+ default:
+ ERROR("SECURE IT handler not define for it : %u\n", id);
+ break;
+ }
+}
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *sp_min_plat_get_bl33_ep_info(void)
+{
+ entry_point_info_t *next_image_info;
+
+ next_image_info = &bl33_image_ep_info;
+
+ if (next_image_info->pc == 0U) {
+ return NULL;
+ }
+
+ return next_image_info;
+}
+
+CASSERT((STM32MP_SEC_SYSRAM_BASE == STM32MP_SYSRAM_BASE) &&
+ ((STM32MP_SEC_SYSRAM_BASE + STM32MP_SEC_SYSRAM_SIZE) <=
+ (STM32MP_SYSRAM_BASE + STM32MP_SYSRAM_SIZE)),
+ assert_secure_sysram_fits_at_begining_of_sysram);
+
+#ifdef STM32MP_NS_SYSRAM_BASE
+CASSERT((STM32MP_NS_SYSRAM_BASE >= STM32MP_SEC_SYSRAM_BASE) &&
+ ((STM32MP_NS_SYSRAM_BASE + STM32MP_NS_SYSRAM_SIZE) ==
+ (STM32MP_SYSRAM_BASE + STM32MP_SYSRAM_SIZE)),
+ assert_non_secure_sysram_fits_at_end_of_sysram);
+
+CASSERT((STM32MP_NS_SYSRAM_BASE & (PAGE_SIZE_4KB - U(1))) == 0U,
+ assert_non_secure_sysram_base_is_4kbyte_aligned);
+
+#define TZMA1_SECURE_RANGE \
+ (((STM32MP_NS_SYSRAM_BASE - STM32MP_SYSRAM_BASE) >> FOUR_KB_SHIFT) - 1U)
+#else
+#define TZMA1_SECURE_RANGE STM32MP1_ETZPC_TZMA_ALL_SECURE
+#endif /* STM32MP_NS_SYSRAM_BASE */
+#define TZMA0_SECURE_RANGE STM32MP1_ETZPC_TZMA_ALL_SECURE
+
+static void stm32mp1_etzpc_early_setup(void)
+{
+ if (etzpc_init() != 0) {
+ panic();
+ }
+
+ etzpc_configure_tzma(STM32MP1_ETZPC_TZMA_ROM, TZMA0_SECURE_RANGE);
+ etzpc_configure_tzma(STM32MP1_ETZPC_TZMA_SYSRAM, TZMA1_SECURE_RANGE);
+}
+
+/*******************************************************************************
+ * Perform any BL32 specific platform actions.
+ ******************************************************************************/
+void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+ u_register_t arg2, u_register_t arg3)
+{
+ bl_params_t *params_from_bl2 = (bl_params_t *)arg0;
+ uintptr_t dt_addr = arg1;
+
+ stm32mp_setup_early_console();
+
+ /* Imprecise aborts can be masked in NonSecure */
+ write_scr(read_scr() | SCR_AW_BIT);
+
+ mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
+ BL_CODE_END - BL_CODE_BASE,
+ MT_CODE | MT_SECURE);
+
+ configure_mmu();
+
+ assert(params_from_bl2 != NULL);
+ assert(params_from_bl2->h.type == PARAM_BL_PARAMS);
+ assert(params_from_bl2->h.version >= VERSION_2);
+
+ bl_params_node_t *bl_params = params_from_bl2->head;
+
+ /*
+ * Copy BL33 entry point information.
+ * They are stored in Secure RAM, in BL2's address space.
+ */
+ while (bl_params != NULL) {
+ if (bl_params->image_id == BL33_IMAGE_ID) {
+ bl33_image_ep_info = *bl_params->ep_info;
+ /*
+ * Check if hw_configuration is given to BL32 and
+ * share it to BL33.
+ */
+ if (arg2 != 0U) {
+ bl33_image_ep_info.args.arg0 = 0U;
+ bl33_image_ep_info.args.arg1 = 0U;
+ bl33_image_ep_info.args.arg2 = arg2;
+ }
+
+ break;
+ }
+
+ bl_params = bl_params->next_params_info;
+ }
+
+ if (dt_open_and_check(dt_addr) < 0) {
+ panic();
+ }
+
+ if (bsec_probe() != 0) {
+ panic();
+ }
+
+ if (stm32mp1_clk_probe() < 0) {
+ panic();
+ }
+
+ (void)stm32mp_uart_console_setup();
+
+ stm32mp1_etzpc_early_setup();
+}
+
+/*******************************************************************************
+ * Initialize the MMU, security and the GIC.
+ ******************************************************************************/
+void sp_min_platform_setup(void)
+{
+ generic_delay_timer_init();
+
+ stm32mp1_gic_init();
+
+ if (stm32_iwdg_init() < 0) {
+ panic();
+ }
+
+ stm32mp_lock_periph_registering();
+
+ stm32mp1_init_scmi_server();
+}
+
+void sp_min_plat_arch_setup(void)
+{
+}
diff --git a/plat/st/stm32mp1/stm32mp1.S b/plat/st/stm32mp1/stm32mp1.S
new file mode 100644
index 0000000..aee4f0e
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1.S
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+.section .bl2_image
+.incbin BL2_BIN_PATH
+
+.section .dtb_image
+.incbin DTB_BIN_PATH
diff --git a/plat/st/stm32mp1/stm32mp1.ld.S b/plat/st/stm32mp1/stm32mp1.ld.S
new file mode 100644
index 0000000..1be8219
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1.ld.S
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP1_LD_S
+#define STM32MP1_LD_S
+
+#include <lib/xlat_tables/xlat_tables_defs.h>
+#include <platform_def.h>
+
+OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
+OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
+
+ENTRY(__BL2_IMAGE_START__)
+
+MEMORY {
+ HEADER (rw) : ORIGIN = 0x00000000, LENGTH = STM32MP_HEADER_RESERVED_SIZE
+ RAM (rwx) : ORIGIN = STM32MP_BINARY_BASE, LENGTH = STM32MP_BINARY_SIZE
+}
+
+SECTIONS
+{
+ /*
+ * TF mapping must conform to ROM code specification.
+ */
+ .header : {
+ __HEADER_START__ = .;
+ KEEP(*(.header))
+ . = ALIGN(4);
+ __HEADER_END__ = .;
+ } >HEADER
+
+ . = STM32MP_BINARY_BASE;
+ .data . : {
+ . = ALIGN(PAGE_SIZE);
+ __DATA_START__ = .;
+ *(.data*)
+
+ /*
+ * dtb.
+ * The strongest and only alignment contraint is MMU 4K page.
+ * Indeed as images below will be removed, 4K pages will be re-used.
+ */
+ . = ( STM32MP_BL2_DTB_BASE - STM32MP_BINARY_BASE );
+ __DTB_IMAGE_START__ = .;
+ *(.dtb_image*)
+ __DTB_IMAGE_END__ = .;
+
+ /*
+ * bl2.
+ * The strongest and only alignment contraint is MMU 4K page.
+ * Indeed as images below will be removed, 4K pages will be re-used.
+ */
+#if SEPARATE_CODE_AND_RODATA
+ . = ( STM32MP_BL2_RO_BASE - STM32MP_BINARY_BASE );
+#else
+ . = ( STM32MP_BL2_BASE - STM32MP_BINARY_BASE );
+#endif
+ __BL2_IMAGE_START__ = .;
+ *(.bl2_image*)
+ __BL2_IMAGE_END__ = .;
+
+ __DATA_END__ = .;
+ } >RAM
+
+ __TF_END__ = .;
+
+}
+#endif /* STM32MP1_LD_S */
diff --git a/plat/st/stm32mp1/stm32mp1_boot_device.c b/plat/st/stm32mp1/stm32mp1_boot_device.c
new file mode 100644
index 0000000..3a8a27a
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_boot_device.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <common/debug.h>
+#include <drivers/nand.h>
+#include <drivers/raw_nand.h>
+#include <drivers/spi_nand.h>
+#include <drivers/spi_nor.h>
+#include <lib/utils.h>
+#include <plat/common/platform.h>
+
+#if STM32MP_RAW_NAND || STM32MP_SPI_NAND
+#if STM32MP13
+void plat_get_scratch_buffer(void **buffer_addr, size_t *buf_size)
+{
+ assert(buffer_addr != NULL);
+ assert(buf_size != NULL);
+
+ *buffer_addr = (void *)STM32MP_MTD_BUFFER;
+ *buf_size = PLATFORM_MTD_MAX_PAGE_SIZE;
+}
+#endif
+
+static int get_data_from_otp(struct nand_device *nand_dev, bool is_slc)
+{
+ uint32_t nand_param;
+ uint32_t nand2_param __maybe_unused;
+
+ /* Check if NAND parameters are stored in OTP */
+ if (stm32_get_otp_value(NAND_OTP, &nand_param) != 0) {
+ ERROR("BSEC: NAND_OTP Error\n");
+ return -EACCES;
+ }
+
+ if (nand_param == 0U) {
+#if STM32MP13
+ if (is_slc) {
+ return 0;
+ }
+#endif
+#if STM32MP15
+ return 0;
+#endif
+ }
+
+ if ((nand_param & NAND_PARAM_STORED_IN_OTP) == 0U) {
+#if STM32MP13
+ if (is_slc) {
+ goto ecc;
+ }
+#endif
+#if STM32MP15
+ goto ecc;
+#endif
+ }
+
+#if STM32MP13
+ if (stm32_get_otp_value(NAND2_OTP, &nand2_param) != 0) {
+ ERROR("BSEC: NAND_OTP Error\n");
+ return -EACCES;
+ }
+
+ /* Check OTP configuration for this device */
+ if ((((nand2_param & NAND2_CONFIG_DISTRIB) == NAND2_PNAND_NAND1_SNAND_NAND2) && !is_slc) ||
+ (((nand2_param & NAND2_CONFIG_DISTRIB) == NAND2_PNAND_NAND2_SNAND_NAND1) && is_slc)) {
+ nand_param = nand2_param << (NAND_PAGE_SIZE_SHIFT - NAND2_PAGE_SIZE_SHIFT);
+ }
+#endif
+
+ /* NAND parameter shall be read from OTP */
+ if ((nand_param & NAND_WIDTH_MASK) != 0U) {
+ nand_dev->buswidth = NAND_BUS_WIDTH_16;
+ } else {
+ nand_dev->buswidth = NAND_BUS_WIDTH_8;
+ }
+
+ switch ((nand_param & NAND_PAGE_SIZE_MASK) >> NAND_PAGE_SIZE_SHIFT) {
+ case NAND_PAGE_SIZE_2K:
+ nand_dev->page_size = 0x800U;
+ break;
+
+ case NAND_PAGE_SIZE_4K:
+ nand_dev->page_size = 0x1000U;
+ break;
+
+ case NAND_PAGE_SIZE_8K:
+ nand_dev->page_size = 0x2000U;
+ break;
+
+ default:
+ ERROR("Cannot read NAND page size\n");
+ return -EINVAL;
+ }
+
+ switch ((nand_param & NAND_BLOCK_SIZE_MASK) >> NAND_BLOCK_SIZE_SHIFT) {
+ case NAND_BLOCK_SIZE_64_PAGES:
+ nand_dev->block_size = 64U * nand_dev->page_size;
+ break;
+
+ case NAND_BLOCK_SIZE_128_PAGES:
+ nand_dev->block_size = 128U * nand_dev->page_size;
+ break;
+
+ case NAND_BLOCK_SIZE_256_PAGES:
+ nand_dev->block_size = 256U * nand_dev->page_size;
+ break;
+
+ default:
+ ERROR("Cannot read NAND block size\n");
+ return -EINVAL;
+ }
+
+ nand_dev->size = ((nand_param & NAND_BLOCK_NB_MASK) >>
+ NAND_BLOCK_NB_SHIFT) *
+ NAND_BLOCK_NB_UNIT * nand_dev->block_size;
+
+ecc:
+ if (is_slc) {
+ switch ((nand_param & NAND_ECC_BIT_NB_MASK) >>
+ NAND_ECC_BIT_NB_SHIFT) {
+ case NAND_ECC_BIT_NB_1_BITS:
+ nand_dev->ecc.max_bit_corr = 1U;
+ break;
+
+ case NAND_ECC_BIT_NB_4_BITS:
+ nand_dev->ecc.max_bit_corr = 4U;
+ break;
+
+ case NAND_ECC_BIT_NB_8_BITS:
+ nand_dev->ecc.max_bit_corr = 8U;
+ break;
+
+ case NAND_ECC_ON_DIE:
+ nand_dev->ecc.mode = NAND_ECC_ONDIE;
+ break;
+
+ default:
+ if (nand_dev->ecc.max_bit_corr == 0U) {
+ ERROR("No valid eccbit number\n");
+ return -EINVAL;
+ }
+ }
+ } else {
+ /* Selected multiple plane NAND */
+ if ((nand_param & NAND_PLANE_BIT_NB_MASK) != 0U) {
+ nand_dev->nb_planes = 2U;
+ } else {
+ nand_dev->nb_planes = 1U;
+ }
+ }
+
+ VERBOSE("OTP: Block %u Page %u Size %llu\n", nand_dev->block_size,
+ nand_dev->page_size, nand_dev->size);
+
+ return 0;
+}
+#endif /* STM32MP_RAW_NAND || STM32MP_SPI_NAND */
+
+#if STM32MP_RAW_NAND
+int plat_get_raw_nand_data(struct rawnand_device *device)
+{
+ device->nand_dev->ecc.mode = NAND_ECC_HW;
+ device->nand_dev->ecc.size = SZ_512;
+
+ return get_data_from_otp(device->nand_dev, true);
+}
+#endif
+
+#if STM32MP_SPI_NAND
+int plat_get_spi_nand_data(struct spinand_device *device)
+{
+ zeromem(&device->spi_read_cache_op, sizeof(struct spi_mem_op));
+ device->spi_read_cache_op.cmd.opcode = SPI_NAND_OP_READ_FROM_CACHE_4X;
+ device->spi_read_cache_op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
+ device->spi_read_cache_op.addr.nbytes = 2U;
+ device->spi_read_cache_op.addr.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
+ device->spi_read_cache_op.dummy.nbytes = 1U;
+ device->spi_read_cache_op.dummy.buswidth = SPI_MEM_BUSWIDTH_1_LINE;
+ device->spi_read_cache_op.data.buswidth = SPI_MEM_BUSWIDTH_4_LINE;
+ device->spi_read_cache_op.data.dir = SPI_MEM_DATA_IN;
+
+ return get_data_from_otp(device->nand_dev, false);
+}
+#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_dbgmcu.c b/plat/st/stm32mp1/stm32mp1_dbgmcu.c
new file mode 100644
index 0000000..08e332a
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_dbgmcu.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2016-2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <common/debug.h>
+#include <drivers/st/bsec.h>
+#include <drivers/st/bsec2_reg.h>
+#include <drivers/st/stm32mp1_rcc.h>
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+
+#include <platform_def.h>
+#include <stm32mp1_dbgmcu.h>
+
+#define DBGMCU_IDC U(0x00)
+
+#define DBGMCU_IDC_DEV_ID_MASK GENMASK(11, 0)
+#define DBGMCU_IDC_REV_ID_MASK GENMASK(31, 16)
+#define DBGMCU_IDC_REV_ID_SHIFT 16
+
+static int stm32mp1_dbgmcu_init(void)
+{
+ if ((bsec_read_debug_conf() & BSEC_DBGSWGEN) == 0U) {
+ INFO("Software access to all debug components is disabled\n");
+ return -1;
+ }
+
+ mmio_setbits_32(RCC_BASE + RCC_DBGCFGR, RCC_DBGCFGR_DBGCKEN);
+
+ return 0;
+}
+
+/*
+ * @brief Get silicon revision from DBGMCU registers.
+ * @param chip_version: pointer to the read value.
+ * @retval 0 on success, negative value on failure.
+ */
+int stm32mp1_dbgmcu_get_chip_version(uint32_t *chip_version)
+{
+ assert(chip_version != NULL);
+
+ if (stm32mp1_dbgmcu_init() != 0) {
+ return -EPERM;
+ }
+
+ *chip_version = (mmio_read_32(DBGMCU_BASE + DBGMCU_IDC) &
+ DBGMCU_IDC_REV_ID_MASK) >> DBGMCU_IDC_REV_ID_SHIFT;
+
+ return 0;
+}
+
+/*
+ * @brief Get device ID from DBGMCU registers.
+ * @param chip_dev_id: pointer to the read value.
+ * @retval 0 on success, negative value on failure.
+ */
+int stm32mp1_dbgmcu_get_chip_dev_id(uint32_t *chip_dev_id)
+{
+ assert(chip_dev_id != NULL);
+
+ if (stm32mp1_dbgmcu_init() != 0) {
+ return -EPERM;
+ }
+
+ *chip_dev_id = mmio_read_32(DBGMCU_BASE + DBGMCU_IDC) &
+ DBGMCU_IDC_DEV_ID_MASK;
+
+ return 0;
+}
diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h
new file mode 100644
index 0000000..f0d8526
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_def.h
@@ -0,0 +1,669 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP1_DEF_H
+#define STM32MP1_DEF_H
+
+#include <common/tbbr/tbbr_img_def.h>
+#include <drivers/st/stm32mp1_rcc.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <dt-bindings/reset/stm32mp1-resets.h>
+#include <lib/utils_def.h>
+#include <lib/xlat_tables/xlat_tables_defs.h>
+
+#ifndef __ASSEMBLER__
+#include <drivers/st/bsec.h>
+#include <drivers/st/stm32mp1_clk.h>
+
+#include <boot_api.h>
+#include <stm32mp_common.h>
+#include <stm32mp_dt.h>
+#include <stm32mp1_dbgmcu.h>
+#include <stm32mp1_private.h>
+#include <stm32mp1_shared_resources.h>
+#endif
+
+#include "stm32mp1_fip_def.h"
+
+/*******************************************************************************
+ * CHIP ID
+ ******************************************************************************/
+#if STM32MP13
+#define STM32MP1_CHIP_ID U(0x501)
+
+#define STM32MP135C_PART_NB U(0x05010000)
+#define STM32MP135A_PART_NB U(0x05010001)
+#define STM32MP133C_PART_NB U(0x050100C0)
+#define STM32MP133A_PART_NB U(0x050100C1)
+#define STM32MP131C_PART_NB U(0x050106C8)
+#define STM32MP131A_PART_NB U(0x050106C9)
+#define STM32MP135F_PART_NB U(0x05010800)
+#define STM32MP135D_PART_NB U(0x05010801)
+#define STM32MP133F_PART_NB U(0x050108C0)
+#define STM32MP133D_PART_NB U(0x050108C1)
+#define STM32MP131F_PART_NB U(0x05010EC8)
+#define STM32MP131D_PART_NB U(0x05010EC9)
+#endif
+#if STM32MP15
+#define STM32MP1_CHIP_ID U(0x500)
+
+#define STM32MP157C_PART_NB U(0x05000000)
+#define STM32MP157A_PART_NB U(0x05000001)
+#define STM32MP153C_PART_NB U(0x05000024)
+#define STM32MP153A_PART_NB U(0x05000025)
+#define STM32MP151C_PART_NB U(0x0500002E)
+#define STM32MP151A_PART_NB U(0x0500002F)
+#define STM32MP157F_PART_NB U(0x05000080)
+#define STM32MP157D_PART_NB U(0x05000081)
+#define STM32MP153F_PART_NB U(0x050000A4)
+#define STM32MP153D_PART_NB U(0x050000A5)
+#define STM32MP151F_PART_NB U(0x050000AE)
+#define STM32MP151D_PART_NB U(0x050000AF)
+#endif
+
+#define STM32MP1_REV_B U(0x2000)
+#if STM32MP13
+#define STM32MP1_REV_Y U(0x1003)
+#define STM32MP1_REV_Z U(0x1001)
+#endif
+#if STM32MP15
+#define STM32MP1_REV_Z U(0x2001)
+#endif
+
+/*******************************************************************************
+ * PACKAGE ID
+ ******************************************************************************/
+#if STM32MP15
+#define PKG_AA_LFBGA448 U(4)
+#define PKG_AB_LFBGA354 U(3)
+#define PKG_AC_TFBGA361 U(2)
+#define PKG_AD_TFBGA257 U(1)
+#endif
+
+/*******************************************************************************
+ * STM32MP1 memory map related constants
+ ******************************************************************************/
+#define STM32MP_ROM_BASE U(0x00000000)
+#define STM32MP_ROM_SIZE U(0x00020000)
+#define STM32MP_ROM_SIZE_2MB_ALIGNED U(0x00200000)
+
+#if STM32MP13
+#define STM32MP_SYSRAM_BASE U(0x2FFE0000)
+#define STM32MP_SYSRAM_SIZE U(0x00020000)
+#define SRAM1_BASE U(0x30000000)
+#define SRAM1_SIZE U(0x00004000)
+#define SRAM2_BASE U(0x30004000)
+#define SRAM2_SIZE U(0x00002000)
+#define SRAM3_BASE U(0x30006000)
+#define SRAM3_SIZE U(0x00002000)
+#define SRAMS_BASE SRAM1_BASE
+#define SRAMS_SIZE_2MB_ALIGNED U(0x00200000)
+#endif /* STM32MP13 */
+#if STM32MP15
+#define STM32MP_SYSRAM_BASE U(0x2FFC0000)
+#define STM32MP_SYSRAM_SIZE U(0x00040000)
+#endif /* STM32MP15 */
+
+#define STM32MP_NS_SYSRAM_SIZE PAGE_SIZE
+#define STM32MP_NS_SYSRAM_BASE (STM32MP_SYSRAM_BASE + \
+ STM32MP_SYSRAM_SIZE - \
+ STM32MP_NS_SYSRAM_SIZE)
+
+#define STM32MP_SCMI_NS_SHM_BASE STM32MP_NS_SYSRAM_BASE
+#define STM32MP_SCMI_NS_SHM_SIZE STM32MP_NS_SYSRAM_SIZE
+
+#define STM32MP_SEC_SYSRAM_BASE STM32MP_SYSRAM_BASE
+#define STM32MP_SEC_SYSRAM_SIZE (STM32MP_SYSRAM_SIZE - \
+ STM32MP_NS_SYSRAM_SIZE)
+
+/* DDR configuration */
+#define STM32MP_DDR_BASE U(0xC0000000)
+#define STM32MP_DDR_MAX_SIZE U(0x40000000) /* Max 1GB */
+
+/* DDR power initializations */
+#ifndef __ASSEMBLER__
+enum ddr_type {
+ STM32MP_DDR3,
+ STM32MP_LPDDR2,
+ STM32MP_LPDDR3
+};
+#endif
+
+/* Section used inside TF binaries */
+#if STM32MP13
+/* 512 Octets reserved for header */
+#define STM32MP_HEADER_RESERVED_SIZE U(0x200)
+
+#define STM32MP_BINARY_BASE STM32MP_SEC_SYSRAM_BASE
+
+#define STM32MP_BINARY_SIZE STM32MP_SEC_SYSRAM_SIZE
+#endif
+#if STM32MP15
+#define STM32MP_PARAM_LOAD_SIZE U(0x00002400) /* 9 KB for param */
+/* 256 Octets reserved for header */
+#define STM32MP_HEADER_SIZE U(0x00000100)
+/* round_up(STM32MP_PARAM_LOAD_SIZE + STM32MP_HEADER_SIZE, PAGE_SIZE) */
+#define STM32MP_HEADER_RESERVED_SIZE U(0x3000)
+
+#define STM32MP_BINARY_BASE (STM32MP_SEC_SYSRAM_BASE + \
+ STM32MP_PARAM_LOAD_SIZE + \
+ STM32MP_HEADER_SIZE)
+
+#define STM32MP_BINARY_SIZE (STM32MP_SEC_SYSRAM_SIZE - \
+ (STM32MP_PARAM_LOAD_SIZE + \
+ STM32MP_HEADER_SIZE))
+#endif
+
+/* BL2 and BL32/sp_min require finer granularity tables */
+#if defined(IMAGE_BL2)
+#define MAX_XLAT_TABLES U(2) /* 8 KB for mapping */
+#endif
+
+#if defined(IMAGE_BL32)
+#define MAX_XLAT_TABLES U(4) /* 16 KB for mapping */
+#endif
+
+/*
+ * MAX_MMAP_REGIONS is usually:
+ * BL stm32mp1_mmap size + mmap regions in *_plat_arch_setup
+ */
+#if defined(IMAGE_BL2)
+ #if STM32MP_USB_PROGRAMMER
+ #define MAX_MMAP_REGIONS 8
+ #else
+ #define MAX_MMAP_REGIONS 7
+ #endif
+#endif
+
+#if STM32MP13
+#define STM32MP_BL33_BASE STM32MP_DDR_BASE
+#endif
+#if STM32MP15
+#define STM32MP_BL33_BASE (STM32MP_DDR_BASE + U(0x100000))
+#endif
+#define STM32MP_BL33_MAX_SIZE U(0x400000)
+
+/* Define maximum page size for NAND devices */
+#define PLATFORM_MTD_MAX_PAGE_SIZE U(0x1000)
+
+/* Define location for the MTD scratch buffer */
+#if STM32MP13
+#define STM32MP_MTD_BUFFER (SRAM1_BASE + \
+ SRAM1_SIZE - \
+ PLATFORM_MTD_MAX_PAGE_SIZE)
+#endif
+/*******************************************************************************
+ * STM32MP1 device/io map related constants (used for MMU)
+ ******************************************************************************/
+#define STM32MP1_DEVICE1_BASE U(0x40000000)
+#define STM32MP1_DEVICE1_SIZE U(0x40000000)
+
+#define STM32MP1_DEVICE2_BASE U(0x80000000)
+#define STM32MP1_DEVICE2_SIZE U(0x40000000)
+
+/*******************************************************************************
+ * STM32MP1 RCC
+ ******************************************************************************/
+#define RCC_BASE U(0x50000000)
+
+/*******************************************************************************
+ * STM32MP1 PWR
+ ******************************************************************************/
+#define PWR_BASE U(0x50001000)
+
+/*******************************************************************************
+ * STM32MP1 GPIO
+ ******************************************************************************/
+#define GPIOA_BASE U(0x50002000)
+#define GPIOB_BASE U(0x50003000)
+#define GPIOC_BASE U(0x50004000)
+#define GPIOD_BASE U(0x50005000)
+#define GPIOE_BASE U(0x50006000)
+#define GPIOF_BASE U(0x50007000)
+#define GPIOG_BASE U(0x50008000)
+#define GPIOH_BASE U(0x50009000)
+#define GPIOI_BASE U(0x5000A000)
+#if STM32MP15
+#define GPIOJ_BASE U(0x5000B000)
+#define GPIOK_BASE U(0x5000C000)
+#define GPIOZ_BASE U(0x54004000)
+#endif
+#define GPIO_BANK_OFFSET U(0x1000)
+
+/* Bank IDs used in GPIO driver API */
+#define GPIO_BANK_A U(0)
+#define GPIO_BANK_B U(1)
+#define GPIO_BANK_C U(2)
+#define GPIO_BANK_D U(3)
+#define GPIO_BANK_E U(4)
+#define GPIO_BANK_F U(5)
+#define GPIO_BANK_G U(6)
+#define GPIO_BANK_H U(7)
+#define GPIO_BANK_I U(8)
+#if STM32MP15
+#define GPIO_BANK_J U(9)
+#define GPIO_BANK_K U(10)
+#define GPIO_BANK_Z U(25)
+
+#define STM32MP_GPIOZ_PIN_MAX_COUNT 8
+#endif
+
+/*******************************************************************************
+ * STM32MP1 UART
+ ******************************************************************************/
+#if STM32MP13
+#define USART1_BASE U(0x4C000000)
+#define USART2_BASE U(0x4C001000)
+#endif
+#if STM32MP15
+#define USART1_BASE U(0x5C000000)
+#define USART2_BASE U(0x4000E000)
+#endif
+#define USART3_BASE U(0x4000F000)
+#define UART4_BASE U(0x40010000)
+#define UART5_BASE U(0x40011000)
+#define USART6_BASE U(0x44003000)
+#define UART7_BASE U(0x40018000)
+#define UART8_BASE U(0x40019000)
+
+/* For UART crash console */
+#define STM32MP_DEBUG_USART_BASE UART4_BASE
+#if STM32MP13
+/* UART4 on HSI@64MHz, TX on GPIOF12 Alternate 8 (Disco board) */
+#define STM32MP_DEBUG_USART_CLK_FRQ 64000000
+#define DEBUG_UART_TX_GPIO_BANK_ADDRESS GPIOD_BASE
+#define DEBUG_UART_TX_GPIO_BANK_CLK_REG RCC_MP_S_AHB4ENSETR
+#define DEBUG_UART_TX_GPIO_BANK_CLK_EN RCC_MP_S_AHB4ENSETR_GPIODEN
+#define DEBUG_UART_TX_GPIO_PORT 6
+#define DEBUG_UART_TX_GPIO_ALTERNATE 8
+#define DEBUG_UART_TX_CLKSRC_REG RCC_UART4CKSELR
+#define DEBUG_UART_TX_CLKSRC RCC_UART4CKSELR_HSI
+#endif /* STM32MP13 */
+#if STM32MP15
+/* UART4 on HSI@64MHz, TX on GPIOG11 Alternate 6 */
+#define STM32MP_DEBUG_USART_CLK_FRQ 64000000
+#define DEBUG_UART_TX_GPIO_BANK_ADDRESS GPIOG_BASE
+#define DEBUG_UART_TX_GPIO_BANK_CLK_REG RCC_MP_AHB4ENSETR
+#define DEBUG_UART_TX_GPIO_BANK_CLK_EN RCC_MP_AHB4ENSETR_GPIOGEN
+#define DEBUG_UART_TX_GPIO_PORT 11
+#define DEBUG_UART_TX_GPIO_ALTERNATE 6
+#define DEBUG_UART_TX_CLKSRC_REG RCC_UART24CKSELR
+#define DEBUG_UART_TX_CLKSRC RCC_UART24CKSELR_HSI
+#endif /* STM32MP15 */
+#define DEBUG_UART_TX_EN_REG RCC_MP_APB1ENSETR
+#define DEBUG_UART_TX_EN RCC_MP_APB1ENSETR_UART4EN
+#define DEBUG_UART_RST_REG RCC_APB1RSTSETR
+#define DEBUG_UART_RST_BIT RCC_APB1RSTSETR_UART4RST
+
+/*******************************************************************************
+ * STM32MP1 ETZPC
+ ******************************************************************************/
+#define STM32MP1_ETZPC_BASE U(0x5C007000)
+
+/* ETZPC TZMA IDs */
+#define STM32MP1_ETZPC_TZMA_ROM U(0)
+#define STM32MP1_ETZPC_TZMA_SYSRAM U(1)
+
+#define STM32MP1_ETZPC_TZMA_ALL_SECURE GENMASK_32(9, 0)
+
+/* ETZPC DECPROT IDs */
+#define STM32MP1_ETZPC_STGENC_ID 0
+#define STM32MP1_ETZPC_BKPSRAM_ID 1
+#define STM32MP1_ETZPC_IWDG1_ID 2
+#define STM32MP1_ETZPC_USART1_ID 3
+#define STM32MP1_ETZPC_SPI6_ID 4
+#define STM32MP1_ETZPC_I2C4_ID 5
+#define STM32MP1_ETZPC_RNG1_ID 7
+#define STM32MP1_ETZPC_HASH1_ID 8
+#define STM32MP1_ETZPC_CRYP1_ID 9
+#define STM32MP1_ETZPC_DDRCTRL_ID 10
+#define STM32MP1_ETZPC_DDRPHYC_ID 11
+#define STM32MP1_ETZPC_I2C6_ID 12
+#define STM32MP1_ETZPC_SEC_ID_LIMIT 13
+
+#define STM32MP1_ETZPC_TIM2_ID 16
+#define STM32MP1_ETZPC_TIM3_ID 17
+#define STM32MP1_ETZPC_TIM4_ID 18
+#define STM32MP1_ETZPC_TIM5_ID 19
+#define STM32MP1_ETZPC_TIM6_ID 20
+#define STM32MP1_ETZPC_TIM7_ID 21
+#define STM32MP1_ETZPC_TIM12_ID 22
+#define STM32MP1_ETZPC_TIM13_ID 23
+#define STM32MP1_ETZPC_TIM14_ID 24
+#define STM32MP1_ETZPC_LPTIM1_ID 25
+#define STM32MP1_ETZPC_WWDG1_ID 26
+#define STM32MP1_ETZPC_SPI2_ID 27
+#define STM32MP1_ETZPC_SPI3_ID 28
+#define STM32MP1_ETZPC_SPDIFRX_ID 29
+#define STM32MP1_ETZPC_USART2_ID 30
+#define STM32MP1_ETZPC_USART3_ID 31
+#define STM32MP1_ETZPC_UART4_ID 32
+#define STM32MP1_ETZPC_UART5_ID 33
+#define STM32MP1_ETZPC_I2C1_ID 34
+#define STM32MP1_ETZPC_I2C2_ID 35
+#define STM32MP1_ETZPC_I2C3_ID 36
+#define STM32MP1_ETZPC_I2C5_ID 37
+#define STM32MP1_ETZPC_CEC_ID 38
+#define STM32MP1_ETZPC_DAC_ID 39
+#define STM32MP1_ETZPC_UART7_ID 40
+#define STM32MP1_ETZPC_UART8_ID 41
+#define STM32MP1_ETZPC_MDIOS_ID 44
+#define STM32MP1_ETZPC_TIM1_ID 48
+#define STM32MP1_ETZPC_TIM8_ID 49
+#define STM32MP1_ETZPC_USART6_ID 51
+#define STM32MP1_ETZPC_SPI1_ID 52
+#define STM32MP1_ETZPC_SPI4_ID 53
+#define STM32MP1_ETZPC_TIM15_ID 54
+#define STM32MP1_ETZPC_TIM16_ID 55
+#define STM32MP1_ETZPC_TIM17_ID 56
+#define STM32MP1_ETZPC_SPI5_ID 57
+#define STM32MP1_ETZPC_SAI1_ID 58
+#define STM32MP1_ETZPC_SAI2_ID 59
+#define STM32MP1_ETZPC_SAI3_ID 60
+#define STM32MP1_ETZPC_DFSDM_ID 61
+#define STM32MP1_ETZPC_TT_FDCAN_ID 62
+#define STM32MP1_ETZPC_LPTIM2_ID 64
+#define STM32MP1_ETZPC_LPTIM3_ID 65
+#define STM32MP1_ETZPC_LPTIM4_ID 66
+#define STM32MP1_ETZPC_LPTIM5_ID 67
+#define STM32MP1_ETZPC_SAI4_ID 68
+#define STM32MP1_ETZPC_VREFBUF_ID 69
+#define STM32MP1_ETZPC_DCMI_ID 70
+#define STM32MP1_ETZPC_CRC2_ID 71
+#define STM32MP1_ETZPC_ADC_ID 72
+#define STM32MP1_ETZPC_HASH2_ID 73
+#define STM32MP1_ETZPC_RNG2_ID 74
+#define STM32MP1_ETZPC_CRYP2_ID 75
+#define STM32MP1_ETZPC_SRAM1_ID 80
+#define STM32MP1_ETZPC_SRAM2_ID 81
+#define STM32MP1_ETZPC_SRAM3_ID 82
+#define STM32MP1_ETZPC_SRAM4_ID 83
+#define STM32MP1_ETZPC_RETRAM_ID 84
+#define STM32MP1_ETZPC_OTG_ID 85
+#define STM32MP1_ETZPC_SDMMC3_ID 86
+#define STM32MP1_ETZPC_DLYBSD3_ID 87
+#define STM32MP1_ETZPC_DMA1_ID 88
+#define STM32MP1_ETZPC_DMA2_ID 89
+#define STM32MP1_ETZPC_DMAMUX_ID 90
+#define STM32MP1_ETZPC_FMC_ID 91
+#define STM32MP1_ETZPC_QSPI_ID 92
+#define STM32MP1_ETZPC_DLYBQ_ID 93
+#define STM32MP1_ETZPC_ETH_ID 94
+#define STM32MP1_ETZPC_RSV_ID 95
+
+#define STM32MP_ETZPC_MAX_ID 96
+
+/*******************************************************************************
+ * STM32MP1 TZC (TZ400)
+ ******************************************************************************/
+#define STM32MP1_TZC_BASE U(0x5C006000)
+
+#if STM32MP13
+#define STM32MP1_FILTER_BIT_ALL TZC_400_REGION_ATTR_FILTER_BIT(0)
+#endif
+#if STM32MP15
+#define STM32MP1_FILTER_BIT_ALL (TZC_400_REGION_ATTR_FILTER_BIT(0) | \
+ TZC_400_REGION_ATTR_FILTER_BIT(1))
+#endif
+
+/*******************************************************************************
+ * STM32MP1 SDMMC
+ ******************************************************************************/
+#define STM32MP_SDMMC1_BASE U(0x58005000)
+#define STM32MP_SDMMC2_BASE U(0x58007000)
+#define STM32MP_SDMMC3_BASE U(0x48004000)
+
+#define STM32MP_MMC_INIT_FREQ U(400000) /*400 KHz*/
+#define STM32MP_SD_NORMAL_SPEED_MAX_FREQ U(25000000) /*25 MHz*/
+#define STM32MP_SD_HIGH_SPEED_MAX_FREQ U(50000000) /*50 MHz*/
+#define STM32MP_EMMC_NORMAL_SPEED_MAX_FREQ U(26000000) /*26 MHz*/
+#define STM32MP_EMMC_HIGH_SPEED_MAX_FREQ U(52000000) /*52 MHz*/
+
+/*******************************************************************************
+ * STM32MP1 BSEC / OTP
+ ******************************************************************************/
+#define STM32MP1_OTP_MAX_ID 0x5FU
+#define STM32MP1_UPPER_OTP_START 0x20U
+
+#define OTP_MAX_SIZE (STM32MP1_OTP_MAX_ID + 1U)
+
+/* OTP labels */
+#define CFG0_OTP "cfg0_otp"
+#define PART_NUMBER_OTP "part_number_otp"
+#if STM32MP15
+#define PACKAGE_OTP "package_otp"
+#endif
+#define HW2_OTP "hw2_otp"
+#if STM32MP13
+#define NAND_OTP "cfg9_otp"
+#define NAND2_OTP "cfg10_otp"
+#endif
+#if STM32MP15
+#define NAND_OTP "nand_otp"
+#endif
+#define MONOTONIC_OTP "monotonic_otp"
+#define UID_OTP "uid_otp"
+#define PKH_OTP "pkh_otp"
+#define ENCKEY_OTP "enckey_otp"
+#define BOARD_ID_OTP "board_id"
+
+/* OTP mask */
+/* CFG0 */
+#if STM32MP13
+#define CFG0_OTP_MODE_MASK GENMASK_32(9, 0)
+#define CFG0_OTP_MODE_SHIFT 0
+#define CFG0_OPEN_DEVICE 0x17U
+#define CFG0_CLOSED_DEVICE 0x3FU
+#define CFG0_CLOSED_DEVICE_NO_BOUNDARY_SCAN 0x17FU
+#define CFG0_CLOSED_DEVICE_NO_JTAG 0x3FFU
+#endif
+#if STM32MP15
+#define CFG0_CLOSED_DEVICE BIT(6)
+#endif
+
+/* PART NUMBER */
+#if STM32MP13
+#define PART_NUMBER_OTP_PART_MASK GENMASK_32(11, 0)
+#endif
+#if STM32MP15
+#define PART_NUMBER_OTP_PART_MASK GENMASK_32(7, 0)
+#endif
+#define PART_NUMBER_OTP_PART_SHIFT 0
+
+/* PACKAGE */
+#if STM32MP15
+#define PACKAGE_OTP_PKG_MASK GENMASK_32(29, 27)
+#define PACKAGE_OTP_PKG_SHIFT 27
+#endif
+
+/* IWDG OTP */
+#define HW2_OTP_IWDG_HW_POS U(3)
+#define HW2_OTP_IWDG_FZ_STOP_POS U(5)
+#define HW2_OTP_IWDG_FZ_STANDBY_POS U(7)
+
+/* HW2 OTP */
+#define HW2_OTP_PRODUCT_BELOW_2V5 BIT(13)
+
+/* NAND OTP */
+/* NAND parameter storage flag */
+#define NAND_PARAM_STORED_IN_OTP BIT(31)
+
+/* NAND page size in bytes */
+#define NAND_PAGE_SIZE_MASK GENMASK_32(30, 29)
+#define NAND_PAGE_SIZE_SHIFT 29
+#define NAND_PAGE_SIZE_2K U(0)
+#define NAND_PAGE_SIZE_4K U(1)
+#define NAND_PAGE_SIZE_8K U(2)
+
+/* NAND block size in pages */
+#define NAND_BLOCK_SIZE_MASK GENMASK_32(28, 27)
+#define NAND_BLOCK_SIZE_SHIFT 27
+#define NAND_BLOCK_SIZE_64_PAGES U(0)
+#define NAND_BLOCK_SIZE_128_PAGES U(1)
+#define NAND_BLOCK_SIZE_256_PAGES U(2)
+
+/* NAND number of block (in unit of 256 blocks) */
+#define NAND_BLOCK_NB_MASK GENMASK_32(26, 19)
+#define NAND_BLOCK_NB_SHIFT 19
+#define NAND_BLOCK_NB_UNIT U(256)
+
+/* NAND bus width in bits */
+#define NAND_WIDTH_MASK BIT(18)
+#define NAND_WIDTH_SHIFT 18
+
+/* NAND number of ECC bits per 512 bytes */
+#define NAND_ECC_BIT_NB_MASK GENMASK_32(17, 15)
+#define NAND_ECC_BIT_NB_SHIFT 15
+#define NAND_ECC_BIT_NB_UNSET U(0)
+#define NAND_ECC_BIT_NB_1_BITS U(1)
+#define NAND_ECC_BIT_NB_4_BITS U(2)
+#define NAND_ECC_BIT_NB_8_BITS U(3)
+#define NAND_ECC_ON_DIE U(4)
+
+/* NAND number of planes */
+#define NAND_PLANE_BIT_NB_MASK BIT(14)
+
+/* NAND2 OTP */
+#define NAND2_PAGE_SIZE_SHIFT 16
+
+/* NAND2 config distribution */
+#define NAND2_CONFIG_DISTRIB BIT(0)
+#define NAND2_PNAND_NAND2_SNAND_NAND1 U(0)
+#define NAND2_PNAND_NAND1_SNAND_NAND2 U(1)
+
+/* MONOTONIC OTP */
+#define MAX_MONOTONIC_VALUE 32
+
+/* UID OTP */
+#define UID_WORD_NB U(3)
+
+/* FWU configuration (max supported value is 15) */
+#define FWU_MAX_TRIAL_REBOOT U(3)
+
+/*******************************************************************************
+ * STM32MP1 TAMP
+ ******************************************************************************/
+#define TAMP_BASE U(0x5C00A000)
+#define TAMP_BKP_REGISTER_BASE (TAMP_BASE + U(0x100))
+#define TAMP_COUNTR U(0x40)
+
+#if !(defined(__LINKER__) || defined(__ASSEMBLER__))
+static inline uintptr_t tamp_bkpr(uint32_t idx)
+{
+ return TAMP_BKP_REGISTER_BASE + (idx << 2);
+}
+#endif
+
+/*******************************************************************************
+ * STM32MP1 USB
+ ******************************************************************************/
+#define USB_OTG_BASE U(0x49000000)
+
+/*******************************************************************************
+ * STM32MP1 DDRCTRL
+ ******************************************************************************/
+#define DDRCTRL_BASE U(0x5A003000)
+
+/*******************************************************************************
+ * STM32MP1 DDRPHYC
+ ******************************************************************************/
+#define DDRPHYC_BASE U(0x5A004000)
+
+/*******************************************************************************
+ * STM32MP1 IWDG
+ ******************************************************************************/
+#define IWDG_MAX_INSTANCE U(2)
+#define IWDG1_INST U(0)
+#define IWDG2_INST U(1)
+
+#define IWDG1_BASE U(0x5C003000)
+#define IWDG2_BASE U(0x5A002000)
+
+/*******************************************************************************
+ * Miscellaneous STM32MP1 peripherals base address
+ ******************************************************************************/
+#define BSEC_BASE U(0x5C005000)
+#if STM32MP13
+#define CRYP_BASE U(0x54002000)
+#endif
+#if STM32MP15
+#define CRYP1_BASE U(0x54001000)
+#endif
+#define DBGMCU_BASE U(0x50081000)
+#if STM32MP13
+#define HASH_BASE U(0x54003000)
+#endif
+#if STM32MP15
+#define HASH1_BASE U(0x54002000)
+#endif
+#if STM32MP13
+#define I2C3_BASE U(0x4C004000)
+#define I2C4_BASE U(0x4C005000)
+#define I2C5_BASE U(0x4C006000)
+#endif
+#if STM32MP15
+#define I2C4_BASE U(0x5C002000)
+#define I2C6_BASE U(0x5c009000)
+#endif
+#if STM32MP13
+#define RNG_BASE U(0x54004000)
+#endif
+#if STM32MP15
+#define RNG1_BASE U(0x54003000)
+#endif
+#define RTC_BASE U(0x5c004000)
+#if STM32MP13
+#define SPI4_BASE U(0x4C002000)
+#define SPI5_BASE U(0x4C003000)
+#endif
+#if STM32MP15
+#define SPI6_BASE U(0x5c001000)
+#endif
+#define STGEN_BASE U(0x5c008000)
+#define SYSCFG_BASE U(0x50020000)
+
+/*******************************************************************************
+ * STM32MP13 SAES
+ ******************************************************************************/
+#define SAES_BASE U(0x54005000)
+
+/*******************************************************************************
+ * STM32MP13 PKA
+ ******************************************************************************/
+#define PKA_BASE U(0x54006000)
+
+/*******************************************************************************
+ * REGULATORS
+ ******************************************************************************/
+/* 3 PWR + 1 VREFBUF + 14 PMIC regulators + 1 FIXED */
+#define PLAT_NB_RDEVS U(19)
+/* 2 FIXED */
+#define PLAT_NB_FIXED_REGS U(2)
+
+/*******************************************************************************
+ * Device Tree defines
+ ******************************************************************************/
+#define DT_BSEC_COMPAT "st,stm32mp15-bsec"
+#if STM32MP13
+#define DT_DDR_COMPAT "st,stm32mp13-ddr"
+#endif
+#if STM32MP15
+#define DT_DDR_COMPAT "st,stm32mp1-ddr"
+#endif
+#define DT_IWDG_COMPAT "st,stm32mp1-iwdg"
+#define DT_PWR_COMPAT "st,stm32mp1,pwr-reg"
+#if STM32MP13
+#define DT_RCC_CLK_COMPAT "st,stm32mp13-rcc"
+#define DT_RCC_SEC_CLK_COMPAT "st,stm32mp13-rcc-secure"
+#endif
+#if STM32MP15
+#define DT_RCC_CLK_COMPAT "st,stm32mp1-rcc"
+#define DT_RCC_SEC_CLK_COMPAT "st,stm32mp1-rcc-secure"
+#endif
+#define DT_SDMMC2_COMPAT "st,stm32-sdmmc2"
+#define DT_UART_COMPAT "st,stm32h7-uart"
+
+#endif /* STM32MP1_DEF_H */
diff --git a/plat/st/stm32mp1/stm32mp1_fconf_firewall.c b/plat/st/stm32mp1/stm32mp1_fconf_firewall.c
new file mode 100644
index 0000000..f2568ab
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_fconf_firewall.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+#include <drivers/arm/tzc400.h>
+#include <drivers/clk.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <lib/fconf/fconf.h>
+#include <lib/object_pool.h>
+#include <libfdt.h>
+#include <tools_share/firmware_image_package.h>
+
+#include <platform_def.h>
+#include <stm32mp_fconf_getter.h>
+
+#define STM32MP_REGION_PARAMS 4
+#define STM32MP_MAX_REGIONS 8
+#define FORCE_SEC_REGION BIT(31)
+
+static uint32_t nb_regions;
+
+struct dt_id_attr {
+ fdt32_t id_attr[STM32MP_MAX_REGIONS];
+};
+
+void stm32mp1_arch_security_setup(void)
+{
+#if STM32MP13
+ clk_enable(TZC);
+#endif
+#if STM32MP15
+ clk_enable(TZC1);
+ clk_enable(TZC2);
+#endif
+
+ tzc400_init(STM32MP1_TZC_BASE);
+ tzc400_disable_filters();
+
+ /*
+ * Region 0 set to cover all DRAM at 0xC000_0000
+ * Only secure access is granted in read/write.
+ */
+ tzc400_configure_region0(TZC_REGION_S_RDWR, 0);
+
+ tzc400_set_action(TZC_ACTION_ERR);
+ tzc400_enable_filters();
+}
+
+void stm32mp1_security_setup(void)
+{
+ uint8_t i;
+
+ assert(nb_regions > 0U);
+
+ tzc400_init(STM32MP1_TZC_BASE);
+ tzc400_disable_filters();
+
+ /*
+ * Region 0 set to cover all DRAM at 0xC000_0000
+ * No access is allowed.
+ */
+ tzc400_configure_region0(TZC_REGION_S_NONE, 0);
+
+ for (i = 1U; i <= nb_regions; i++) {
+ tzc400_update_filters(i, STM32MP1_FILTER_BIT_ALL);
+ }
+
+ tzc400_set_action(TZC_ACTION_INT);
+ tzc400_enable_filters();
+}
+
+static int fconf_populate_stm32mp1_firewall(uintptr_t config)
+{
+ int node, len;
+ unsigned int i;
+ const struct dt_id_attr *conf_list;
+ const void *dtb = (const void *)config;
+
+ /* Assert the node offset point to "st,mem-firewall" compatible property */
+ const char *compatible_str = "st,mem-firewall";
+
+ node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
+ if (node < 0) {
+ ERROR("FCONF: Can't find %s compatible in dtb\n", compatible_str);
+ return node;
+ }
+
+ conf_list = (const struct dt_id_attr *)fdt_getprop(dtb, node, "memory-ranges", &len);
+ if (conf_list == NULL) {
+ WARN("FCONF: Read cell failed for %s\n", "memory-ranges");
+ return -1;
+ }
+
+ /* Locate the memory cells and read all values */
+ for (i = 0U; i < (unsigned int)(len / (sizeof(uint32_t) * STM32MP_REGION_PARAMS)); i++) {
+ uint32_t base;
+ uint32_t size;
+ uint32_t sec_attr;
+ uint32_t nsaid;
+
+ base = fdt32_to_cpu(conf_list->id_attr[i * STM32MP_REGION_PARAMS]);
+ size = fdt32_to_cpu(conf_list->id_attr[i * STM32MP_REGION_PARAMS + 1]);
+ sec_attr = fdt32_to_cpu(conf_list->id_attr[i * STM32MP_REGION_PARAMS + 2]);
+ nsaid = fdt32_to_cpu(conf_list->id_attr[i * STM32MP_REGION_PARAMS + 3]);
+
+ VERBOSE("FCONF: stm32mp1-firewall cell found with value = 0x%x 0x%x 0x%x 0x%x\n",
+ base, size, sec_attr, nsaid);
+
+ nb_regions++;
+
+ /* Configure region but keep disabled for secure access for BL2 load */
+ tzc400_configure_region(0U, nb_regions, (unsigned long long)base,
+ (unsigned long long)base + size - 1ULL, sec_attr, nsaid);
+ }
+
+ /* Force flush as the value will be used cache off */
+ flush_dcache_range((uintptr_t)&nb_regions, sizeof(uint32_t));
+
+ return 0;
+}
+
+FCONF_REGISTER_POPULATOR(FW_CONFIG, stm32mp1_firewall, fconf_populate_stm32mp1_firewall);
diff --git a/plat/st/stm32mp1/stm32mp1_fip_def.h b/plat/st/stm32mp1/stm32mp1_fip_def.h
new file mode 100644
index 0000000..4098386
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_fip_def.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2021-2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP1_FIP_DEF_H
+#define STM32MP1_FIP_DEF_H
+
+#if STM32MP15_OPTEE_RSV_SHM
+#define STM32MP_DDR_S_SIZE U(0x01E00000) /* 30 MB */
+#define STM32MP_DDR_SHMEM_SIZE U(0x00200000) /* 2 MB */
+#else
+#define STM32MP_DDR_S_SIZE U(0x02000000) /* 32 MB */
+#define STM32MP_DDR_SHMEM_SIZE U(0) /* empty */
+#endif
+
+#if TRUSTED_BOARD_BOOT && !STM32MP_USE_EXTERNAL_HEAP
+#if STM32MP15
+#define STM32MP_BL2_RO_SIZE U(0x00014000) /* 80 KB */
+#define STM32MP_BL2_SIZE U(0x0001B000) /* 108 KB for BL2 */
+#endif /* STM32MP15 */
+#else /* TRUSTED_BOARD_BOOT && !STM32MP_USE_EXTERNAL_HEAP */
+#if STM32MP13
+#if BL2_IN_XIP_MEM
+#define STM32MP_BL2_RO_SIZE U(0x00015000) /* 84 KB */
+#define STM32MP_BL2_SIZE U(0x00017000) /* 92 KB for BL2 */
+#else
+/* STM32MP_BL2_RO_SIZE not used if !BL2_IN_XIP_MEM */
+#define STM32MP_BL2_SIZE U(0x0001B000) /* 108KB for BL2 */
+ /* with 20KB for DTB, SYSRAM is full */
+#endif
+#endif /* STM32MP13 */
+#if STM32MP15
+#define STM32MP_BL2_RO_SIZE U(0x00011000) /* 68 KB */
+#define STM32MP_BL2_SIZE U(0x00016000) /* 88 KB for BL2 */
+#endif /* STM32MP15 */
+#endif /* TRUSTED_BOARD_BOOT && !STM32MP_USE_EXTERNAL_HEAP */
+
+#if STM32MP13
+#if TRUSTED_BOARD_BOOT
+#define STM32MP_BL2_DTB_SIZE U(0x00005000) /* 20 KB for DTB */
+#else /* TRUSTED_BOARD_BOOT */
+#define STM32MP_BL2_DTB_SIZE U(0x00004000) /* 16 KB for DTB */
+#endif /* TRUSTED_BOARD_BOOT */
+#endif /* STM32MP13 */
+#if STM32MP15
+#define STM32MP_BL2_DTB_SIZE U(0x00007000) /* 28 KB for DTB */
+#endif /* STM32MP15 */
+#define STM32MP_BL32_SIZE U(0x0001B000) /* 108 KB for BL32 */
+#define STM32MP_BL32_DTB_SIZE U(0x00005000) /* 20 KB for DTB */
+#define STM32MP_FW_CONFIG_MAX_SIZE PAGE_SIZE /* 4 KB for FCONF DTB */
+#define STM32MP_HW_CONFIG_MAX_SIZE U(0x40000) /* 256 KB for HW config DTB */
+
+#if STM32MP13
+#define STM32MP_BL2_BASE (STM32MP_BL2_DTB_BASE + \
+ STM32MP_BL2_DTB_SIZE)
+#endif /* STM32MP13 */
+#if STM32MP15
+#define STM32MP_BL2_BASE (STM32MP_SEC_SYSRAM_BASE + \
+ STM32MP_SEC_SYSRAM_SIZE - \
+ STM32MP_BL2_SIZE)
+#endif /* STM32MP15 */
+
+#define STM32MP_BL2_RO_BASE STM32MP_BL2_BASE
+
+#define STM32MP_BL2_RW_BASE (STM32MP_BL2_RO_BASE + \
+ STM32MP_BL2_RO_SIZE)
+
+#if STM32MP13
+#define STM32MP_BL2_RW_SIZE (STM32MP_SYSRAM_BASE + \
+ STM32MP_SYSRAM_SIZE - \
+ STM32MP_BL2_RW_BASE)
+
+#define STM32MP_BL2_DTB_BASE STM32MP_SEC_SYSRAM_BASE
+#endif /* STM32MP13 */
+#if STM32MP15
+#define STM32MP_BL2_RW_SIZE (STM32MP_SEC_SYSRAM_BASE + \
+ STM32MP_SEC_SYSRAM_SIZE - \
+ STM32MP_BL2_RW_BASE)
+
+#define STM32MP_BL2_DTB_BASE (STM32MP_BL2_BASE - \
+ STM32MP_BL2_DTB_SIZE)
+#endif /* STM32MP15 */
+
+#define STM32MP_BL32_DTB_BASE STM32MP_SYSRAM_BASE
+
+#define STM32MP_BL32_BASE (STM32MP_BL32_DTB_BASE + \
+ STM32MP_BL32_DTB_SIZE)
+
+
+#if defined(IMAGE_BL2)
+#define STM32MP_DTB_SIZE STM32MP_BL2_DTB_SIZE
+#define STM32MP_DTB_BASE STM32MP_BL2_DTB_BASE
+#endif
+#if defined(IMAGE_BL32)
+#define STM32MP_DTB_SIZE STM32MP_BL32_DTB_SIZE
+#define STM32MP_DTB_BASE STM32MP_BL32_DTB_BASE
+#endif
+
+#ifdef AARCH32_SP_OPTEE
+#define STM32MP_OPTEE_BASE STM32MP_SEC_SYSRAM_BASE
+
+#define STM32MP_OPTEE_SIZE (STM32MP_BL2_DTB_BASE - \
+ STM32MP_OPTEE_BASE)
+#endif
+
+#if STM32MP13
+#define STM32MP_FW_CONFIG_BASE SRAM3_BASE
+#endif /* STM32MP13 */
+#if STM32MP15
+#define STM32MP_FW_CONFIG_BASE (STM32MP_SYSRAM_BASE + \
+ STM32MP_SYSRAM_SIZE - \
+ PAGE_SIZE)
+#endif /* STM32MP15 */
+#define STM32MP_HW_CONFIG_BASE (STM32MP_BL33_BASE + \
+ STM32MP_BL33_MAX_SIZE)
+
+/*
+ * MAX_MMAP_REGIONS is usually:
+ * BL stm32mp1_mmap size + mmap regions in *_plat_arch_setup
+ */
+#if defined(IMAGE_BL32)
+#define MAX_MMAP_REGIONS 10
+#endif
+
+/*******************************************************************************
+ * STM32MP1 RAW partition offset for devices without GPT
+ ******************************************************************************/
+#define STM32MP_EMMC_BOOT_FIP_OFFSET U(0x00040000)
+#ifndef STM32MP_NOR_FIP_OFFSET
+#define STM32MP_NOR_FIP_OFFSET U(0x00080000)
+#endif
+#ifndef STM32MP_NAND_FIP_OFFSET
+#define STM32MP_NAND_FIP_OFFSET U(0x00200000)
+#endif
+
+#endif /* STM32MP1_FIP_DEF_H */
diff --git a/plat/st/stm32mp1/stm32mp1_gic.c b/plat/st/stm32mp1/stm32mp1_gic.c
new file mode 100644
index 0000000..851a9cf
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_gic.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <libfdt.h>
+
+#include <platform_def.h>
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/gicv2.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <lib/utils.h>
+#include <plat/common/platform.h>
+
+struct stm32_gic_instance {
+ uint32_t cells;
+ uint32_t phandle_node;
+};
+
+/******************************************************************************
+ * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
+ * interrupts.
+ *****************************************************************************/
+static const interrupt_prop_t stm32mp1_interrupt_props[] = {
+ PLATFORM_G1S_PROPS(GICV2_INTR_GROUP0),
+ PLATFORM_G0_PROPS(GICV2_INTR_GROUP0)
+};
+
+/* Fix target_mask_array as secondary core is not able to initialize it */
+static unsigned int target_mask_array[PLATFORM_CORE_COUNT] = {1, 2};
+
+static gicv2_driver_data_t platform_gic_data = {
+ .interrupt_props = stm32mp1_interrupt_props,
+ .interrupt_props_num = ARRAY_SIZE(stm32mp1_interrupt_props),
+ .target_masks = target_mask_array,
+ .target_masks_num = ARRAY_SIZE(target_mask_array),
+};
+
+static struct stm32_gic_instance stm32_gic;
+
+void stm32mp1_gic_init(void)
+{
+ int node;
+ void *fdt;
+ const fdt32_t *cuint;
+ struct dt_node_info dt_gic;
+
+ if (fdt_get_address(&fdt) == 0) {
+ panic();
+ }
+
+ node = dt_get_node(&dt_gic, -1, "arm,cortex-a7-gic");
+ if (node < 0) {
+ panic();
+ }
+
+ platform_gic_data.gicd_base = dt_gic.base;
+
+ cuint = fdt_getprop(fdt, node, "reg", NULL);
+ if (cuint == NULL) {
+ panic();
+ }
+
+ platform_gic_data.gicc_base = fdt32_to_cpu(*(cuint + 2));
+
+ cuint = fdt_getprop(fdt, node, "#interrupt-cells", NULL);
+ if (cuint == NULL) {
+ panic();
+ }
+
+ stm32_gic.cells = fdt32_to_cpu(*cuint);
+
+ stm32_gic.phandle_node = fdt_get_phandle(fdt, node);
+ if (stm32_gic.phandle_node == 0U) {
+ panic();
+ }
+
+ gicv2_driver_init(&platform_gic_data);
+ gicv2_distif_init();
+
+ stm32mp1_gic_pcpu_init();
+}
+
+void stm32mp1_gic_pcpu_init(void)
+{
+ gicv2_pcpu_distif_init();
+ gicv2_set_pe_target_mask(plat_my_core_pos());
+ gicv2_cpuif_enable();
+}
diff --git a/plat/st/stm32mp1/stm32mp1_helper.S b/plat/st/stm32mp1/stm32mp1_helper.S
new file mode 100644
index 0000000..eb8823b
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_helper.S
@@ -0,0 +1,336 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <common/bl_common.h>
+#include <drivers/st/stm32_gpio.h>
+
+#define GPIO_TX_SHIFT (DEBUG_UART_TX_GPIO_PORT << 1)
+
+ .globl platform_mem_init
+ .globl plat_report_exception
+ .globl plat_report_prefetch_abort
+ .globl plat_report_data_abort
+ .globl plat_get_my_entrypoint
+ .globl plat_secondary_cold_boot_setup
+ .globl plat_reset_handler
+ .globl plat_is_my_cpu_primary
+ .globl plat_my_core_pos
+ .globl plat_crash_console_init
+ .globl plat_crash_console_flush
+ .globl plat_crash_console_putc
+ .globl plat_panic_handler
+
+func platform_mem_init
+ /* Nothing to do, don't need to init SYSRAM */
+ bx lr
+endfunc platform_mem_init
+
+#if DEBUG
+func plat_report_exception
+ mov r8, lr
+
+ /*
+ * Test if an abort occurred
+ * In this case the error message has already been displayed
+ * by dedicated functions
+ */
+ cmp r0, #MODE32_abt
+ beq 1f
+
+ /* Test for an undefined instruction */
+ cmp r0, #MODE32_und
+ bne other_exception_lbl
+ ldr r4, =undefined_str
+ bl asm_print_str
+ mrs r4, lr_und
+ b print_exception_info
+
+other_exception_lbl:
+ /* Other exceptions */
+ mov r9, r0
+ ldr r4, =exception_start_str
+ bl asm_print_str
+ mov r4, r9
+ bl asm_print_hex
+ ldr r4, =exception_end_str
+ bl asm_print_str
+ mov r4, r6
+
+print_exception_info:
+ bl asm_print_hex
+
+ ldr r4, =end_error_str
+ bl asm_print_str
+
+1:
+ bx r8
+endfunc plat_report_exception
+
+func plat_report_prefetch_abort
+ mov r8, lr
+ mov r9, r0
+
+ ldr r4, =prefetch_abort_str
+ bl asm_print_str
+
+ mov r4, r9
+ sub r4, r4, #4
+ bl asm_print_hex
+
+ ldr r4, =ifsr_str
+ bl asm_print_str
+
+ ldcopr r4, IFSR
+ bl asm_print_hex
+
+ ldr r4, =ifar_str
+ bl asm_print_str
+
+ ldcopr r4, IFAR
+ bl asm_print_hex
+
+ ldr r4, =end_error_str
+ bl asm_print_str
+
+ bx r8
+endfunc plat_report_prefetch_abort
+
+func plat_report_data_abort
+ mov r8, lr
+ mov r9, r0
+
+ ldr r4, =data_abort_str
+ bl asm_print_str
+
+ mov r4, r9
+ sub r4, r4, #8
+ bl asm_print_hex
+
+ ldr r4, =dfsr_str
+ bl asm_print_str
+
+ ldcopr r4, DFSR
+ bl asm_print_hex
+
+ ldr r4, =dfar_str
+ bl asm_print_str
+
+ ldcopr r4, DFAR
+ bl asm_print_hex
+
+ ldr r4, =end_error_str
+ bl asm_print_str
+
+ bx r8
+endfunc plat_report_data_abort
+#endif /* DEBUG */
+
+func plat_reset_handler
+ bx lr
+endfunc plat_reset_handler
+
+ /* ------------------------------------------------------------------
+ * unsigned long plat_get_my_entrypoint (void);
+ *
+ * Main job of this routine is to distinguish between a cold and warm
+ * boot.
+ *
+ * Currently supports only cold boot
+ * ------------------------------------------------------------------
+ */
+func plat_get_my_entrypoint
+ mov r0, #0
+ bx lr
+endfunc plat_get_my_entrypoint
+
+ /* ---------------------------------------------
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * Cold-booting secondary CPUs is not supported.
+ * ---------------------------------------------
+ */
+func plat_secondary_cold_boot_setup
+ b .
+endfunc plat_secondary_cold_boot_setup
+
+ /* -----------------------------------------------------
+ * unsigned int plat_is_my_cpu_primary (void);
+ *
+ * Find out whether the current cpu is the primary cpu.
+ * -----------------------------------------------------
+ */
+func plat_is_my_cpu_primary
+ ldcopr r0, MPIDR
+ ldr r1, =(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+ and r0, r1
+ cmp r0, #STM32MP_PRIMARY_CPU
+ moveq r0, #1
+ movne r0, #0
+ bx lr
+endfunc plat_is_my_cpu_primary
+
+ /* -------------------------------------------
+ * int plat_stm32mp1_get_core_pos(int mpidr);
+ *
+ * Return CorePos = (ClusterId * 4) + CoreId
+ * -------------------------------------------
+ */
+func plat_stm32mp1_get_core_pos
+ and r1, r0, #MPIDR_CPU_MASK
+ and r0, r0, #MPIDR_CLUSTER_MASK
+ add r0, r1, r0, LSR #6
+ bx lr
+endfunc plat_stm32mp1_get_core_pos
+
+ /* ------------------------------------
+ * unsigned int plat_my_core_pos(void)
+ * ------------------------------------
+ */
+func plat_my_core_pos
+ ldcopr r0, MPIDR
+ b plat_stm32mp1_get_core_pos
+endfunc plat_my_core_pos
+
+ /* ---------------------------------------------
+ * int plat_crash_console_init(void)
+ *
+ * Initialize the crash console without a C Runtime stack.
+ * ---------------------------------------------
+ */
+func plat_crash_console_init
+ /* Reset UART peripheral */
+ ldr r1, =(RCC_BASE + DEBUG_UART_RST_REG)
+ ldr r2, =DEBUG_UART_RST_BIT
+ str r2, [r1]
+1:
+ ldr r0, [r1]
+ ands r2, r0, r2
+ beq 1b
+ str r2, [r1, #4] /* RSTCLR register */
+2:
+ ldr r0, [r1]
+ ands r2, r0, r2
+ bne 2b
+ /* Enable GPIOs for UART TX */
+ ldr r1, =(RCC_BASE + DEBUG_UART_TX_GPIO_BANK_CLK_REG)
+ ldr r2, [r1]
+ /* Configure GPIO */
+ orr r2, r2, #DEBUG_UART_TX_GPIO_BANK_CLK_EN
+ str r2, [r1]
+ ldr r1, =DEBUG_UART_TX_GPIO_BANK_ADDRESS
+ /* Set GPIO mode alternate */
+ ldr r2, [r1, #GPIO_MODE_OFFSET]
+ bic r2, r2, #(GPIO_MODE_MASK << GPIO_TX_SHIFT)
+ orr r2, r2, #(GPIO_MODE_ALTERNATE << GPIO_TX_SHIFT)
+ str r2, [r1, #GPIO_MODE_OFFSET]
+ /* Set GPIO speed low */
+ ldr r2, [r1, #GPIO_SPEED_OFFSET]
+ bic r2, r2, #(GPIO_SPEED_MASK << GPIO_TX_SHIFT)
+ str r2, [r1, #GPIO_SPEED_OFFSET]
+ /* Set no-pull */
+ ldr r2, [r1, #GPIO_PUPD_OFFSET]
+ bic r2, r2, #(GPIO_PULL_MASK << GPIO_TX_SHIFT)
+ str r2, [r1, #GPIO_PUPD_OFFSET]
+ /* Set alternate */
+#if DEBUG_UART_TX_GPIO_PORT >= GPIO_ALT_LOWER_LIMIT
+ ldr r2, [r1, #GPIO_AFRH_OFFSET]
+ bic r2, r2, #(GPIO_ALTERNATE_MASK << \
+ ((DEBUG_UART_TX_GPIO_PORT - GPIO_ALT_LOWER_LIMIT) << 2))
+ orr r2, r2, #(DEBUG_UART_TX_GPIO_ALTERNATE << \
+ ((DEBUG_UART_TX_GPIO_PORT - GPIO_ALT_LOWER_LIMIT) << 2))
+ str r2, [r1, #GPIO_AFRH_OFFSET]
+#else
+ ldr r2, [r1, #GPIO_AFRL_OFFSET]
+ bic r2, r2, #(GPIO_ALTERNATE_MASK << (DEBUG_UART_TX_GPIO_PORT << 2))
+ orr r2, r2, #(DEBUG_UART_TX_GPIO_ALTERNATE << (DEBUG_UART_TX_GPIO_PORT << 2))
+ str r2, [r1, #GPIO_AFRL_OFFSET]
+#endif
+ /* Enable UART clock, with its source */
+ ldr r1, =(RCC_BASE + DEBUG_UART_TX_CLKSRC_REG)
+ mov r2, #DEBUG_UART_TX_CLKSRC
+ str r2, [r1]
+ ldr r1, =(RCC_BASE + DEBUG_UART_TX_EN_REG)
+ ldr r2, [r1]
+ orr r2, r2, #DEBUG_UART_TX_EN
+ str r2, [r1]
+
+ ldr r0, =STM32MP_DEBUG_USART_BASE
+ ldr r1, =STM32MP_DEBUG_USART_CLK_FRQ
+ ldr r2, =STM32MP_UART_BAUDRATE
+ b console_stm32_core_init
+endfunc plat_crash_console_init
+
+ /* ---------------------------------------------
+ * void plat_crash_console_flush(void)
+ *
+ * Flush the crash console without a C Runtime stack.
+ * ---------------------------------------------
+ */
+func plat_crash_console_flush
+ ldr r0, =STM32MP_DEBUG_USART_BASE
+ b console_stm32_core_flush
+endfunc plat_crash_console_flush
+
+ /* ---------------------------------------------
+ * int plat_crash_console_putc(int c)
+ *
+ * Print a character on the crash console without a C Runtime stack.
+ * Clobber list : r1 - r3
+ *
+ * In case of bootloading through uart, we keep console crash as this.
+ * Characters could be sent to the programmer, but will be ignored.
+ * No specific code in that case.
+ * ---------------------------------------------
+ */
+func plat_crash_console_putc
+ ldr r1, =STM32MP_DEBUG_USART_BASE
+ b console_stm32_core_putc
+endfunc plat_crash_console_putc
+
+ /* ----------------------------------------------------------
+ * void plat_panic_handler(void) __dead2;
+ * Report exception + endless loop.
+ *
+ * r6 holds the address where the fault occurred.
+ * Filling lr with this value allows debuggers to reconstruct
+ * the backtrace.
+ * ----------------------------------------------------------
+ */
+func plat_panic_handler
+ mrs r0, cpsr
+ and r0, #MODE32_MASK
+ bl plat_report_exception
+ mov lr, r6
+ b .
+endfunc plat_panic_handler
+
+#if DEBUG
+.section .rodata.rev_err_str, "aS"
+prefetch_abort_str:
+ .asciz "\nPrefetch Abort at: 0x"
+data_abort_str:
+ .asciz "\nData Abort at: 0x"
+undefined_str:
+ .asciz "\nUndefined instruction at: 0x"
+exception_start_str:
+ .asciz "\nException mode=0x"
+exception_end_str:
+ .asciz " at: 0x"
+dfsr_str:
+ .asciz " DFSR = 0x"
+dfar_str:
+ .asciz " DFAR = 0x"
+ifsr_str:
+ .asciz " IFSR = 0x"
+ifar_str:
+ .asciz " IFAR = 0x"
+end_error_str:
+ .asciz "\n\r"
+#endif
diff --git a/plat/st/stm32mp1/stm32mp1_pm.c b/plat/st/stm32mp1/stm32mp1_pm.c
new file mode 100644
index 0000000..6e438c4
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_pm.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <arch_helpers.h>
+#include <bl32/sp_min/platform_sp_min.h>
+#include <common/debug.h>
+#include <drivers/arm/gic_common.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/clk.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <plat/common/platform.h>
+
+#include <platform_def.h>
+
+static uintptr_t stm32_sec_entrypoint;
+static uint32_t cntfrq_core0;
+
+/*******************************************************************************
+ * STM32MP1 handler called when a CPU is about to enter standby.
+ * call by core 1 to enter in wfi
+ ******************************************************************************/
+static void stm32_cpu_standby(plat_local_state_t cpu_state)
+{
+ uint32_t interrupt = GIC_SPURIOUS_INTERRUPT;
+
+ assert(cpu_state == ARM_LOCAL_STATE_RET);
+
+ /*
+ * Enter standby state
+ * dsb is good practice before using wfi to enter low power states
+ */
+ isb();
+ dsb();
+ while (interrupt == GIC_SPURIOUS_INTERRUPT) {
+ wfi();
+
+ /* Acknoledge IT */
+ interrupt = gicv2_acknowledge_interrupt();
+ /* If Interrupt == 1022 it will be acknowledged by non secure */
+ if ((interrupt != PENDING_G1_INTID) &&
+ (interrupt != GIC_SPURIOUS_INTERRUPT)) {
+ gicv2_end_of_interrupt(interrupt);
+ }
+ }
+}
+
+/*******************************************************************************
+ * STM32MP1 handler called when a power domain is about to be turned on. The
+ * mpidr determines the CPU to be turned on.
+ * call by core 0 to activate core 1
+ ******************************************************************************/
+static int stm32_pwr_domain_on(u_register_t mpidr)
+{
+ unsigned long current_cpu_mpidr = read_mpidr_el1();
+ uintptr_t bkpr_core1_addr =
+ tamp_bkpr(BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX);
+ uintptr_t bkpr_core1_magic =
+ tamp_bkpr(BOOT_API_CORE1_MAGIC_NUMBER_TAMP_BCK_REG_IDX);
+
+ if (mpidr == current_cpu_mpidr) {
+ return PSCI_E_INVALID_PARAMS;
+ }
+
+ /* Only one valid entry point */
+ if (stm32_sec_entrypoint != (uintptr_t)&sp_min_warm_entrypoint) {
+ return PSCI_E_INVALID_ADDRESS;
+ }
+
+ clk_enable(RTCAPB);
+
+ cntfrq_core0 = read_cntfrq_el0();
+
+ /* Write entrypoint in backup RAM register */
+ mmio_write_32(bkpr_core1_addr, stm32_sec_entrypoint);
+
+ /* Write magic number in backup register */
+ mmio_write_32(bkpr_core1_magic, BOOT_API_A7_CORE1_MAGIC_NUMBER);
+
+ clk_disable(RTCAPB);
+
+ /* Generate an IT to core 1 */
+ gicv2_raise_sgi(ARM_IRQ_SEC_SGI_0, false, STM32MP_SECONDARY_CPU);
+
+ return PSCI_E_SUCCESS;
+}
+
+/*******************************************************************************
+ * STM32MP1 handler called when a power domain is about to be turned off. The
+ * target_state encodes the power state that each level should transition to.
+ ******************************************************************************/
+static void stm32_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ /* Nothing to do */
+}
+
+/*******************************************************************************
+ * STM32MP1 handler called when a power domain is about to be suspended. The
+ * target_state encodes the power state that each level should transition to.
+ ******************************************************************************/
+static void stm32_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+ /* Nothing to do, power domain is not disabled */
+}
+
+/*******************************************************************************
+ * STM32MP1 handler called when a power domain has just been powered on after
+ * being turned off earlier. The target_state encodes the low power state that
+ * each level has woken up from.
+ * call by core 1 just after wake up
+ ******************************************************************************/
+static void stm32_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ stm32mp1_gic_pcpu_init();
+
+ write_cntfrq_el0(cntfrq_core0);
+}
+
+/*******************************************************************************
+ * STM32MP1 handler called when a power domain has just been powered on after
+ * having been suspended earlier. The target_state encodes the low power state
+ * that each level has woken up from.
+ ******************************************************************************/
+static void stm32_pwr_domain_suspend_finish(const psci_power_state_t
+ *target_state)
+{
+ /* Nothing to do, power domain is not disabled */
+}
+
+static void __dead2 stm32_pwr_domain_pwr_down_wfi(const psci_power_state_t
+ *target_state)
+{
+ ERROR("stm32mpu1 Power Down WFI: operation not handled.\n");
+ panic();
+}
+
+static void __dead2 stm32_system_off(void)
+{
+ ERROR("stm32mpu1 System Off: operation not handled.\n");
+ panic();
+}
+
+static void __dead2 stm32_system_reset(void)
+{
+ mmio_setbits_32(stm32mp_rcc_base() + RCC_MP_GRSTCSETR,
+ RCC_MP_GRSTCSETR_MPSYSRST);
+
+ /* Loop in case system reset is not immediately caught */
+ for ( ; ; ) {
+ ;
+ }
+}
+
+static int stm32_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ int pstate = psci_get_pstate_type(power_state);
+
+ if (pstate != 0) {
+ return PSCI_E_INVALID_PARAMS;
+ }
+
+ if (psci_get_pstate_pwrlvl(power_state)) {
+ return PSCI_E_INVALID_PARAMS;
+ }
+
+ if (psci_get_pstate_id(power_state)) {
+ return PSCI_E_INVALID_PARAMS;
+ }
+
+ req_state->pwr_domain_state[0] = ARM_LOCAL_STATE_RET;
+ req_state->pwr_domain_state[1] = ARM_LOCAL_STATE_RUN;
+
+ return PSCI_E_SUCCESS;
+}
+
+static int stm32_validate_ns_entrypoint(uintptr_t entrypoint)
+{
+ /* The non-secure entry point must be in DDR */
+ if (entrypoint < STM32MP_DDR_BASE) {
+ return PSCI_E_INVALID_ADDRESS;
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
+static int stm32_node_hw_state(u_register_t target_cpu,
+ unsigned int power_level)
+{
+ /*
+ * The format of 'power_level' is implementation-defined, but 0 must
+ * mean a CPU. Only allow level 0.
+ */
+ if (power_level != MPIDR_AFFLVL0) {
+ return PSCI_E_INVALID_PARAMS;
+ }
+
+ /*
+ * From psci view the CPU 0 is always ON,
+ * CPU 1 can be SUSPEND or RUNNING.
+ * Therefore do not manage POWER OFF state and always return HW_ON.
+ */
+
+ return (int)HW_ON;
+}
+
+/*******************************************************************************
+ * Export the platform handlers. The ARM Standard platform layer will take care
+ * of registering the handlers with PSCI.
+ ******************************************************************************/
+static const plat_psci_ops_t stm32_psci_ops = {
+ .cpu_standby = stm32_cpu_standby,
+ .pwr_domain_on = stm32_pwr_domain_on,
+ .pwr_domain_off = stm32_pwr_domain_off,
+ .pwr_domain_suspend = stm32_pwr_domain_suspend,
+ .pwr_domain_on_finish = stm32_pwr_domain_on_finish,
+ .pwr_domain_suspend_finish = stm32_pwr_domain_suspend_finish,
+ .pwr_domain_pwr_down_wfi = stm32_pwr_domain_pwr_down_wfi,
+ .system_off = stm32_system_off,
+ .system_reset = stm32_system_reset,
+ .validate_power_state = stm32_validate_power_state,
+ .validate_ns_entrypoint = stm32_validate_ns_entrypoint,
+ .get_node_hw_state = stm32_node_hw_state
+};
+
+/*******************************************************************************
+ * Export the platform specific power ops.
+ ******************************************************************************/
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const plat_psci_ops_t **psci_ops)
+{
+ stm32_sec_entrypoint = sec_entrypoint;
+ *psci_ops = &stm32_psci_ops;
+
+ return 0;
+}
diff --git a/plat/st/stm32mp1/stm32mp1_private.c b/plat/st/stm32mp1/stm32mp1_private.c
new file mode 100644
index 0000000..9bdb075
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_private.c
@@ -0,0 +1,788 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <drivers/clk.h>
+#include <drivers/st/stm32_gpio.h>
+#include <drivers/st/stm32_iwdg.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <libfdt.h>
+
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+/* Internal layout of the 32bit OTP word board_id */
+#define BOARD_ID_BOARD_NB_MASK GENMASK(31, 16)
+#define BOARD_ID_BOARD_NB_SHIFT 16
+#define BOARD_ID_VARCPN_MASK GENMASK(15, 12)
+#define BOARD_ID_VARCPN_SHIFT 12
+#define BOARD_ID_REVISION_MASK GENMASK(11, 8)
+#define BOARD_ID_REVISION_SHIFT 8
+#define BOARD_ID_VARFG_MASK GENMASK(7, 4)
+#define BOARD_ID_VARFG_SHIFT 4
+#define BOARD_ID_BOM_MASK GENMASK(3, 0)
+
+#define BOARD_ID2NB(_id) (((_id) & BOARD_ID_BOARD_NB_MASK) >> \
+ BOARD_ID_BOARD_NB_SHIFT)
+#define BOARD_ID2VARCPN(_id) (((_id) & BOARD_ID_VARCPN_MASK) >> \
+ BOARD_ID_VARCPN_SHIFT)
+#define BOARD_ID2REV(_id) (((_id) & BOARD_ID_REVISION_MASK) >> \
+ BOARD_ID_REVISION_SHIFT)
+#define BOARD_ID2VARFG(_id) (((_id) & BOARD_ID_VARFG_MASK) >> \
+ BOARD_ID_VARFG_SHIFT)
+#define BOARD_ID2BOM(_id) ((_id) & BOARD_ID_BOM_MASK)
+
+#if STM32MP13
+#define TAMP_BOOT_MODE_BACKUP_REG_ID U(30)
+#endif
+#if STM32MP15
+#define TAMP_BOOT_MODE_BACKUP_REG_ID U(20)
+#endif
+#define TAMP_BOOT_MODE_ITF_MASK GENMASK(15, 8)
+#define TAMP_BOOT_MODE_ITF_SHIFT 8
+#define TAMP_BOOT_MODE_AUTH_MASK GENMASK(23, 16)
+#define TAMP_BOOT_MODE_AUTH_SHIFT 16
+
+/*
+ * Backup register to store fwu update information.
+ * It should be writeable only by secure world, but also readable by non secure
+ * (so it should be in Zone 2).
+ */
+#define TAMP_BOOT_FWU_INFO_REG_ID U(10)
+#define TAMP_BOOT_FWU_INFO_IDX_MSK GENMASK(3, 0)
+#define TAMP_BOOT_FWU_INFO_IDX_OFF U(0)
+#define TAMP_BOOT_FWU_INFO_CNT_MSK GENMASK(7, 4)
+#define TAMP_BOOT_FWU_INFO_CNT_OFF U(4)
+
+#if defined(IMAGE_BL2)
+#define MAP_SEC_SYSRAM MAP_REGION_FLAT(STM32MP_SYSRAM_BASE, \
+ STM32MP_SYSRAM_SIZE, \
+ MT_MEMORY | \
+ MT_RW | \
+ MT_SECURE | \
+ MT_EXECUTE_NEVER)
+#elif defined(IMAGE_BL32)
+#define MAP_SEC_SYSRAM MAP_REGION_FLAT(STM32MP_SEC_SYSRAM_BASE, \
+ STM32MP_SEC_SYSRAM_SIZE, \
+ MT_MEMORY | \
+ MT_RW | \
+ MT_SECURE | \
+ MT_EXECUTE_NEVER)
+
+/* Non-secure SYSRAM is used a uncached memory for SCMI message transfer */
+#define MAP_NS_SYSRAM MAP_REGION_FLAT(STM32MP_NS_SYSRAM_BASE, \
+ STM32MP_NS_SYSRAM_SIZE, \
+ MT_DEVICE | \
+ MT_RW | \
+ MT_NS | \
+ MT_EXECUTE_NEVER)
+#endif
+
+#if STM32MP13
+#define MAP_SRAM_ALL MAP_REGION_FLAT(SRAMS_BASE, \
+ SRAMS_SIZE_2MB_ALIGNED, \
+ MT_MEMORY | \
+ MT_RW | \
+ MT_SECURE | \
+ MT_EXECUTE_NEVER)
+#endif
+
+#define MAP_DEVICE1 MAP_REGION_FLAT(STM32MP1_DEVICE1_BASE, \
+ STM32MP1_DEVICE1_SIZE, \
+ MT_DEVICE | \
+ MT_RW | \
+ MT_SECURE | \
+ MT_EXECUTE_NEVER)
+
+#define MAP_DEVICE2 MAP_REGION_FLAT(STM32MP1_DEVICE2_BASE, \
+ STM32MP1_DEVICE2_SIZE, \
+ MT_DEVICE | \
+ MT_RW | \
+ MT_SECURE | \
+ MT_EXECUTE_NEVER)
+
+#if defined(IMAGE_BL2)
+static const mmap_region_t stm32mp1_mmap[] = {
+ MAP_SEC_SYSRAM,
+#if STM32MP13
+ MAP_SRAM_ALL,
+#endif
+ MAP_DEVICE1,
+#if STM32MP_RAW_NAND
+ MAP_DEVICE2,
+#endif
+ {0}
+};
+#endif
+#if defined(IMAGE_BL32)
+static const mmap_region_t stm32mp1_mmap[] = {
+ MAP_SEC_SYSRAM,
+ MAP_NS_SYSRAM,
+ MAP_DEVICE1,
+ MAP_DEVICE2,
+ {0}
+};
+#endif
+
+void configure_mmu(void)
+{
+ mmap_add(stm32mp1_mmap);
+ init_xlat_tables();
+
+ enable_mmu_svc_mon(0);
+}
+
+uintptr_t stm32_get_gpio_bank_base(unsigned int bank)
+{
+#if STM32MP13
+ assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_I);
+#endif
+#if STM32MP15
+ if (bank == GPIO_BANK_Z) {
+ return GPIOZ_BASE;
+ }
+
+ assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_K);
+#endif
+
+ return GPIOA_BASE + (bank * GPIO_BANK_OFFSET);
+}
+
+uint32_t stm32_get_gpio_bank_offset(unsigned int bank)
+{
+#if STM32MP13
+ assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_I);
+#endif
+#if STM32MP15
+ if (bank == GPIO_BANK_Z) {
+ return 0;
+ }
+
+ assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_K);
+#endif
+
+ return bank * GPIO_BANK_OFFSET;
+}
+
+bool stm32_gpio_is_secure_at_reset(unsigned int bank)
+{
+#if STM32MP13
+ return true;
+#endif
+#if STM32MP15
+ if (bank == GPIO_BANK_Z) {
+ return true;
+ }
+
+ return false;
+#endif
+}
+
+unsigned long stm32_get_gpio_bank_clock(unsigned int bank)
+{
+#if STM32MP13
+ assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_I);
+#endif
+#if STM32MP15
+ if (bank == GPIO_BANK_Z) {
+ return GPIOZ;
+ }
+
+ assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_K);
+#endif
+
+ return GPIOA + (bank - GPIO_BANK_A);
+}
+
+int stm32_get_gpio_bank_pinctrl_node(void *fdt, unsigned int bank)
+{
+ const char *node_compatible = NULL;
+
+ switch (bank) {
+ case GPIO_BANK_A:
+ case GPIO_BANK_B:
+ case GPIO_BANK_C:
+ case GPIO_BANK_D:
+ case GPIO_BANK_E:
+ case GPIO_BANK_F:
+ case GPIO_BANK_G:
+ case GPIO_BANK_H:
+ case GPIO_BANK_I:
+#if STM32MP13
+ node_compatible = "st,stm32mp135-pinctrl";
+ break;
+#endif
+#if STM32MP15
+ case GPIO_BANK_J:
+ case GPIO_BANK_K:
+ node_compatible = "st,stm32mp157-pinctrl";
+ break;
+ case GPIO_BANK_Z:
+ node_compatible = "st,stm32mp157-z-pinctrl";
+ break;
+#endif
+ default:
+ panic();
+ }
+
+ return fdt_node_offset_by_compatible(fdt, -1, node_compatible);
+}
+
+#if STM32MP_UART_PROGRAMMER || !defined(IMAGE_BL2)
+/*
+ * UART Management
+ */
+static const uintptr_t stm32mp1_uart_addresses[8] = {
+ USART1_BASE,
+ USART2_BASE,
+ USART3_BASE,
+ UART4_BASE,
+ UART5_BASE,
+ USART6_BASE,
+ UART7_BASE,
+ UART8_BASE,
+};
+
+uintptr_t get_uart_address(uint32_t instance_nb)
+{
+ if ((instance_nb == 0U) ||
+ (instance_nb > ARRAY_SIZE(stm32mp1_uart_addresses))) {
+ return 0U;
+ }
+
+ return stm32mp1_uart_addresses[instance_nb - 1U];
+}
+#endif
+
+#if STM32MP_USB_PROGRAMMER
+struct gpio_bank_pin_list {
+ uint32_t bank;
+ uint32_t pin;
+};
+
+static const struct gpio_bank_pin_list gpio_list[] = {
+ { /* USART2_RX: GPIOA3 */
+ .bank = 0U,
+ .pin = 3U,
+ },
+ { /* USART3_RX: GPIOB12 */
+ .bank = 1U,
+ .pin = 12U,
+ },
+ { /* UART4_RX: GPIOB2 */
+ .bank = 1U,
+ .pin = 2U,
+ },
+ { /* UART5_RX: GPIOB4 */
+ .bank = 1U,
+ .pin = 5U,
+ },
+ { /* USART6_RX: GPIOC7 */
+ .bank = 2U,
+ .pin = 7U,
+ },
+ { /* UART7_RX: GPIOF6 */
+ .bank = 5U,
+ .pin = 6U,
+ },
+ { /* UART8_RX: GPIOE0 */
+ .bank = 4U,
+ .pin = 0U,
+ },
+};
+
+void stm32mp1_deconfigure_uart_pins(void)
+{
+ size_t i;
+
+ for (i = 0U; i < ARRAY_SIZE(gpio_list); i++) {
+ set_gpio_reset_cfg(gpio_list[i].bank, gpio_list[i].pin);
+ }
+}
+#endif
+
+uint32_t stm32mp_get_chip_version(void)
+{
+#if STM32MP13
+ return stm32mp1_syscfg_get_chip_version();
+#endif
+#if STM32MP15
+ uint32_t version = 0U;
+
+ if (stm32mp1_dbgmcu_get_chip_version(&version) < 0) {
+ INFO("Cannot get CPU version, debug disabled\n");
+ return 0U;
+ }
+
+ return version;
+#endif
+}
+
+uint32_t stm32mp_get_chip_dev_id(void)
+{
+#if STM32MP13
+ return stm32mp1_syscfg_get_chip_dev_id();
+#endif
+#if STM32MP15
+ uint32_t dev_id;
+
+ if (stm32mp1_dbgmcu_get_chip_dev_id(&dev_id) < 0) {
+ INFO("Use default chip ID, debug disabled\n");
+ dev_id = STM32MP1_CHIP_ID;
+ }
+
+ return dev_id;
+#endif
+}
+
+static uint32_t get_part_number(void)
+{
+ static uint32_t part_number;
+
+ if (part_number != 0U) {
+ return part_number;
+ }
+
+ if (stm32_get_otp_value(PART_NUMBER_OTP, &part_number) != 0) {
+ panic();
+ }
+
+ part_number = (part_number & PART_NUMBER_OTP_PART_MASK) >>
+ PART_NUMBER_OTP_PART_SHIFT;
+
+ part_number |= stm32mp_get_chip_dev_id() << 16;
+
+ return part_number;
+}
+
+#if STM32MP15
+static uint32_t get_cpu_package(void)
+{
+ uint32_t package;
+
+ if (stm32_get_otp_value(PACKAGE_OTP, &package) != 0) {
+ panic();
+ }
+
+ package = (package & PACKAGE_OTP_PKG_MASK) >>
+ PACKAGE_OTP_PKG_SHIFT;
+
+ return package;
+}
+#endif
+
+void stm32mp_get_soc_name(char name[STM32_SOC_NAME_SIZE])
+{
+ char *cpu_s, *cpu_r, *pkg;
+
+ /* MPUs Part Numbers */
+ switch (get_part_number()) {
+#if STM32MP13
+ case STM32MP135F_PART_NB:
+ cpu_s = "135F";
+ break;
+ case STM32MP135D_PART_NB:
+ cpu_s = "135D";
+ break;
+ case STM32MP135C_PART_NB:
+ cpu_s = "135C";
+ break;
+ case STM32MP135A_PART_NB:
+ cpu_s = "135A";
+ break;
+ case STM32MP133F_PART_NB:
+ cpu_s = "133F";
+ break;
+ case STM32MP133D_PART_NB:
+ cpu_s = "133D";
+ break;
+ case STM32MP133C_PART_NB:
+ cpu_s = "133C";
+ break;
+ case STM32MP133A_PART_NB:
+ cpu_s = "133A";
+ break;
+ case STM32MP131F_PART_NB:
+ cpu_s = "131F";
+ break;
+ case STM32MP131D_PART_NB:
+ cpu_s = "131D";
+ break;
+ case STM32MP131C_PART_NB:
+ cpu_s = "131C";
+ break;
+ case STM32MP131A_PART_NB:
+ cpu_s = "131A";
+ break;
+#endif
+#if STM32MP15
+ case STM32MP157C_PART_NB:
+ cpu_s = "157C";
+ break;
+ case STM32MP157A_PART_NB:
+ cpu_s = "157A";
+ break;
+ case STM32MP153C_PART_NB:
+ cpu_s = "153C";
+ break;
+ case STM32MP153A_PART_NB:
+ cpu_s = "153A";
+ break;
+ case STM32MP151C_PART_NB:
+ cpu_s = "151C";
+ break;
+ case STM32MP151A_PART_NB:
+ cpu_s = "151A";
+ break;
+ case STM32MP157F_PART_NB:
+ cpu_s = "157F";
+ break;
+ case STM32MP157D_PART_NB:
+ cpu_s = "157D";
+ break;
+ case STM32MP153F_PART_NB:
+ cpu_s = "153F";
+ break;
+ case STM32MP153D_PART_NB:
+ cpu_s = "153D";
+ break;
+ case STM32MP151F_PART_NB:
+ cpu_s = "151F";
+ break;
+ case STM32MP151D_PART_NB:
+ cpu_s = "151D";
+ break;
+#endif
+ default:
+ cpu_s = "????";
+ break;
+ }
+
+ /* Package */
+#if STM32MP13
+ /* On STM32MP13, package is not present in OTP */
+ pkg = "";
+#endif
+#if STM32MP15
+ switch (get_cpu_package()) {
+ case PKG_AA_LFBGA448:
+ pkg = "AA";
+ break;
+ case PKG_AB_LFBGA354:
+ pkg = "AB";
+ break;
+ case PKG_AC_TFBGA361:
+ pkg = "AC";
+ break;
+ case PKG_AD_TFBGA257:
+ pkg = "AD";
+ break;
+ default:
+ pkg = "??";
+ break;
+ }
+#endif
+
+ /* REVISION */
+ switch (stm32mp_get_chip_version()) {
+ case STM32MP1_REV_B:
+ cpu_r = "B";
+ break;
+#if STM32MP13
+ case STM32MP1_REV_Y:
+ cpu_r = "Y";
+ break;
+#endif
+ case STM32MP1_REV_Z:
+ cpu_r = "Z";
+ break;
+ default:
+ cpu_r = "?";
+ break;
+ }
+
+ snprintf(name, STM32_SOC_NAME_SIZE,
+ "STM32MP%s%s Rev.%s", cpu_s, pkg, cpu_r);
+}
+
+void stm32mp_print_cpuinfo(void)
+{
+ char name[STM32_SOC_NAME_SIZE];
+
+ stm32mp_get_soc_name(name);
+ NOTICE("CPU: %s\n", name);
+}
+
+void stm32mp_print_boardinfo(void)
+{
+ uint32_t board_id = 0;
+
+ if (stm32_get_otp_value(BOARD_ID_OTP, &board_id) != 0) {
+ return;
+ }
+
+ if (board_id != 0U) {
+ char rev[2];
+
+ rev[0] = BOARD_ID2REV(board_id) - 1 + 'A';
+ rev[1] = '\0';
+ NOTICE("Board: MB%04x Var%u.%u Rev.%s-%02u\n",
+ BOARD_ID2NB(board_id),
+ BOARD_ID2VARCPN(board_id),
+ BOARD_ID2VARFG(board_id),
+ rev,
+ BOARD_ID2BOM(board_id));
+ }
+}
+
+/* Return true when SoC provides a single Cortex-A7 core, and false otherwise */
+bool stm32mp_is_single_core(void)
+{
+#if STM32MP13
+ return true;
+#endif
+#if STM32MP15
+ bool single_core = false;
+
+ switch (get_part_number()) {
+ case STM32MP151A_PART_NB:
+ case STM32MP151C_PART_NB:
+ case STM32MP151D_PART_NB:
+ case STM32MP151F_PART_NB:
+ single_core = true;
+ break;
+ default:
+ break;
+ }
+
+ return single_core;
+#endif
+}
+
+/* Return true when device is in closed state */
+bool stm32mp_is_closed_device(void)
+{
+ uint32_t value;
+
+ if (stm32_get_otp_value(CFG0_OTP, &value) != 0) {
+ return true;
+ }
+
+#if STM32MP13
+ value = (value & CFG0_OTP_MODE_MASK) >> CFG0_OTP_MODE_SHIFT;
+
+ switch (value) {
+ case CFG0_OPEN_DEVICE:
+ return false;
+ case CFG0_CLOSED_DEVICE:
+ case CFG0_CLOSED_DEVICE_NO_BOUNDARY_SCAN:
+ case CFG0_CLOSED_DEVICE_NO_JTAG:
+ return true;
+ default:
+ panic();
+ }
+#endif
+#if STM32MP15
+ return (value & CFG0_CLOSED_DEVICE) == CFG0_CLOSED_DEVICE;
+#endif
+}
+
+/* Return true when device supports secure boot */
+bool stm32mp_is_auth_supported(void)
+{
+ bool supported = false;
+
+ switch (get_part_number()) {
+#if STM32MP13
+ case STM32MP131C_PART_NB:
+ case STM32MP131F_PART_NB:
+ case STM32MP133C_PART_NB:
+ case STM32MP133F_PART_NB:
+ case STM32MP135C_PART_NB:
+ case STM32MP135F_PART_NB:
+#endif
+#if STM32MP15
+ case STM32MP151C_PART_NB:
+ case STM32MP151F_PART_NB:
+ case STM32MP153C_PART_NB:
+ case STM32MP153F_PART_NB:
+ case STM32MP157C_PART_NB:
+ case STM32MP157F_PART_NB:
+#endif
+ supported = true;
+ break;
+ default:
+ break;
+ }
+
+ return supported;
+}
+
+uint32_t stm32_iwdg_get_instance(uintptr_t base)
+{
+ switch (base) {
+ case IWDG1_BASE:
+ return IWDG1_INST;
+ case IWDG2_BASE:
+ return IWDG2_INST;
+ default:
+ panic();
+ }
+}
+
+uint32_t stm32_iwdg_get_otp_config(uint32_t iwdg_inst)
+{
+ uint32_t iwdg_cfg = 0U;
+ uint32_t otp_value;
+
+ if (stm32_get_otp_value(HW2_OTP, &otp_value) != 0) {
+ panic();
+ }
+
+ if ((otp_value & BIT(iwdg_inst + HW2_OTP_IWDG_HW_POS)) != 0U) {
+ iwdg_cfg |= IWDG_HW_ENABLED;
+ }
+
+ if ((otp_value & BIT(iwdg_inst + HW2_OTP_IWDG_FZ_STOP_POS)) != 0U) {
+ iwdg_cfg |= IWDG_DISABLE_ON_STOP;
+ }
+
+ if ((otp_value & BIT(iwdg_inst + HW2_OTP_IWDG_FZ_STANDBY_POS)) != 0U) {
+ iwdg_cfg |= IWDG_DISABLE_ON_STANDBY;
+ }
+
+ return iwdg_cfg;
+}
+
+#if defined(IMAGE_BL2)
+uint32_t stm32_iwdg_shadow_update(uint32_t iwdg_inst, uint32_t flags)
+{
+ uint32_t otp_value;
+ uint32_t otp;
+ uint32_t result;
+
+ if (stm32_get_otp_index(HW2_OTP, &otp, NULL) != 0) {
+ panic();
+ }
+
+ if (stm32_get_otp_value(HW2_OTP, &otp_value) != 0) {
+ panic();
+ }
+
+ if ((flags & IWDG_DISABLE_ON_STOP) != 0) {
+ otp_value |= BIT(iwdg_inst + HW2_OTP_IWDG_FZ_STOP_POS);
+ }
+
+ if ((flags & IWDG_DISABLE_ON_STANDBY) != 0) {
+ otp_value |= BIT(iwdg_inst + HW2_OTP_IWDG_FZ_STANDBY_POS);
+ }
+
+ result = bsec_write_otp(otp_value, otp);
+ if (result != BSEC_OK) {
+ return result;
+ }
+
+ /* Sticky lock OTP_IWDG (read and write) */
+ if ((bsec_set_sr_lock(otp) != BSEC_OK) ||
+ (bsec_set_sw_lock(otp) != BSEC_OK)) {
+ return BSEC_LOCK_FAIL;
+ }
+
+ return BSEC_OK;
+}
+#endif
+
+void stm32_save_boot_interface(uint32_t interface, uint32_t instance)
+{
+ uintptr_t bkpr_itf_idx = tamp_bkpr(TAMP_BOOT_MODE_BACKUP_REG_ID);
+
+ clk_enable(RTCAPB);
+
+ mmio_clrsetbits_32(bkpr_itf_idx,
+ TAMP_BOOT_MODE_ITF_MASK,
+ ((interface << 4) | (instance & 0xFU)) <<
+ TAMP_BOOT_MODE_ITF_SHIFT);
+
+ clk_disable(RTCAPB);
+}
+
+void stm32_get_boot_interface(uint32_t *interface, uint32_t *instance)
+{
+ static uint32_t itf;
+
+ if (itf == 0U) {
+ uintptr_t bkpr = tamp_bkpr(TAMP_BOOT_MODE_BACKUP_REG_ID);
+
+ clk_enable(RTCAPB);
+
+ itf = (mmio_read_32(bkpr) & TAMP_BOOT_MODE_ITF_MASK) >>
+ TAMP_BOOT_MODE_ITF_SHIFT;
+
+ clk_disable(RTCAPB);
+ }
+
+ *interface = itf >> 4;
+ *instance = itf & 0xFU;
+}
+
+void stm32_save_boot_auth(uint32_t auth_status, uint32_t boot_partition)
+{
+ uint32_t boot_status = tamp_bkpr(TAMP_BOOT_MODE_BACKUP_REG_ID);
+
+ clk_enable(RTCAPB);
+
+ mmio_clrsetbits_32(boot_status,
+ TAMP_BOOT_MODE_AUTH_MASK,
+ ((auth_status << 4) | (boot_partition & 0xFU)) <<
+ TAMP_BOOT_MODE_AUTH_SHIFT);
+
+ clk_disable(RTCAPB);
+}
+
+#if PSA_FWU_SUPPORT
+void stm32mp1_fwu_set_boot_idx(void)
+{
+ clk_enable(RTCAPB);
+ mmio_clrsetbits_32(tamp_bkpr(TAMP_BOOT_FWU_INFO_REG_ID),
+ TAMP_BOOT_FWU_INFO_IDX_MSK,
+ (plat_fwu_get_boot_idx() << TAMP_BOOT_FWU_INFO_IDX_OFF) &
+ TAMP_BOOT_FWU_INFO_IDX_MSK);
+ clk_disable(RTCAPB);
+}
+
+uint32_t stm32_get_and_dec_fwu_trial_boot_cnt(void)
+{
+ uintptr_t bkpr_fwu_cnt = tamp_bkpr(TAMP_BOOT_FWU_INFO_REG_ID);
+ uint32_t try_cnt;
+
+ clk_enable(RTCAPB);
+ try_cnt = (mmio_read_32(bkpr_fwu_cnt) & TAMP_BOOT_FWU_INFO_CNT_MSK) >>
+ TAMP_BOOT_FWU_INFO_CNT_OFF;
+
+ assert(try_cnt <= FWU_MAX_TRIAL_REBOOT);
+
+ if (try_cnt != 0U) {
+ mmio_clrsetbits_32(bkpr_fwu_cnt, TAMP_BOOT_FWU_INFO_CNT_MSK,
+ (try_cnt - 1U) << TAMP_BOOT_FWU_INFO_CNT_OFF);
+ }
+ clk_disable(RTCAPB);
+
+ return try_cnt;
+}
+
+void stm32_set_max_fwu_trial_boot_cnt(void)
+{
+ uintptr_t bkpr_fwu_cnt = tamp_bkpr(TAMP_BOOT_FWU_INFO_REG_ID);
+
+ clk_enable(RTCAPB);
+ mmio_clrsetbits_32(bkpr_fwu_cnt, TAMP_BOOT_FWU_INFO_CNT_MSK,
+ (FWU_MAX_TRIAL_REBOOT << TAMP_BOOT_FWU_INFO_CNT_OFF) &
+ TAMP_BOOT_FWU_INFO_CNT_MSK);
+ clk_disable(RTCAPB);
+}
+#endif /* PSA_FWU_SUPPORT */
diff --git a/plat/st/stm32mp1/stm32mp1_scmi.c b/plat/st/stm32mp1/stm32mp1_scmi.c
new file mode 100644
index 0000000..98585dc
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_scmi.c
@@ -0,0 +1,479 @@
+/*
+ * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <assert.h>
+#include <stdint.h>
+
+#include <platform_def.h>
+
+#include <drivers/clk.h>
+#include <drivers/scmi-msg.h>
+#include <drivers/scmi.h>
+#include <drivers/st/stm32mp1_clk.h>
+#include <drivers/st/stm32mp_reset.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <dt-bindings/reset/stm32mp1-resets.h>
+
+#define TIMEOUT_US_1MS 1000U
+
+#define SCMI_CLOCK_NAME_SIZE 16U
+#define SCMI_RSTD_NAME_SIZE 16U
+
+/*
+ * struct stm32_scmi_clk - Data for the exposed clock
+ * @clock_id: Clock identifier in RCC clock driver
+ * @name: Clock string ID exposed to agent
+ * @enabled: State of the SCMI clock
+ */
+struct stm32_scmi_clk {
+ unsigned long clock_id;
+ const char *name;
+ bool enabled;
+};
+
+/*
+ * struct stm32_scmi_rstd - Data for the exposed reset controller
+ * @reset_id: Reset identifier in RCC reset driver
+ * @name: Reset string ID exposed to agent
+ */
+struct stm32_scmi_rstd {
+ unsigned long reset_id;
+ const char *name;
+};
+
+/* Locate all non-secure SMT message buffers in last page of SYSRAM */
+#define SMT_BUFFER_BASE STM32MP_SCMI_NS_SHM_BASE
+#define SMT_BUFFER0_BASE SMT_BUFFER_BASE
+#define SMT_BUFFER1_BASE (SMT_BUFFER_BASE + 0x200)
+
+CASSERT((STM32MP_SCMI_NS_SHM_BASE + STM32MP_SCMI_NS_SHM_SIZE) >=
+ (SMT_BUFFER1_BASE + SMT_BUF_SLOT_SIZE),
+ assert_scmi_non_secure_shm_fits_scmi_overall_buffer_size);
+
+static struct scmi_msg_channel scmi_channel[] = {
+ [0] = {
+ .shm_addr = SMT_BUFFER0_BASE,
+ .shm_size = SMT_BUF_SLOT_SIZE,
+ },
+ [1] = {
+ .shm_addr = SMT_BUFFER1_BASE,
+ .shm_size = SMT_BUF_SLOT_SIZE,
+ },
+};
+
+struct scmi_msg_channel *plat_scmi_get_channel(unsigned int agent_id)
+{
+ assert(agent_id < ARRAY_SIZE(scmi_channel));
+
+ return &scmi_channel[agent_id];
+}
+
+#define CLOCK_CELL(_scmi_id, _id, _name, _init_enabled) \
+ [_scmi_id] = { \
+ .clock_id = _id, \
+ .name = _name, \
+ .enabled = _init_enabled, \
+ }
+
+static struct stm32_scmi_clk stm32_scmi0_clock[] = {
+ CLOCK_CELL(CK_SCMI0_HSE, CK_HSE, "ck_hse", true),
+ CLOCK_CELL(CK_SCMI0_HSI, CK_HSI, "ck_hsi", true),
+ CLOCK_CELL(CK_SCMI0_CSI, CK_CSI, "ck_csi", true),
+ CLOCK_CELL(CK_SCMI0_LSE, CK_LSE, "ck_lse", true),
+ CLOCK_CELL(CK_SCMI0_LSI, CK_LSI, "ck_lsi", true),
+ CLOCK_CELL(CK_SCMI0_PLL2_Q, PLL2_Q, "pll2_q", true),
+ CLOCK_CELL(CK_SCMI0_PLL2_R, PLL2_R, "pll2_r", true),
+ CLOCK_CELL(CK_SCMI0_MPU, CK_MPU, "ck_mpu", true),
+ CLOCK_CELL(CK_SCMI0_AXI, CK_AXI, "ck_axi", true),
+ CLOCK_CELL(CK_SCMI0_BSEC, BSEC, "bsec", true),
+ CLOCK_CELL(CK_SCMI0_CRYP1, CRYP1, "cryp1", false),
+ CLOCK_CELL(CK_SCMI0_GPIOZ, GPIOZ, "gpioz", false),
+ CLOCK_CELL(CK_SCMI0_HASH1, HASH1, "hash1", false),
+ CLOCK_CELL(CK_SCMI0_I2C4, I2C4_K, "i2c4_k", false),
+ CLOCK_CELL(CK_SCMI0_I2C6, I2C6_K, "i2c6_k", false),
+ CLOCK_CELL(CK_SCMI0_IWDG1, IWDG1, "iwdg1", false),
+ CLOCK_CELL(CK_SCMI0_RNG1, RNG1_K, "rng1_k", true),
+ CLOCK_CELL(CK_SCMI0_RTC, RTC, "ck_rtc", true),
+ CLOCK_CELL(CK_SCMI0_RTCAPB, RTCAPB, "rtcapb", true),
+ CLOCK_CELL(CK_SCMI0_SPI6, SPI6_K, "spi6_k", false),
+ CLOCK_CELL(CK_SCMI0_USART1, USART1_K, "usart1_k", false),
+};
+
+static struct stm32_scmi_clk stm32_scmi1_clock[] = {
+ CLOCK_CELL(CK_SCMI1_PLL3_Q, PLL3_Q, "pll3_q", true),
+ CLOCK_CELL(CK_SCMI1_PLL3_R, PLL3_R, "pll3_r", true),
+ CLOCK_CELL(CK_SCMI1_MCU, CK_MCU, "ck_mcu", false),
+};
+
+#define RESET_CELL(_scmi_id, _id, _name) \
+ [_scmi_id] = { \
+ .reset_id = _id, \
+ .name = _name, \
+ }
+
+static struct stm32_scmi_rstd stm32_scmi0_reset_domain[] = {
+ RESET_CELL(RST_SCMI0_SPI6, SPI6_R, "spi6"),
+ RESET_CELL(RST_SCMI0_I2C4, I2C4_R, "i2c4"),
+ RESET_CELL(RST_SCMI0_I2C6, I2C6_R, "i2c6"),
+ RESET_CELL(RST_SCMI0_USART1, USART1_R, "usart1"),
+ RESET_CELL(RST_SCMI0_STGEN, STGEN_R, "stgen"),
+ RESET_CELL(RST_SCMI0_GPIOZ, GPIOZ_R, "gpioz"),
+ RESET_CELL(RST_SCMI0_CRYP1, CRYP1_R, "cryp1"),
+ RESET_CELL(RST_SCMI0_HASH1, HASH1_R, "hash1"),
+ RESET_CELL(RST_SCMI0_RNG1, RNG1_R, "rng1"),
+ RESET_CELL(RST_SCMI0_MDMA, MDMA_R, "mdma"),
+ RESET_CELL(RST_SCMI0_MCU, MCU_R, "mcu"),
+};
+
+struct scmi_agent_resources {
+ struct stm32_scmi_clk *clock;
+ size_t clock_count;
+ struct stm32_scmi_rstd *rstd;
+ size_t rstd_count;
+};
+
+static const struct scmi_agent_resources agent_resources[] = {
+ [0] = {
+ .clock = stm32_scmi0_clock,
+ .clock_count = ARRAY_SIZE(stm32_scmi0_clock),
+ .rstd = stm32_scmi0_reset_domain,
+ .rstd_count = ARRAY_SIZE(stm32_scmi0_reset_domain),
+ },
+ [1] = {
+ .clock = stm32_scmi1_clock,
+ .clock_count = ARRAY_SIZE(stm32_scmi1_clock),
+ },
+};
+
+static const struct scmi_agent_resources *find_resource(unsigned int agent_id)
+{
+ assert(agent_id < ARRAY_SIZE(agent_resources));
+
+ return &agent_resources[agent_id];
+}
+
+#if ENABLE_ASSERTIONS
+static size_t plat_scmi_protocol_count_paranoid(void)
+{
+ unsigned int n = 0U;
+ unsigned int count = 0U;
+
+ for (n = 0U; n < ARRAY_SIZE(agent_resources); n++) {
+ if (agent_resources[n].clock_count) {
+ count++;
+ break;
+ }
+ }
+
+ for (n = 0U; n < ARRAY_SIZE(agent_resources); n++) {
+ if (agent_resources[n].rstd_count) {
+ count++;
+ break;
+ }
+ }
+
+ return count;
+}
+#endif
+
+static const char vendor[] = "ST";
+static const char sub_vendor[] = "";
+
+const char *plat_scmi_vendor_name(void)
+{
+ return vendor;
+}
+
+const char *plat_scmi_sub_vendor_name(void)
+{
+ return sub_vendor;
+}
+
+/* Currently supporting Clocks and Reset Domains */
+static const uint8_t plat_protocol_list[] = {
+ SCMI_PROTOCOL_ID_CLOCK,
+ SCMI_PROTOCOL_ID_RESET_DOMAIN,
+ 0U /* Null termination */
+};
+
+size_t plat_scmi_protocol_count(void)
+{
+ const size_t count = ARRAY_SIZE(plat_protocol_list) - 1U;
+
+ assert(count == plat_scmi_protocol_count_paranoid());
+
+ return count;
+}
+
+const uint8_t *plat_scmi_protocol_list(unsigned int agent_id __unused)
+{
+ assert(plat_scmi_protocol_count_paranoid() ==
+ (ARRAY_SIZE(plat_protocol_list) - 1U));
+
+ return plat_protocol_list;
+}
+
+/*
+ * Platform SCMI clocks
+ */
+static struct stm32_scmi_clk *find_clock(unsigned int agent_id,
+ unsigned int scmi_id)
+{
+ const struct scmi_agent_resources *resource = find_resource(agent_id);
+ size_t n = 0U;
+
+ if (resource != NULL) {
+ for (n = 0U; n < resource->clock_count; n++) {
+ if (n == scmi_id) {
+ return &resource->clock[n];
+ }
+ }
+ }
+
+ return NULL;
+}
+
+size_t plat_scmi_clock_count(unsigned int agent_id)
+{
+ const struct scmi_agent_resources *resource = find_resource(agent_id);
+
+ if (resource == NULL) {
+ return 0U;
+ }
+
+ return resource->clock_count;
+}
+
+const char *plat_scmi_clock_get_name(unsigned int agent_id,
+ unsigned int scmi_id)
+{
+ struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
+
+ if ((clock == NULL) ||
+ !stm32mp_nsec_can_access_clock(clock->clock_id)) {
+ return NULL;
+ }
+
+ return clock->name;
+}
+
+int32_t plat_scmi_clock_rates_array(unsigned int agent_id, unsigned int scmi_id,
+ unsigned long *array, size_t *nb_elts)
+{
+ struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
+
+ if (clock == NULL) {
+ return SCMI_NOT_FOUND;
+ }
+
+ if (!stm32mp_nsec_can_access_clock(clock->clock_id)) {
+ return SCMI_DENIED;
+ }
+
+ if (array == NULL) {
+ *nb_elts = 1U;
+ } else if (*nb_elts == 1U) {
+ *array = clk_get_rate(clock->clock_id);
+ } else {
+ return SCMI_GENERIC_ERROR;
+ }
+
+ return SCMI_SUCCESS;
+}
+
+unsigned long plat_scmi_clock_get_rate(unsigned int agent_id,
+ unsigned int scmi_id)
+{
+ struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
+
+ if ((clock == NULL) ||
+ !stm32mp_nsec_can_access_clock(clock->clock_id)) {
+ return 0U;
+ }
+
+ return clk_get_rate(clock->clock_id);
+}
+
+int32_t plat_scmi_clock_get_state(unsigned int agent_id, unsigned int scmi_id)
+{
+ struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
+
+ if ((clock == NULL) ||
+ !stm32mp_nsec_can_access_clock(clock->clock_id)) {
+ return 0U;
+ }
+
+ return (int32_t)clock->enabled;
+}
+
+int32_t plat_scmi_clock_set_state(unsigned int agent_id, unsigned int scmi_id,
+ bool enable_not_disable)
+{
+ struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
+
+ if (clock == NULL) {
+ return SCMI_NOT_FOUND;
+ }
+
+ if (!stm32mp_nsec_can_access_clock(clock->clock_id)) {
+ return SCMI_DENIED;
+ }
+
+ if (enable_not_disable) {
+ if (!clock->enabled) {
+ VERBOSE("SCMI clock %u enable\n", scmi_id);
+ clk_enable(clock->clock_id);
+ clock->enabled = true;
+ }
+ } else {
+ if (clock->enabled) {
+ VERBOSE("SCMI clock %u disable\n", scmi_id);
+ clk_disable(clock->clock_id);
+ clock->enabled = false;
+ }
+ }
+
+ return SCMI_SUCCESS;
+}
+
+/*
+ * Platform SCMI reset domains
+ */
+static struct stm32_scmi_rstd *find_rstd(unsigned int agent_id,
+ unsigned int scmi_id)
+{
+ const struct scmi_agent_resources *resource = find_resource(agent_id);
+ size_t n;
+
+ if (resource != NULL) {
+ for (n = 0U; n < resource->rstd_count; n++) {
+ if (n == scmi_id) {
+ return &resource->rstd[n];
+ }
+ }
+ }
+
+ return NULL;
+}
+
+const char *plat_scmi_rstd_get_name(unsigned int agent_id, unsigned int scmi_id)
+{
+ const struct stm32_scmi_rstd *rstd = find_rstd(agent_id, scmi_id);
+
+ if (rstd == NULL) {
+ return NULL;
+ }
+
+ return rstd->name;
+}
+
+size_t plat_scmi_rstd_count(unsigned int agent_id)
+{
+ const struct scmi_agent_resources *resource = find_resource(agent_id);
+
+ if (resource == NULL) {
+ return 0U;
+ }
+
+ return resource->rstd_count;
+}
+
+int32_t plat_scmi_rstd_autonomous(unsigned int agent_id, unsigned int scmi_id,
+ uint32_t state)
+{
+ const struct stm32_scmi_rstd *rstd = find_rstd(agent_id, scmi_id);
+
+ if (rstd == NULL) {
+ return SCMI_NOT_FOUND;
+ }
+
+ if (!stm32mp_nsec_can_access_reset(rstd->reset_id)) {
+ return SCMI_DENIED;
+ }
+
+ /* Supports only reset with context loss */
+ if (state != 0U) {
+ return SCMI_NOT_SUPPORTED;
+ }
+
+ VERBOSE("SCMI reset %lu cycle\n", rstd->reset_id);
+
+ if (stm32mp_reset_assert(rstd->reset_id, TIMEOUT_US_1MS)) {
+ return SCMI_HARDWARE_ERROR;
+ }
+
+ if (stm32mp_reset_deassert(rstd->reset_id, TIMEOUT_US_1MS)) {
+ return SCMI_HARDWARE_ERROR;
+ }
+
+ return SCMI_SUCCESS;
+}
+
+int32_t plat_scmi_rstd_set_state(unsigned int agent_id, unsigned int scmi_id,
+ bool assert_not_deassert)
+{
+ const struct stm32_scmi_rstd *rstd = find_rstd(agent_id, scmi_id);
+
+ if (rstd == NULL) {
+ return SCMI_NOT_FOUND;
+ }
+
+ if (!stm32mp_nsec_can_access_reset(rstd->reset_id)) {
+ return SCMI_DENIED;
+ }
+
+ if (assert_not_deassert) {
+ VERBOSE("SCMI reset %lu set\n", rstd->reset_id);
+ stm32mp_reset_set(rstd->reset_id);
+ } else {
+ VERBOSE("SCMI reset %lu release\n", rstd->reset_id);
+ stm32mp_reset_release(rstd->reset_id);
+ }
+
+ return SCMI_SUCCESS;
+}
+
+/*
+ * Initialize platform SCMI resources
+ */
+void stm32mp1_init_scmi_server(void)
+{
+ size_t i;
+
+ for (i = 0U; i < ARRAY_SIZE(scmi_channel); i++) {
+ scmi_smt_init_agent_channel(&scmi_channel[i]);
+ }
+
+ for (i = 0U; i < ARRAY_SIZE(agent_resources); i++) {
+ const struct scmi_agent_resources *res = &agent_resources[i];
+ size_t j;
+
+ for (j = 0U; j < res->clock_count; j++) {
+ struct stm32_scmi_clk *clk = &res->clock[j];
+
+ if ((clk->name == NULL) ||
+ (strlen(clk->name) >= SCMI_CLOCK_NAME_SIZE)) {
+ ERROR("Invalid SCMI clock name\n");
+ panic();
+ }
+
+ /* Sync SCMI clocks with their targeted initial state */
+ if (clk->enabled &&
+ stm32mp_nsec_can_access_clock(clk->clock_id)) {
+ clk_enable(clk->clock_id);
+ }
+ }
+
+ for (j = 0U; j < res->rstd_count; j++) {
+ struct stm32_scmi_rstd *rstd = &res->rstd[j];
+
+ if ((rstd->name == NULL) ||
+ (strlen(rstd->name) >= SCMI_RSTD_NAME_SIZE)) {
+ ERROR("Invalid SCMI reset domain name\n");
+ panic();
+ }
+ }
+ }
+}
diff --git a/plat/st/stm32mp1/stm32mp1_shared_resources.c b/plat/st/stm32mp1/stm32mp1_shared_resources.c
new file mode 100644
index 0000000..a0ca697
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_shared_resources.c
@@ -0,0 +1,596 @@
+/*
+ * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <drivers/st/etzpc.h>
+#include <drivers/st/stm32_gpio.h>
+
+#include <platform_def.h>
+#include <stm32mp_shared_resources.h>
+
+/*
+ * Once one starts to get the resource registering state, one cannot register
+ * new resources. This ensures resource state cannot change.
+ */
+static bool registering_locked;
+
+/*
+ * Shared peripherals and resources registration
+ *
+ * Each resource assignation is stored in a table. The state defaults
+ * to PERIPH_UNREGISTERED if the resource is not explicitly assigned.
+ *
+ * Resource driver that as not embedded (a.k.a their related CFG_xxx build
+ * directive is disabled) are assigned to the non-secure world.
+ *
+ * Each pin of the GPIOZ bank can be secure or non-secure.
+ *
+ * It is the platform responsibility the ensure resource assignation
+ * matches the access permission firewalls configuration.
+ */
+enum shres_state {
+ SHRES_UNREGISTERED = 0,
+ SHRES_SECURE,
+ SHRES_NON_SECURE,
+};
+
+/* Force uint8_t array for array of enum shres_state for size considerations */
+static uint8_t shres_state[STM32MP1_SHRES_COUNT];
+
+static const char *shres2str_id_tbl[STM32MP1_SHRES_COUNT] __unused = {
+ [STM32MP1_SHRES_GPIOZ(0)] = "GPIOZ0",
+ [STM32MP1_SHRES_GPIOZ(1)] = "GPIOZ1",
+ [STM32MP1_SHRES_GPIOZ(2)] = "GPIOZ2",
+ [STM32MP1_SHRES_GPIOZ(3)] = "GPIOZ3",
+ [STM32MP1_SHRES_GPIOZ(4)] = "GPIOZ4",
+ [STM32MP1_SHRES_GPIOZ(5)] = "GPIOZ5",
+ [STM32MP1_SHRES_GPIOZ(6)] = "GPIOZ6",
+ [STM32MP1_SHRES_GPIOZ(7)] = "GPIOZ7",
+ [STM32MP1_SHRES_IWDG1] = "IWDG1",
+ [STM32MP1_SHRES_USART1] = "USART1",
+ [STM32MP1_SHRES_SPI6] = "SPI6",
+ [STM32MP1_SHRES_I2C4] = "I2C4",
+ [STM32MP1_SHRES_RNG1] = "RNG1",
+ [STM32MP1_SHRES_HASH1] = "HASH1",
+ [STM32MP1_SHRES_CRYP1] = "CRYP1",
+ [STM32MP1_SHRES_I2C6] = "I2C6",
+ [STM32MP1_SHRES_RTC] = "RTC",
+ [STM32MP1_SHRES_MCU] = "MCU",
+ [STM32MP1_SHRES_MDMA] = "MDMA",
+ [STM32MP1_SHRES_PLL3] = "PLL3",
+};
+
+static const char __unused *shres2str_id(enum stm32mp_shres id)
+{
+ assert(id < ARRAY_SIZE(shres2str_id_tbl));
+
+ return shres2str_id_tbl[id];
+}
+
+static const char __unused *shres2str_state_tbl[] = {
+ [SHRES_UNREGISTERED] = "unregistered",
+ [SHRES_NON_SECURE] = "non-secure",
+ [SHRES_SECURE] = "secure",
+};
+
+static const char __unused *shres2str_state(unsigned int state)
+{
+ assert(state < ARRAY_SIZE(shres2str_state_tbl));
+
+ return shres2str_state_tbl[state];
+}
+
+/* Get resource state: these accesses lock the registering support */
+static void lock_registering(void)
+{
+ registering_locked = true;
+}
+
+static bool periph_is_non_secure(enum stm32mp_shres id)
+{
+ lock_registering();
+
+ return (shres_state[id] == SHRES_NON_SECURE) ||
+ (shres_state[id] == SHRES_UNREGISTERED);
+}
+
+static bool periph_is_secure(enum stm32mp_shres id)
+{
+ return !periph_is_non_secure(id);
+}
+
+/* GPIOZ pin count is saved in RAM to prevent parsing FDT several times */
+static int8_t gpioz_nbpin = -1;
+
+static unsigned int get_gpio_nbpin(unsigned int bank)
+{
+ if (bank != GPIO_BANK_Z) {
+ int count = fdt_get_gpio_bank_pin_count(bank);
+
+ assert((count >= 0) && ((unsigned int)count <= (GPIO_PIN_MAX + 1)));
+
+ return (unsigned int)count;
+ }
+
+ if (gpioz_nbpin < 0) {
+ int count = fdt_get_gpio_bank_pin_count(GPIO_BANK_Z);
+
+ assert((count == 0) || (count == STM32MP_GPIOZ_PIN_MAX_COUNT));
+
+ gpioz_nbpin = count;
+ }
+
+ return (unsigned int)gpioz_nbpin;
+}
+
+static unsigned int get_gpioz_nbpin(void)
+{
+ return get_gpio_nbpin(GPIO_BANK_Z);
+}
+
+static void register_periph(enum stm32mp_shres id, unsigned int state)
+{
+ assert((id < STM32MP1_SHRES_COUNT) &&
+ ((state == SHRES_SECURE) || (state == SHRES_NON_SECURE)));
+
+ if (registering_locked) {
+ if (shres_state[id] == state) {
+ return;
+ }
+ panic();
+ }
+
+ if ((shres_state[id] != SHRES_UNREGISTERED) &&
+ (shres_state[id] != state)) {
+ VERBOSE("Cannot change %s from %s to %s\n",
+ shres2str_id(id),
+ shres2str_state(shres_state[id]),
+ shres2str_state(state));
+ panic();
+ }
+
+ if (shres_state[id] == SHRES_UNREGISTERED) {
+ VERBOSE("Register %s as %s\n",
+ shres2str_id(id), shres2str_state(state));
+ }
+
+ if ((id >= STM32MP1_SHRES_GPIOZ(0)) &&
+ (id <= STM32MP1_SHRES_GPIOZ(7)) &&
+ ((unsigned int)(id - STM32MP1_SHRES_GPIOZ(0)) >= get_gpioz_nbpin())) {
+ ERROR("Invalid GPIO pin %d, %u pin(s) available\n",
+ (int)(id - STM32MP1_SHRES_GPIOZ(0)), get_gpioz_nbpin());
+ panic();
+ }
+
+ shres_state[id] = (uint8_t)state;
+
+ /* Explore clock tree to lock dependencies */
+ if (state == SHRES_SECURE) {
+ enum stm32mp_shres clock_res_id;
+
+ switch (id) {
+ case STM32MP1_SHRES_GPIOZ(0):
+ case STM32MP1_SHRES_GPIOZ(1):
+ case STM32MP1_SHRES_GPIOZ(2):
+ case STM32MP1_SHRES_GPIOZ(3):
+ case STM32MP1_SHRES_GPIOZ(4):
+ case STM32MP1_SHRES_GPIOZ(5):
+ case STM32MP1_SHRES_GPIOZ(6):
+ case STM32MP1_SHRES_GPIOZ(7):
+ clock_res_id = GPIOZ;
+ break;
+ case STM32MP1_SHRES_IWDG1:
+ clock_res_id = IWDG1;
+ break;
+ case STM32MP1_SHRES_USART1:
+ clock_res_id = USART1_K;
+ break;
+ case STM32MP1_SHRES_SPI6:
+ clock_res_id = SPI6_K;
+ break;
+ case STM32MP1_SHRES_I2C4:
+ clock_res_id = I2C4_K;
+ break;
+ case STM32MP1_SHRES_RNG1:
+ clock_res_id = RNG1_K;
+ break;
+ case STM32MP1_SHRES_HASH1:
+ clock_res_id = HASH1;
+ break;
+ case STM32MP1_SHRES_CRYP1:
+ clock_res_id = CRYP1;
+ break;
+ case STM32MP1_SHRES_I2C6:
+ clock_res_id = I2C6_K;
+ break;
+ case STM32MP1_SHRES_RTC:
+ clock_res_id = RTC;
+ break;
+ default:
+ /* No clock resource dependency */
+ return;
+ }
+
+ stm32mp1_register_clock_parents_secure(clock_res_id);
+ }
+}
+
+/* Register resource by ID */
+void stm32mp_register_secure_periph(enum stm32mp_shres id)
+{
+ register_periph(id, SHRES_SECURE);
+}
+
+void stm32mp_register_non_secure_periph(enum stm32mp_shres id)
+{
+ register_periph(id, SHRES_NON_SECURE);
+}
+
+static void register_periph_iomem(uintptr_t base, unsigned int state)
+{
+ enum stm32mp_shres id;
+
+ switch (base) {
+ case CRYP1_BASE:
+ id = STM32MP1_SHRES_CRYP1;
+ break;
+ case HASH1_BASE:
+ id = STM32MP1_SHRES_HASH1;
+ break;
+ case I2C4_BASE:
+ id = STM32MP1_SHRES_I2C4;
+ break;
+ case I2C6_BASE:
+ id = STM32MP1_SHRES_I2C6;
+ break;
+ case IWDG1_BASE:
+ id = STM32MP1_SHRES_IWDG1;
+ break;
+ case RNG1_BASE:
+ id = STM32MP1_SHRES_RNG1;
+ break;
+ case RTC_BASE:
+ id = STM32MP1_SHRES_RTC;
+ break;
+ case SPI6_BASE:
+ id = STM32MP1_SHRES_SPI6;
+ break;
+ case USART1_BASE:
+ id = STM32MP1_SHRES_USART1;
+ break;
+
+ case GPIOA_BASE:
+ case GPIOB_BASE:
+ case GPIOC_BASE:
+ case GPIOD_BASE:
+ case GPIOE_BASE:
+ case GPIOF_BASE:
+ case GPIOG_BASE:
+ case GPIOH_BASE:
+ case GPIOI_BASE:
+ case GPIOJ_BASE:
+ case GPIOK_BASE:
+ case USART2_BASE:
+ case USART3_BASE:
+ case UART4_BASE:
+ case UART5_BASE:
+ case USART6_BASE:
+ case UART7_BASE:
+ case UART8_BASE:
+ case IWDG2_BASE:
+ /* Allow drivers to register some non-secure resources */
+ VERBOSE("IO for non-secure resource 0x%x\n",
+ (unsigned int)base);
+ if (state != SHRES_NON_SECURE) {
+ panic();
+ }
+
+ return;
+
+ default:
+ panic();
+ }
+
+ register_periph(id, state);
+}
+
+void stm32mp_register_secure_periph_iomem(uintptr_t base)
+{
+ register_periph_iomem(base, SHRES_SECURE);
+}
+
+void stm32mp_register_non_secure_periph_iomem(uintptr_t base)
+{
+ register_periph_iomem(base, SHRES_NON_SECURE);
+}
+
+void stm32mp_register_secure_gpio(unsigned int bank, unsigned int pin)
+{
+ switch (bank) {
+ case GPIO_BANK_Z:
+ register_periph(STM32MP1_SHRES_GPIOZ(pin), SHRES_SECURE);
+ break;
+ default:
+ ERROR("GPIO bank %u cannot be secured\n", bank);
+ panic();
+ }
+}
+
+void stm32mp_register_non_secure_gpio(unsigned int bank, unsigned int pin)
+{
+ switch (bank) {
+ case GPIO_BANK_Z:
+ register_periph(STM32MP1_SHRES_GPIOZ(pin), SHRES_NON_SECURE);
+ break;
+ default:
+ break;
+ }
+}
+
+static bool stm32mp_gpio_bank_is_non_secure(unsigned int bank)
+{
+ unsigned int non_secure = 0U;
+ unsigned int i;
+
+ lock_registering();
+
+ if (bank != GPIO_BANK_Z) {
+ return true;
+ }
+
+ for (i = 0U; i < get_gpioz_nbpin(); i++) {
+ if (periph_is_non_secure(STM32MP1_SHRES_GPIOZ(i))) {
+ non_secure++;
+ }
+ }
+
+ return non_secure == get_gpioz_nbpin();
+}
+
+static bool stm32mp_gpio_bank_is_secure(unsigned int bank)
+{
+ unsigned int secure = 0U;
+ unsigned int i;
+
+ lock_registering();
+
+ if (bank != GPIO_BANK_Z) {
+ return false;
+ }
+
+ for (i = 0U; i < get_gpioz_nbpin(); i++) {
+ if (periph_is_secure(STM32MP1_SHRES_GPIOZ(i))) {
+ secure++;
+ }
+ }
+
+ return secure == get_gpioz_nbpin();
+}
+
+bool stm32mp_nsec_can_access_clock(unsigned long clock_id)
+{
+ enum stm32mp_shres shres_id = STM32MP1_SHRES_COUNT;
+
+ switch (clock_id) {
+ case CK_CSI:
+ case CK_HSE:
+ case CK_HSE_DIV2:
+ case CK_HSI:
+ case CK_LSE:
+ case CK_LSI:
+ case PLL1_P:
+ case PLL1_Q:
+ case PLL1_R:
+ case PLL2_P:
+ case PLL2_Q:
+ case PLL2_R:
+ case PLL3_P:
+ case PLL3_Q:
+ case PLL3_R:
+ case RTCAPB:
+ return true;
+ case GPIOZ:
+ /* Allow clock access if at least one pin is non-secure */
+ return !stm32mp_gpio_bank_is_secure(GPIO_BANK_Z);
+ case CRYP1:
+ shres_id = STM32MP1_SHRES_CRYP1;
+ break;
+ case HASH1:
+ shres_id = STM32MP1_SHRES_HASH1;
+ break;
+ case I2C4_K:
+ shres_id = STM32MP1_SHRES_I2C4;
+ break;
+ case I2C6_K:
+ shres_id = STM32MP1_SHRES_I2C6;
+ break;
+ case IWDG1:
+ shres_id = STM32MP1_SHRES_IWDG1;
+ break;
+ case RNG1_K:
+ shres_id = STM32MP1_SHRES_RNG1;
+ break;
+ case RTC:
+ shres_id = STM32MP1_SHRES_RTC;
+ break;
+ case SPI6_K:
+ shres_id = STM32MP1_SHRES_SPI6;
+ break;
+ case USART1_K:
+ shres_id = STM32MP1_SHRES_USART1;
+ break;
+ default:
+ return false;
+ }
+
+ return periph_is_non_secure(shres_id);
+}
+
+bool stm32mp_nsec_can_access_reset(unsigned int reset_id)
+{
+ enum stm32mp_shres shres_id = STM32MP1_SHRES_COUNT;
+
+ switch (reset_id) {
+ case CRYP1_R:
+ shres_id = STM32MP1_SHRES_CRYP1;
+ break;
+ case GPIOZ_R:
+ /* GPIOZ reset mandates all pins are non-secure */
+ return stm32mp_gpio_bank_is_non_secure(GPIO_BANK_Z);
+ case HASH1_R:
+ shres_id = STM32MP1_SHRES_HASH1;
+ break;
+ case I2C4_R:
+ shres_id = STM32MP1_SHRES_I2C4;
+ break;
+ case I2C6_R:
+ shres_id = STM32MP1_SHRES_I2C6;
+ break;
+ case MCU_R:
+ shres_id = STM32MP1_SHRES_MCU;
+ break;
+ case MDMA_R:
+ shres_id = STM32MP1_SHRES_MDMA;
+ break;
+ case RNG1_R:
+ shres_id = STM32MP1_SHRES_RNG1;
+ break;
+ case SPI6_R:
+ shres_id = STM32MP1_SHRES_SPI6;
+ break;
+ case USART1_R:
+ shres_id = STM32MP1_SHRES_USART1;
+ break;
+ default:
+ return false;
+ }
+
+ return periph_is_non_secure(shres_id);
+}
+
+static bool mckprot_protects_periph(enum stm32mp_shres id)
+{
+ switch (id) {
+ case STM32MP1_SHRES_MCU:
+ case STM32MP1_SHRES_PLL3:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/* ETZPC configuration at drivers initialization completion */
+static enum etzpc_decprot_attributes shres2decprot_attr(enum stm32mp_shres id)
+{
+ assert((id < STM32MP1_SHRES_GPIOZ(0)) ||
+ (id > STM32MP1_SHRES_GPIOZ(7)));
+
+ if (periph_is_non_secure(id)) {
+ return ETZPC_DECPROT_NS_RW;
+ }
+
+ return ETZPC_DECPROT_S_RW;
+}
+
+static void set_etzpc_secure_configuration(void)
+{
+ /* Some system peripherals shall be secure */
+ etzpc_configure_decprot(STM32MP1_ETZPC_STGENC_ID, ETZPC_DECPROT_S_RW);
+ etzpc_configure_decprot(STM32MP1_ETZPC_BKPSRAM_ID, ETZPC_DECPROT_S_RW);
+ etzpc_configure_decprot(STM32MP1_ETZPC_DDRCTRL_ID,
+ ETZPC_DECPROT_NS_R_S_W);
+ etzpc_configure_decprot(STM32MP1_ETZPC_DDRPHYC_ID,
+ ETZPC_DECPROT_NS_R_S_W);
+
+ /* Configure ETZPC with peripheral registering */
+ etzpc_configure_decprot(STM32MP1_ETZPC_CRYP1_ID,
+ shres2decprot_attr(STM32MP1_SHRES_CRYP1));
+ etzpc_configure_decprot(STM32MP1_ETZPC_HASH1_ID,
+ shres2decprot_attr(STM32MP1_SHRES_HASH1));
+ etzpc_configure_decprot(STM32MP1_ETZPC_I2C4_ID,
+ shres2decprot_attr(STM32MP1_SHRES_I2C4));
+ etzpc_configure_decprot(STM32MP1_ETZPC_I2C6_ID,
+ shres2decprot_attr(STM32MP1_SHRES_I2C6));
+ etzpc_configure_decprot(STM32MP1_ETZPC_IWDG1_ID,
+ shres2decprot_attr(STM32MP1_SHRES_IWDG1));
+ etzpc_configure_decprot(STM32MP1_ETZPC_RNG1_ID,
+ shres2decprot_attr(STM32MP1_SHRES_RNG1));
+ etzpc_configure_decprot(STM32MP1_ETZPC_USART1_ID,
+ shres2decprot_attr(STM32MP1_SHRES_USART1));
+ etzpc_configure_decprot(STM32MP1_ETZPC_SPI6_ID,
+ shres2decprot_attr(STM32MP1_SHRES_SPI6));
+}
+
+static void check_rcc_secure_configuration(void)
+{
+ uint32_t n;
+ uint32_t error = 0U;
+ bool mckprot = stm32mp1_rcc_is_mckprot();
+ bool secure = stm32mp1_rcc_is_secure();
+
+ for (n = 0U; n < ARRAY_SIZE(shres_state); n++) {
+ if (shres_state[n] != SHRES_SECURE) {
+ continue;
+ }
+
+ if (!secure || (mckprot_protects_periph(n) && (!mckprot))) {
+ ERROR("RCC %s MCKPROT %s and %s secure\n",
+ secure ? "secure" : "non-secure",
+ mckprot ? "set" : "not set",
+ shres2str_id(n));
+ error++;
+ }
+ }
+
+ if (error != 0U) {
+ panic();
+ }
+}
+
+static void set_gpio_secure_configuration(void)
+{
+ uint32_t pin;
+
+ for (pin = 0U; pin < get_gpioz_nbpin(); pin++) {
+ bool secure_state = periph_is_secure(STM32MP1_SHRES_GPIOZ(pin));
+
+ set_gpio_secure_cfg(GPIO_BANK_Z, pin, secure_state);
+ }
+}
+
+static void print_shared_resources_state(void)
+{
+ unsigned int id;
+
+ for (id = 0U; id < STM32MP1_SHRES_COUNT; id++) {
+ switch (shres_state[id]) {
+ case SHRES_SECURE:
+ INFO("stm32mp1 %s is secure\n", shres2str_id(id));
+ break;
+ case SHRES_NON_SECURE:
+ case SHRES_UNREGISTERED:
+ VERBOSE("stm32mp %s is non-secure\n", shres2str_id(id));
+ break;
+ default:
+ VERBOSE("stm32mp %s is invalid\n", shres2str_id(id));
+ panic();
+ }
+ }
+}
+
+void stm32mp_lock_periph_registering(void)
+{
+ registering_locked = true;
+
+ print_shared_resources_state();
+
+ check_rcc_secure_configuration();
+ set_etzpc_secure_configuration();
+ set_gpio_secure_configuration();
+}
diff --git a/plat/st/stm32mp1/stm32mp1_stack_protector.c b/plat/st/stm32mp1/stm32mp1_stack_protector.c
new file mode 100644
index 0000000..14e8e16
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_stack_protector.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <arch_helpers.h>
+#include <plat/common/platform.h>
+
+#define RANDOM_CANARY_VALUE 2144346116U
+
+u_register_t plat_get_stack_protector_canary(void)
+{
+ /*
+ * Ideally, a random number should be returned instead of the
+ * combination of a timer's value and a compile-time constant.
+ */
+ return RANDOM_CANARY_VALUE ^ (u_register_t)read_cntpct_el0();
+}
+
diff --git a/plat/st/stm32mp1/stm32mp1_syscfg.c b/plat/st/stm32mp1/stm32mp1_syscfg.c
new file mode 100644
index 0000000..ff79428
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_syscfg.c
@@ -0,0 +1,411 @@
+/*
+ * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <common/debug.h>
+#include <drivers/clk.h>
+#include <drivers/delay_timer.h>
+#include <drivers/st/stpmic1.h>
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <libfdt.h>
+
+#include <platform_def.h>
+#include <stm32mp_common.h>
+#include <stm32mp_dt.h>
+#include <stm32mp1_private.h>
+
+/*
+ * SYSCFG REGISTER OFFSET (base relative)
+ */
+#define SYSCFG_BOOTR 0x00U
+#define SYSCFG_BOOTCR 0x0CU
+#if STM32MP15
+#define SYSCFG_IOCTRLSETR 0x18U
+#define SYSCFG_ICNR 0x1CU
+#endif
+#define SYSCFG_CMPCR 0x20U
+#define SYSCFG_CMPENSETR 0x24U
+#define SYSCFG_CMPENCLRR 0x28U
+#if STM32MP13
+#define SYSCFG_CMPSD1CR 0x30U
+#define SYSCFG_CMPSD1ENSETR 0x34U
+#define SYSCFG_CMPSD1ENCLRR 0x38U
+#define SYSCFG_CMPSD2CR 0x40U
+#define SYSCFG_CMPSD2ENSETR 0x44U
+#define SYSCFG_CMPSD2ENCLRR 0x48U
+#define SYSCFG_HSLVEN0R 0x50U
+#endif
+#define SYSCFG_IDC 0x380U
+
+#define CMPCR_CMPENSETR_OFFSET 0x4U
+#define CMPCR_CMPENCLRR_OFFSET 0x8U
+
+/*
+ * SYSCFG_BOOTR Register
+ */
+#define SYSCFG_BOOTR_BOOT_MASK GENMASK(2, 0)
+#if STM32MP15
+#define SYSCFG_BOOTR_BOOTPD_MASK GENMASK(6, 4)
+#define SYSCFG_BOOTR_BOOTPD_SHIFT 4
+#endif
+
+/*
+ * SYSCFG_BOOTCR Register
+ */
+#define SYSCFG_BOOTCR_BMEN BIT(0)
+
+/*
+ * SYSCFG_IOCTRLSETR Register
+ */
+#define SYSCFG_IOCTRLSETR_HSLVEN_TRACE BIT(0)
+#define SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI BIT(1)
+#define SYSCFG_IOCTRLSETR_HSLVEN_ETH BIT(2)
+#define SYSCFG_IOCTRLSETR_HSLVEN_SDMMC BIT(3)
+#define SYSCFG_IOCTRLSETR_HSLVEN_SPI BIT(4)
+
+/*
+ * SYSCFG_ICNR Register
+ */
+#define SYSCFG_ICNR_AXI_M9 BIT(9)
+
+/*
+ * SYSCFG_CMPCR Register
+ */
+#define SYSCFG_CMPCR_SW_CTRL BIT(1)
+#define SYSCFG_CMPCR_READY BIT(8)
+#define SYSCFG_CMPCR_RANSRC GENMASK(19, 16)
+#define SYSCFG_CMPCR_RANSRC_SHIFT 16
+#define SYSCFG_CMPCR_RAPSRC GENMASK(23, 20)
+#define SYSCFG_CMPCR_ANSRC_SHIFT 24
+
+#define SYSCFG_CMPCR_READY_TIMEOUT_US 10000U
+
+/*
+ * SYSCFG_CMPENSETR Register
+ */
+#define SYSCFG_CMPENSETR_MPU_EN BIT(0)
+
+/*
+ * HSLV definitions
+ */
+#define HSLV_IDX_TPIU 0U
+#define HSLV_IDX_QSPI 1U
+#define HSLV_IDX_ETH1 2U
+#define HSLV_IDX_ETH2 3U
+#define HSLV_IDX_SDMMC1 4U
+#define HSLV_IDX_SDMMC2 5U
+#define HSLV_IDX_SPI1 6U
+#define HSLV_IDX_SPI2 7U
+#define HSLV_IDX_SPI3 8U
+#define HSLV_IDX_SPI4 9U
+#define HSLV_IDX_SPI5 10U
+#define HSLV_IDX_LTDC 11U
+#define HSLV_NB_IDX 12U
+
+#define HSLV_KEY 0x1018U
+
+/*
+ * SYSCFG_IDC Register
+ */
+#define SYSCFG_IDC_DEV_ID_MASK GENMASK(11, 0)
+#define SYSCFG_IDC_REV_ID_MASK GENMASK(31, 16)
+#define SYSCFG_IDC_REV_ID_SHIFT 16
+
+static void enable_io_comp_cell_finish(uintptr_t cmpcr_off)
+{
+ uint64_t start;
+
+ start = timeout_init_us(SYSCFG_CMPCR_READY_TIMEOUT_US);
+
+ while ((mmio_read_32(SYSCFG_BASE + cmpcr_off) & SYSCFG_CMPCR_READY) == 0U) {
+ if (timeout_elapsed(start)) {
+ /* Failure on IO compensation enable is not a issue: warn only. */
+ WARN("IO compensation cell not ready\n");
+ break;
+ }
+ }
+
+ mmio_clrbits_32(SYSCFG_BASE + cmpcr_off, SYSCFG_CMPCR_SW_CTRL);
+}
+
+static void disable_io_comp_cell(uintptr_t cmpcr_off)
+{
+ uint32_t value;
+
+ if (((mmio_read_32(SYSCFG_BASE + cmpcr_off) & SYSCFG_CMPCR_READY) == 0U) ||
+ ((mmio_read_32(SYSCFG_BASE + cmpcr_off + CMPCR_CMPENSETR_OFFSET) &
+ SYSCFG_CMPENSETR_MPU_EN) == 0U)) {
+ return;
+ }
+
+ value = mmio_read_32(SYSCFG_BASE + cmpcr_off) >> SYSCFG_CMPCR_ANSRC_SHIFT;
+
+ mmio_clrbits_32(SYSCFG_BASE + cmpcr_off, SYSCFG_CMPCR_RANSRC | SYSCFG_CMPCR_RAPSRC);
+
+ value <<= SYSCFG_CMPCR_RANSRC_SHIFT;
+ value |= mmio_read_32(SYSCFG_BASE + cmpcr_off);
+
+ mmio_write_32(SYSCFG_BASE + cmpcr_off, value | SYSCFG_CMPCR_SW_CTRL);
+
+ mmio_setbits_32(SYSCFG_BASE + cmpcr_off + CMPCR_CMPENCLRR_OFFSET, SYSCFG_CMPENSETR_MPU_EN);
+}
+
+#if STM32MP13
+static int get_regu_max_voltage(void *fdt, int sdmmc_node,
+ const char *regu_name, uint32_t *regu_val)
+{
+ int node;
+ const fdt32_t *cuint;
+
+ cuint = fdt_getprop(fdt, sdmmc_node, regu_name, NULL);
+ if (cuint == NULL) {
+ return -ENODEV;
+ }
+
+ node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint));
+ if (node < 0) {
+ return -ENODEV;
+ }
+
+ cuint = fdt_getprop(fdt, node, "regulator-max-microvolt", NULL);
+ if (cuint == NULL) {
+ return -ENODEV;
+ }
+
+ *regu_val = fdt32_to_cpu(*cuint);
+
+ return 0;
+}
+
+static bool sdmmc_is_low_voltage(uintptr_t sdmmc_base)
+{
+ int ret;
+ int node;
+ void *fdt = NULL;
+ uint32_t regu_max_val;
+
+ if (fdt_get_address(&fdt) == 0) {
+ return false;
+ }
+
+ if (fdt == NULL) {
+ return false;
+ }
+
+ node = dt_match_instance_by_compatible(DT_SDMMC2_COMPAT, sdmmc_base);
+ if (node < 0) {
+ /* No SD or eMMC device on this instance, enable HSLV */
+ return true;
+ }
+
+ ret = get_regu_max_voltage(fdt, node, "vqmmc-supply", &regu_max_val);
+ if ((ret < 0) || (regu_max_val > 1800000U)) {
+ /*
+ * The vqmmc-supply property should always be present for eMMC.
+ * For SD-card, if it is not, then the card only supports 3.3V.
+ */
+ return false;
+ }
+
+ return true;
+}
+
+static void enable_hslv_by_index(uint32_t index)
+{
+ bool apply_hslv;
+
+ assert(index < HSLV_NB_IDX);
+
+ switch (index) {
+ case HSLV_IDX_SDMMC1:
+ apply_hslv = sdmmc_is_low_voltage(STM32MP_SDMMC1_BASE);
+ break;
+ case HSLV_IDX_SDMMC2:
+ apply_hslv = sdmmc_is_low_voltage(STM32MP_SDMMC2_BASE);
+ break;
+ default:
+ apply_hslv = true;
+ break;
+ }
+
+ if (apply_hslv) {
+ mmio_write_32(SYSCFG_BASE + SYSCFG_HSLVEN0R + index * sizeof(uint32_t), HSLV_KEY);
+ }
+}
+#endif
+
+static void enable_high_speed_mode_low_voltage(void)
+{
+#if STM32MP13
+ uint32_t idx;
+
+ for (idx = 0U; idx < HSLV_NB_IDX; idx++) {
+ enable_hslv_by_index(idx);
+ }
+#endif
+#if STM32MP15
+ mmio_write_32(SYSCFG_BASE + SYSCFG_IOCTRLSETR,
+ SYSCFG_IOCTRLSETR_HSLVEN_TRACE |
+ SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI |
+ SYSCFG_IOCTRLSETR_HSLVEN_ETH |
+ SYSCFG_IOCTRLSETR_HSLVEN_SDMMC |
+ SYSCFG_IOCTRLSETR_HSLVEN_SPI);
+#endif
+}
+
+static void stm32mp1_syscfg_set_hslv(void)
+{
+ uint32_t otp_value;
+ uint32_t vdd_voltage;
+ bool product_below_2v5;
+
+ /*
+ * High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI
+ * and TRACE. Needed above ~50MHz and conditioned by AFMUX selection.
+ * It could be disabled for low frequencies or if AFMUX is selected
+ * but the function is not used, typically for TRACE.
+ * If high speed low voltage pad mode is node enable, platform will
+ * over consume.
+ *
+ * WARNING:
+ * Enabling High Speed mode while VDD > 2.7V
+ * with the OTP product_below_2v5 (OTP 18, BIT 13)
+ * erroneously set to 1 can damage the SoC!
+ * => TF-A enables the low power mode only if VDD < 2.7V (in DT)
+ * but this value needs to be consistent with board design.
+ */
+ if (stm32_get_otp_value(HW2_OTP, &otp_value) != 0) {
+ panic();
+ }
+
+ product_below_2v5 = (otp_value & HW2_OTP_PRODUCT_BELOW_2V5) != 0U;
+
+ /* Get VDD supply */
+ vdd_voltage = dt_get_pwr_vdd_voltage();
+
+ /* Check if VDD is Low Voltage */
+ if (vdd_voltage == 0U) {
+ WARN("VDD unknown\n");
+ } else if (vdd_voltage < 2700000U) {
+ enable_high_speed_mode_low_voltage();
+
+ if (!product_below_2v5) {
+ INFO("Product_below_2v5=0: HSLVEN protected by HW\n");
+ }
+ } else {
+ if (product_below_2v5) {
+ ERROR("Product_below_2v5=1:\n");
+ ERROR("\tHSLVEN update is destructive,\n");
+ ERROR("\tno update as VDD > 2.7V\n");
+ panic();
+ }
+ }
+}
+
+void stm32mp1_syscfg_init(void)
+{
+#if STM32MP15
+ uint32_t bootr;
+
+ /*
+ * Interconnect update : select master using the port 1.
+ * LTDC = AXI_M9.
+ */
+ mmio_write_32(SYSCFG_BASE + SYSCFG_ICNR, SYSCFG_ICNR_AXI_M9);
+
+ /* Disable Pull-Down for boot pin connected to VDD */
+ bootr = mmio_read_32(SYSCFG_BASE + SYSCFG_BOOTR) &
+ SYSCFG_BOOTR_BOOT_MASK;
+ mmio_clrsetbits_32(SYSCFG_BASE + SYSCFG_BOOTR, SYSCFG_BOOTR_BOOTPD_MASK,
+ bootr << SYSCFG_BOOTR_BOOTPD_SHIFT);
+#endif
+
+ stm32mp1_syscfg_set_hslv();
+
+ stm32mp1_syscfg_enable_io_compensation_start();
+}
+
+void stm32mp1_syscfg_enable_io_compensation_start(void)
+{
+ /*
+ * Activate automatic I/O compensation.
+ * Warning: need to ensure CSI enabled and ready in clock driver.
+ * Enable non-secure clock, we assume non-secure is suspended.
+ */
+ clk_enable(SYSCFG);
+
+ mmio_setbits_32(SYSCFG_BASE + CMPCR_CMPENSETR_OFFSET + SYSCFG_CMPCR,
+ SYSCFG_CMPENSETR_MPU_EN);
+#if STM32MP13
+ mmio_setbits_32(SYSCFG_BASE + CMPCR_CMPENSETR_OFFSET + SYSCFG_CMPSD1CR,
+ SYSCFG_CMPENSETR_MPU_EN);
+ mmio_setbits_32(SYSCFG_BASE + CMPCR_CMPENSETR_OFFSET + SYSCFG_CMPSD2CR,
+ SYSCFG_CMPENSETR_MPU_EN);
+
+#endif
+}
+
+void stm32mp1_syscfg_enable_io_compensation_finish(void)
+{
+ enable_io_comp_cell_finish(SYSCFG_CMPCR);
+#if STM32MP13
+ enable_io_comp_cell_finish(SYSCFG_CMPSD1CR);
+ enable_io_comp_cell_finish(SYSCFG_CMPSD2CR);
+#endif
+}
+
+void stm32mp1_syscfg_disable_io_compensation(void)
+{
+ clk_enable(SYSCFG);
+
+ /*
+ * Deactivate automatic I/O compensation.
+ * Warning: CSI is disabled automatically in STOP if not
+ * requested for other usages and always OFF in STANDBY.
+ * Disable non-secure SYSCFG clock, we assume non-secure is suspended.
+ */
+ disable_io_comp_cell(SYSCFG_CMPCR);
+#if STM32MP13
+ disable_io_comp_cell(SYSCFG_CMPSD1CR);
+ disable_io_comp_cell(SYSCFG_CMPSD2CR);
+#endif
+
+ clk_disable(SYSCFG);
+}
+
+/*
+ * @brief Get silicon revision from SYSCFG registers.
+ * @retval chip version (REV_ID).
+ */
+uint32_t stm32mp1_syscfg_get_chip_version(void)
+{
+ return (mmio_read_32(SYSCFG_BASE + SYSCFG_IDC) &
+ SYSCFG_IDC_REV_ID_MASK) >> SYSCFG_IDC_REV_ID_SHIFT;
+}
+
+/*
+ * @brief Get device ID from SYSCFG registers.
+ * @retval device ID (DEV_ID).
+ */
+uint32_t stm32mp1_syscfg_get_chip_dev_id(void)
+{
+ return mmio_read_32(SYSCFG_BASE + SYSCFG_IDC) & SYSCFG_IDC_DEV_ID_MASK;
+}
+
+#if STM32MP13
+void stm32mp1_syscfg_boot_mode_enable(void)
+{
+ mmio_setbits_32(SYSCFG_BASE + SYSCFG_BOOTCR, SYSCFG_BOOTCR_BMEN);
+}
+
+void stm32mp1_syscfg_boot_mode_disable(void)
+{
+ mmio_clrbits_32(SYSCFG_BASE + SYSCFG_BOOTCR, SYSCFG_BOOTCR_BMEN);
+}
+#endif
diff --git a/plat/st/stm32mp1/stm32mp1_tbb_cert.c b/plat/st/stm32mp1/stm32mp1_tbb_cert.c
new file mode 100644
index 0000000..0e77397
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_tbb_cert.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "tbbr/tbb_ext.h"
+#include "tbbr/tbb_key.h"
+
+#include "tbbr/stm32mp1_tbb_cert.h"
+
+/*
+ * Certificates used in the chain of trust
+ *
+ * The order of the certificates must follow the enumeration specified in
+ * stm32mp1_tbb_cert.h. All certificates are self-signed, so the issuer certificate
+ * field points to itself.
+ */
+static cert_t stm32mp1_tbb_certs[] = {
+ [0] = {
+ .id = STM32MP_CONFIG_CERT,
+ .opt = "stm32mp-cfg-cert",
+ .help_msg = "STM32MP Config Certificate (output file)",
+ .fn = NULL,
+ .cn = "STM32MP config FW Certificate",
+ .key = ROT_KEY,
+ .issuer = STM32MP_CONFIG_CERT,
+ .ext = {
+ TRUSTED_FW_NVCOUNTER_EXT,
+ HW_CONFIG_HASH_EXT,
+ FW_CONFIG_HASH_EXT
+ },
+ .num_ext = 3
+ },
+};
+
+PLAT_REGISTER_COT(stm32mp1_tbb_certs);
diff --git a/plat/st/stm32mp1/stm32mp1_topology.c b/plat/st/stm32mp1/stm32mp1_topology.c
new file mode 100644
index 0000000..59a0c17
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_topology.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <lib/psci/psci.h>
+#include <plat/common/platform.h>
+
+/* 1 cluster, all cores into */
+static const unsigned char stm32mp1_power_domain_tree_desc[] = {
+ PLATFORM_CLUSTER_COUNT,
+ PLATFORM_CORE_COUNT,
+};
+
+/* This function returns the platform topology */
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return stm32mp1_power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * This function implements a part of the critical interface between the psci
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is returned
+ * in case the MPIDR is invalid.
+ ******************************************************************************/
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+ unsigned int cluster_id, cpu_id;
+ u_register_t mpidr_copy = mpidr;
+
+ mpidr_copy &= MPIDR_AFFINITY_MASK;
+
+ if ((mpidr_copy & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) != 0U) {
+ return -1;
+ }
+
+ cluster_id = (mpidr_copy >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+ cpu_id = (mpidr_copy >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+
+ if (cluster_id >= PLATFORM_CLUSTER_COUNT) {
+ return -1;
+ }
+
+ /*
+ * Validate cpu_id by checking whether it represents a CPU in one
+ * of the two clusters present on the platform.
+ */
+ if (cpu_id >= PLATFORM_CORE_COUNT) {
+ return -1;
+ }
+
+ return (int)cpu_id;
+}
diff --git a/plat/st/stm32mp1/stm32mp1_usb_dfu.c b/plat/st/stm32mp1/stm32mp1_usb_dfu.c
new file mode 100644
index 0000000..0fe2d24
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_usb_dfu.c
@@ -0,0 +1,423 @@
+/*
+ * Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <limits.h>
+#include <string.h>
+
+#include <common/debug.h>
+#include <drivers/st/bsec.h>
+#include <drivers/st/stm32mp1_usb.h>
+#include <drivers/usb_device.h>
+
+#include <platform_def.h>
+#include <stm32cubeprogrammer.h>
+#include <stm32mp_common.h>
+#include <usb_dfu.h>
+
+/* String size (1 byte) + type (1 byte) + 24 UTF16 characters: 2 bytes each */
+#define SIZ_STRING_SERIAL U(24)
+#define USB_SIZ_STRING_SERIAL (1U + 1U + (SIZ_STRING_SERIAL * 2U))
+#define USBD_MAX_STR_DESC_SIZ 0x100
+#define USBD_VID 0x0483
+#define USBD_PID 0xDF11
+#define USBD_LANGID_STRING 0x409
+#define USBD_MANUFACTURER_STRING "STMicroelectronics"
+#define USBD_CONFIGURATION_STRING "DFU Config"
+#define USBD_INTERFACE_STRING "DFU Interface"
+
+#if STM32MP13
+#define USB_DFU_ITF_NUM 2
+#endif
+#if STM32MP15
+#define USB_DFU_ITF_NUM 6
+#endif
+
+#define USB_DFU_CONFIG_DESC_SIZ USB_DFU_DESC_SIZ(USB_DFU_ITF_NUM)
+
+/* DFU devices */
+static struct usb_dfu_handle usb_dfu_handle;
+
+/* USB Standard Device Descriptor */
+static const uint8_t usb_stm32mp1_desc[USB_LEN_DEV_DESC] = {
+ USB_LEN_DEV_DESC, /* bLength */
+ USB_DESC_TYPE_DEVICE, /* bDescriptorType */
+ 0x00, /* bcdUSB */
+ 0x02, /* version */
+ 0x00, /* bDeviceClass */
+ 0x00, /* bDeviceSubClass */
+ 0x00, /* bDeviceProtocol */
+ USB_MAX_EP0_SIZE, /* bMaxPacketSize */
+ LOBYTE(USBD_VID), /* idVendor */
+ HIBYTE(USBD_VID), /* idVendor */
+ LOBYTE(USBD_PID), /* idVendor */
+ HIBYTE(USBD_PID), /* idVendor */
+ 0x00, /* bcdDevice rel. 2.00 */
+ 0x02,
+ USBD_IDX_MFC_STR, /* Index of manufacturer string */
+ USBD_IDX_PRODUCT_STR, /* Index of product string */
+ USBD_IDX_SERIAL_STR, /* Index of serial number string */
+ USBD_MAX_NUM_CONFIGURATION /* bNumConfigurations */
+}; /* USB_DeviceDescriptor */
+
+/* USB Standard String Descriptor */
+static const uint8_t usb_stm32mp1_lang_id_desc[USB_LEN_LANGID_STR_DESC] = {
+ USB_LEN_LANGID_STR_DESC,
+ USB_DESC_TYPE_STRING,
+ LOBYTE(USBD_LANGID_STRING),
+ HIBYTE(USBD_LANGID_STRING),
+};
+
+/* USB Standard Device Descriptor */
+static const uint8_t
+usbd_stm32mp1_qualifier_desc[USB_LEN_DEV_QUALIFIER_DESC] = {
+ USB_LEN_DEV_QUALIFIER_DESC,
+ USB_DESC_TYPE_DEVICE_QUALIFIER,
+ 0x00,
+ 0x02,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x40,
+ 0x01,
+ 0x00,
+};
+
+/* USB serial number: build dynamically */
+static uint8_t usb_stm32mp1_serial[USB_SIZ_STRING_SERIAL + 1];
+
+/* USB DFU device Configuration Descriptor */
+static const uint8_t usb_stm32mp1_config_desc[USB_DFU_CONFIG_DESC_SIZ] = {
+ 0x09, /* bLength: Configuration Descriptor size */
+ USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
+ USB_DFU_CONFIG_DESC_SIZ, /* wTotalLength: Bytes returned */
+ 0x00,
+ 0x01, /* bNumInterfaces: 1 interface */
+ 0x01, /* bConfigurationValue: Configuration value */
+ 0x02, /* iConfiguration: Index of string descriptor for configuration */
+ 0xC0, /* bmAttributes: bus powered and Supprts Remote Wakeup */
+ 0x32, /* MaxPower 100 mA: this current is used for detecting Vbus */
+
+ /* Descriptor of DFU interface 0 Alternate setting 0..N */
+ USBD_DFU_IF_DESC(0),
+ USBD_DFU_IF_DESC(1),
+#if USB_DFU_ITF_NUM > 2
+ USBD_DFU_IF_DESC(2),
+#endif
+#if USB_DFU_ITF_NUM > 3
+ USBD_DFU_IF_DESC(3),
+#endif
+#if USB_DFU_ITF_NUM > 4
+ USBD_DFU_IF_DESC(4),
+#endif
+#if USB_DFU_ITF_NUM > 5
+ USBD_DFU_IF_DESC(5),
+#endif
+ /* DFU Functional Descriptor */
+ 0x09, /* blength = 9 Bytes */
+ DFU_DESCRIPTOR_TYPE, /* DFU Functional Descriptor */
+ DFU_BM_ATTRIBUTE, /* bmAttribute for DFU */
+ 0xFF, /* DetachTimeOut = 255 ms */
+ 0x00,
+ TRANSFER_SIZE_BYTES(USBD_DFU_XFER_SIZE), /* TransferSize = 1024 Byte */
+ ((USB_DFU_VERSION >> 0) & 0xFF), /* bcdDFUVersion */
+ ((USB_DFU_VERSION >> 8) & 0xFF)
+};
+
+/* The user strings: one by alternate as defined in USBD_DFU_IF_DESC */
+#if STM32MP13
+const char *const if_desc_string[USB_DFU_ITF_NUM] = {
+ "@SSBL /0x03/1*16Me",
+ "@virtual /0xF1/1*512Ba"
+};
+#endif
+#if STM32MP15
+const char *const if_desc_string[USB_DFU_ITF_NUM] = {
+ "@Partition0 /0x00/1*256Ke",
+ "@FSBL /0x01/1*1Me",
+ "@Partition2 /0x02/1*1Me",
+ "@Partition3 /0x03/1*16Me",
+ "@Partition4 /0x04/1*16Me",
+ "@virtual /0xF1/1*512Ba"
+};
+#endif
+
+/* Buffer to build the unicode string provided to USB device stack */
+static uint8_t usb_str_dec[USBD_MAX_STR_DESC_SIZ];
+
+/*
+ * Convert Ascii string into unicode one
+ * desc : descriptor buffer
+ * unicode : Formatted string buffer (unicode)
+ * len : descriptor length
+ */
+static void stm32mp1_get_string(const char *desc, uint8_t *unicode, uint16_t *len)
+{
+ uint8_t idx = 0U;
+
+ if (desc == NULL) {
+ return;
+ }
+
+ *len = strlen(desc) * 2U + 2U;
+ unicode[idx++] = *len;
+ unicode[idx++] = USB_DESC_TYPE_STRING;
+
+ while (*desc != '\0') {
+ unicode[idx++] = *desc++;
+ unicode[idx++] = 0x00U;
+ }
+}
+
+/*
+ * Create the serial number string descriptor
+ */
+static void update_serial_num_string(void)
+{
+ uint8_t i;
+ char serial_string[SIZ_STRING_SERIAL + 2U];
+ /* serial number is set to 0 */
+ uint32_t deviceserial[UID_WORD_NB] = {0U, 0U, 0U};
+ uint32_t otp;
+ uint32_t len;
+ uint16_t length;
+
+ if (stm32_get_otp_index(UID_OTP, &otp, &len) != 0) {
+ ERROR("BSEC: Get UID_OTP number Error\n");
+ return;
+ }
+
+ if ((len / __WORD_BIT) != UID_WORD_NB) {
+ ERROR("BSEC: Get UID_OTP length Error\n");
+ return;
+ }
+
+ for (i = 0; i < UID_WORD_NB; i++) {
+ if (bsec_shadow_read_otp(&deviceserial[i], i + otp) !=
+ BSEC_OK) {
+ ERROR("BSEC: UID%d Error\n", i);
+ return;
+ }
+ }
+ /* build serial number with OTP value as in ROM code */
+ snprintf(serial_string, sizeof(serial_string), "%08X%08X%08X",
+ deviceserial[0], deviceserial[1], deviceserial[2]);
+
+ length = USB_SIZ_STRING_SERIAL;
+ stm32mp1_get_string(serial_string, usb_stm32mp1_serial, &length);
+}
+
+/*
+ * Return Device Qualifier descriptor
+ * length : pointer data length
+ * return : pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_get_qualifier_desc(uint16_t *length)
+{
+ *length = sizeof(usbd_stm32mp1_qualifier_desc);
+
+ return (uint8_t *)usbd_stm32mp1_qualifier_desc;
+}
+
+/*
+ * Return configuration descriptor
+ * length : pointer data length
+ * return : pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_get_config_desc(uint16_t *length)
+{
+ *length = sizeof(usb_stm32mp1_config_desc);
+
+ return (uint8_t *)usb_stm32mp1_config_desc;
+}
+
+/*
+ * Returns the device descriptor.
+ * length: Pointer to data length variable
+ * return : Pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_device_desc(uint16_t *length)
+{
+ *length = sizeof(usb_stm32mp1_desc);
+
+ return (uint8_t *)usb_stm32mp1_desc;
+}
+
+/*
+ * Returns the LangID string descriptor.
+ * length: Pointer to data length variable
+ * return : Pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_lang_id_desc(uint16_t *length)
+{
+ *length = sizeof(usb_stm32mp1_lang_id_desc);
+
+ return (uint8_t *)usb_stm32mp1_lang_id_desc;
+}
+
+/*
+ * Returns the product string descriptor.
+ * length: Pointer to data length variable
+ * return : Pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_product_desc(uint16_t *length)
+{
+ char name[STM32_SOC_NAME_SIZE];
+ char product[128];
+ uint32_t chip_id;
+ uint32_t chip_version;
+
+ stm32mp_get_soc_name(name);
+ chip_id = stm32mp_get_chip_dev_id();
+ chip_version = stm32mp_get_chip_version();
+
+ snprintf(product, sizeof(product),
+ "DFU @Device ID /0x%03X, @Revision ID /0x%04X, @Name /%s,",
+ chip_id, chip_version, name);
+
+ stm32mp1_get_string(product, usb_str_dec, length);
+
+ return usb_str_dec;
+}
+
+/*
+ * Returns the manufacturer string descriptor.
+ * length: Pointer to data length variable
+ * return : Pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_manufacturer_desc(uint16_t *length)
+{
+ stm32mp1_get_string(USBD_MANUFACTURER_STRING, usb_str_dec, length);
+
+ return usb_str_dec;
+}
+
+/*
+ * Returns the serial number string descriptor.
+ * length: Pointer to data length variable
+ * return : Pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_serial_desc(uint16_t *length)
+{
+ *length = USB_SIZ_STRING_SERIAL;
+
+ return (uint8_t *)usb_stm32mp1_serial;
+}
+
+/*
+ * Returns the configuration string descriptor.
+ * length: Pointer to data length variable
+ * return : Pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_config_desc(uint16_t *length)
+{
+ stm32mp1_get_string(USBD_CONFIGURATION_STRING, usb_str_dec, length);
+
+ return usb_str_dec;
+}
+
+/*
+ * Returns the interface string descriptor.
+ * length : Pointer to data length variable
+ * return : Pointer to descriptor buffer
+ */
+static uint8_t *stm32mp1_interface_desc(uint16_t *length)
+{
+ stm32mp1_get_string(USBD_INTERFACE_STRING, usb_str_dec, length);
+
+ return usb_str_dec;
+}
+
+/*
+ * Manages the transfer of memory interfaces string descriptors.
+ * index: descriptor index
+ * length : pointer data length
+ * return : pointer to the descriptor table or NULL if the descriptor
+ * is not supported.
+ */
+static uint8_t *stm32mp1_get_usr_desc(uint8_t index, uint16_t *length)
+{
+ if (index >= ARRAY_SIZE(if_desc_string)) {
+ return NULL;
+ }
+
+ stm32mp1_get_string(if_desc_string[index], usb_str_dec, length);
+
+ return usb_str_dec;
+}
+
+static const struct usb_desc dfu_desc = {
+ .get_device_desc = stm32mp1_device_desc,
+ .get_lang_id_desc = stm32mp1_lang_id_desc,
+ .get_manufacturer_desc = stm32mp1_manufacturer_desc,
+ .get_product_desc = stm32mp1_product_desc,
+ .get_configuration_desc = stm32mp1_config_desc,
+ .get_serial_desc = stm32mp1_serial_desc,
+ .get_interface_desc = stm32mp1_interface_desc,
+ .get_usr_desc = stm32mp1_get_usr_desc,
+ .get_config_desc = stm32mp1_get_config_desc,
+ .get_device_qualifier_desc = stm32mp1_get_qualifier_desc,
+ /* only HS is supported, as ROM code */
+ .get_other_speed_config_desc = NULL,
+};
+
+static struct usb_handle usb_core_handle;
+static struct pcd_handle pcd_handle;
+
+struct usb_handle *usb_dfu_plat_init(void)
+{
+ /* Prepare USB Driver */
+ pcd_handle.in_ep[0].maxpacket = USB_MAX_EP0_SIZE;
+ pcd_handle.out_ep[0].maxpacket = USB_MAX_EP0_SIZE;
+ stm32mp1_usb_init_driver(&usb_core_handle, &pcd_handle,
+ (uint32_t *)USB_OTG_BASE);
+
+#if STM32MP15
+ /* STM32MP15 = keep the configuration from ROM code */
+ usb_core_handle.ep0_state = USBD_EP0_DATA_IN;
+ usb_core_handle.dev_state = USBD_STATE_CONFIGURED;
+#endif
+
+ /* Update the serial number string descriptor from the unique ID */
+ update_serial_num_string();
+
+ /* Prepare USB DFU stack */
+ usb_dfu_register(&usb_core_handle, &usb_dfu_handle);
+
+ /* Register DFU descriptor in USB stack */
+ register_platform(&usb_core_handle, &dfu_desc);
+
+ return &usb_core_handle;
+}
+
+/* Link between USB alternate and STM32CubeProgramer phase */
+uint8_t usb_dfu_get_phase(uint8_t alt)
+{
+ uint8_t ret;
+
+ switch (alt) {
+#if STM32MP13
+ case 0:
+ ret = PHASE_SSBL;
+ break;
+ case 1:
+ ret = PHASE_CMD;
+ break;
+#endif
+#if STM32MP15
+ case 3:
+ ret = PHASE_SSBL;
+ break;
+ case 5:
+ ret = PHASE_CMD;
+ break;
+#endif
+ default:
+ ret = PHASE_RESET;
+ break;
+ }
+
+ return ret;
+}