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