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