1*54fd6939SJiyong Park /*
2*54fd6939SJiyong Park * Copyright 2021 NXP
3*54fd6939SJiyong Park *
4*54fd6939SJiyong Park * SPDX-License-Identifier: BSD-3-Clause
5*54fd6939SJiyong Park *
6*54fd6939SJiyong Park */
7*54fd6939SJiyong Park
8*54fd6939SJiyong Park #include <stdint.h>
9*54fd6939SJiyong Park #include <stdio.h>
10*54fd6939SJiyong Park #include <stdlib.h>
11*54fd6939SJiyong Park
12*54fd6939SJiyong Park #include <snvs.h>
13*54fd6939SJiyong Park
14*54fd6939SJiyong Park static uintptr_t g_nxp_snvs_addr;
15*54fd6939SJiyong Park
snvs_init(uintptr_t nxp_snvs_addr)16*54fd6939SJiyong Park void snvs_init(uintptr_t nxp_snvs_addr)
17*54fd6939SJiyong Park {
18*54fd6939SJiyong Park g_nxp_snvs_addr = nxp_snvs_addr;
19*54fd6939SJiyong Park }
20*54fd6939SJiyong Park
get_snvs_state(void)21*54fd6939SJiyong Park uint32_t get_snvs_state(void)
22*54fd6939SJiyong Park {
23*54fd6939SJiyong Park struct snvs_regs *snvs = (struct snvs_regs *) (g_nxp_snvs_addr);
24*54fd6939SJiyong Park
25*54fd6939SJiyong Park return (snvs_read32(&snvs->hp_stat) & HPSTS_MASK_SSM_ST);
26*54fd6939SJiyong Park }
27*54fd6939SJiyong Park
do_snvs_state_transition(uint32_t state_transtion_bit,uint32_t target_state)28*54fd6939SJiyong Park static uint32_t do_snvs_state_transition(uint32_t state_transtion_bit,
29*54fd6939SJiyong Park uint32_t target_state)
30*54fd6939SJiyong Park {
31*54fd6939SJiyong Park struct snvs_regs *snvs = (struct snvs_regs *) (g_nxp_snvs_addr);
32*54fd6939SJiyong Park uint32_t sts = get_snvs_state();
33*54fd6939SJiyong Park uint32_t fetch_cnt = 16U;
34*54fd6939SJiyong Park uint32_t val = snvs_read32(&snvs->hp_com) | state_transtion_bit;
35*54fd6939SJiyong Park
36*54fd6939SJiyong Park snvs_write32(&snvs->hp_com, val);
37*54fd6939SJiyong Park
38*54fd6939SJiyong Park /* polling loop till SNVS is in target state */
39*54fd6939SJiyong Park do {
40*54fd6939SJiyong Park sts = get_snvs_state();
41*54fd6939SJiyong Park } while ((sts != target_state) && ((--fetch_cnt) != 0));
42*54fd6939SJiyong Park
43*54fd6939SJiyong Park return sts;
44*54fd6939SJiyong Park }
transition_snvs_non_secure(void)45*54fd6939SJiyong Park void transition_snvs_non_secure(void)
46*54fd6939SJiyong Park {
47*54fd6939SJiyong Park struct snvs_regs *snvs = (struct snvs_regs *) (g_nxp_snvs_addr);
48*54fd6939SJiyong Park uint32_t sts = get_snvs_state();
49*54fd6939SJiyong Park
50*54fd6939SJiyong Park switch (sts) {
51*54fd6939SJiyong Park /* If initial state is check or Non-Secure, then
52*54fd6939SJiyong Park * set the Software Security Violation Bit and
53*54fd6939SJiyong Park * transition to Non-Secure State.
54*54fd6939SJiyong Park */
55*54fd6939SJiyong Park case HPSTS_CHECK_SSM_ST:
56*54fd6939SJiyong Park sts = do_snvs_state_transition(HPCOM_SW_SV, HPSTS_NON_SECURE_SSM_ST);
57*54fd6939SJiyong Park break;
58*54fd6939SJiyong Park
59*54fd6939SJiyong Park /* If initial state is Trusted, Secure or Soft-Fail, then
60*54fd6939SJiyong Park * first set the Software Security Violation Bit and
61*54fd6939SJiyong Park * transition to Soft-Fail State.
62*54fd6939SJiyong Park */
63*54fd6939SJiyong Park case HPSTS_TRUST_SSM_ST:
64*54fd6939SJiyong Park case HPSTS_SECURE_SSM_ST:
65*54fd6939SJiyong Park case HPSTS_SOFT_FAIL_SSM_ST:
66*54fd6939SJiyong Park sts = do_snvs_state_transition(HPCOM_SW_SV, HPSTS_NON_SECURE_SSM_ST);
67*54fd6939SJiyong Park
68*54fd6939SJiyong Park /* If SSM Soft Fail to Non-Secure State Transition
69*54fd6939SJiyong Park * Disable is not set, then set SSM_ST bit and
70*54fd6939SJiyong Park * transition to Non-Secure State.
71*54fd6939SJiyong Park */
72*54fd6939SJiyong Park if ((snvs_read32(&snvs->hp_com) & HPCOM_SSM_SFNS_DIS) == 0) {
73*54fd6939SJiyong Park sts = do_snvs_state_transition(HPCOM_SSM_ST, HPSTS_NON_SECURE_SSM_ST);
74*54fd6939SJiyong Park }
75*54fd6939SJiyong Park break;
76*54fd6939SJiyong Park default:
77*54fd6939SJiyong Park break;
78*54fd6939SJiyong Park }
79*54fd6939SJiyong Park }
80*54fd6939SJiyong Park
transition_snvs_soft_fail(void)81*54fd6939SJiyong Park void transition_snvs_soft_fail(void)
82*54fd6939SJiyong Park {
83*54fd6939SJiyong Park do_snvs_state_transition(HPCOM_SW_FSV, HPSTS_SOFT_FAIL_SSM_ST);
84*54fd6939SJiyong Park }
85*54fd6939SJiyong Park
transition_snvs_trusted(void)86*54fd6939SJiyong Park uint32_t transition_snvs_trusted(void)
87*54fd6939SJiyong Park {
88*54fd6939SJiyong Park struct snvs_regs *snvs = (struct snvs_regs *) (g_nxp_snvs_addr);
89*54fd6939SJiyong Park uint32_t sts = get_snvs_state();
90*54fd6939SJiyong Park
91*54fd6939SJiyong Park switch (sts) {
92*54fd6939SJiyong Park /* If initial state is check, set the SSM_ST bit to
93*54fd6939SJiyong Park * change the state to trusted.
94*54fd6939SJiyong Park */
95*54fd6939SJiyong Park case HPSTS_CHECK_SSM_ST:
96*54fd6939SJiyong Park sts = do_snvs_state_transition(HPCOM_SSM_ST, HPSTS_TRUST_SSM_ST);
97*54fd6939SJiyong Park break;
98*54fd6939SJiyong Park /* If SSM Secure to Trusted State Transition Disable
99*54fd6939SJiyong Park * is not set, then set SSM_ST bit and
100*54fd6939SJiyong Park * transition to Trusted State.
101*54fd6939SJiyong Park */
102*54fd6939SJiyong Park case HPSTS_SECURE_SSM_ST:
103*54fd6939SJiyong Park if ((snvs_read32(&snvs->hp_com) & HPCOM_SSM_ST_DIS) == 0) {
104*54fd6939SJiyong Park sts = do_snvs_state_transition(HPCOM_SSM_ST, HPSTS_TRUST_SSM_ST);
105*54fd6939SJiyong Park }
106*54fd6939SJiyong Park break;
107*54fd6939SJiyong Park /* If initial state is Soft-Fail or Non-Secure, then
108*54fd6939SJiyong Park * transition to Trusted is not Possible.
109*54fd6939SJiyong Park */
110*54fd6939SJiyong Park default:
111*54fd6939SJiyong Park break;
112*54fd6939SJiyong Park }
113*54fd6939SJiyong Park
114*54fd6939SJiyong Park return sts;
115*54fd6939SJiyong Park }
116*54fd6939SJiyong Park
transition_snvs_secure(void)117*54fd6939SJiyong Park uint32_t transition_snvs_secure(void)
118*54fd6939SJiyong Park {
119*54fd6939SJiyong Park uint32_t sts = get_snvs_state();
120*54fd6939SJiyong Park
121*54fd6939SJiyong Park if (sts == HPSTS_SECURE_SSM_ST) {
122*54fd6939SJiyong Park return sts;
123*54fd6939SJiyong Park }
124*54fd6939SJiyong Park
125*54fd6939SJiyong Park if (sts != HPSTS_TRUST_SSM_ST) {
126*54fd6939SJiyong Park sts = transition_snvs_trusted();
127*54fd6939SJiyong Park if (sts != HPSTS_TRUST_SSM_ST) {
128*54fd6939SJiyong Park return sts;
129*54fd6939SJiyong Park }
130*54fd6939SJiyong Park }
131*54fd6939SJiyong Park
132*54fd6939SJiyong Park sts = do_snvs_state_transition(HPCOM_SSM_ST, HPSTS_TRUST_SSM_ST);
133*54fd6939SJiyong Park
134*54fd6939SJiyong Park return sts;
135*54fd6939SJiyong Park }
136*54fd6939SJiyong Park
snvs_write_lp_gpr_bit(uint32_t offset,uint32_t bit_pos,bool flag_val)137*54fd6939SJiyong Park void snvs_write_lp_gpr_bit(uint32_t offset, uint32_t bit_pos, bool flag_val)
138*54fd6939SJiyong Park {
139*54fd6939SJiyong Park if (flag_val) {
140*54fd6939SJiyong Park snvs_write32(g_nxp_snvs_addr + offset,
141*54fd6939SJiyong Park (snvs_read32(g_nxp_snvs_addr + offset))
142*54fd6939SJiyong Park | (1 << bit_pos));
143*54fd6939SJiyong Park } else {
144*54fd6939SJiyong Park snvs_write32(g_nxp_snvs_addr + offset,
145*54fd6939SJiyong Park (snvs_read32(g_nxp_snvs_addr + offset))
146*54fd6939SJiyong Park & ~(1 << bit_pos));
147*54fd6939SJiyong Park }
148*54fd6939SJiyong Park }
149*54fd6939SJiyong Park
snvs_read_lp_gpr_bit(uint32_t offset,uint32_t bit_pos)150*54fd6939SJiyong Park uint32_t snvs_read_lp_gpr_bit(uint32_t offset, uint32_t bit_pos)
151*54fd6939SJiyong Park {
152*54fd6939SJiyong Park return (snvs_read32(g_nxp_snvs_addr + offset) & (1 << bit_pos));
153*54fd6939SJiyong Park }
154*54fd6939SJiyong Park
snvs_disable_zeroize_lp_gpr(void)155*54fd6939SJiyong Park void snvs_disable_zeroize_lp_gpr(void)
156*54fd6939SJiyong Park {
157*54fd6939SJiyong Park snvs_write_lp_gpr_bit(NXP_LPCR_OFFSET,
158*54fd6939SJiyong Park NXP_GPR_Z_DIS_BIT,
159*54fd6939SJiyong Park true);
160*54fd6939SJiyong Park }
161*54fd6939SJiyong Park
162*54fd6939SJiyong Park #if defined(NXP_NV_SW_MAINT_LAST_EXEC_DATA) && defined(NXP_COINED_BB)
snvs_write_app_data_bit(uint32_t bit_pos)163*54fd6939SJiyong Park void snvs_write_app_data_bit(uint32_t bit_pos)
164*54fd6939SJiyong Park {
165*54fd6939SJiyong Park snvs_write_lp_gpr_bit(NXP_APP_DATA_LP_GPR_OFFSET,
166*54fd6939SJiyong Park bit_pos,
167*54fd6939SJiyong Park true);
168*54fd6939SJiyong Park }
169*54fd6939SJiyong Park
snvs_read_app_data(void)170*54fd6939SJiyong Park uint32_t snvs_read_app_data(void)
171*54fd6939SJiyong Park {
172*54fd6939SJiyong Park return snvs_read32(g_nxp_snvs_addr + NXP_APP_DATA_LP_GPR_OFFSET);
173*54fd6939SJiyong Park }
174*54fd6939SJiyong Park
snvs_read_app_data_bit(uint32_t bit_pos)175*54fd6939SJiyong Park uint32_t snvs_read_app_data_bit(uint32_t bit_pos)
176*54fd6939SJiyong Park {
177*54fd6939SJiyong Park uint8_t ret = snvs_read_lp_gpr_bit(NXP_APP_DATA_LP_GPR_OFFSET, bit_pos);
178*54fd6939SJiyong Park
179*54fd6939SJiyong Park return ((ret != 0U) ? 1U : 0U);
180*54fd6939SJiyong Park }
181*54fd6939SJiyong Park
snvs_clear_app_data(void)182*54fd6939SJiyong Park void snvs_clear_app_data(void)
183*54fd6939SJiyong Park {
184*54fd6939SJiyong Park snvs_write32(g_nxp_snvs_addr + NXP_APP_DATA_LP_GPR_OFFSET, 0x0);
185*54fd6939SJiyong Park }
186*54fd6939SJiyong Park #endif
187