xref: /aosp_15_r20/external/arm-trusted-firmware/drivers/nxp/sec_mon/snvs.c (revision 54fd6939e177f8ff529b10183254802c76df6d08)
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