Merge branch 'master' of git://git.denx.de/u-boot-uniphier
[platform/kernel/u-boot.git] / drivers / misc / fsl_sec_mon.c
1 /*
2  * Copyright 2015 Freescale Semiconductor, Inc.
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  */
6
7 #include <common.h>
8 #include <fsl_sec_mon.h>
9
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
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
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
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 }