187 lines
4.3 KiB
C
187 lines
4.3 KiB
C
/*
|
|
* 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
|