blob: cea69bbe607a5ce5f13db8ede7c38d98cf0b4b7f [file] [log] [blame]
/*
* Copyright (c) 2018 Nordic Semiconductor ASA.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/arch/arm/aarch32/cortex_m/cmsis.h>
#include <aarch32/cortex_m/tz.h>
#include <aarch32/cortex_m/exc.h>
static void configure_nonsecure_vtor_offset(uint32_t vtor_ns)
{
SCB_NS->VTOR = vtor_ns;
}
static void configure_nonsecure_msp(uint32_t msp_ns)
{
__TZ_set_MSP_NS(msp_ns);
}
static void configure_nonsecure_psp(uint32_t psp_ns)
{
__TZ_set_PSP_NS(psp_ns);
}
static void configure_nonsecure_control(uint32_t spsel_ns, uint32_t npriv_ns)
{
uint32_t control_ns = __TZ_get_CONTROL_NS();
/* Only nPRIV and SPSEL bits are banked between security states. */
control_ns &= ~(CONTROL_SPSEL_Msk | CONTROL_nPRIV_Msk);
if (spsel_ns) {
control_ns |= CONTROL_SPSEL_Msk;
}
if (npriv_ns) {
control_ns |= CONTROL_nPRIV_Msk;
}
__TZ_set_CONTROL_NS(control_ns);
}
#if defined(CONFIG_ARMV8_M_MAINLINE)
/* Only ARMv8-M Mainline implementations have Non-Secure instances of
* Stack Pointer Limit registers.
*/
void tz_nonsecure_msplim_set(uint32_t val)
{
__TZ_set_MSPLIM_NS(val);
}
void tz_nonsecure_psplim_set(uint32_t val)
{
__TZ_set_PSPLIM_NS(val);
}
#endif /* CONFIG_ARMV8_M_MAINLINE */
void tz_nonsecure_state_setup(const tz_nonsecure_setup_conf_t *p_ns_conf)
{
configure_nonsecure_vtor_offset(p_ns_conf->vtor_ns);
configure_nonsecure_msp(p_ns_conf->msp_ns);
configure_nonsecure_psp(p_ns_conf->psp_ns);
/* Select which stack-pointer to use (MSP or PSP) and
* the privilege level for thread mode.
*/
configure_nonsecure_control(p_ns_conf->control_ns.spsel,
p_ns_conf->control_ns.npriv);
}
void tz_nbanked_exception_target_state_set(int secure_state)
{
uint32_t aircr_payload = SCB->AIRCR & (~(SCB_AIRCR_VECTKEY_Msk));
if (secure_state) {
aircr_payload &= ~(SCB_AIRCR_BFHFNMINS_Msk);
} else {
aircr_payload |= SCB_AIRCR_BFHFNMINS_Msk;
}
SCB->AIRCR = ((AIRCR_VECT_KEY_PERMIT_WRITE << SCB_AIRCR_VECTKEY_Pos)
& SCB_AIRCR_VECTKEY_Msk)
| aircr_payload;
}
void tz_nonsecure_exception_prio_config(int secure_boost)
{
uint32_t aircr_payload = SCB->AIRCR & (~(SCB_AIRCR_VECTKEY_Msk));
if (secure_boost) {
aircr_payload |= SCB_AIRCR_PRIS_Msk;
} else {
aircr_payload &= ~(SCB_AIRCR_PRIS_Msk);
}
SCB->AIRCR = ((AIRCR_VECT_KEY_PERMIT_WRITE << SCB_AIRCR_VECTKEY_Pos)
& SCB_AIRCR_VECTKEY_Msk)
| aircr_payload;
}
void tz_nonsecure_system_reset_req_block(int block)
{
uint32_t aircr_payload = SCB->AIRCR & (~(SCB_AIRCR_VECTKEY_Msk));
if (block) {
aircr_payload |= SCB_AIRCR_SYSRESETREQS_Msk;
} else {
aircr_payload &= ~(SCB_AIRCR_SYSRESETREQS_Msk);
}
SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos)
& SCB_AIRCR_VECTKEY_Msk)
| aircr_payload;
}
#if defined(CONFIG_ARMV7_M_ARMV8_M_FP)
void tz_nonsecure_fpu_access_enable(void)
{
SCB->NSACR |=
(1UL << SCB_NSACR_CP10_Pos) | (1UL << SCB_NSACR_CP11_Pos);
}
#endif /* CONFIG_ARMV7_M_ARMV8_M_FP */
void tz_sau_configure(int enable, int allns)
{
if (enable) {
TZ_SAU_Enable();
} else {
TZ_SAU_Disable();
if (allns) {
SAU->CTRL |= SAU_CTRL_ALLNS_Msk;
} else {
SAU->CTRL &= ~(SAU_CTRL_ALLNS_Msk);
}
}
}
uint32_t tz_sau_number_of_regions_get(void)
{
return SAU->TYPE & SAU_TYPE_SREGION_Msk;
}
#if defined(CONFIG_CPU_HAS_ARM_SAU)
#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U)
int tz_sau_region_configure_enable(tz_sau_conf_t *p_sau_conf)
{
uint32_t regions = tz_sau_number_of_regions_get();
if ((p_sau_conf->region_num == 0) ||
(p_sau_conf->region_num > (regions - 1))) {
return 0;
}
/* Valid region */
SAU->RNR = p_sau_conf->region_num & SAU_RNR_REGION_Msk;
if (p_sau_conf->enable) {
SAU->RLAR = SAU_RLAR_ENABLE_Msk
| (SAU_RLAR_LADDR_Msk & p_sau_conf->limit_addr)
| (p_sau_conf->nsc ? SAU_RLAR_NSC_Msk : 0);
SAU->RBAR = p_sau_conf->base_addr & SAU_RBAR_BADDR_Msk;
} else {
SAU->RLAR &= ~(SAU_RLAR_ENABLE_Msk);
}
return 1;
}
#else
#error "ARM SAU not implemented"
#endif
#endif /* CONFIG_CPU_HAS_ARM_SAU */