1 /*
2 * Copyright (c) 2019-2022 Arm Limited
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "ppc_rss_drv.h"
18 #include <stdint.h>
19 #include <stdbool.h>
20 #include <platform_regs.h>
21
22 /* Default peripheral states */
23 #define SECURE_AS_DEFAULT_PERIPHERAL_STATE true
24 #define PRIVILEGE_ONLY_AS_DEFAULT_PERIPHERAL_STATE true
25
ppc_rss_init(struct ppc_rss_dev_t * dev)26 enum ppc_rss_error_t ppc_rss_init(struct ppc_rss_dev_t* dev)
27 {
28 struct rss_sacfg_t* p_sacfg =
29 (struct rss_sacfg_t*)dev->cfg->sacfg_base;
30 struct rss_nsacfg_t* p_nsacfg =
31 (struct rss_nsacfg_t*)dev->cfg->nsacfg_base;
32
33 switch(dev->cfg->ppc_name) {
34 /* Case for MAIN0 */
35 case PPC_RSS_MAIN0:
36 dev->data->sacfg_ns_ppc = &p_sacfg->mainnsppc0;
37 dev->data->sacfg_sp_ppc = &p_sacfg->mainspppc0;
38 dev->data->nsacfg_nsp_ppc = &p_nsacfg->mainnspppc0;
39 dev->data->int_bit_mask = MAIN_PPC0_INT_POS_MASK;
40 break;
41
42 /* Case for MAIN EXPX */
43 case PPC_RSS_MAIN_EXP0:
44 dev->data->sacfg_ns_ppc = &p_sacfg-> mainnsppcexp0;
45 dev->data->sacfg_sp_ppc = &p_sacfg-> mainspppcexp0;
46 dev->data->nsacfg_nsp_ppc = &p_nsacfg->mainnspppcexp0;
47 dev->data->int_bit_mask = MAIN_PPCEXP0_INT_POS_MASK;
48 break;
49 case PPC_RSS_MAIN_EXP1:
50 dev->data->sacfg_ns_ppc = &p_sacfg->mainnsppcexp1;
51 dev->data->sacfg_sp_ppc = &p_sacfg->mainspppcexp1;
52 dev->data->nsacfg_nsp_ppc = &p_nsacfg->mainnspppcexp1;
53 dev->data->int_bit_mask = MAIN_PPCEXP1_INT_POS_MASK;
54 break;
55 case PPC_RSS_MAIN_EXP2:
56 dev->data->sacfg_ns_ppc = &p_sacfg->mainnsppcexp2;
57 dev->data->sacfg_sp_ppc = &p_sacfg->mainspppcexp2;
58 dev->data->nsacfg_nsp_ppc = &p_nsacfg->mainnspppcexp2;
59 dev->data->int_bit_mask = MAIN_PPCEXP2_INT_POS_MASK;
60 break;
61 case PPC_RSS_MAIN_EXP3:
62 dev->data->sacfg_ns_ppc = &p_sacfg->mainnsppcexp3;
63 dev->data->sacfg_sp_ppc = &p_sacfg->mainspppcexp3;
64 dev->data->nsacfg_nsp_ppc = &p_nsacfg->mainnspppcexp3;
65 dev->data->int_bit_mask = MAIN_PPCEXP3_INT_POS_MASK;
66 break;
67
68 /* Case for PERIPHX */
69 case PPC_RSS_PERIPH0:
70 dev->data->sacfg_ns_ppc = &p_sacfg->periphnsppc0;
71 dev->data->sacfg_sp_ppc = &p_sacfg->periphspppc0;
72 dev->data->nsacfg_nsp_ppc = &p_nsacfg->periphnspppc0;
73 dev->data->int_bit_mask = PERIPH_PPC0_INT_POS_MASK;
74 break;
75 case PPC_RSS_PERIPH1:
76 dev->data->sacfg_ns_ppc = &p_sacfg->periphnsppc1;
77 dev->data->sacfg_sp_ppc = &p_sacfg->periphspppc1;
78 dev->data->nsacfg_nsp_ppc = &p_nsacfg->periphnspppc1;
79 dev->data->int_bit_mask = PERIPH_PPC1_INT_POS_MASK;
80 break;
81
82 /* Case for PERIPH EXPX */
83 case PPC_RSS_PERIPH_EXP0:
84 dev->data->sacfg_ns_ppc = &p_sacfg->periphnsppcexp0;
85 dev->data->sacfg_sp_ppc = &p_sacfg->periphspppcexp0;
86 dev->data->nsacfg_nsp_ppc = &p_nsacfg->periphnspppcexp0;
87 dev->data->int_bit_mask = PERIPH_PPCEXP0_INT_POS_MASK;
88 break;
89 case PPC_RSS_PERIPH_EXP1:
90 dev->data->sacfg_ns_ppc = &p_sacfg->periphnsppcexp1;
91 dev->data->sacfg_sp_ppc = &p_sacfg->periphspppcexp1;
92 dev->data->nsacfg_nsp_ppc = &p_nsacfg->periphnspppcexp1;
93 dev->data->int_bit_mask = PERIPH_PPCEXP1_INT_POS_MASK;
94 break;
95 case PPC_RSS_PERIPH_EXP2:
96 dev->data->sacfg_ns_ppc = &p_sacfg->periphnsppcexp2;
97 dev->data->sacfg_sp_ppc = &p_sacfg->periphspppcexp2;
98 dev->data->nsacfg_nsp_ppc = &p_nsacfg->periphnspppcexp2;
99 dev->data->int_bit_mask = PERIPH_PPCEXP2_INT_POS_MASK;
100 break;
101 case PPC_RSS_PERIPH_EXP3:
102 dev->data->sacfg_ns_ppc = &p_sacfg->periphnsppcexp3;
103 dev->data->sacfg_sp_ppc = &p_sacfg->periphspppcexp3;
104 dev->data->nsacfg_nsp_ppc = &p_nsacfg->periphnspppcexp3;
105 dev->data->int_bit_mask = PERIPH_PPCEXP3_INT_POS_MASK;
106 break;
107 default:
108 return PPC_RSS_ERR_INVALID_PARAM;
109 }
110
111 dev->data->is_initialized = true;
112
113 return PPC_RSS_ERR_NONE;
114 }
115
116 enum ppc_rss_error_t
ppc_rss_config_privilege(struct ppc_rss_dev_t * dev,uint32_t mask,enum ppc_rss_sec_attr_t sec_attr,enum ppc_rss_priv_attr_t priv_attr)117 ppc_rss_config_privilege(struct ppc_rss_dev_t* dev, uint32_t mask,
118 enum ppc_rss_sec_attr_t sec_attr,
119 enum ppc_rss_priv_attr_t priv_attr)
120 {
121 if(dev->data->is_initialized != true) {
122 return PPC_RSS_ERR_NOT_INIT;
123 }
124
125 if(sec_attr == PPC_RSS_SECURE_ACCESS) {
126 #if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U))
127 /* Uses secure unprivileged access address (SACFG) to set privilege
128 * attribute
129 */
130 if(priv_attr == PPC_RSS_PRIV_ONLY_ACCESS) {
131 *(dev->data->sacfg_sp_ppc) &= ~mask;
132 } else {
133 *(dev->data->sacfg_sp_ppc) |= mask;
134 }
135 #else
136 /* Configuring security from Non-Secure application is not permitted. */
137 return PPC_RSS_ERR_NOT_PERMITTED;
138 #endif
139 } else {
140 /* Uses non-secure unprivileged access address (NSACFG) to set
141 * privilege attribute */
142 if(priv_attr == PPC_RSS_PRIV_ONLY_ACCESS) {
143 *(dev->data->nsacfg_nsp_ppc) &= ~mask;
144 } else {
145 *(dev->data->nsacfg_nsp_ppc) |= mask;
146 }
147 }
148
149 return PPC_RSS_ERR_NONE;
150 }
151
ppc_rss_is_periph_priv_only(struct ppc_rss_dev_t * dev,uint32_t mask)152 bool ppc_rss_is_periph_priv_only(struct ppc_rss_dev_t* dev,
153 uint32_t mask)
154 {
155 if(dev->data->is_initialized != true) {
156 /* Return true as the default configuration is privilege only */
157 return true;
158 }
159
160 #if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U))
161 /* In secure domain either secure or non-secure privilege access is returned
162 * based on the configuration */
163 if ((*(dev->data->sacfg_ns_ppc) & mask) == 0) {
164 /* Returns secure unprivileged access (SACFG) */
165 return ((*(dev->data->sacfg_sp_ppc) & mask) == 0);
166 } else {
167 /* Returns non-secure unprivileged access (NSACFG) */
168 return ((*(dev->data->nsacfg_nsp_ppc) & mask) == 0);
169 }
170 #else
171 /* Returns non-secure unprivileged access (NSACFG) */
172 return ((*(dev->data->nsacfg_nsp_ppc) & mask) == 0);
173 #endif
174 }
175
176 /* Secure only functions */
177 #if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U))
178
179 enum ppc_rss_error_t
ppc_rss_config_security(struct ppc_rss_dev_t * dev,uint32_t mask,enum ppc_rss_sec_attr_t sec_attr)180 ppc_rss_config_security(struct ppc_rss_dev_t* dev, uint32_t mask,
181 enum ppc_rss_sec_attr_t sec_attr)
182 {
183 if(dev->data->is_initialized != true) {
184 return PPC_RSS_ERR_NOT_INIT;
185 }
186
187 if(sec_attr == PPC_RSS_SECURE_ACCESS) {
188 *(dev->data->sacfg_ns_ppc) &= ~mask;
189 } else {
190 *(dev->data->sacfg_ns_ppc) |= mask;
191 }
192
193 return PPC_RSS_ERR_NONE;
194 }
195
ppc_rss_is_periph_secure(struct ppc_rss_dev_t * dev,uint32_t mask)196 bool ppc_rss_is_periph_secure(struct ppc_rss_dev_t* dev,
197 uint32_t mask)
198 {
199 if(dev->data->is_initialized != true) {
200 /* Return true as the default configuration is secure */
201 return true;
202 }
203
204 return ((*(dev->data->sacfg_ns_ppc) & mask) == 0);
205 }
206
ppc_rss_irq_enable(struct ppc_rss_dev_t * dev)207 enum ppc_rss_error_t ppc_rss_irq_enable(struct ppc_rss_dev_t* dev)
208 {
209 struct rss_sacfg_t* p_sacfg =
210 (struct rss_sacfg_t*)dev->cfg->sacfg_base;
211
212 if(dev->data->is_initialized != true) {
213 return PPC_RSS_ERR_NOT_INIT;
214 }
215
216 p_sacfg->secppcinten |= dev->data->int_bit_mask;
217
218 return PPC_RSS_ERR_NONE;
219 }
220
ppc_rss_irq_disable(struct ppc_rss_dev_t * dev)221 void ppc_rss_irq_disable(struct ppc_rss_dev_t* dev)
222 {
223 struct rss_sacfg_t* p_sacfg =
224 (struct rss_sacfg_t*)dev->cfg->sacfg_base;
225
226 if(dev->data->is_initialized == true) {
227 p_sacfg->secppcinten &= ~(dev->data->int_bit_mask);
228 }
229 }
230
ppc_rss_clear_irq(struct ppc_rss_dev_t * dev)231 void ppc_rss_clear_irq(struct ppc_rss_dev_t* dev)
232 {
233 struct rss_sacfg_t* p_sacfg =
234 (struct rss_sacfg_t*)dev->cfg->sacfg_base;
235
236 if(dev->data->is_initialized == true) {
237 p_sacfg->secppcintclr = dev->data->int_bit_mask;
238 }
239 }
240
ppc_rss_irq_state(struct ppc_rss_dev_t * dev)241 bool ppc_rss_irq_state(struct ppc_rss_dev_t* dev)
242 {
243 struct rss_sacfg_t* p_sacfg =
244 (struct rss_sacfg_t*)dev->cfg->sacfg_base;
245
246 if(dev->data->is_initialized != true) {
247 return false;
248 }
249
250 return ((p_sacfg->secppcintstat & dev->data->int_bit_mask) != 0);
251 }
252
253 #endif /* (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)) */
254