stm32mp1: Add DDR support and its security with TZC400

The DDR driver is under dual license, BSD and GPLv2.
The configuration parameters are taken from device tree.

Signed-off-by: Yann Gautier <yann.gautier@st.com>
Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com>
Signed-off-by: Nicolas Le Bayon <nicolas.le.bayon@st.com>
Signed-off-by: Lionel Debieve <lionel.debieve@st.com>
diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c
index 84484e1..9f2d8bd 100644
--- a/plat/st/stm32mp1/bl2_plat_setup.c
+++ b/plat/st/stm32mp1/bl2_plat_setup.c
@@ -22,6 +22,7 @@
 #include <stm32mp1_private.h>
 #include <stm32mp1_context.h>
 #include <stm32mp1_pwr.h>
+#include <stm32mp1_ram.h>
 #include <stm32mp1_rcc.h>
 #include <stm32mp1_reset.h>
 #include <string.h>
@@ -35,10 +36,18 @@
 
 void bl2_platform_setup(void)
 {
+	int ret;
+
 	if (dt_check_pmic()) {
 		initialize_pmic();
 	}
 
+	ret = stm32mp1_ddr_probe();
+	if (ret < 0) {
+		ERROR("Invalid DDR init: error %d\n", ret);
+		panic();
+	}
+
 	INFO("BL2 runs SP_MIN setup\n");
 }
 
@@ -146,5 +155,7 @@
 		ERROR("Cannot save boot interface\n");
 	}
 
+	stm32mp1_arch_security_setup();
+
 	stm32mp1_io_setup();
 }
diff --git a/plat/st/stm32mp1/include/stm32mp1_dt.h b/plat/st/stm32mp1/include/stm32mp1_dt.h
index 1b1024a..58e10d1 100644
--- a/plat/st/stm32mp1/include/stm32mp1_dt.h
+++ b/plat/st/stm32mp1/include/stm32mp1_dt.h
@@ -35,6 +35,7 @@
 int dt_get_node(struct dt_node_info *info, int offset, const char *compat);
 int dt_get_stdout_uart_info(struct dt_node_info *info);
 int dt_get_stdout_node_offset(void);
+uint32_t dt_get_ddr_size(void);
 const char *dt_get_board_model(void);
 
 #endif /* __STM32MP1_DT_H__ */
diff --git a/plat/st/stm32mp1/include/stm32mp1_private.h b/plat/st/stm32mp1/include/stm32mp1_private.h
index 6a0449e..41c46e8 100644
--- a/plat/st/stm32mp1/include/stm32mp1_private.h
+++ b/plat/st/stm32mp1/include/stm32mp1_private.h
@@ -10,6 +10,8 @@
 void stm32mp1_io_setup(void);
 void configure_mmu(void);
 
+void stm32mp1_arch_security_setup(void);
+
 void stm32mp1_save_boot_ctx_address(uintptr_t address);
 uintptr_t stm32mp1_get_boot_ctx_address(void);
 
diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk
index bd74d0f..1609213 100644
--- a/plat/st/stm32mp1/platform.mk
+++ b/plat/st/stm32mp1/platform.mk
@@ -37,10 +37,12 @@
 PLAT_BL_COMMON_SOURCES	+=	lib/cpus/aarch32/cortex_a7.S
 
 PLAT_BL_COMMON_SOURCES	+=	${LIBFDT_SRCS}						\
+				drivers/arm/tzc/tzc400.c				\
 				drivers/delay_timer/delay_timer.c			\
 				drivers/delay_timer/generic_delay_timer.c		\
 				drivers/st/clk/stm32mp1_clk.c				\
 				drivers/st/clk/stm32mp1_clkfunc.c			\
+				drivers/st/ddr/stm32mp1_ddr_helpers.c			\
 				drivers/st/gpio/stm32_gpio.c				\
 				drivers/st/pmic/stm32_i2c.c				\
 				drivers/st/pmic/stm32mp1_pmic.c				\
@@ -48,13 +50,17 @@
 				drivers/st/reset/stm32mp1_reset.c			\
 				plat/st/stm32mp1/stm32mp1_context.c			\
 				plat/st/stm32mp1/stm32mp1_dt.c				\
-				plat/st/stm32mp1/stm32mp1_helper.S
+				plat/st/stm32mp1/stm32mp1_helper.S			\
+				plat/st/stm32mp1/stm32mp1_security.c
 
 BL2_SOURCES		+=	drivers/io/io_dummy.c					\
 				drivers/io/io_storage.c					\
 				plat/st/stm32mp1/bl2_io_storage.c			\
 				plat/st/stm32mp1/bl2_plat_setup.c
 
+BL2_SOURCES		+=	drivers/st/ddr/stm32mp1_ddr.c				\
+				drivers/st/ddr/stm32mp1_ram.c
+
 BL2_SOURCES		+=	common/desc_image_load.c				\
 				plat/st/stm32mp1/plat_bl2_mem_params_desc.c		\
 				plat/st/stm32mp1/plat_image_load.c
