blob: 927d0a80d540ce59b8d57099cf025f8234e4275c [file] [log] [blame]
Per Åstrand79929ff2021-01-26 14:42:43 +01001/*
2 * Copyright (c) 2016-2019 Arm Limited. All rights reserved.
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/**
18 * \file mpc_sie_drv.h
19 * \brief Generic driver for ARM SIE Memory Protection
20 * Controllers (MPC).
21 */
22
23#ifndef __MPC_SIE__DRV_H__
24#define __MPC_SIE__DRV_H__
25
26#include <stdint.h>
27#include <stdbool.h>
28
29#ifdef __cplusplus
30extern "C" {
31#endif
32
33/* Error code returned by the driver functions */
34enum mpc_sie_error_t {
35 MPC_SIE_ERR_NONE, /*!< No error */
36 MPC_SIE_INVALID_ARG, /*!< MPC invalid input arguments */
37 MPC_SIE_NOT_INIT, /*!< MPC not initialized */
38 MPC_SIE_ERR_NOT_IN_RANGE, /*!< Address does not belong to a range
39 * controlled by the MPC */
40 MPC_SIE_ERR_NOT_ALIGNED, /*!< Address is not aligned on the block size
41 * of this MPC
42 */
43 MPC_SIE_ERR_INVALID_RANGE, /*!< The given address range to configure
44 * is invalid. This could be because:
45 * - The base and limit swapped
46 * - The base and limit addresses
47 * are in different ranges
48 */
49 MPC_SIE_ERR_RANGE_SEC_ATTR_NON_COMPATIBLE, /*!< The given range cannot be
50 * accessed with the wanted
51 * security attributes
52 */
53 MPC_SIE_UNSUPPORTED_HARDWARE_VERSION, /*!< MPC hardware version read from
54 * PIDR0 is not supported
55 */
56 MPC_SIE_ERR_GATING_NOT_PRESENT /*!< MPC gating not present in HW */
57};
58
59/* Security attribute used in various place of the API */
60enum mpc_sie_sec_attr_t {
61 MPC_SIE_SEC_ATTR_SECURE, /*!< Secure attribute */
62 MPC_SIE_SEC_ATTR_NONSECURE, /*!< Non-secure attribute */
63 /*!< Used when getting the configuration of a memory range and some blocks
64 * are secure whereas some other are non secure
65 */
66 MPC_SIE_SEC_ATTR_MIXED,
67};
68
69/* What can happen when trying to do an illegal memory access */
70enum mpc_sie_sec_resp_t {
71 MPC_SIE_RESP_RAZ_WI, /*!< Read As Zero, Write Ignored */
72 MPC_SIE_RESP_BUS_ERROR, /*!< Bus error */
73 MPC_SIE_RESP_WAIT_GATING_DISABLED /*!< Wait until gating is disabled */
74};
75
76/* Description of a memory range controlled by the MPC */
77struct mpc_sie_memory_range_t {
78 const uint32_t base; /*!< Base address (included in the range) */
79 const uint32_t limit; /*!< Limit address (included in the range) */
80 const uint32_t range_offset; /*!< Offset of current range area to the 0
81 * point of the whole area (the sum of the
82 * sizes of the previous memory ranges
83 * covered by the same MPC)
84 */
85 const enum mpc_sie_sec_attr_t attr; /*!< Optional security attribute
86 * needed to be matched when
87 * accessing this range.
88 * For example, the non-secure
89 * alias of a memory region can not
90 * be accessed using secure access,
91 * and configuring the MPC to
92 * secure using that range will not
93 * be permitted by the driver.
94 */
95};
96
97/* ARM MPC SIE device configuration structure */
98struct mpc_sie_dev_cfg_t {
99 const uint32_t base; /*!< MPC base address */
100};
101
102/* ARM MPC SIE device data structure */
103struct mpc_sie_dev_data_t {
104 /*!< Array of pointers to memory ranges controlled by the MPC */
105 const struct mpc_sie_memory_range_t** range_list;
106 uint8_t nbr_of_ranges; /*!< Number of memory ranges in the list */
107 bool is_initialized; /*!< Indicates if the MPC driver
108 * is initialized and enabled
109 */
110 uint32_t sie_version; /*!< SIE version */
111};
112
113/* ARM MPC SIE device structure */
114struct mpc_sie_dev_t {
115 const struct mpc_sie_dev_cfg_t* const cfg; /*!< MPC configuration */
116 struct mpc_sie_dev_data_t* const data; /*!< MPC data */
117};
118
119/**
120 * \brief Initializes a MPC device.
121 *
122 * \param[in] dev MPC device \ref mpc_sie_dev_t
123 * \param[in] range_list List of memory ranges controller by the MPC
124 * (\ref mpc_sie_memory_range_t). This list can not
125 * freed after the initializations.
126 * \param[in] nbr_of_ranges Number of memory ranges
127 *
128 * \return Returns error code as specified in \ref mpc_sie_error_t
129 *
130 * \note This function doesn't check if dev is NULL.
131 */
132enum mpc_sie_error_t mpc_sie_init(struct mpc_sie_dev_t* dev,
133 const struct mpc_sie_memory_range_t** range_list,
134 uint8_t nbr_of_ranges);
135
136/**
137 * \brief Gets MPC block size. All regions must be aligned on this block
138 * size (base address and limit+1 address).
139 *
140 * \param[in] dev MPC device \ref mpc_sie_dev_t
141 * \param[out] blk_size MPC block size
142 *
143 * \return Returns error code as specified in \ref mpc_sie_error_t
144 *
145 * \note This function doesn't check if dev is NULL.
146 */
147enum mpc_sie_error_t mpc_sie_get_block_size(struct mpc_sie_dev_t* dev,
148 uint32_t* blk_size);
149
150/**
151 * \brief Configures a memory region (base and limit included).
152 *
153 * \param[in] dev MPC device \ref mpc_sie_dev_t
154 * \param[in] base Base address of the region to poll. This bound is
155 * included. It does not need to be aligned in any way.
156 *
157 * \param[in] limit Limit address of the region to poll. This bound is
158 * included. (limit+1) does not need to be aligned
159 * in any way.
160 * \param[in] attr Security attribute of the region. If the region has mixed
161 * secure/non-secure, a special value is returned
162 * (\ref mpc_sie_sec_attr_t).
163 *
164 * In case base and limit+1 addresses are not aligned on
165 * the block size, the enclosing region with base and
166 * limit+1 aligned on block size will be queried.
167 * In case of early termination of the function (error), the
168 * security attribute will be set to MPC_SIE_ATTR_MIXED.
169 *
170 * \return Returns error code as specified in \ref mpc_sie_error_t
171 *
172 * \note This function doesn't check if dev is NULL.
173 */
174enum mpc_sie_error_t mpc_sie_config_region(struct mpc_sie_dev_t* dev,
175 const uint32_t base,
176 const uint32_t limit,
177 enum mpc_sie_sec_attr_t attr);
178
179/**
180 * \brief Gets a memory region configuration(base and limit included).
181 *
182 * \param[in] dev MPC device \ref mpc_sie_dev_t
183 * \param[in] base Base address of the region to get the configuration.
184 * \param[in] limit Limit address of the region to get the configuration.
185 * \param[out] attr Security attribute of the region
186 * \ref mpc_sie_sec_attr_t
187 *
188 * \return Returns error code as specified in \ref mpc_sie_error_t
189 *
190 * \note This function doesn't check if dev is NULL.
191 */
192enum mpc_sie_error_t mpc_sie_get_region_config(struct mpc_sie_dev_t* dev,
193 uint32_t base,
194 uint32_t limit,
195 enum mpc_sie_sec_attr_t* attr);
196
197/**
198 * \brief Gets the MPC control value.
199 *
200 * \param[in] dev MPC device \ref mpc_sie_dev_t
201 * \param[out] ctrl_val Current MPC control value.
202 *
203 * \return Returns error code as specified in \ref mpc_sie_error_t
204 *
205 * \note This function doesn't check if dev is NULL.
206 */
207enum mpc_sie_error_t mpc_sie_get_ctrl(struct mpc_sie_dev_t* dev,
208 uint32_t* ctrl_val);
209
210/**
211 * \brief Sets the MPC control value.
212 *
213 * \param[in] dev MPC device \ref mpc_sie_dev_t
214 * \param[in] mpc_ctrl New MPC control value
215 *
216 * \return Returns error code as specified in \ref mpc_sie_error_t
217 *
218 * \note This function doesn't check if dev is NULL.
219 */
220enum mpc_sie_error_t mpc_sie_set_ctrl(struct mpc_sie_dev_t* dev,
221 uint32_t mpc_ctrl);
222
223/**
224 * \brief Gets the configured secure response.
225 *
226 * \param[in] dev MPC device \ref mpc_sie_dev_t
227 * \param[out] sec_rep Configured secure response (\ref mpc_sie_sec_resp_t).
228 *
229 * \return Returns error code as specified in \ref mpc_sie_error_t
230 *
231 * \note This function doesn't check if dev is NULL.
232 */
233enum mpc_sie_error_t mpc_sie_get_sec_resp(struct mpc_sie_dev_t* dev,
234 enum mpc_sie_sec_resp_t* sec_rep);
235
236/**
237 * \brief Sets the response type when SW asks to gate the incoming transfers.
238 *
239 * \param[in] dev MPC device \ref mpc_sie_dev_t
240 * \param[in] sec_rep Secure response to configure (\ref mpc_sie_sec_resp_t).
241 *
242 * \note This function doesn't check if dev is NULL.
243 */
244enum mpc_sie_error_t mpc_sie_set_sec_resp(struct mpc_sie_dev_t* dev,
245 enum mpc_sie_sec_resp_t sec_rep);
246
247/**
248 * \brief Enables MPC interrupt.
249 *
250 * \param[in] dev MPC device \ref mpc_sie_dev_t
251 *
252 * \return Returns error code as specified in \ref mpc_sie_error_t
253 *
254 * \note This function doesn't check if dev is NULL.
255 */
256enum mpc_sie_error_t mpc_sie_irq_enable(struct mpc_sie_dev_t* dev);
257
258/**
259 * \brief Disables MPC interrupt
260 *
261 * \param[in] dev MPC device \ref mpc_sie_dev_t
262 *
263 * \note This function doesn't check if dev is NULL.
264 */
265void mpc_sie_irq_disable(struct mpc_sie_dev_t* dev);
266
267/**
268 * \brief Clears MPC interrupt.
269 *
270 * \param[in] dev MPC device \ref mpc_sie_dev_t
271 *
272 * \note This function doesn't check if dev is NULL.
273 */
274void mpc_sie_clear_irq(struct mpc_sie_dev_t* dev);
275
276/**
277 * \brief Returns the MPC interrupt state.
278 *
279 * \param[in] dev MPC device \ref mpc_sie_dev_t
280 *
281 * \return Returns 1 if the interrupt is active, 0 otherwise.
282 *
283 * \note This function doesn't check if dev is NULL.
284 */
285uint32_t mpc_sie_irq_state(struct mpc_sie_dev_t* dev);
286
287/**
288 * \brief Locks down the MPC configuration.
289 *
290 * \param[in] dev MPC device \ref mpc_sie_dev_t
291 *
292 * \return Returns error code as specified in \ref mpc_sie_error_t
293 *
294 * \note This function doesn't check if dev is NULL.
295 */
296enum mpc_sie_error_t mpc_sie_lock_down(struct mpc_sie_dev_t* dev);
297
298/**
299 * \brief Returns if gating is present in hardware.
300 *
301 * \param[in] dev MPC device \ref mpc_sie_dev_t
302 * \param[out] gating_present Returns if gating is present in hardware.
303 *
304 * \return Returns error code as specified in \ref mpc_sie_error_t
305 *
306 * \note This function doesn't check if dev is NULL.
307 */
308enum mpc_sie_error_t mpc_sie_is_gating_present(struct mpc_sie_dev_t* dev,
309 bool* gating_present);
310
311/**
312 * \brief Returns the value of Peripheral ID 0 register.
313 *
314 * \param[in] dev MPC device \ref mpc_sie_dev_t
315 *
316 * \return Returns the value of Peripheral ID 0 register.
317 *
318 * \note This function doesn't check if dev is NULL.
319 */
320uint32_t get_sie_version(struct mpc_sie_dev_t* dev);
321
322/**
323 * \brief Reads bit indicating acknowledge for gating incoming transfers.
324 *
325 * \param[in] dev MPC device \ref mpc_sie_dev_t
326 *
327 * \return True if acknowledge is set.
328 *
329 * \note This function doesn't check if dev is NULL.
330 */
331bool mpc_sie_get_gate_ack(struct mpc_sie_dev_t* dev);
332
333/**
334 * \brief Sets bit to request for gating incoming transfers.
335 *
336 * \param[in] dev MPC device \ref mpc_sie_dev_t
337 *
338 * \note This function doesn't check if dev is NULL.
339 */
340void mpc_sie_request_gating(struct mpc_sie_dev_t* dev);
341
342/**
343 * \brief Clears bit to request for gating incoming transfers.
344 *
345 * \param[in] dev MPC device \ref mpc_sie_dev_t
346 *
347 * \note This function doesn't check if dev is NULL.
348 */
349void mpc_sie_release_gating(struct mpc_sie_dev_t* dev);
350
351#ifdef __cplusplus
352}
353#endif
354#endif /* __MPC_SIE_DRV_H__ */