[270] | 1 | ;/**************************************************************************//**
|
---|
| 2 | ; * @file core_ca_mmu.h
|
---|
| 3 | ; * @brief MMU Startup File for A9_MP Device Series
|
---|
| 4 | ; * @version V1.01
|
---|
| 5 | ; * @date 10 Sept 2014
|
---|
| 6 | ; *
|
---|
| 7 | ; * @note
|
---|
| 8 | ; *
|
---|
| 9 | ; ******************************************************************************/
|
---|
| 10 | ;/* Copyright (c) 2012-2014 ARM LIMITED
|
---|
| 11 | ;
|
---|
| 12 | ; All rights reserved.
|
---|
| 13 | ; Redistribution and use in source and binary forms, with or without
|
---|
| 14 | ; modification, are permitted provided that the following conditions are met:
|
---|
| 15 | ; - Redistributions of source code must retain the above copyright
|
---|
| 16 | ; notice, this list of conditions and the following disclaimer.
|
---|
| 17 | ; - Redistributions in binary form must reproduce the above copyright
|
---|
| 18 | ; notice, this list of conditions and the following disclaimer in the
|
---|
| 19 | ; documentation and/or other materials provided with the distribution.
|
---|
| 20 | ; - Neither the name of ARM nor the names of its contributors may be used
|
---|
| 21 | ; to endorse or promote products derived from this software without
|
---|
| 22 | ; specific prior written permission.
|
---|
| 23 | ; *
|
---|
| 24 | ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
---|
| 25 | ; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
---|
| 26 | ; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
---|
| 27 | ; ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
|
---|
| 28 | ; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
---|
| 29 | ; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
---|
| 30 | ; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
---|
| 31 | ; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
---|
| 32 | ; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
---|
| 33 | ; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
---|
| 34 | ; POSSIBILITY OF SUCH DAMAGE.
|
---|
| 35 | ; ---------------------------------------------------------------------------*/
|
---|
| 36 |
|
---|
| 37 | #ifdef __cplusplus
|
---|
| 38 | extern "C" {
|
---|
| 39 | #endif
|
---|
| 40 |
|
---|
| 41 | #ifndef _MMU_FUNC_H
|
---|
| 42 | #define _MMU_FUNC_H
|
---|
| 43 |
|
---|
| 44 | #define SECTION_DESCRIPTOR (0x2)
|
---|
| 45 | #define SECTION_MASK (0xFFFFFFFC)
|
---|
| 46 |
|
---|
| 47 | #define SECTION_TEXCB_MASK (0xFFFF8FF3)
|
---|
| 48 | #define SECTION_B_SHIFT (2)
|
---|
| 49 | #define SECTION_C_SHIFT (3)
|
---|
| 50 | #define SECTION_TEX0_SHIFT (12)
|
---|
| 51 | #define SECTION_TEX1_SHIFT (13)
|
---|
| 52 | #define SECTION_TEX2_SHIFT (14)
|
---|
| 53 |
|
---|
| 54 | #define SECTION_XN_MASK (0xFFFFFFEF)
|
---|
| 55 | #define SECTION_XN_SHIFT (4)
|
---|
| 56 |
|
---|
| 57 | #define SECTION_DOMAIN_MASK (0xFFFFFE1F)
|
---|
| 58 | #define SECTION_DOMAIN_SHIFT (5)
|
---|
| 59 |
|
---|
| 60 | #define SECTION_P_MASK (0xFFFFFDFF)
|
---|
| 61 | #define SECTION_P_SHIFT (9)
|
---|
| 62 |
|
---|
| 63 | #define SECTION_AP_MASK (0xFFFF73FF)
|
---|
| 64 | #define SECTION_AP_SHIFT (10)
|
---|
| 65 | #define SECTION_AP2_SHIFT (15)
|
---|
| 66 |
|
---|
| 67 | #define SECTION_S_MASK (0xFFFEFFFF)
|
---|
| 68 | #define SECTION_S_SHIFT (16)
|
---|
| 69 |
|
---|
| 70 | #define SECTION_NG_MASK (0xFFFDFFFF)
|
---|
| 71 | #define SECTION_NG_SHIFT (17)
|
---|
| 72 |
|
---|
| 73 | #define SECTION_NS_MASK (0xFFF7FFFF)
|
---|
| 74 | #define SECTION_NS_SHIFT (19)
|
---|
| 75 |
|
---|
| 76 |
|
---|
| 77 | #define PAGE_L1_DESCRIPTOR (0x1)
|
---|
| 78 | #define PAGE_L1_MASK (0xFFFFFFFC)
|
---|
| 79 |
|
---|
| 80 | #define PAGE_L2_4K_DESC (0x2)
|
---|
| 81 | #define PAGE_L2_4K_MASK (0xFFFFFFFD)
|
---|
| 82 |
|
---|
| 83 | #define PAGE_L2_64K_DESC (0x1)
|
---|
| 84 | #define PAGE_L2_64K_MASK (0xFFFFFFFC)
|
---|
| 85 |
|
---|
| 86 | #define PAGE_4K_TEXCB_MASK (0xFFFFFE33)
|
---|
| 87 | #define PAGE_4K_B_SHIFT (2)
|
---|
| 88 | #define PAGE_4K_C_SHIFT (3)
|
---|
| 89 | #define PAGE_4K_TEX0_SHIFT (6)
|
---|
| 90 | #define PAGE_4K_TEX1_SHIFT (7)
|
---|
| 91 | #define PAGE_4K_TEX2_SHIFT (8)
|
---|
| 92 |
|
---|
| 93 | #define PAGE_64K_TEXCB_MASK (0xFFFF8FF3)
|
---|
| 94 | #define PAGE_64K_B_SHIFT (2)
|
---|
| 95 | #define PAGE_64K_C_SHIFT (3)
|
---|
| 96 | #define PAGE_64K_TEX0_SHIFT (12)
|
---|
| 97 | #define PAGE_64K_TEX1_SHIFT (13)
|
---|
| 98 | #define PAGE_64K_TEX2_SHIFT (14)
|
---|
| 99 |
|
---|
| 100 | #define PAGE_TEXCB_MASK (0xFFFF8FF3)
|
---|
| 101 | #define PAGE_B_SHIFT (2)
|
---|
| 102 | #define PAGE_C_SHIFT (3)
|
---|
| 103 | #define PAGE_TEX_SHIFT (12)
|
---|
| 104 |
|
---|
| 105 | #define PAGE_XN_4K_MASK (0xFFFFFFFE)
|
---|
| 106 | #define PAGE_XN_4K_SHIFT (0)
|
---|
| 107 | #define PAGE_XN_64K_MASK (0xFFFF7FFF)
|
---|
| 108 | #define PAGE_XN_64K_SHIFT (15)
|
---|
| 109 |
|
---|
| 110 |
|
---|
| 111 | #define PAGE_DOMAIN_MASK (0xFFFFFE1F)
|
---|
| 112 | #define PAGE_DOMAIN_SHIFT (5)
|
---|
| 113 |
|
---|
| 114 | #define PAGE_P_MASK (0xFFFFFDFF)
|
---|
| 115 | #define PAGE_P_SHIFT (9)
|
---|
| 116 |
|
---|
| 117 | #define PAGE_AP_MASK (0xFFFFFDCF)
|
---|
| 118 | #define PAGE_AP_SHIFT (4)
|
---|
| 119 | #define PAGE_AP2_SHIFT (9)
|
---|
| 120 |
|
---|
| 121 | #define PAGE_S_MASK (0xFFFFFBFF)
|
---|
| 122 | #define PAGE_S_SHIFT (10)
|
---|
| 123 |
|
---|
| 124 | #define PAGE_NG_MASK (0xFFFFF7FF)
|
---|
| 125 | #define PAGE_NG_SHIFT (11)
|
---|
| 126 |
|
---|
| 127 | #define PAGE_NS_MASK (0xFFFFFFF7)
|
---|
| 128 | #define PAGE_NS_SHIFT (3)
|
---|
| 129 |
|
---|
| 130 | #define OFFSET_1M (0x00100000)
|
---|
| 131 | #define OFFSET_64K (0x00010000)
|
---|
| 132 | #define OFFSET_4K (0x00001000)
|
---|
| 133 |
|
---|
| 134 | #define DESCRIPTOR_FAULT (0x00000000)
|
---|
| 135 |
|
---|
| 136 | /* ########################### MMU Function Access ########################### */
|
---|
| 137 | /** \ingroup MMU_FunctionInterface
|
---|
| 138 | \defgroup MMU_Functions MMU Functions Interface
|
---|
| 139 | @{
|
---|
| 140 | */
|
---|
| 141 |
|
---|
| 142 | /* Attributes enumerations */
|
---|
| 143 |
|
---|
| 144 | /* Region size attributes */
|
---|
| 145 | typedef enum
|
---|
| 146 | {
|
---|
| 147 | SECTION,
|
---|
| 148 | PAGE_4k,
|
---|
| 149 | PAGE_64k,
|
---|
| 150 | } mmu_region_size_Type;
|
---|
| 151 |
|
---|
| 152 | /* Region type attributes */
|
---|
| 153 | typedef enum
|
---|
| 154 | {
|
---|
| 155 | NORMAL,
|
---|
| 156 | DEVICE,
|
---|
| 157 | SHARED_DEVICE,
|
---|
| 158 | NON_SHARED_DEVICE,
|
---|
| 159 | STRONGLY_ORDERED
|
---|
| 160 | } mmu_memory_Type;
|
---|
| 161 |
|
---|
| 162 | /* Region cacheability attributes */
|
---|
| 163 | typedef enum
|
---|
| 164 | {
|
---|
| 165 | NON_CACHEABLE,
|
---|
| 166 | WB_WA,
|
---|
| 167 | WT,
|
---|
| 168 | WB_NO_WA,
|
---|
| 169 | } mmu_cacheability_Type;
|
---|
| 170 |
|
---|
| 171 | /* Region parity check attributes */
|
---|
| 172 | typedef enum
|
---|
| 173 | {
|
---|
| 174 | ECC_DISABLED,
|
---|
| 175 | ECC_ENABLED,
|
---|
| 176 | } mmu_ecc_check_Type;
|
---|
| 177 |
|
---|
| 178 | /* Region execution attributes */
|
---|
| 179 | typedef enum
|
---|
| 180 | {
|
---|
| 181 | EXECUTE,
|
---|
| 182 | NON_EXECUTE,
|
---|
| 183 | } mmu_execute_Type;
|
---|
| 184 |
|
---|
| 185 | /* Region global attributes */
|
---|
| 186 | typedef enum
|
---|
| 187 | {
|
---|
| 188 | GLOBAL,
|
---|
| 189 | NON_GLOBAL,
|
---|
| 190 | } mmu_global_Type;
|
---|
| 191 |
|
---|
| 192 | /* Region shareability attributes */
|
---|
| 193 | typedef enum
|
---|
| 194 | {
|
---|
| 195 | NON_SHARED,
|
---|
| 196 | SHARED,
|
---|
| 197 | } mmu_shared_Type;
|
---|
| 198 |
|
---|
| 199 | /* Region security attributes */
|
---|
| 200 | typedef enum
|
---|
| 201 | {
|
---|
| 202 | SECURE,
|
---|
| 203 | NON_SECURE,
|
---|
| 204 | } mmu_secure_Type;
|
---|
| 205 |
|
---|
| 206 | /* Region access attributes */
|
---|
| 207 | typedef enum
|
---|
| 208 | {
|
---|
| 209 | NO_ACCESS,
|
---|
| 210 | RW,
|
---|
| 211 | READ,
|
---|
| 212 | } mmu_access_Type;
|
---|
| 213 |
|
---|
| 214 | /* Memory Region definition */
|
---|
| 215 | typedef struct RegionStruct {
|
---|
| 216 | mmu_region_size_Type rg_t;
|
---|
| 217 | mmu_memory_Type mem_t;
|
---|
| 218 | uint8_t domain;
|
---|
| 219 | mmu_cacheability_Type inner_norm_t;
|
---|
| 220 | mmu_cacheability_Type outer_norm_t;
|
---|
| 221 | mmu_ecc_check_Type e_t;
|
---|
| 222 | mmu_execute_Type xn_t;
|
---|
| 223 | mmu_global_Type g_t;
|
---|
| 224 | mmu_secure_Type sec_t;
|
---|
| 225 | mmu_access_Type priv_t;
|
---|
| 226 | mmu_access_Type user_t;
|
---|
| 227 | mmu_shared_Type sh_t;
|
---|
| 228 |
|
---|
| 229 | } mmu_region_attributes_Type;
|
---|
| 230 |
|
---|
| 231 | /** \brief Set section execution-never attribute
|
---|
| 232 |
|
---|
| 233 | The function sets section execution-never attribute
|
---|
| 234 |
|
---|
| 235 | \param [out] descriptor_l1 L1 descriptor.
|
---|
| 236 | \param [in] xn Section execution-never attribute : EXECUTE , NON_EXECUTE.
|
---|
| 237 |
|
---|
| 238 | \return 0
|
---|
| 239 | */
|
---|
| 240 | __STATIC_INLINE int __xn_section(uint32_t *descriptor_l1, mmu_execute_Type xn)
|
---|
| 241 | {
|
---|
| 242 | *descriptor_l1 &= SECTION_XN_MASK;
|
---|
| 243 | *descriptor_l1 |= ((xn & 0x1) << SECTION_XN_SHIFT);
|
---|
| 244 | return 0;
|
---|
| 245 | }
|
---|
| 246 |
|
---|
| 247 | /** \brief Set section domain
|
---|
| 248 |
|
---|
| 249 | The function sets section domain
|
---|
| 250 |
|
---|
| 251 | \param [out] descriptor_l1 L1 descriptor.
|
---|
| 252 | \param [in] domain Section domain
|
---|
| 253 |
|
---|
| 254 | \return 0
|
---|
| 255 | */
|
---|
| 256 | __STATIC_INLINE int __domain_section(uint32_t *descriptor_l1, uint8_t domain)
|
---|
| 257 | {
|
---|
| 258 | *descriptor_l1 &= SECTION_DOMAIN_MASK;
|
---|
| 259 | *descriptor_l1 |= ((domain & 0xF) << SECTION_DOMAIN_SHIFT);
|
---|
| 260 | return 0;
|
---|
| 261 | }
|
---|
| 262 |
|
---|
| 263 | /** \brief Set section parity check
|
---|
| 264 |
|
---|
| 265 | The function sets section parity check
|
---|
| 266 |
|
---|
| 267 | \param [out] descriptor_l1 L1 descriptor.
|
---|
| 268 | \param [in] p_bit Parity check: ECC_DISABLED, ECC_ENABLED
|
---|
| 269 |
|
---|
| 270 | \return 0
|
---|
| 271 | */
|
---|
| 272 | __STATIC_INLINE int __p_section(uint32_t *descriptor_l1, mmu_ecc_check_Type p_bit)
|
---|
| 273 | {
|
---|
| 274 | *descriptor_l1 &= SECTION_P_MASK;
|
---|
| 275 | *descriptor_l1 |= ((p_bit & 0x1) << SECTION_P_SHIFT);
|
---|
| 276 | return 0;
|
---|
| 277 | }
|
---|
| 278 |
|
---|
| 279 | /** \brief Set section access privileges
|
---|
| 280 |
|
---|
| 281 | The function sets section access privileges
|
---|
| 282 |
|
---|
| 283 | \param [out] descriptor_l1 L1 descriptor.
|
---|
| 284 | \param [in] user User Level Access: NO_ACCESS, RW, READ
|
---|
| 285 | \param [in] priv Privilege Level Access: NO_ACCESS, RW, READ
|
---|
| 286 | \param [in] afe Access flag enable
|
---|
| 287 |
|
---|
| 288 | \return 0
|
---|
| 289 | */
|
---|
| 290 | __STATIC_INLINE int __ap_section(uint32_t *descriptor_l1, mmu_access_Type user, mmu_access_Type priv, uint32_t afe)
|
---|
| 291 | {
|
---|
| 292 | uint32_t ap = 0;
|
---|
| 293 |
|
---|
| 294 | if (afe == 0) { //full access
|
---|
| 295 | if ((priv == NO_ACCESS) && (user == NO_ACCESS)) { ap = 0x0; }
|
---|
| 296 | else if ((priv == RW) && (user == NO_ACCESS)) { ap = 0x1; }
|
---|
| 297 | else if ((priv == RW) && (user == READ)) { ap = 0x2; }
|
---|
| 298 | else if ((priv == RW) && (user == RW)) { ap = 0x3; }
|
---|
| 299 | else if ((priv == READ) && (user == NO_ACCESS)) { ap = 0x5; }
|
---|
| 300 | else if ((priv == READ) && (user == READ)) { ap = 0x7; }
|
---|
| 301 | }
|
---|
| 302 |
|
---|
| 303 | else { //Simplified access
|
---|
| 304 | if ((priv == RW) && (user == NO_ACCESS)) { ap = 0x1; }
|
---|
| 305 | else if ((priv == RW) && (user == RW)) { ap = 0x3; }
|
---|
| 306 | else if ((priv == READ) && (user == NO_ACCESS)) { ap = 0x5; }
|
---|
| 307 | else if ((priv == READ) && (user == READ)) { ap = 0x7; }
|
---|
| 308 | }
|
---|
| 309 |
|
---|
| 310 | *descriptor_l1 &= SECTION_AP_MASK;
|
---|
| 311 | *descriptor_l1 |= (ap & 0x3) << SECTION_AP_SHIFT;
|
---|
| 312 | *descriptor_l1 |= ((ap & 0x4)>>2) << SECTION_AP2_SHIFT;
|
---|
| 313 |
|
---|
| 314 | return 0;
|
---|
| 315 | }
|
---|
| 316 |
|
---|
| 317 | /** \brief Set section shareability
|
---|
| 318 |
|
---|
| 319 | The function sets section shareability
|
---|
| 320 |
|
---|
| 321 | \param [out] descriptor_l1 L1 descriptor.
|
---|
| 322 | \param [in] s_bit Section shareability: NON_SHARED, SHARED
|
---|
| 323 |
|
---|
| 324 | \return 0
|
---|
| 325 | */
|
---|
| 326 | __STATIC_INLINE int __shared_section(uint32_t *descriptor_l1, mmu_shared_Type s_bit)
|
---|
| 327 | {
|
---|
| 328 | *descriptor_l1 &= SECTION_S_MASK;
|
---|
| 329 | *descriptor_l1 |= ((s_bit & 0x1) << SECTION_S_SHIFT);
|
---|
| 330 | return 0;
|
---|
| 331 | }
|
---|
| 332 |
|
---|
| 333 | /** \brief Set section Global attribute
|
---|
| 334 |
|
---|
| 335 | The function sets section Global attribute
|
---|
| 336 |
|
---|
| 337 | \param [out] descriptor_l1 L1 descriptor.
|
---|
| 338 | \param [in] g_bit Section attribute: GLOBAL, NON_GLOBAL
|
---|
| 339 |
|
---|
| 340 | \return 0
|
---|
| 341 | */
|
---|
| 342 | __STATIC_INLINE int __global_section(uint32_t *descriptor_l1, mmu_global_Type g_bit)
|
---|
| 343 | {
|
---|
| 344 | *descriptor_l1 &= SECTION_NG_MASK;
|
---|
| 345 | *descriptor_l1 |= ((g_bit & 0x1) << SECTION_NG_SHIFT);
|
---|
| 346 | return 0;
|
---|
| 347 | }
|
---|
| 348 |
|
---|
| 349 | /** \brief Set section Security attribute
|
---|
| 350 |
|
---|
| 351 | The function sets section Global attribute
|
---|
| 352 |
|
---|
| 353 | \param [out] descriptor_l1 L1 descriptor.
|
---|
| 354 | \param [in] s_bit Section Security attribute: SECURE, NON_SECURE
|
---|
| 355 |
|
---|
| 356 | \return 0
|
---|
| 357 | */
|
---|
| 358 | __STATIC_INLINE int __secure_section(uint32_t *descriptor_l1, mmu_secure_Type s_bit)
|
---|
| 359 | {
|
---|
| 360 | *descriptor_l1 &= SECTION_NS_MASK;
|
---|
| 361 | *descriptor_l1 |= ((s_bit & 0x1) << SECTION_NS_SHIFT);
|
---|
| 362 | return 0;
|
---|
| 363 | }
|
---|
| 364 |
|
---|
| 365 | /* Page 4k or 64k */
|
---|
| 366 | /** \brief Set 4k/64k page execution-never attribute
|
---|
| 367 |
|
---|
| 368 | The function sets 4k/64k page execution-never attribute
|
---|
| 369 |
|
---|
| 370 | \param [out] descriptor_l2 L2 descriptor.
|
---|
| 371 | \param [in] xn Page execution-never attribute : EXECUTE , NON_EXECUTE.
|
---|
| 372 | \param [in] page Page size: PAGE_4k, PAGE_64k,
|
---|
| 373 |
|
---|
| 374 | \return 0
|
---|
| 375 | */
|
---|
| 376 | __STATIC_INLINE int __xn_page(uint32_t *descriptor_l2, mmu_execute_Type xn, mmu_region_size_Type page)
|
---|
| 377 | {
|
---|
| 378 | if (page == PAGE_4k)
|
---|
| 379 | {
|
---|
| 380 | *descriptor_l2 &= PAGE_XN_4K_MASK;
|
---|
| 381 | *descriptor_l2 |= ((xn & 0x1) << PAGE_XN_4K_SHIFT);
|
---|
| 382 | }
|
---|
| 383 | else
|
---|
| 384 | {
|
---|
| 385 | *descriptor_l2 &= PAGE_XN_64K_MASK;
|
---|
| 386 | *descriptor_l2 |= ((xn & 0x1) << PAGE_XN_64K_SHIFT);
|
---|
| 387 | }
|
---|
| 388 | return 0;
|
---|
| 389 | }
|
---|
| 390 |
|
---|
| 391 | /** \brief Set 4k/64k page domain
|
---|
| 392 |
|
---|
| 393 | The function sets 4k/64k page domain
|
---|
| 394 |
|
---|
| 395 | \param [out] descriptor_l1 L1 descriptor.
|
---|
| 396 | \param [in] domain Page domain
|
---|
| 397 |
|
---|
| 398 | \return 0
|
---|
| 399 | */
|
---|
| 400 | __STATIC_INLINE int __domain_page(uint32_t *descriptor_l1, uint8_t domain)
|
---|
| 401 | {
|
---|
| 402 | *descriptor_l1 &= PAGE_DOMAIN_MASK;
|
---|
| 403 | *descriptor_l1 |= ((domain & 0xf) << PAGE_DOMAIN_SHIFT);
|
---|
| 404 | return 0;
|
---|
| 405 | }
|
---|
| 406 |
|
---|
| 407 | /** \brief Set 4k/64k page parity check
|
---|
| 408 |
|
---|
| 409 | The function sets 4k/64k page parity check
|
---|
| 410 |
|
---|
| 411 | \param [out] descriptor_l1 L1 descriptor.
|
---|
| 412 | \param [in] p_bit Parity check: ECC_DISABLED, ECC_ENABLED
|
---|
| 413 |
|
---|
| 414 | \return 0
|
---|
| 415 | */
|
---|
| 416 | __STATIC_INLINE int __p_page(uint32_t *descriptor_l1, mmu_ecc_check_Type p_bit)
|
---|
| 417 | {
|
---|
| 418 | *descriptor_l1 &= SECTION_P_MASK;
|
---|
| 419 | *descriptor_l1 |= ((p_bit & 0x1) << SECTION_P_SHIFT);
|
---|
| 420 | return 0;
|
---|
| 421 | }
|
---|
| 422 |
|
---|
| 423 | /** \brief Set 4k/64k page access privileges
|
---|
| 424 |
|
---|
| 425 | The function sets 4k/64k page access privileges
|
---|
| 426 |
|
---|
| 427 | \param [out] descriptor_l2 L2 descriptor.
|
---|
| 428 | \param [in] user User Level Access: NO_ACCESS, RW, READ
|
---|
| 429 | \param [in] priv Privilege Level Access: NO_ACCESS, RW, READ
|
---|
| 430 | \param [in] afe Access flag enable
|
---|
| 431 |
|
---|
| 432 | \return 0
|
---|
| 433 | */
|
---|
| 434 | __STATIC_INLINE int __ap_page(uint32_t *descriptor_l2, mmu_access_Type user, mmu_access_Type priv, uint32_t afe)
|
---|
| 435 | {
|
---|
| 436 | uint32_t ap = 0;
|
---|
| 437 |
|
---|
| 438 | if (afe == 0) { //full access
|
---|
| 439 | if ((priv == NO_ACCESS) && (user == NO_ACCESS)) { ap = 0x0; }
|
---|
| 440 | else if ((priv == RW) && (user == NO_ACCESS)) { ap = 0x1; }
|
---|
| 441 | else if ((priv == RW) && (user == READ)) { ap = 0x2; }
|
---|
| 442 | else if ((priv == RW) && (user == RW)) { ap = 0x3; }
|
---|
| 443 | else if ((priv == READ) && (user == NO_ACCESS)) { ap = 0x5; }
|
---|
| 444 | else if ((priv == READ) && (user == READ)) { ap = 0x6; }
|
---|
| 445 | }
|
---|
| 446 |
|
---|
| 447 | else { //Simplified access
|
---|
| 448 | if ((priv == RW) && (user == NO_ACCESS)) { ap = 0x1; }
|
---|
| 449 | else if ((priv == RW) && (user == RW)) { ap = 0x3; }
|
---|
| 450 | else if ((priv == READ) && (user == NO_ACCESS)) { ap = 0x5; }
|
---|
| 451 | else if ((priv == READ) && (user == READ)) { ap = 0x7; }
|
---|
| 452 | }
|
---|
| 453 |
|
---|
| 454 | *descriptor_l2 &= PAGE_AP_MASK;
|
---|
| 455 | *descriptor_l2 |= (ap & 0x3) << PAGE_AP_SHIFT;
|
---|
| 456 | *descriptor_l2 |= ((ap & 0x4)>>2) << PAGE_AP2_SHIFT;
|
---|
| 457 |
|
---|
| 458 | return 0;
|
---|
| 459 | }
|
---|
| 460 |
|
---|
| 461 | /** \brief Set 4k/64k page shareability
|
---|
| 462 |
|
---|
| 463 | The function sets 4k/64k page shareability
|
---|
| 464 |
|
---|
| 465 | \param [out] descriptor_l2 L2 descriptor.
|
---|
| 466 | \param [in] s_bit 4k/64k page shareability: NON_SHARED, SHARED
|
---|
| 467 |
|
---|
| 468 | \return 0
|
---|
| 469 | */
|
---|
| 470 | __STATIC_INLINE int __shared_page(uint32_t *descriptor_l2, mmu_shared_Type s_bit)
|
---|
| 471 | {
|
---|
| 472 | *descriptor_l2 &= PAGE_S_MASK;
|
---|
| 473 | *descriptor_l2 |= ((s_bit & 0x1) << PAGE_S_SHIFT);
|
---|
| 474 | return 0;
|
---|
| 475 | }
|
---|
| 476 |
|
---|
| 477 | /** \brief Set 4k/64k page Global attribute
|
---|
| 478 |
|
---|
| 479 | The function sets 4k/64k page Global attribute
|
---|
| 480 |
|
---|
| 481 | \param [out] descriptor_l2 L2 descriptor.
|
---|
| 482 | \param [in] g_bit 4k/64k page attribute: GLOBAL, NON_GLOBAL
|
---|
| 483 |
|
---|
| 484 | \return 0
|
---|
| 485 | */
|
---|
| 486 | __STATIC_INLINE int __global_page(uint32_t *descriptor_l2, mmu_global_Type g_bit)
|
---|
| 487 | {
|
---|
| 488 | *descriptor_l2 &= PAGE_NG_MASK;
|
---|
| 489 | *descriptor_l2 |= ((g_bit & 0x1) << PAGE_NG_SHIFT);
|
---|
| 490 | return 0;
|
---|
| 491 | }
|
---|
| 492 |
|
---|
| 493 | /** \brief Set 4k/64k page Security attribute
|
---|
| 494 |
|
---|
| 495 | The function sets 4k/64k page Global attribute
|
---|
| 496 |
|
---|
| 497 | \param [out] descriptor_l1 L1 descriptor.
|
---|
| 498 | \param [in] s_bit 4k/64k page Security attribute: SECURE, NON_SECURE
|
---|
| 499 |
|
---|
| 500 | \return 0
|
---|
| 501 | */
|
---|
| 502 | __STATIC_INLINE int __secure_page(uint32_t *descriptor_l1, mmu_secure_Type s_bit)
|
---|
| 503 | {
|
---|
| 504 | *descriptor_l1 &= PAGE_NS_MASK;
|
---|
| 505 | *descriptor_l1 |= ((s_bit & 0x1) << PAGE_NS_SHIFT);
|
---|
| 506 | return 0;
|
---|
| 507 | }
|
---|
| 508 |
|
---|
| 509 |
|
---|
| 510 | /** \brief Set Section memory attributes
|
---|
| 511 |
|
---|
| 512 | The function sets section memory attributes
|
---|
| 513 |
|
---|
| 514 | \param [out] descriptor_l1 L1 descriptor.
|
---|
| 515 | \param [in] mem Section memory type: NORMAL, DEVICE, SHARED_DEVICE, NON_SHARED_DEVICE, STRONGLY_ORDERED
|
---|
| 516 | \param [in] outer Outer cacheability: NON_CACHEABLE, WB_WA, WT, WB_NO_WA,
|
---|
| 517 | \param [in] inner Inner cacheability: NON_CACHEABLE, WB_WA, WT, WB_NO_WA,
|
---|
| 518 |
|
---|
| 519 | \return 0
|
---|
| 520 | */
|
---|
| 521 | __STATIC_INLINE int __memory_section(uint32_t *descriptor_l1, mmu_memory_Type mem, mmu_cacheability_Type outer, mmu_cacheability_Type inner)
|
---|
| 522 | {
|
---|
| 523 | *descriptor_l1 &= SECTION_TEXCB_MASK;
|
---|
| 524 |
|
---|
| 525 | if (STRONGLY_ORDERED == mem)
|
---|
| 526 | {
|
---|
| 527 | return 0;
|
---|
| 528 | }
|
---|
| 529 | else if (SHARED_DEVICE == mem)
|
---|
| 530 | {
|
---|
| 531 | *descriptor_l1 |= (1 << SECTION_B_SHIFT);
|
---|
| 532 | }
|
---|
| 533 | else if (NON_SHARED_DEVICE == mem)
|
---|
| 534 | {
|
---|
| 535 | *descriptor_l1 |= (1 << SECTION_TEX1_SHIFT);
|
---|
| 536 | }
|
---|
| 537 | else if (NORMAL == mem)
|
---|
| 538 | {
|
---|
| 539 | *descriptor_l1 |= 1 << SECTION_TEX2_SHIFT;
|
---|
| 540 | switch(inner)
|
---|
| 541 | {
|
---|
| 542 | case NON_CACHEABLE:
|
---|
| 543 | break;
|
---|
| 544 | case WB_WA:
|
---|
| 545 | *descriptor_l1 |= (1 << SECTION_B_SHIFT);
|
---|
| 546 | break;
|
---|
| 547 | case WT:
|
---|
| 548 | *descriptor_l1 |= 1 << SECTION_C_SHIFT;
|
---|
| 549 | break;
|
---|
| 550 | case WB_NO_WA:
|
---|
| 551 | *descriptor_l1 |= (1 << SECTION_B_SHIFT) | (1 << SECTION_C_SHIFT);
|
---|
| 552 | break;
|
---|
| 553 | }
|
---|
| 554 | switch(outer)
|
---|
| 555 | {
|
---|
| 556 | case NON_CACHEABLE:
|
---|
| 557 | break;
|
---|
| 558 | case WB_WA:
|
---|
| 559 | *descriptor_l1 |= (1 << SECTION_TEX0_SHIFT);
|
---|
| 560 | break;
|
---|
| 561 | case WT:
|
---|
| 562 | *descriptor_l1 |= 1 << SECTION_TEX1_SHIFT;
|
---|
| 563 | break;
|
---|
| 564 | case WB_NO_WA:
|
---|
| 565 | *descriptor_l1 |= (1 << SECTION_TEX0_SHIFT) | (1 << SECTION_TEX0_SHIFT);
|
---|
| 566 | break;
|
---|
| 567 | }
|
---|
| 568 | }
|
---|
| 569 |
|
---|
| 570 | return 0;
|
---|
| 571 | }
|
---|
| 572 |
|
---|
| 573 | /** \brief Set 4k/64k page memory attributes
|
---|
| 574 |
|
---|
| 575 | The function sets 4k/64k page memory attributes
|
---|
| 576 |
|
---|
| 577 | \param [out] descriptor_l2 L2 descriptor.
|
---|
| 578 | \param [in] mem 4k/64k page memory type: NORMAL, DEVICE, SHARED_DEVICE, NON_SHARED_DEVICE, STRONGLY_ORDERED
|
---|
| 579 | \param [in] outer Outer cacheability: NON_CACHEABLE, WB_WA, WT, WB_NO_WA,
|
---|
| 580 | \param [in] inner Inner cacheability: NON_CACHEABLE, WB_WA, WT, WB_NO_WA,
|
---|
| 581 |
|
---|
| 582 | \return 0
|
---|
| 583 | */
|
---|
| 584 | __STATIC_INLINE int __memory_page(uint32_t *descriptor_l2, mmu_memory_Type mem, mmu_cacheability_Type outer, mmu_cacheability_Type inner, mmu_region_size_Type page)
|
---|
| 585 | {
|
---|
| 586 | *descriptor_l2 &= PAGE_4K_TEXCB_MASK;
|
---|
| 587 |
|
---|
| 588 | if (page == PAGE_64k)
|
---|
| 589 | {
|
---|
| 590 | //same as section
|
---|
| 591 | __memory_section(descriptor_l2, mem, outer, inner);
|
---|
| 592 | }
|
---|
| 593 | else
|
---|
| 594 | {
|
---|
| 595 | if (STRONGLY_ORDERED == mem)
|
---|
| 596 | {
|
---|
| 597 | return 0;
|
---|
| 598 | }
|
---|
| 599 | else if (SHARED_DEVICE == mem)
|
---|
| 600 | {
|
---|
| 601 | *descriptor_l2 |= (1 << PAGE_4K_B_SHIFT);
|
---|
| 602 | }
|
---|
| 603 | else if (NON_SHARED_DEVICE == mem)
|
---|
| 604 | {
|
---|
| 605 | *descriptor_l2 |= (1 << PAGE_4K_TEX1_SHIFT);
|
---|
| 606 | }
|
---|
| 607 | else if (NORMAL == mem)
|
---|
| 608 | {
|
---|
| 609 | *descriptor_l2 |= 1 << PAGE_4K_TEX2_SHIFT;
|
---|
| 610 | switch(inner)
|
---|
| 611 | {
|
---|
| 612 | case NON_CACHEABLE:
|
---|
| 613 | break;
|
---|
| 614 | case WB_WA:
|
---|
| 615 | *descriptor_l2 |= (1 << PAGE_4K_B_SHIFT);
|
---|
| 616 | break;
|
---|
| 617 | case WT:
|
---|
| 618 | *descriptor_l2 |= 1 << PAGE_4K_C_SHIFT;
|
---|
| 619 | break;
|
---|
| 620 | case WB_NO_WA:
|
---|
| 621 | *descriptor_l2 |= (1 << PAGE_4K_B_SHIFT) | (1 << PAGE_4K_C_SHIFT);
|
---|
| 622 | break;
|
---|
| 623 | }
|
---|
| 624 | switch(outer)
|
---|
| 625 | {
|
---|
| 626 | case NON_CACHEABLE:
|
---|
| 627 | break;
|
---|
| 628 | case WB_WA:
|
---|
| 629 | *descriptor_l2 |= (1 << PAGE_4K_TEX0_SHIFT);
|
---|
| 630 | break;
|
---|
| 631 | case WT:
|
---|
| 632 | *descriptor_l2 |= 1 << PAGE_4K_TEX1_SHIFT;
|
---|
| 633 | break;
|
---|
| 634 | case WB_NO_WA:
|
---|
| 635 | *descriptor_l2 |= (1 << PAGE_4K_TEX0_SHIFT) | (1 << PAGE_4K_TEX0_SHIFT);
|
---|
| 636 | break;
|
---|
| 637 | }
|
---|
| 638 | }
|
---|
| 639 | }
|
---|
| 640 |
|
---|
| 641 | return 0;
|
---|
| 642 | }
|
---|
| 643 |
|
---|
| 644 | /** \brief Create a L1 section descriptor
|
---|
| 645 |
|
---|
| 646 | The function creates a section descriptor.
|
---|
| 647 |
|
---|
| 648 | Assumptions:
|
---|
| 649 | - 16MB super sections not supported
|
---|
| 650 | - TEX remap disabled, so memory type and attributes are described directly by bits in the descriptor
|
---|
| 651 | - Functions always return 0
|
---|
| 652 |
|
---|
| 653 | \param [out] descriptor L1 descriptor
|
---|
| 654 | \param [out] descriptor2 L2 descriptor
|
---|
| 655 | \param [in] reg Section attributes
|
---|
| 656 |
|
---|
| 657 | \return 0
|
---|
| 658 | */
|
---|
| 659 | __STATIC_INLINE int __get_section_descriptor(uint32_t *descriptor, mmu_region_attributes_Type reg)
|
---|
| 660 | {
|
---|
| 661 | *descriptor = 0;
|
---|
| 662 |
|
---|
| 663 | __memory_section(descriptor, reg.mem_t, reg.outer_norm_t, reg.inner_norm_t);
|
---|
| 664 | __xn_section(descriptor,reg.xn_t);
|
---|
| 665 | __domain_section(descriptor, reg.domain);
|
---|
| 666 | __p_section(descriptor, reg.e_t);
|
---|
| 667 | __ap_section(descriptor, reg.priv_t, reg.user_t, 1);
|
---|
| 668 | __shared_section(descriptor,reg.sh_t);
|
---|
| 669 | __global_section(descriptor,reg.g_t);
|
---|
| 670 | __secure_section(descriptor,reg.sec_t);
|
---|
| 671 | *descriptor &= SECTION_MASK;
|
---|
| 672 | *descriptor |= SECTION_DESCRIPTOR;
|
---|
| 673 |
|
---|
| 674 | return 0;
|
---|
| 675 |
|
---|
| 676 | }
|
---|
| 677 |
|
---|
| 678 |
|
---|
| 679 | /** \brief Create a L1 and L2 4k/64k page descriptor
|
---|
| 680 |
|
---|
| 681 | The function creates a 4k/64k page descriptor.
|
---|
| 682 | Assumptions:
|
---|
| 683 | - TEX remap disabled, so memory type and attributes are described directly by bits in the descriptor
|
---|
| 684 | - Functions always return 0
|
---|
| 685 |
|
---|
| 686 | \param [out] descriptor L1 descriptor
|
---|
| 687 | \param [out] descriptor2 L2 descriptor
|
---|
| 688 | \param [in] reg 4k/64k page attributes
|
---|
| 689 |
|
---|
| 690 | \return 0
|
---|
| 691 | */
|
---|
| 692 | __STATIC_INLINE int __get_page_descriptor(uint32_t *descriptor, uint32_t *descriptor2, mmu_region_attributes_Type reg)
|
---|
| 693 | {
|
---|
| 694 | *descriptor = 0;
|
---|
| 695 | *descriptor2 = 0;
|
---|
| 696 |
|
---|
| 697 | switch (reg.rg_t)
|
---|
| 698 | {
|
---|
| 699 | case PAGE_4k:
|
---|
| 700 | __memory_page(descriptor2, reg.mem_t, reg.outer_norm_t, reg.inner_norm_t, PAGE_4k);
|
---|
| 701 | __xn_page(descriptor2, reg.xn_t, PAGE_4k);
|
---|
| 702 | __domain_page(descriptor, reg.domain);
|
---|
| 703 | __p_page(descriptor, reg.e_t);
|
---|
| 704 | __ap_page(descriptor2, reg.priv_t, reg.user_t, 1);
|
---|
| 705 | __shared_page(descriptor2,reg.sh_t);
|
---|
| 706 | __global_page(descriptor2,reg.g_t);
|
---|
| 707 | __secure_page(descriptor,reg.sec_t);
|
---|
| 708 | *descriptor &= PAGE_L1_MASK;
|
---|
| 709 | *descriptor |= PAGE_L1_DESCRIPTOR;
|
---|
| 710 | *descriptor2 &= PAGE_L2_4K_MASK;
|
---|
| 711 | *descriptor2 |= PAGE_L2_4K_DESC;
|
---|
| 712 | break;
|
---|
| 713 |
|
---|
| 714 | case PAGE_64k:
|
---|
| 715 | __memory_page(descriptor2, reg.mem_t, reg.outer_norm_t, reg.inner_norm_t, PAGE_64k);
|
---|
| 716 | __xn_page(descriptor2, reg.xn_t, PAGE_64k);
|
---|
| 717 | __domain_page(descriptor, reg.domain);
|
---|
| 718 | __p_page(descriptor, reg.e_t);
|
---|
| 719 | __ap_page(descriptor2, reg.priv_t, reg.user_t, 1);
|
---|
| 720 | __shared_page(descriptor2,reg.sh_t);
|
---|
| 721 | __global_page(descriptor2,reg.g_t);
|
---|
| 722 | __secure_page(descriptor,reg.sec_t);
|
---|
| 723 | *descriptor &= PAGE_L1_MASK;
|
---|
| 724 | *descriptor |= PAGE_L1_DESCRIPTOR;
|
---|
| 725 | *descriptor2 &= PAGE_L2_64K_MASK;
|
---|
| 726 | *descriptor2 |= PAGE_L2_64K_DESC;
|
---|
| 727 | break;
|
---|
| 728 |
|
---|
| 729 | case SECTION:
|
---|
| 730 | //error
|
---|
| 731 | break;
|
---|
| 732 |
|
---|
| 733 | }
|
---|
| 734 |
|
---|
| 735 | return 0;
|
---|
| 736 |
|
---|
| 737 | }
|
---|
| 738 |
|
---|
| 739 | /** \brief Create a 1MB Section
|
---|
| 740 |
|
---|
| 741 | \param [in] ttb Translation table base address
|
---|
| 742 | \param [in] base_address Section base address
|
---|
| 743 | \param [in] count Number of sections to create
|
---|
| 744 | \param [in] descriptor_l1 L1 descriptor (region attributes)
|
---|
| 745 |
|
---|
| 746 | */
|
---|
| 747 | __STATIC_INLINE void __TTSection(uint32_t *ttb, uint32_t base_address, uint32_t count, uint32_t descriptor_l1)
|
---|
| 748 | {
|
---|
| 749 | uint32_t offset;
|
---|
| 750 | uint32_t entry;
|
---|
| 751 | uint32_t i;
|
---|
| 752 |
|
---|
| 753 | offset = base_address >> 20;
|
---|
| 754 | entry = (base_address & 0xFFF00000) | descriptor_l1;
|
---|
| 755 |
|
---|
| 756 | //4 bytes aligned
|
---|
| 757 | ttb = ttb + offset;
|
---|
| 758 |
|
---|
| 759 | for (i = 0; i < count; i++ )
|
---|
| 760 | {
|
---|
| 761 | //4 bytes aligned
|
---|
| 762 | *ttb++ = entry;
|
---|
| 763 | entry += OFFSET_1M;
|
---|
| 764 | }
|
---|
| 765 | }
|
---|
| 766 |
|
---|
| 767 | /** \brief Create a 4k page entry
|
---|
| 768 |
|
---|
| 769 | \param [in] ttb L1 table base address
|
---|
| 770 | \param [in] base_address 4k base address
|
---|
| 771 | \param [in] count Number of 4k pages to create
|
---|
| 772 | \param [in] descriptor_l1 L1 descriptor (region attributes)
|
---|
| 773 | \param [in] ttb_l2 L2 table base address
|
---|
| 774 | \param [in] descriptor_l2 L2 descriptor (region attributes)
|
---|
| 775 |
|
---|
| 776 | */
|
---|
| 777 | __STATIC_INLINE void __TTPage_4k(uint32_t *ttb, uint32_t base_address, uint32_t count, uint32_t descriptor_l1, uint32_t *ttb_l2, uint32_t descriptor_l2 )
|
---|
| 778 | {
|
---|
| 779 |
|
---|
| 780 | uint32_t offset, offset2;
|
---|
| 781 | uint32_t entry, entry2;
|
---|
| 782 | uint32_t i;
|
---|
| 783 |
|
---|
| 784 |
|
---|
| 785 | offset = base_address >> 20;
|
---|
| 786 | entry = ((int)ttb_l2 & 0xFFFFFC00) | descriptor_l1;
|
---|
| 787 |
|
---|
| 788 | //4 bytes aligned
|
---|
| 789 | ttb += offset;
|
---|
| 790 | //create l1_entry
|
---|
| 791 | *ttb = entry;
|
---|
| 792 |
|
---|
| 793 | offset2 = (base_address & 0xff000) >> 12;
|
---|
| 794 | ttb_l2 += offset2;
|
---|
| 795 | entry2 = (base_address & 0xFFFFF000) | descriptor_l2;
|
---|
| 796 | for (i = 0; i < count; i++ )
|
---|
| 797 | {
|
---|
| 798 | //4 bytes aligned
|
---|
| 799 | *ttb_l2++ = entry2;
|
---|
| 800 | entry2 += OFFSET_4K;
|
---|
| 801 | }
|
---|
| 802 | }
|
---|
| 803 |
|
---|
| 804 | /** \brief Create a 64k page entry
|
---|
| 805 |
|
---|
| 806 | \param [in] ttb L1 table base address
|
---|
| 807 | \param [in] base_address 64k base address
|
---|
| 808 | \param [in] count Number of 64k pages to create
|
---|
| 809 | \param [in] descriptor_l1 L1 descriptor (region attributes)
|
---|
| 810 | \param [in] ttb_l2 L2 table base address
|
---|
| 811 | \param [in] descriptor_l2 L2 descriptor (region attributes)
|
---|
| 812 |
|
---|
| 813 | */
|
---|
| 814 | __STATIC_INLINE void __TTPage_64k(uint32_t *ttb, uint32_t base_address, uint32_t count, uint32_t descriptor_l1, uint32_t *ttb_l2, uint32_t descriptor_l2 )
|
---|
| 815 | {
|
---|
| 816 | uint32_t offset, offset2;
|
---|
| 817 | uint32_t entry, entry2;
|
---|
| 818 | uint32_t i,j;
|
---|
| 819 |
|
---|
| 820 |
|
---|
| 821 | offset = base_address >> 20;
|
---|
| 822 | entry = ((int)ttb_l2 & 0xFFFFFC00) | descriptor_l1;
|
---|
| 823 |
|
---|
| 824 | //4 bytes aligned
|
---|
| 825 | ttb += offset;
|
---|
| 826 | //create l1_entry
|
---|
| 827 | *ttb = entry;
|
---|
| 828 |
|
---|
| 829 | offset2 = (base_address & 0xff000) >> 12;
|
---|
| 830 | ttb_l2 += offset2;
|
---|
| 831 | entry2 = (base_address & 0xFFFF0000) | descriptor_l2;
|
---|
| 832 | for (i = 0; i < count; i++ )
|
---|
| 833 | {
|
---|
| 834 | //create 16 entries
|
---|
| 835 | for (j = 0; j < 16; j++)
|
---|
| 836 | //4 bytes aligned
|
---|
| 837 | *ttb_l2++ = entry2;
|
---|
| 838 | entry2 += OFFSET_64K;
|
---|
| 839 | }
|
---|
| 840 | }
|
---|
| 841 |
|
---|
| 842 | /*@} end of MMU_Functions */
|
---|
| 843 | #endif
|
---|
| 844 |
|
---|
| 845 | #ifdef __cplusplus
|
---|
| 846 | }
|
---|
| 847 | #endif
|
---|