stm32mp1: Add BL32 SP_min secure monitor
Signed-off-by: Yann Gautier <yann.gautier@st.com> Signed-off-by: Mathieu Belou <mathieu.belou@st.com> Signed-off-by: Lionel Debieve <lionel.debieve@st.com> Signed-off-by: Etienne Carriere <etienne.carriere@st.com> Signed-off-by: Nicolas Le Bayon <nicolas.le.bayon@st.com>
This commit is contained in:
parent
10a511ceaa
commit
964dfee1a2
|
@ -18,7 +18,11 @@
|
|||
******************************************************************************/
|
||||
|
||||
/* Size of cacheable stacks */
|
||||
#if defined(IMAGE_BL32)
|
||||
#define PLATFORM_STACK_SIZE 0x600
|
||||
#else
|
||||
#define PLATFORM_STACK_SIZE 0xC00
|
||||
#endif
|
||||
|
||||
/* SSBL = second stage boot loader */
|
||||
#define BL33_IMAGE_NAME "ssbl"
|
||||
|
|
|
@ -11,8 +11,12 @@ void stm32mp1_io_setup(void);
|
|||
void configure_mmu(void);
|
||||
|
||||
void stm32mp1_arch_security_setup(void);
|
||||
void stm32mp1_security_setup(void);
|
||||
|
||||
void stm32mp1_save_boot_ctx_address(uintptr_t address);
|
||||
uintptr_t stm32mp1_get_boot_ctx_address(void);
|
||||
|
||||
void stm32mp1_gic_pcpu_init(void);
|
||||
void stm32mp1_gic_init(void);
|
||||
|
||||
#endif /* __STM32MP1_PRIVATE_H__ */
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
#
|
||||
# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
SP_MIN_WITH_SECURE_FIQ := 1
|
||||
|
||||
BL32_SOURCES += 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_topology.c
|
||||
# Generic GIC v2
|
||||
BL32_SOURCES += drivers/arm/gic/common/gic_common.c \
|
||||
drivers/arm/gic/v2/gicv2_helpers.c \
|
||||
drivers/arm/gic/v2/gicv2_main.c \
|
||||
plat/common/plat_gicv2.c \
|
||||
plat/st/stm32mp1/stm32mp1_gic.c
|
||||
|
||||
# Generic PSCI
|
||||
BL32_SOURCES += plat/common/plat_psci_common.c
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <arm_gic.h>
|
||||
#include <assert.h>
|
||||
#include <bl_common.h>
|
||||
#include <console.h>
|
||||
#include <context.h>
|
||||
#include <context_mgmt.h>
|
||||
#include <debug.h>
|
||||
#include <dt-bindings/clock/stm32mp1-clks.h>
|
||||
#include <generic_delay_timer.h>
|
||||
#include <mmio.h>
|
||||
#include <platform.h>
|
||||
#include <platform_def.h>
|
||||
#include <platform_sp_min.h>
|
||||
#include <stm32mp1_clk.h>
|
||||
#include <stm32mp1_dt.h>
|
||||
#include <stm32mp1_private.h>
|
||||
#include <string.h>
|
||||
#include <tzc400.h>
|
||||
#include <xlat_tables_v2.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)
|
||||
{
|
||||
switch (id) {
|
||||
case STM32MP1_IRQ_TZC400:
|
||||
ERROR("STM32MP1_IRQ_TZC400 generated\n");
|
||||
panic();
|
||||
break;
|
||||
case STM32MP1_IRQ_AXIERRIRQ:
|
||||
ERROR("STM32MP1_IRQ_AXIERRIRQ generated\n");
|
||||
panic();
|
||||
break;
|
||||
default:
|
||||
ERROR("SECURE IT handler not define for it : %i", 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;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* 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)
|
||||
{
|
||||
struct dt_node_info dt_dev_info;
|
||||
int result;
|
||||
bl_params_t *params_from_bl2 = (bl_params_t *)arg0;
|
||||
|
||||
/* Imprecise aborts can be masked in NonSecure */
|
||||
write_scr(read_scr() | SCR_AW_BIT);
|
||||
|
||||
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;
|
||||
break;
|
||||
}
|
||||
|
||||
bl_params = bl_params->next_params_info;
|
||||
}
|
||||
|
||||
if (dt_open_and_check() < 0) {
|
||||
panic();
|
||||
}
|
||||
|
||||
if (stm32mp1_clk_probe() < 0) {
|
||||
panic();
|
||||
}
|
||||
|
||||
result = dt_get_stdout_uart_info(&dt_dev_info);
|
||||
|
||||
if ((result > 0) && dt_dev_info.status) {
|
||||
if (console_init(dt_dev_info.base, 0, STM32MP1_UART_BAUDRATE)
|
||||
== 0) {
|
||||
panic();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Initialize the MMU, security and the GIC.
|
||||
******************************************************************************/
|
||||
void sp_min_platform_setup(void)
|
||||
{
|
||||
mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
|
||||
BL_CODE_END - BL_CODE_BASE,
|
||||
MT_CODE | MT_SECURE);
|
||||
|
||||
configure_mmu();
|
||||
|
||||
/* Initialize tzc400 after DDR initialization */
|
||||
stm32mp1_security_setup();
|
||||
|
||||
generic_delay_timer_init();
|
||||
|
||||
stm32mp1_gic_init();
|
||||
}
|
||||
|
||||
void sp_min_plat_arch_setup(void)
|
||||
{
|
||||
}
|
|
@ -43,6 +43,14 @@
|
|||
MT_SECURE | \
|
||||
MT_EXECUTE_NEVER)
|
||||
|
||||
#define MAP_DDR_NS MAP_REGION_FLAT(STM32MP1_DDR_BASE, \
|
||||
STM32MP1_DDR_MAX_SIZE, \
|
||||
MT_MEMORY | \
|
||||
MT_RW | \
|
||||
MT_NS | \
|
||||
MT_EXECUTE_NEVER)
|
||||
|
||||
#if defined(IMAGE_BL2)
|
||||
static const mmap_region_t stm32mp1_mmap[] = {
|
||||
MAP_SRAM,
|
||||
MAP_DEVICE1,
|
||||
|
@ -50,6 +58,16 @@ static const mmap_region_t stm32mp1_mmap[] = {
|
|||
MAP_DDR,
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
#if defined(IMAGE_BL32)
|
||||
static const mmap_region_t stm32mp1_mmap[] = {
|
||||
MAP_SRAM,
|
||||
MAP_DEVICE1,
|
||||
MAP_DEVICE2,
|
||||
MAP_DDR_NS,
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
|
||||
void configure_mmu(void)
|
||||
{
|
||||
|
|
|
@ -71,7 +71,12 @@ enum ddr_type {
|
|||
* MAX_MMAP_REGIONS is usually:
|
||||
* BL stm32mp1_mmap size + mmap regions in *_plat_arch_setup
|
||||
*/
|
||||
#define MAX_MMAP_REGIONS 11
|
||||
#if defined(IMAGE_BL2)
|
||||
#define MAX_MMAP_REGIONS 11
|
||||
#endif
|
||||
#if defined(IMAGE_BL32)
|
||||
#define MAX_MMAP_REGIONS 6
|
||||
#endif
|
||||
|
||||
/* DTB initialization value */
|
||||
#define STM32MP1_DTB_SIZE U(0x00004000) /* 16Ko for DTB */
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <bl_common.h>
|
||||
#include <gicv2.h>
|
||||
#include <platform.h>
|
||||
#include <platform_def.h>
|
||||
#include <utils.h>
|
||||
|
||||
#include <stm32mp1_private.h>
|
||||
|
||||
/******************************************************************************
|
||||
* 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)
|
||||
};
|
||||
|
||||
static unsigned int target_mask_array[PLATFORM_CORE_COUNT];
|
||||
|
||||
static const gicv2_driver_data_t platform_gic_data = {
|
||||
.gicd_base = STM32MP1_GICD_BASE,
|
||||
.gicc_base = STM32MP1_GICC_BASE,
|
||||
.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),
|
||||
};
|
||||
|
||||
void stm32mp1_gic_init(void)
|
||||
{
|
||||
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();
|
||||
}
|
|
@ -0,0 +1,255 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <assert.h>
|
||||
#include <boot_api.h>
|
||||
#include <debug.h>
|
||||
#include <dt-bindings/clock/stm32mp1-clks.h>
|
||||
#include <errno.h>
|
||||
#include <gic_common.h>
|
||||
#include <gicv2.h>
|
||||
#include <mmio.h>
|
||||
#include <platform_def.h>
|
||||
#include <platform.h>
|
||||
#include <psci.h>
|
||||
#include <stm32mp1_clk.h>
|
||||
#include <stm32mp1_private.h>
|
||||
#include <stm32mp1_rcc.h>
|
||||
|
||||
static uint32_t stm32_sec_entrypoint;
|
||||
static uint32_t cntfrq_core0;
|
||||
|
||||
#define SEND_SECURE_IT_TO_CORE_1 0x20000U
|
||||
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
*/
|
||||
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();
|
||||
uint32_t tamp_clk_off = 0;
|
||||
uint32_t bkpr_core1_addr =
|
||||
tamp_bkpr(BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX);
|
||||
uint32_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;
|
||||
}
|
||||
|
||||
if ((stm32_sec_entrypoint < STM32MP1_SRAM_BASE) ||
|
||||
(stm32_sec_entrypoint > (STM32MP1_SRAM_BASE +
|
||||
(STM32MP1_SRAM_SIZE - 1)))) {
|
||||
return PSCI_E_INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
if (!stm32mp1_clk_is_enabled(RTCAPB)) {
|
||||
tamp_clk_off = 1;
|
||||
if (stm32mp1_clk_enable(RTCAPB) != 0) {
|
||||
panic();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (tamp_clk_off != 0U) {
|
||||
if (stm32mp1_clk_disable(RTCAPB) != 0) {
|
||||
panic();
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate an IT to core 1 */
|
||||
mmio_write_32(STM32MP1_GICD_BASE + GICD_SGIR,
|
||||
SEND_SECURE_IT_TO_CORE_1 | ARM_IRQ_SEC_SGI_0);
|
||||
|
||||
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(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 < STM32MP1_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;
|
||||
}
|
|
@ -15,6 +15,46 @@
|
|||
#include <tzc400.h>
|
||||
#include "platform_def.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Initialize the TrustZone Controller. Configure Region 0 with Secure RW access
|
||||
* and allow Non-Secure masters full access.
|
||||
******************************************************************************/
|
||||
static void init_tzc400(void)
|
||||
{
|
||||
unsigned long long region_base, region_top;
|
||||
unsigned long long ddr_base = STM32MP1_DDR_BASE;
|
||||
unsigned long long ddr_size = (unsigned long long)dt_get_ddr_size();
|
||||
|
||||
tzc400_init(STM32MP1_TZC_BASE);
|
||||
|
||||
tzc400_disable_filters();
|
||||
|
||||
/* Region 1 set to cover all DRAM at 0xC000_0000. Apply the
|
||||
* same configuration to all filters in the TZC.
|
||||
*/
|
||||
region_base = ddr_base;
|
||||
region_top = ddr_base + (ddr_size - 1U);
|
||||
tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 1,
|
||||
region_base,
|
||||
region_top,
|
||||
TZC_REGION_S_RDWR,
|
||||
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) |
|
||||
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_GPU_ID) |
|
||||
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_LCD_ID) |
|
||||
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_MDMA_ID) |
|
||||
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DMA_ID) |
|
||||
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_HOST_ID) |
|
||||
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_OTG_ID) |
|
||||
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID) |
|
||||
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_ETH_ID) |
|
||||
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DAP_ID));
|
||||
|
||||
/* Raise an exception if a NS device tries to access secure memory */
|
||||
tzc400_set_action(TZC_ACTION_ERR);
|
||||
|
||||
tzc400_enable_filters();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Initialize the TrustZone Controller.
|
||||
* Early initialization create only one region with full access to secure.
|
||||
|
@ -76,3 +116,12 @@ void stm32mp1_arch_security_setup(void)
|
|||
{
|
||||
early_init_tzc400();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Initialize the secure environment. At this moment only the TrustZone
|
||||
* Controller is initialized.
|
||||
******************************************************************************/
|
||||
void stm32mp1_security_setup(void)
|
||||
{
|
||||
init_tzc400();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <platform_def.h>
|
||||
#include <platform.h>
|
||||
#include <psci.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;
|
||||
}
|
Loading…
Reference in New Issue