blob: 05f5a934f7a7dbbe8dd5766a5e21c9fdefe53399 [file] [log] [blame]
Miklos Balint386b8b52017-11-29 13:12:32 +00001/*
2 * Copyright (c) 2017, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8#include "mpu_armv8m_drv.h"
9#include "core_cm33.h"
10
11/*
12 * FixMe:
13 * This is a beta quality driver for MPU in v8M. To be finalized and integrated
14 * into platform code
15 */
16
17enum mpu_armv8m_error_t mpu_armv8m_enable(struct mpu_armv8m_dev_t *dev,
18 uint32_t privdef_en,
19 uint32_t hfnmi_en)
20{
21 /*No error checking*/
22
23 MPU_Type *mpu = (MPU_Type *)dev->base;
24
25 mpu->CTRL =
26 (privdef_en ? MPU_CTRL_PRIVDEFENA_Msk : 0) |
27 (hfnmi_en ? MPU_CTRL_HFNMIENA_Msk : 0);
28
29 /*Ensure all configuration is written before enable*/
30
31 mpu->CTRL |= MPU_CTRL_ENABLE_Msk;
32
33 /* Enable MPU before next instruction */
34 __asm("DSB");
35 __asm("ISB");
36 return MPU_ARMV8M_OK;
37}
38
39enum mpu_armv8m_error_t mpu_armv8m_disable(struct mpu_armv8m_dev_t *dev)
40{
41 MPU_Type *mpu = (MPU_Type *)dev->base;
42
43 /* Reset all fields as enable does full setup */
44 mpu->CTRL = 0;
45
46 return MPU_ARMV8M_OK;
47}
48
49
50enum mpu_armv8m_error_t mpu_armv8m_region_enable(
51 struct mpu_armv8m_dev_t *dev,
52 struct mpu_armv8m_region_cfg_t *region_cfg)
53{
54 MPU_Type *mpu = (MPU_Type *)dev->base;
55
56 enum mpu_armv8m_error_t ret_val = MPU_ARMV8M_OK;
57 uint32_t ctrl_before;
58 uint32_t base_cfg;
59 uint32_t limit_cfg;
60
61 /*FIXME : Add complete error checking*/
62 if ((region_cfg->region_base & ~MPU_RBAR_ADDR_Msk) != 0) {
63 return MPU_ARMV8M_ERROR;
64 }
65 /* region_limit doesn't need to be aligned but the scatter
66 * file needs to be setup to ensure that services do not overlap.
67 */
68
69 ctrl_before = mpu->CTRL;
70 mpu->CTRL = 0;
71
72 mpu->RNR = region_cfg->region_nr & MPU_RNR_REGION_Msk;
73
74 /* This 0s the lower bits of the base address */
75 base_cfg = region_cfg->region_base & MPU_RBAR_ADDR_Msk;
76 base_cfg |= (region_cfg->attr_sh << MPU_RBAR_SH_Pos) & MPU_RBAR_SH_Msk;
77 base_cfg |= (region_cfg->attr_access << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk;
78 base_cfg |= (region_cfg->attr_exec << MPU_RBAR_XN_Pos) & MPU_RBAR_XN_Msk;
79
80 mpu->RBAR = base_cfg;
81
82 /*This 0s the lower bits of base address but they are treated as 1 */
83 limit_cfg = (region_cfg->region_limit-1) & MPU_RLAR_LIMIT_Msk;
84
85 /*FIXME: Enable the memory attr setting */
86 limit_cfg |= MPU_RLAR_EN_Msk;
87
88 mpu->RLAR = limit_cfg;
89
90 /*Restore main MPU control*/
91 mpu->CTRL = ctrl_before;
92
93 /* Enable MPU before the next instruction */
94 __asm("DSB");
95 __asm("ISB");
96
97 return ret_val;
98}
99
100
101enum mpu_armv8m_error_t mpu_armv8m_region_disable(
102 struct mpu_armv8m_dev_t *dev,
103 uint32_t region_nr)
104{
105
106 MPU_Type *mpu = (MPU_Type *)dev->base;
107
108 enum mpu_armv8m_error_t ret_val = MPU_ARMV8M_OK;
109 uint32_t ctrl_before;
110
111 /*FIXME : Add complete error checking*/
112
113 ctrl_before = mpu->CTRL;
114 mpu->CTRL = 0;
115
116 mpu->RNR = region_nr & MPU_RNR_REGION_Msk;
117
118 mpu->RBAR = 0;
119 mpu->RLAR = 0;
120
121 /*Restore main MPU control*/
122 mpu->CTRL = ctrl_before;
123
124 return ret_val;
125}
126
127enum mpu_armv8m_error_t mpu_armv8m_clean(struct mpu_armv8m_dev_t *dev)
128{
129 MPU_Type *mpu = (MPU_Type *)dev->base;
130 uint32_t i = (mpu->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos;
131
132 while (i > 0) {
133 mpu_armv8m_region_disable(dev, i-1);
134 i--;
135 }
136
137 return MPU_ARMV8M_OK;
138
139}