diff options
Diffstat (limited to 'platform/ext/target/arm/mps2/an519/target_cfg.c')
-rw-r--r-- | platform/ext/target/arm/mps2/an519/target_cfg.c | 478 |
1 files changed, 478 insertions, 0 deletions
diff --git a/platform/ext/target/arm/mps2/an519/target_cfg.c b/platform/ext/target/arm/mps2/an519/target_cfg.c new file mode 100644 index 0000000000..e61858b86b --- /dev/null +++ b/platform/ext/target/arm/mps2/an519/target_cfg.c @@ -0,0 +1,478 @@ +/* + * Copyright (c) 2018-2024, Arm Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tfm_hal_device_header.h" +#include "target_cfg.h" +#include "Driver_MPC.h" +#include "platform_retarget_dev.h" +#include "region_defs.h" +#include "tfm_plat_defs.h" +#include "region.h" + +#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0])) + +/* The section names come from the scatter file */ +REGION_DECLARE(Load$$LR$$, LR_NS_PARTITION, $$Base); +REGION_DECLARE(Image$$, ER_VENEER, $$Base); +REGION_DECLARE(Image$$, VENEER_ALIGN, $$Limit); +#ifdef BL2 +REGION_DECLARE(Load$$LR$$, LR_SECONDARY_PARTITION, $$Base); +#endif /* BL2 */ + +const struct memory_region_limits memory_regions = { + .non_secure_code_start = + (uint32_t)®ION_NAME(Load$$LR$$, LR_NS_PARTITION, $$Base) + + BL2_HEADER_SIZE, + + .non_secure_partition_base = + (uint32_t)®ION_NAME(Load$$LR$$, LR_NS_PARTITION, $$Base), + + .non_secure_partition_limit = + (uint32_t)®ION_NAME(Load$$LR$$, LR_NS_PARTITION, $$Base) + + NS_PARTITION_SIZE - 1, + + .veneer_base = + (uint32_t)®ION_NAME(Image$$, ER_VENEER, $$Base), + + .veneer_limit = + (uint32_t)®ION_NAME(Image$$, VENEER_ALIGN, $$Limit), + +#ifdef BL2 + .secondary_partition_base = + (uint32_t)®ION_NAME(Load$$LR$$, LR_SECONDARY_PARTITION, $$Base), + + .secondary_partition_limit = + (uint32_t)®ION_NAME(Load$$LR$$, LR_SECONDARY_PARTITION, $$Base) + + SECONDARY_PARTITION_SIZE - 1, +#endif /* BL2 */ +}; + +/* Allows software, via SAU, to define the code region as a NSC */ +#define NSCCFG_CODENSC 1 + +/* Import MPC driver */ +extern ARM_DRIVER_MPC Driver_SRAM1_MPC, Driver_SRAM2_MPC; + +/* Define Peripherals NS address range for the platform */ +#define PERIPHERALS_BASE_NS_START (0x40000000) +#define PERIPHERALS_BASE_NS_END (0x4FFFFFFF) + +/* Enable system reset request for CPU 0 */ +#define ENABLE_CPU0_SYSTEM_RESET_REQUEST (1U << 4U) + +/* To write into AIRCR register, 0x5FA value must be write to the VECTKEY field, + * otherwise the processor ignores the write. + */ +#define SCB_AIRCR_WRITE_MASK ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos)) + +/* Debug configuration flags */ +#define SPNIDEN_SEL_STATUS (0x01u << 7) +#define SPNIDEN_STATUS (0x01u << 6) +#define SPIDEN_SEL_STATUS (0x01u << 5) +#define SPIDEN_STATUS (0x01u << 4) +#define NIDEN_SEL_STATUS (0x01u << 3) +#define NIDEN_STATUS (0x01u << 2) +#define DBGEN_SEL_STATUS (0x01u << 1) +#define DBGEN_STATUS (0x01u << 0) + +#define All_SEL_STATUS (SPNIDEN_SEL_STATUS | SPIDEN_SEL_STATUS | \ + NIDEN_SEL_STATUS | DBGEN_SEL_STATUS) + +struct platform_data_t tfm_peripheral_std_uart = { + UART0_BASE_NS, + UART0_BASE_NS + 0xFFF, + PPC_SP_DO_NOT_CONFIGURE, + -1 +}; + +struct platform_data_t tfm_peripheral_uart1 = { + UART1_BASE_S, + UART1_BASE_S + 0xFFF, + PPC_SP_APB_PPC_EXP1, + CMSDK_UART1_APB_PPC_POS +}; + +struct platform_data_t tfm_peripheral_timer0 = { + CMSDK_TIMER0_BASE_S, + CMSDK_TIMER1_BASE_S - 1, + PPC_SP_APB_PPC0, + CMSDK_TIMER0_APB_PPC_POS +}; + +enum tfm_plat_err_t enable_fault_handlers(void) +{ + /* Secure fault is not present in the Baseline implementation. */ + /* Fault handler enable registers are not present in a Baseline + * implementation. + */ + return TFM_PLAT_ERR_SUCCESS; +} + +enum tfm_plat_err_t system_reset_cfg(void) +{ + struct sysctrl_t *sysctrl = (struct sysctrl_t *)CMSDK_SYSCTRL_BASE_S; + uint32_t reg_value = SCB->AIRCR; + + /* Enable system reset request for CPU 0, to be triggered via + * NVIC_SystemReset function. + */ + sysctrl->resetmask |= ENABLE_CPU0_SYSTEM_RESET_REQUEST; + + /* Clear SCB_AIRCR_VECTKEY value */ + reg_value &= ~(uint32_t)(SCB_AIRCR_VECTKEY_Msk); + + /* Enable system reset request for the secure world only */ + reg_value |= (uint32_t)(SCB_AIRCR_WRITE_MASK | SCB_AIRCR_SYSRESETREQS_Msk); + + SCB->AIRCR = reg_value; + + return TFM_PLAT_ERR_SUCCESS; +} + +enum tfm_plat_err_t init_debug(void) +{ + volatile struct sysctrl_t *sys_ctrl = + (struct sysctrl_t *)CMSDK_SYSCTRL_BASE_S; + +#if defined(DAUTH_NONE) + /* Set all the debug enable selector bits to 1 */ + sys_ctrl->secdbgset = All_SEL_STATUS; + /* Set all the debug enable bits to 0 */ + sys_ctrl->secdbgclr = + DBGEN_STATUS | NIDEN_STATUS | SPIDEN_STATUS | SPNIDEN_STATUS; +#elif defined(DAUTH_NS_ONLY) + /* Set all the debug enable selector bits to 1 */ + sys_ctrl->secdbgset = All_SEL_STATUS; + /* Set the debug enable bits to 1 for NS, and 0 for S mode */ + sys_ctrl->secdbgset = DBGEN_STATUS | NIDEN_STATUS; + sys_ctrl->secdbgclr = SPIDEN_STATUS | SPNIDEN_STATUS; +#elif defined(DAUTH_FULL) + /* Set all the debug enable selector bits to 1 */ + sys_ctrl->secdbgset = All_SEL_STATUS; + /* Set all the debug enable bits to 1 */ + sys_ctrl->secdbgset = + DBGEN_STATUS | NIDEN_STATUS | SPIDEN_STATUS | SPNIDEN_STATUS; +#else + +#if !defined(DAUTH_CHIP_DEFAULT) +#error "No debug authentication setting is provided." +#endif + + /* Set all the debug enable selector bits to 0 */ + sys_ctrl->secdbgclr = All_SEL_STATUS; + + /* No need to set any enable bits because the value depends on + * input signals. + */ +#endif + return TFM_PLAT_ERR_SUCCESS; +} + +/*----------------- NVIC interrupt target state to NS configuration ----------*/ +enum tfm_plat_err_t nvic_interrupt_target_state_cfg(void) +{ + /* Target every interrupt to NS; unimplemented interrupts will be WI */ + for (uint8_t i=0; i<sizeof(NVIC->ITNS)/sizeof(NVIC->ITNS[0]); i++) { + NVIC->ITNS[i] = 0xFFFFFFFF; + } + + /* Make sure that MPC and PPC are targeted to S state */ + NVIC_ClearTargetState(MPC_IRQn); + NVIC_ClearTargetState(PPC_IRQn); + +#ifdef SECURE_UART1 + /* UART1 is a secure peripheral, so its IRQs have to target S state */ + NVIC_ClearTargetState(UARTRX1_IRQn); + NVIC_ClearTargetState(UARTTX1_IRQn); + NVIC_ClearTargetState(UART1_IRQn); +#endif + + return TFM_PLAT_ERR_SUCCESS; +} + +/*----------------- NVIC interrupt enabling for S peripherals ----------------*/ +enum tfm_plat_err_t nvic_interrupt_enable(void) +{ + struct spctrl_def* spctrl = CMSDK_SPCTRL; + int32_t ret = ARM_DRIVER_OK; + + /* MPC interrupt enabling */ + ret = Driver_SRAM1_MPC.EnableInterrupt(); + if (ret != ARM_DRIVER_OK) { + return TFM_PLAT_ERR_SYSTEM_ERR; + } + ret = Driver_SRAM2_MPC.EnableInterrupt(); + if (ret != ARM_DRIVER_OK) { + return TFM_PLAT_ERR_SYSTEM_ERR; + } + NVIC_EnableIRQ(MPC_IRQn); + + /* PPC interrupt enabling */ + /* Clear pending PPC interrupts */ + /* In the PPC configuration function, we have used the Non-Secure + * Privilege Control Block to grant unprivilged NS access to some + * peripherals used by NS. That triggers a PPC0 exception as that + * register is meant for NS privileged access only. Clear it here + */ + spctrl->secppcintclr = CMSDK_APB_PPC0_INT_POS_MASK; + + /* Enable PPC interrupts for APB PPC */ + spctrl->secppcinten |= CMSDK_APB_PPC0_INT_POS_MASK | + CMSDK_APB_PPC1_INT_POS_MASK | + CMSDK_APB_PPCEXP0_INT_POS_MASK | + CMSDK_APB_PPCEXP1_INT_POS_MASK | + CMSDK_APB_PPCEXP2_INT_POS_MASK | + CMSDK_APB_PPCEXP3_INT_POS_MASK; + NVIC_EnableIRQ(PPC_IRQn); + + return TFM_PLAT_ERR_SUCCESS; +} + +/*------------------- SAU/IDAU configuration functions -----------------------*/ +struct sau_cfg_t { + uint32_t RBAR; + uint32_t RLAR; + bool nsc; +}; + +const struct sau_cfg_t sau_cfg[] = { + { + ((uint32_t)®ION_NAME(Load$$LR$$, LR_NS_PARTITION, $$Base)), + ((uint32_t)®ION_NAME(Load$$LR$$, LR_NS_PARTITION, $$Base) + + NS_PARTITION_SIZE - 1), + false, + }, + { + NS_DATA_START, + NS_DATA_LIMIT, + false, + }, + { + (uint32_t)®ION_NAME(Image$$, ER_VENEER, $$Base), + (uint32_t)®ION_NAME(Image$$, VENEER_ALIGN, $$Limit) - 1, + true, + }, + { + PERIPHERALS_BASE_NS_START, +#ifdef SECURE_UART1 + (UART1_BASE_NS - 1), + false, + }, + { + UART2_BASE_NS, +#endif + PERIPHERALS_BASE_NS_END, + false, + }, +#ifdef BL2 + { + (uint32_t)®ION_NAME(Load$$LR$$, LR_SECONDARY_PARTITION, $$Base), + (uint32_t)®ION_NAME(Load$$LR$$, LR_SECONDARY_PARTITION, $$Base) + + SECONDARY_PARTITION_SIZE - 1, + false, + }, +#endif +}; + +void sau_and_idau_cfg(void) +{ + struct spctrl_def *spctrl = CMSDK_SPCTRL; + uint32_t i; + + /* Ensure all memory accesses are completed */ + __DMB(); + + /* Enables SAU */ + TZ_SAU_Enable(); + + for (i = 0; i < ARRAY_SIZE(sau_cfg); i++) { + SAU->RNR = i; + SAU->RBAR = sau_cfg[i].RBAR & SAU_RBAR_BADDR_Msk; + SAU->RLAR = (sau_cfg[i].RLAR & SAU_RLAR_LADDR_Msk) | + (sau_cfg[i].nsc ? SAU_RLAR_NSC_Msk : 0U) | + SAU_RLAR_ENABLE_Msk; + } + + /* Allows SAU to define the code region as a NSC */ + spctrl->nsccfg |= NSCCFG_CODENSC; + + /* Ensure the write is completed and flush pipeline */ + __DSB(); + __ISB(); +} + +/*------------------- Memory configuration functions -------------------------*/ + +int32_t mpc_init_cfg(void) +{ + int32_t ret = ARM_DRIVER_OK; + + ret = Driver_SRAM1_MPC.Initialize(); + if (ret != ARM_DRIVER_OK) { + return ret; + } + + ret = Driver_SRAM1_MPC.ConfigRegion( + memory_regions.non_secure_partition_base, + memory_regions.non_secure_partition_limit, + ARM_MPC_ATTR_NONSECURE); + if (ret != ARM_DRIVER_OK) { + return ret; + } + +#ifdef BL2 + /* Secondary image region */ + ret = Driver_SRAM1_MPC.ConfigRegion(memory_regions.secondary_partition_base, + memory_regions.secondary_partition_limit, + ARM_MPC_ATTR_NONSECURE); + if (ret != ARM_DRIVER_OK) { + return ret; + } +#endif /* BL2 */ + + ret = Driver_SRAM2_MPC.Initialize(); + if (ret != ARM_DRIVER_OK) { + return ret; + } + + ret = Driver_SRAM2_MPC.ConfigRegion(NS_DATA_START, NS_DATA_LIMIT, + ARM_MPC_ATTR_NONSECURE); + if (ret != ARM_DRIVER_OK) { + return ret; + } + + /* Lock down the MPC configuration */ + ret = Driver_SRAM1_MPC.LockDown(); + if (ret != ARM_DRIVER_OK) { + return ret; + } + + ret = Driver_SRAM2_MPC.LockDown(); + if (ret != ARM_DRIVER_OK) { + return ret; + } + + /* Add barriers to assure the MPC configuration is done before continue + * the execution. + */ + __DSB(); + __ISB(); + + return ARM_DRIVER_OK; +} + +/*---------------------- PPC configuration functions -------------------------*/ + +void ppc_init_cfg(void) +{ + struct spctrl_def* spctrl = CMSDK_SPCTRL; + struct nspctrl_def* nspctrl = CMSDK_NSPCTRL; + + /* Grant non-secure access to peripherals in the PPC0 + * (timer0 and 1, dualtimer, watchdog, mhu 0 and 1) + */ + spctrl->apbnsppc0 |= (1U << CMSDK_TIMER0_APB_PPC_POS) | + (1U << CMSDK_TIMER1_APB_PPC_POS) | + (1U << CMSDK_DTIMER_APB_PPC_POS) | + (1U << CMSDK_MHU0_APB_PPC_POS) | + (1U << CMSDK_MHU1_APB_PPC_POS); + + /* Grant non-secure access for APB peripherals on EXP1 */ + spctrl->apbnsppcexp1 |= (1U << CMSDK_SPI0_APB_PPC_POS) | + (1U << CMSDK_SPI1_APB_PPC_POS) | + (1U << CMSDK_SPI2_APB_PPC_POS) | + (1U << CMSDK_SPI3_APB_PPC_POS) | + (1U << CMSDK_SPI4_APB_PPC_POS) | + (1U << CMSDK_UART0_APB_PPC_POS) | +#ifdef SECURE_UART1 + /* To statically configure a peripheral as secure, skip PPC NS peripheral + * configuration for the given device. + */ +#else + (1U << CMSDK_UART1_APB_PPC_POS) | +#endif + (1U << CMSDK_UART2_APB_PPC_POS) | + (1U << CMSDK_UART3_APB_PPC_POS) | + (1U << CMSDK_UART4_APB_PPC_POS) | + (1U << CMSDK_I2C0_APB_PPC_POS) | + (1U << CMSDK_I2C1_APB_PPC_POS) | + (1U << CMSDK_I2C2_APB_PPC_POS) | + (1U << CMSDK_I2C3_APB_PPC_POS); + /* Grant non-secure access for APB peripherals on EXP2 */ + spctrl->apbnsppcexp2 |= (1U << CMSDK_FPGA_SCC_PPC_POS) | + (1U << CMSDK_FPGA_AUDIO_PPC_POS) | + (1U << CMSDK_FPGA_IO_PPC_POS); + + /* Grant non-secure access to all peripherals on AHB EXP: + * Make sure that all possible peripherals are enabled by default + */ + spctrl->ahbnsppcexp0 |= (1U << CMSDK_VGA_PPC_POS) | + (1U << CMSDK_GPIO0_PPC_POS) | + (1U << CMSDK_GPIO1_PPC_POS) | + (1U << CMSDK_GPIO2_PPC_POS) | + (1U << CMSDK_GPIO3_PPC_POS) | + (1U << MPS2_ETHERNET_PPC_POS); + + spctrl->ahbnsppcexp1 |= (1U << CMSDK_DMA0_PPC_POS) | + (1U << CMSDK_DMA1_PPC_POS) | + (1U << CMSDK_DMA2_PPC_POS) | + (1U << CMSDK_DMA3_PPC_POS); + + /* in NS, grant un-privileged for UART0 */ + nspctrl->apbnspppcexp1 |= (1U << CMSDK_UART0_APB_PPC_POS); + + /* in NS, grant un-privileged access for LEDs */ + nspctrl->apbnspppcexp2 |= (1U << CMSDK_FPGA_SCC_PPC_POS) | + (1U << CMSDK_FPGA_IO_PPC_POS); + + /* Configure the response to a security violation as a + * bus error instead of RAZ/WI + */ + spctrl->secrespcfg |= 1U; +} + +void ppc_configure_to_non_secure(enum ppc_bank_e bank, uint16_t pos) +{ + /* Setting NS flag for peripheral to enable NS access */ + struct spctrl_def* spctrl = CMSDK_SPCTRL; + ((uint32_t*)&(spctrl->ahbnsppc0))[bank] |= (1U << pos); +} + +void ppc_configure_to_secure(enum ppc_bank_e bank, uint16_t pos) +{ + /* Clear NS flag for peripheral to prevent NS access */ + struct spctrl_def* spctrl = CMSDK_SPCTRL; + ((uint32_t*)&(spctrl->ahbnsppc0))[bank] &= ~(1U << pos); +} + +void ppc_en_secure_unpriv(enum ppc_bank_e bank, uint16_t pos) +{ + struct spctrl_def* spctrl = CMSDK_SPCTRL; + ((uint32_t*)&(spctrl->ahbspppc0))[bank] |= (1U << pos); +} + +void ppc_clr_secure_unpriv(enum ppc_bank_e bank, uint16_t pos) +{ + struct spctrl_def* spctrl = CMSDK_SPCTRL; + ((uint32_t*)&(spctrl->ahbspppc0))[bank] &= ~(1U << pos); +} + +void ppc_clear_irq(void) +{ + struct spctrl_def* spctrl = CMSDK_SPCTRL; + /* Clear APB PPC EXP2 IRQ */ + spctrl->secppcintclr = CMSDK_APB_PPCEXP2_INT_POS_MASK; +} |