1 /*
2  * Copyright (c) 2017-2024, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #ifndef __MPU_ARMV8M_DRV_H__
9 #define __MPU_ARMV8M_DRV_H__
10 
11 #include <stdint.h>
12 
13 #include "tfm_hal_device_header.h"
14 
15 #define PRIVILEGED_DEFAULT_ENABLE 1
16 #define PRIVILEGED_DEFAULT_DISABLE 0
17 #define HARDFAULT_NMI_ENABLE      1
18 
19 /* MAIR_ATTR */
20 #define MPU_ARMV8M_MAIR_ATTR_DEVICE_VAL      0x04
21 #define MPU_ARMV8M_MAIR_ATTR_DEVICE_IDX      0
22 #define MPU_ARMV8M_MAIR_ATTR_CODE_VAL        0xAA
23 #define MPU_ARMV8M_MAIR_ATTR_CODE_IDX        1
24 #define MPU_ARMV8M_MAIR_ATTR_DATA_VAL        0xFF
25 #define MPU_ARMV8M_MAIR_ATTR_DATA_IDX        2
26 #define MPU_ARMV8M_MAIR_ATTR_DATANOCACHE_VAL 0x44
27 #define MPU_ARMV8M_MAIR_ATTR_DATANOCACHE_IDX 3
28 
29 struct mpu_armv8m_dev_t {
30     const uint32_t base;
31 };
32 
33 enum mpu_armv8m_error_t {
34     MPU_ARMV8M_OK,
35     MPU_ARMV8M_ERROR
36 };
37 
38 enum mpu_armv8m_attr_exec_t {
39     MPU_ARMV8M_XN_EXEC_OK,
40     MPU_ARMV8M_XN_EXEC_NEVER
41 };
42 
43 enum mpu_armv8m_attr_access_t {
44     MPU_ARMV8M_AP_RW_PRIV_ONLY,
45     MPU_ARMV8M_AP_RW_PRIV_UNPRIV,
46     MPU_ARMV8M_AP_RO_PRIV_ONLY,
47     MPU_ARMV8M_AP_RO_PRIV_UNPRIV
48 };
49 
50 enum mpu_armv8m_attr_shared_t {
51     MPU_ARMV8M_SH_NONE,
52     MPU_ARMV8M_SH_UNUSED,
53     MPU_ARMV8M_SH_OUTER,
54     MPU_ARMV8M_SH_INNER
55 };
56 
57 struct mpu_armv8m_region_cfg_t {
58     uint32_t region_nr;
59     uint32_t region_base;
60     uint32_t region_limit;
61     uint32_t region_attridx;
62     enum mpu_armv8m_attr_exec_t     attr_exec;
63     enum mpu_armv8m_attr_access_t   attr_access;
64     enum mpu_armv8m_attr_shared_t   attr_sh;
65 #ifdef FLOW_CONTROL
66     uint32_t flow_step_enable;
67     uint32_t flow_ctrl_enable;
68     uint32_t flow_step_check;
69     uint32_t flow_ctrl_check;
70 #endif
71 };
72 
73 struct mpu_armv8m_region_cfg_raw_t {
74     uint32_t region_nr;
75     uint32_t region_base;
76     uint32_t region_limit;
77 };
78 
79 
80 /**
81  * \brief Enable MPU
82  *
83  * \param[in] dev            MPU device \ref mpu_armv8m_dev_t
84  * \param[in] privdef_en     privilege default region 1:enable 0:disable
85  * \param[in] hfnmi_en       mpu for hard fault & nmi  1:enable 0:disable
86  *
87  * \return Error code \ref mpu_armv8m_error_t
88  *
89  * \note This function doesn't check if dev is NULL.
90  */
91 
92 enum mpu_armv8m_error_t mpu_armv8m_enable(struct mpu_armv8m_dev_t *dev,
93                                           uint32_t privdef_en,
94                                           uint32_t hfnmi_en);
95 
96 /**
97  * \brief Check MPU enabled
98  *
99  * \param[in] dev            MPU device \ref mpu_armv8m_dev_t
100  * \param[in] privdef_en     privilege default region 1:enable 0:disable
101  * \param[in] hfnmi_en       mpu for hard fault & nmi  1:enable 0:disable
102  *
103  * \return Error code \ref mpu_armv8m_error_t
104  *
105  * \note This function doesn't check if dev is NULL.
106  */
107 
108 enum mpu_armv8m_error_t mpu_armv8m_check(struct mpu_armv8m_dev_t *dev,
109                                          uint32_t privdef_en,
110                                          uint32_t hfnmi_en);
111 
112 /**
113  * \brief Disable MPU
114  *
115  * \param[in] dev            MPU device \ref mpu_armv8m_dev_t
116  *
117  * \return Error code \ref mpu_armv8m_error_t
118  *
119  * \note This function doesn't check if dev is NULL.
120  */
121 enum mpu_armv8m_error_t mpu_armv8m_disable(struct mpu_armv8m_dev_t *dev);
122 
123 /**
124  * \brief Disable MPU and clean all regions
125  *
126  * \param[in] dev            MPU device \ref mpu_armv8m_dev_t
127  *
128  * \return Error code \ref mpu_armv8m_error_t
129  *
130  * \note This function doesn't check if dev is NULL.
131  */
132 enum mpu_armv8m_error_t mpu_armv8m_clean(struct mpu_armv8m_dev_t *dev);
133 
134 /**
135  * \brief Enable MPU Region
136  *
137  * \param[in] dev            MPU device \ref mpu_armv8m_dev_t
138  * \param[in] region_cfg     MPU region config \ref mpu_armv8m_region_cfg_t
139  *
140  * \return Error code \ref mpu_armv8m_error_t
141  *
142  * \note This function doesn't check if dev is NULL.
143  */
144 enum mpu_armv8m_error_t mpu_armv8m_region_enable(
145                                 struct mpu_armv8m_dev_t *dev,
146                                 struct mpu_armv8m_region_cfg_t *region_cfg);
147 
148 /**
149  * \brief Check enabled MPU Region
150  *
151  * \param[in] dev            MPU device \ref mpu_armv8m_dev_t
152  * \param[in] region_cfg     MPU region config \ref mpu_armv8m_region_cfg_t
153  *
154  * \return Error code \ref mpu_armv8m_error_t
155  *
156  * \note This function doesn't check if dev is NULL.
157  */
158  enum mpu_armv8m_error_t mpu_armv8m_region_enable_check(
159                                 struct mpu_armv8m_dev_t *dev,
160                                 struct mpu_armv8m_region_cfg_t *region_cfg);
161 
162 /**
163  * \brief Disable MPU Region
164  *
165  * \param[in] dev            MPU device \ref mpu_armv8m_dev_t
166  * \param[in] region_nr      Region number
167  *
168  * \return Error code \ref mpu_armv8m_error_t
169  *
170  * \note This function doesn't check if dev is NULL.
171  */
172 enum mpu_armv8m_error_t mpu_armv8m_region_disable(
173                                 struct mpu_armv8m_dev_t *dev,
174                                 uint32_t region_nr);
175 
176 /**
177  * \brief Check disabled MPU Region
178  *
179  * \param[in] dev            MPU device \ref mpu_armv8m_dev_t
180  * \param[in] region_nr      Region number
181  *
182  * \return Error code \ref mpu_armv8m_error_t
183  *
184  * \note This function doesn't check if dev is NULL.
185  */
186 enum mpu_armv8m_error_t mpu_armv8m_region_disable_check(
187                                 struct mpu_armv8m_dev_t *dev,
188                                 uint32_t region_nr);
189 /**
190  * \brief Configure only MPU Region without enabling it
191  *
192  * \param[in] dev            MPU device \ref mpu_armv8m_dev_t
193  * \param[in] region_cfg     MPU region config \ref mpu_armv8m_region_cfg_t
194  *
195  * \return Error code \ref arm_mpu_error_t
196  *
197  * \note This function doesn't check if dev is NULL.
198  */
199 enum mpu_armv8m_error_t mpu_armv8m_region_config_only(
200                                 struct mpu_armv8m_dev_t *dev,
201                                 struct mpu_armv8m_region_cfg_t *region_cfg);
202 
203 /**
204  * \brief Check configured only MPU Region
205  *
206  * \param[in] dev            MPU device \ref mpu_armv8m_dev_t
207  * \param[in] region_cfg     MPU region config \ref mpu_armv8m_region_cfg_t
208  *
209  * \return Error code \ref arm_mpu_error_t
210  *
211  * \note This function doesn't check if dev is NULL.
212  */
213  enum mpu_armv8m_error_t mpu_armv8m_region_config_only_check(
214                                 struct mpu_armv8m_dev_t *dev,
215                                 struct mpu_armv8m_region_cfg_t *region_cfg);
216 #endif /* __MPU_ARMV8M_DRV_H__ */
217