diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:13:47 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:13:47 +0000 |
commit | 102b0d2daa97dae68d3eed54d8fe37a9cc38a892 (patch) | |
tree | bcf648efac40ca6139842707f0eba5a4496a6dd2 /drivers/nxp/sec_mon/snvs.c | |
parent | Initial commit. (diff) | |
download | arm-trusted-firmware-upstream/2.8.0+dfsg.tar.xz arm-trusted-firmware-upstream/2.8.0+dfsg.zip |
Adding upstream version 2.8.0+dfsg.upstream/2.8.0+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/nxp/sec_mon/snvs.c')
-rw-r--r-- | drivers/nxp/sec_mon/snvs.c | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/drivers/nxp/sec_mon/snvs.c b/drivers/nxp/sec_mon/snvs.c new file mode 100644 index 0000000..6208b67 --- /dev/null +++ b/drivers/nxp/sec_mon/snvs.c @@ -0,0 +1,186 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> + +#include <snvs.h> + +static uintptr_t g_nxp_snvs_addr; + +void snvs_init(uintptr_t nxp_snvs_addr) +{ + g_nxp_snvs_addr = nxp_snvs_addr; +} + +uint32_t get_snvs_state(void) +{ + struct snvs_regs *snvs = (struct snvs_regs *) (g_nxp_snvs_addr); + + return (snvs_read32(&snvs->hp_stat) & HPSTS_MASK_SSM_ST); +} + +static uint32_t do_snvs_state_transition(uint32_t state_transtion_bit, + uint32_t target_state) +{ + struct snvs_regs *snvs = (struct snvs_regs *) (g_nxp_snvs_addr); + uint32_t sts = get_snvs_state(); + uint32_t fetch_cnt = 16U; + uint32_t val = snvs_read32(&snvs->hp_com) | state_transtion_bit; + + snvs_write32(&snvs->hp_com, val); + + /* polling loop till SNVS is in target state */ + do { + sts = get_snvs_state(); + } while ((sts != target_state) && ((--fetch_cnt) != 0)); + + return sts; +} +void transition_snvs_non_secure(void) +{ + struct snvs_regs *snvs = (struct snvs_regs *) (g_nxp_snvs_addr); + uint32_t sts = get_snvs_state(); + + switch (sts) { + /* If initial state is check or Non-Secure, then + * set the Software Security Violation Bit and + * transition to Non-Secure State. + */ + case HPSTS_CHECK_SSM_ST: + sts = do_snvs_state_transition(HPCOM_SW_SV, HPSTS_NON_SECURE_SSM_ST); + break; + + /* If initial state is Trusted, Secure or Soft-Fail, then + * first set the Software Security Violation Bit and + * transition to Soft-Fail State. + */ + case HPSTS_TRUST_SSM_ST: + case HPSTS_SECURE_SSM_ST: + case HPSTS_SOFT_FAIL_SSM_ST: + sts = do_snvs_state_transition(HPCOM_SW_SV, HPSTS_NON_SECURE_SSM_ST); + + /* If SSM Soft Fail to Non-Secure State Transition + * Disable is not set, then set SSM_ST bit and + * transition to Non-Secure State. + */ + if ((snvs_read32(&snvs->hp_com) & HPCOM_SSM_SFNS_DIS) == 0) { + sts = do_snvs_state_transition(HPCOM_SSM_ST, HPSTS_NON_SECURE_SSM_ST); + } + break; + default: + break; + } +} + +void transition_snvs_soft_fail(void) +{ + do_snvs_state_transition(HPCOM_SW_FSV, HPSTS_SOFT_FAIL_SSM_ST); +} + +uint32_t transition_snvs_trusted(void) +{ + struct snvs_regs *snvs = (struct snvs_regs *) (g_nxp_snvs_addr); + uint32_t sts = get_snvs_state(); + + switch (sts) { + /* If initial state is check, set the SSM_ST bit to + * change the state to trusted. + */ + case HPSTS_CHECK_SSM_ST: + sts = do_snvs_state_transition(HPCOM_SSM_ST, HPSTS_TRUST_SSM_ST); + break; + /* If SSM Secure to Trusted State Transition Disable + * is not set, then set SSM_ST bit and + * transition to Trusted State. + */ + case HPSTS_SECURE_SSM_ST: + if ((snvs_read32(&snvs->hp_com) & HPCOM_SSM_ST_DIS) == 0) { + sts = do_snvs_state_transition(HPCOM_SSM_ST, HPSTS_TRUST_SSM_ST); + } + break; + /* If initial state is Soft-Fail or Non-Secure, then + * transition to Trusted is not Possible. + */ + default: + break; + } + + return sts; +} + +uint32_t transition_snvs_secure(void) +{ + uint32_t sts = get_snvs_state(); + + if (sts == HPSTS_SECURE_SSM_ST) { + return sts; + } + + if (sts != HPSTS_TRUST_SSM_ST) { + sts = transition_snvs_trusted(); + if (sts != HPSTS_TRUST_SSM_ST) { + return sts; + } + } + + sts = do_snvs_state_transition(HPCOM_SSM_ST, HPSTS_TRUST_SSM_ST); + + return sts; +} + +void snvs_write_lp_gpr_bit(uint32_t offset, uint32_t bit_pos, bool flag_val) +{ + if (flag_val) { + snvs_write32(g_nxp_snvs_addr + offset, + (snvs_read32(g_nxp_snvs_addr + offset)) + | (1 << bit_pos)); + } else { + snvs_write32(g_nxp_snvs_addr + offset, + (snvs_read32(g_nxp_snvs_addr + offset)) + & ~(1 << bit_pos)); + } +} + +uint32_t snvs_read_lp_gpr_bit(uint32_t offset, uint32_t bit_pos) +{ + return (snvs_read32(g_nxp_snvs_addr + offset) & (1 << bit_pos)); +} + +void snvs_disable_zeroize_lp_gpr(void) +{ + snvs_write_lp_gpr_bit(NXP_LPCR_OFFSET, + NXP_GPR_Z_DIS_BIT, + true); +} + +#if defined(NXP_NV_SW_MAINT_LAST_EXEC_DATA) && defined(NXP_COINED_BB) +void snvs_write_app_data_bit(uint32_t bit_pos) +{ + snvs_write_lp_gpr_bit(NXP_APP_DATA_LP_GPR_OFFSET, + bit_pos, + true); +} + +uint32_t snvs_read_app_data(void) +{ + return snvs_read32(g_nxp_snvs_addr + NXP_APP_DATA_LP_GPR_OFFSET); +} + +uint32_t snvs_read_app_data_bit(uint32_t bit_pos) +{ + uint8_t ret = snvs_read_lp_gpr_bit(NXP_APP_DATA_LP_GPR_OFFSET, bit_pos); + + return ((ret != 0U) ? 1U : 0U); +} + +void snvs_clear_app_data(void) +{ + snvs_write32(g_nxp_snvs_addr + NXP_APP_DATA_LP_GPR_OFFSET, 0x0); +} +#endif |