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