1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright 2015 Freescale Semiconductor, Inc. 4 */ 5 6#include <common.h> 7#include <fsl_sec_mon.h> 8#include <linux/delay.h> 9 10static u32 get_sec_mon_state(void) 11{ 12 struct ccsr_sec_mon_regs *sec_mon_regs = (void *) 13 (CONFIG_SYS_SEC_MON_ADDR); 14 return sec_mon_in32(&sec_mon_regs->hp_stat) & HPSR_SSM_ST_MASK; 15} 16 17static int set_sec_mon_state_non_sec(void) 18{ 19 u32 sts; 20 int timeout = 10; 21 struct ccsr_sec_mon_regs *sec_mon_regs = (void *) 22 (CONFIG_SYS_SEC_MON_ADDR); 23 24 sts = get_sec_mon_state(); 25 26 switch (sts) { 27 /* 28 * If initial state is check or Non-Secure, then set the Software 29 * Security Violation Bit and transition to Non-Secure State. 30 */ 31 case HPSR_SSM_ST_CHECK: 32 printf("SEC_MON state transitioning to Non Secure.\n"); 33 sec_mon_setbits32(&sec_mon_regs->hp_com, HPCOMR_SW_SV); 34 35 /* polling loop till SEC_MON is in Non Secure state */ 36 while (timeout) { 37 sts = get_sec_mon_state(); 38 39 if ((sts & HPSR_SSM_ST_MASK) == 40 HPSR_SSM_ST_NON_SECURE) 41 break; 42 43 udelay(10); 44 timeout--; 45 } 46 47 if (timeout == 0) { 48 printf("SEC_MON state transition timeout.\n"); 49 return -1; 50 } 51 break; 52 53 /* 54 * If initial state is Trusted, Secure or Soft-Fail, then first set 55 * the Software Security Violation Bit and transition to Soft-Fail 56 * State. 57 */ 58 case HPSR_SSM_ST_TRUST: 59 case HPSR_SSM_ST_SECURE: 60 case HPSR_SSM_ST_SOFT_FAIL: 61 printf("SEC_MON state transitioning to Soft Fail.\n"); 62 sec_mon_setbits32(&sec_mon_regs->hp_com, HPCOMR_SW_SV); 63 64 /* polling loop till SEC_MON is in Soft-Fail state */ 65 while (timeout) { 66 sts = get_sec_mon_state(); 67 68 if ((sts & HPSR_SSM_ST_MASK) == 69 HPSR_SSM_ST_SOFT_FAIL) 70 break; 71 72 udelay(10); 73 timeout--; 74 } 75 76 if (timeout == 0) { 77 printf("SEC_MON state transition timeout.\n"); 78 return -1; 79 } 80 81 timeout = 10; 82 83 /* 84 * If SSM Soft Fail to Non-Secure State Transition 85 * disable is not set, then set SSM_ST bit and 86 * transition to Non-Secure State. 87 */ 88 if ((sec_mon_in32(&sec_mon_regs->hp_com) & 89 HPCOMR_SSM_SFNS_DIS) == 0) { 90 printf("SEC_MON state transitioning to Non Secure.\n"); 91 sec_mon_setbits32(&sec_mon_regs->hp_com, HPCOMR_SSM_ST); 92 93 /* polling loop till SEC_MON is in Non Secure*/ 94 while (timeout) { 95 sts = get_sec_mon_state(); 96 97 if ((sts & HPSR_SSM_ST_MASK) == 98 HPSR_SSM_ST_NON_SECURE) 99 break; 100 101 udelay(10); 102 timeout--; 103 } 104 105 if (timeout == 0) { 106 printf("SEC_MON state transition timeout.\n"); 107 return -1; 108 } 109 } 110 break; 111 default: 112 printf("SEC_MON already in Non Secure state.\n"); 113 return 0; 114 } 115 return 0; 116} 117 118static int set_sec_mon_state_soft_fail(void) 119{ 120 u32 sts; 121 int timeout = 10; 122 struct ccsr_sec_mon_regs *sec_mon_regs = (void *) 123 (CONFIG_SYS_SEC_MON_ADDR); 124 125 printf("SEC_MON state transitioning to Soft Fail.\n"); 126 sec_mon_setbits32(&sec_mon_regs->hp_com, HPCOMR_SW_FSV); 127 128 /* polling loop till SEC_MON is in Soft-Fail state */ 129 while (timeout) { 130 sts = get_sec_mon_state(); 131 132 if ((sts & HPSR_SSM_ST_MASK) == 133 HPSR_SSM_ST_SOFT_FAIL) 134 break; 135 136 udelay(10); 137 timeout--; 138 } 139 140 if (timeout == 0) { 141 printf("SEC_MON state transition timeout.\n"); 142 return -1; 143 } 144 return 0; 145} 146 147int set_sec_mon_state(u32 state) 148{ 149 int ret = -1; 150 151 switch (state) { 152 case HPSR_SSM_ST_NON_SECURE: 153 ret = set_sec_mon_state_non_sec(); 154 break; 155 case HPSR_SSM_ST_SOFT_FAIL: 156 ret = set_sec_mon_state_soft_fail(); 157 break; 158 default: 159 printf("SEC_MON state transition not supported.\n"); 160 return 0; 161 } 162 163 return ret; 164} 165