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();
+}