diff --git a/plat/st/stm32mp1/stm32mp1_common.c b/plat/st/stm32mp1/stm32mp1_common.c
index 9f1126b..e2f90d2 100644
--- a/plat/st/stm32mp1/stm32mp1_common.c
+++ b/plat/st/stm32mp1/stm32mp1_common.c
@@ -36,10 +36,18 @@
 					MT_SECURE | \
 					MT_EXECUTE_NEVER)
 
+#define MAP_DDR		MAP_REGION_FLAT(STM32MP1_DDR_BASE, \
+					STM32MP1_DDR_MAX_SIZE, \
+					MT_MEMORY | \
+					MT_RW | \
+					MT_SECURE | \
+					MT_EXECUTE_NEVER)
+
 static const mmap_region_t stm32mp1_mmap[] = {
 	MAP_SRAM,
 	MAP_DEVICE1,
 	MAP_DEVICE2,
+	MAP_DDR,
 	{0}
 };
 
diff --git a/plat/st/stm32mp1/stm32mp1_dt.c b/plat/st/stm32mp1/stm32mp1_dt.c
index 7caf655..bde968a 100644
--- a/plat/st/stm32mp1/stm32mp1_dt.c
+++ b/plat/st/stm32mp1/stm32mp1_dt.c
@@ -11,7 +11,9 @@
 #include <stm32_gpio.h>
 #include <stm32mp1_clk.h>
 #include <stm32mp1_clkfunc.h>
+#include <stm32mp1_ddr.h>
 #include <stm32mp1_dt.h>
+#include <stm32mp1_ram.h>
 
 #define DT_GPIO_BANK_SHIFT	12
 #define DT_GPIO_BANK_MASK	0x1F000U
@@ -441,6 +443,24 @@
 }
 
 /*******************************************************************************
+ * This function gets DDR size information from the DT.
+ * Returns value in bytes if success, and STM32MP1_DDR_SIZE_DFLT else.
+ ******************************************************************************/
+uint32_t dt_get_ddr_size(void)
+{
+	int node;
+
+	node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT);
+	if (node < 0) {
+		INFO("%s: Cannot read DDR node in DT\n", __func__);
+		return STM32MP1_DDR_SIZE_DFLT;
+	}
+
+	return fdt_read_uint32_default(node, "st,mem-size",
+				       STM32MP1_DDR_SIZE_DFLT);
+}
+
+/*******************************************************************************
  * This function retrieves board model from DT
  * Returns string taken from model node, NULL otherwise
  ******************************************************************************/
diff --git a/plat/st/stm32mp1/stm32mp1_security.c b/plat/st/stm32mp1/stm32mp1_security.c
new file mode 100644
index 0000000..0cdf305
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_security.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <mmio.h>
+#include <stdint.h>
+#include <stm32mp1_clk.h>
+#include <stm32mp1_dt.h>
+#include <stm32mp1_private.h>
+#include <stm32mp1_rcc.h>
+#include <tzc400.h>
+#include "platform_def.h"
+
+/*******************************************************************************
+ * Initialize the TrustZone Controller.
+ * Early initialization create only one region with full access to secure.
+ * This setting is used before and during DDR initialization.
+ ******************************************************************************/
+static void early_init_tzc400(void)
+{
+	uint32_t rstsr, rst_standby;
+
+	rstsr = mmio_read_32(RCC_BASE + RCC_MP_RSTSCLRR);
+
+	/* No warning if return from (C)STANDBY */
+	rst_standby = rstsr &
+		(RCC_MP_RSTSCLRR_STDBYRSTF | RCC_MP_RSTSCLRR_CSTDBYRSTF);
+
+	if (stm32mp1_clk_is_enabled(TZC1) && (rst_standby == 0U)) {
+		WARN("TZC400 port 1 clock already enable\n");
+	}
+
+	if (stm32mp1_clk_is_enabled(TZC2) && (rst_standby == 0U)) {
+		WARN("TZC400 port 2 clock already enable\n");
+	}
+
+	if (stm32mp1_clk_enable(TZC1) != 0) {
+		ERROR("Cannot enable TZC1 clock\n");
+		panic();
+	}
+	if (stm32mp1_clk_enable(TZC2) != 0) {
+		ERROR("Cannot enable TZC2 clock\n");
+		panic();
+	}
+
+	tzc400_init(STM32MP1_TZC_BASE);
+
+	tzc400_disable_filters();
+
+	/*
+	 * Region 1 set to cover Non-Secure DRAM at 0x8000_0000. Apply the
+	 * same configuration to all filters in the TZC.
+	 */
+	tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 1,
+				STM32MP1_DDR_BASE,
+				STM32MP1_DDR_BASE +
+				(STM32MP1_DDR_MAX_SIZE - 1U),
+				TZC_REGION_S_RDWR,
+				TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID));
+
+	/* Raise an exception if a NS device tries to access secure memory */
+	tzc400_set_action(TZC_ACTION_ERR);
+
+	tzc400_enable_filters();
+}
+
+/*******************************************************************************
+ * Initialize the secure environment. At this moment only the TrustZone
+ * Controller is initialized.
+ ******************************************************************************/
+void stm32mp1_arch_security_setup(void)
+{
+	early_init_tzc400();
+}