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 16 void snvs_init(uintptr_t nxp_snvs_addr) 17 { 18 g_nxp_snvs_addr = nxp_snvs_addr; 19 } 20 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 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 } 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 81 void transition_snvs_soft_fail(void) 82 { 83 do_snvs_state_transition(HPCOM_SW_FSV, HPSTS_SOFT_FAIL_SSM_ST); 84 } 85 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 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 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 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 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) 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 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 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 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