aboutsummaryrefslogtreecommitdiff
path: root/platform/ext/target/mps2/an521/target_cfg.c
diff options
context:
space:
mode:
Diffstat (limited to 'platform/ext/target/mps2/an521/target_cfg.c')
-rw-r--r--platform/ext/target/mps2/an521/target_cfg.c292
1 files changed, 292 insertions, 0 deletions
diff --git a/platform/ext/target/mps2/an521/target_cfg.c b/platform/ext/target/mps2/an521/target_cfg.c
new file mode 100644
index 0000000000..65904d6231
--- /dev/null
+++ b/platform/ext/target/mps2/an521/target_cfg.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2017 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 <arm_cmse.h>
+
+#include "cmsis.h"
+#include "target_cfg.h"
+#include "Driver_MPC.h"
+#include "platform_retarget_dev.h"
+#include "region_defs.h"
+#include "tfm_secure_api.h"
+
+/*
+ * This function pointer is meant to only hold non secure function pointers.
+ * It will be turned into a non-secure one (LSB cleared) before being called
+ * whatever happens anyway (unless cast to another function pointer type).
+ * Registers will be cleared before branching so that no information leaks
+ * from secure to non-secure world.
+ */
+typedef void __attribute__((cmse_nonsecure_call)) (*nsfptr_t) (void);
+
+/* 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)
+
+void configure_ns_code()
+{
+ /* SCB_NS.VTOR points to the Non-secure vector table base address */
+ SCB_NS->VTOR = (NS_CODE_START);
+
+ /* Setups Main stack pointer of the non-secure code */
+ uint32_t ns_msp = *((uint32_t*)(NS_CODE_START));
+ __TZ_set_MSP_NS(ns_msp);
+}
+
+void jump_to_ns_code()
+{
+ /* The entry contains address of the Reset_handler (CMSIS-CORE) function */
+ uint32_t entry_ptr = *((uint32_t*)(NS_CODE_START + 4));
+
+ /* Clears LSB of the function address to indicate the function-call
+ will perform the switch from secure to non-secure */
+ nsfptr_t ns_entry = (nsfptr_t) cmse_nsfptr_create(entry_ptr);
+
+ /* All changes made to memory will be effective after this point */
+ __DSB();
+ __ISB();
+
+ /* Calls the non-secure Reset_Handler to jump to the non-secure binary */
+ ns_entry();
+}
+
+void enable_fault_handlers(void)
+{
+ /* Enables BUS, MEM, USG and Secure faults */
+ SCB->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk
+ | SCB_SHCSR_BUSFAULTENA_Msk
+ | SCB_SHCSR_MEMFAULTENA_Msk
+ | SCB_SHCSR_SECUREFAULTENA_Msk;
+
+ /* CFSR register setting to enable precise errors */
+ SCB->CFSR |= SCB_CFSR_PRECISERR_Msk;
+}
+
+/*------------------- NVIC interrupt target state to NS configuration ----------*/
+void nvic_interrupt_target_state_cfg()
+{
+ /* 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);
+
+ /* 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);
+}
+
+/*------------------- NVIC interrupt enabling for S peripherals ----------------*/
+void nvic_interrupt_enable()
+{
+ struct spctrl_def* spctrl = CMSDK_SPCTRL;
+
+ /* MPC interrupt enabling */
+ Driver_SRAM1_MPC.EnableInterrupt();
+ Driver_SRAM2_MPC.EnableInterrupt();
+ 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;
+ spctrl->secppcinten |= CMSDK_APB_PPC1_INT_POS_MASK;
+ spctrl->secppcinten |= CMSDK_APB_PPCEXP0_INT_POS_MASK;
+ spctrl->secppcinten |= CMSDK_APB_PPCEXP1_INT_POS_MASK;
+ spctrl->secppcinten |= CMSDK_APB_PPCEXP2_INT_POS_MASK;
+ spctrl->secppcinten |= CMSDK_APB_PPCEXP3_INT_POS_MASK;
+ NVIC_EnableIRQ(PPC_IRQn);
+}
+
+/*------------------- SAU/IDAU configuration functions -------------------------*/
+
+void sau_and_idau_cfg(void)
+{
+ /* Enables SAU */
+ TZ_SAU_Enable();
+
+ /* Configures SAU regions to be non-secure */
+ SAU->RNR = TFM_NS_REGION_CODE;
+ SAU->RBAR = (NS_PARTITION_START & SAU_RBAR_BADDR_Msk);
+ SAU->RLAR = (NS_PARTITION_LIMIT & SAU_RLAR_LADDR_Msk) | SAU_RLAR_ENABLE_Msk;
+
+ SAU->RNR = TFM_NS_REGION_DATA;
+ SAU->RBAR = (NS_DATA_START & SAU_RBAR_BADDR_Msk);
+ SAU->RLAR = (NS_DATA_LIMIT & SAU_RLAR_LADDR_Msk) | SAU_RLAR_ENABLE_Msk;
+
+ /* Configures veneers region to be non-secure callable */
+ SAU->RNR = TFM_NS_REGION_VENEER;
+ SAU->RBAR = (CMSE_VENEER_REGION_START & SAU_RBAR_BADDR_Msk);
+ SAU->RLAR = (CMSE_VENEER_REGION_LIMIT & SAU_RLAR_LADDR_Msk)
+ | SAU_RLAR_ENABLE_Msk
+ | SAU_RLAR_NSC_Msk;
+
+ /* Configure the peripherals space */
+ /* Only UART1 is configured as a secure peripheral */
+ SAU->RNR = TFM_NS_REGION_PERIPH_1;
+ SAU->RBAR = (PERIPHERALS_BASE_NS_START & SAU_RBAR_BADDR_Msk);
+ SAU->RLAR = ((UART1_BASE_NS-1) & SAU_RLAR_LADDR_Msk)
+ | SAU_RLAR_ENABLE_Msk;
+
+ /* The UART1 range is considered as a (secure) gap */
+
+ SAU->RNR = TFM_NS_REGION_PERIPH_2;
+ SAU->RBAR = (UART2_BASE_NS & SAU_RBAR_BADDR_Msk);
+ SAU->RLAR = (PERIPHERALS_BASE_NS_END & SAU_RLAR_LADDR_Msk)
+ | SAU_RLAR_ENABLE_Msk;
+
+ /* Allows SAU to define the code region as a NSC */
+ struct spctrl_def* spctrl = CMSDK_SPCTRL;
+ spctrl->nsccfg |= NSCCFG_CODENSC;
+}
+
+/*------------------- Memory configuration functions -------------------------*/
+
+void mpc_init_cfg(void)
+{
+ Driver_SRAM1_MPC.Initialize();
+ Driver_SRAM1_MPC.ConfigRegion(NS_PARTITION_START,
+ NS_PARTITION_LIMIT,
+ ARM_MPC_ATTR_NONSECURE);
+
+ Driver_SRAM2_MPC.Initialize();
+ Driver_SRAM2_MPC.ConfigRegion(NS_DATA_START, NS_DATA_LIMIT,
+ ARM_MPC_ATTR_NONSECURE);
+
+ /* Lock down the MPC configuration */
+ Driver_SRAM1_MPC.LockDown();
+ Driver_SRAM2_MPC.LockDown();
+
+ /* Add barriers to assure the MPC configuration is done before continue
+ * the execution. */
+ __DSB();
+ __ISB();
+}
+
+/*------------------- 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);
+ spctrl->apbnsppc0 |= (1U << CMSDK_TIMER1_APB_PPC_POS);
+ spctrl->apbnsppc0 |= (1U << CMSDK_DTIMER_APB_PPC_POS);
+ spctrl->apbnsppc0 |= (1U << CMSDK_MHU0_APB_PPC_POS);
+ spctrl->apbnsppc0 |= (1U << CMSDK_MHU1_APB_PPC_POS);
+ /* Grant non-secure access to S32K Timer in PPC1*/
+ spctrl->apbnsppc1 |= (1U << CMSDK_S32K_TIMER_PPC_POS);
+ /* Grant non-secure access for APB peripherals on EXP1 */
+ spctrl->apbnsppcexp1 |= (1U << CMSDK_SPI0_APB_PPC_POS);
+ spctrl->apbnsppcexp1 |= (1U << CMSDK_SPI1_APB_PPC_POS);
+ spctrl->apbnsppcexp1 |= (1U << CMSDK_SPI2_APB_PPC_POS);
+ spctrl->apbnsppcexp1 |= (1U << CMSDK_SPI3_APB_PPC_POS);
+ spctrl->apbnsppcexp1 |= (1U << CMSDK_SPI4_APB_PPC_POS);
+ spctrl->apbnsppcexp1 |= (1U << CMSDK_UART0_APB_PPC_POS);
+ /* Do not do it for UART1 as it's a Secure peripheral */
+ spctrl->apbnsppcexp1 |= (1U << CMSDK_UART2_APB_PPC_POS);
+ spctrl->apbnsppcexp1 |= (1U << CMSDK_UART3_APB_PPC_POS);
+ spctrl->apbnsppcexp1 |= (1U << CMSDK_UART4_APB_PPC_POS);
+ spctrl->apbnsppcexp1 |= (1U << CMSDK_I2C0_APB_PPC_POS);
+ spctrl->apbnsppcexp1 |= (1U << CMSDK_I2C1_APB_PPC_POS);
+ spctrl->apbnsppcexp1 |= (1U << CMSDK_I2C2_APB_PPC_POS);
+ spctrl->apbnsppcexp1 |= (1U << CMSDK_I2C3_APB_PPC_POS);
+ /* Grant non-secure access for APB peripherals on EXP2 */
+ spctrl->apbnsppcexp2 |= (1U << CMSDK_FPGA_SCC_PPC_POS);
+ spctrl->apbnsppcexp2 |= (1U << CMSDK_FPGA_AUDIO_PPC_POS);
+ spctrl->apbnsppcexp2 |= (1U << CMSDK_FPGA_IO_PPC_POS);
+ /* Grant non-secure access for AHB peripherals on PPC0 */
+ spctrl->ahbnsppc0 |= (1U << CMSDK_VGA_PPC_POS);
+ spctrl->ahbnsppc0 |= (1U << CMSDK_GPIO0_PPC_POS);
+ spctrl->ahbnsppc0 |= (1U << CMSDK_GPIO1_PPC_POS);
+ spctrl->ahbnsppc0 |= (1U << CMSDK_GPIO2_PPC_POS);
+ spctrl->ahbnsppc0 |= (1U << CMSDK_GPIO3_PPC_POS);
+
+ /* Grant non-secure access to all peripherals on AHB EXP:
+ * The SSE-200 doesn't have any peripheral connected to
+ * the AHB expansions. But the SIE-200 has peripherals,
+ * in particular the Ethernet driver on EXP1. Make sure
+ * that all possible peripherals are enabled by default
+ */
+ spctrl->ahbnsppcexp0 = 0xFFFFFFFF;
+ spctrl->ahbnsppcexp1 = 0xFFFFFFFF;
+ spctrl->ahbnsppcexp2 = 0xFFFFFFFF;
+ spctrl->ahbnsppcexp3 = 0xFFFFFFFF;
+
+ /* 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);
+ nspctrl->apbnspppcexp2 |= (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)
+{
+ /* Clear NS flag for peripheral to prevent 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 APC PPC EXP2 IRQ */
+ spctrl->secppcintclr |= CMSDK_APB_PPCEXP2_INT_POS_MASK;
+}