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 
get_sec_mon_state(void)10 static 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 
set_sec_mon_state_non_sec(void)17 static 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 
set_sec_mon_state_soft_fail(void)118 static 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 
set_sec_mon_state(u32 state)147 int 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