e9f351dc3aa468424cebb34d5a11aeb4438f4dee
[oweals/u-boot.git] / drivers / misc / fsl_sec_mon.c
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 }