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