1 /*
2  * Copyright (c) 2017-2023, 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 #include "fih.h"
13 
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17 
18 #define PRIVILEGED_DEFAULT_ENABLE 1
19 #define HARDFAULT_NMI_ENABLE      1
20 
21 /* MAIR_ATTR */
22 #define MPU_ARMV8M_MAIR_ATTR_DEVICE_VAL      0x04
23 #define MPU_ARMV8M_MAIR_ATTR_DEVICE_IDX      0
24 #define MPU_ARMV8M_MAIR_ATTR_CODE_VAL        0xAA
25 #define MPU_ARMV8M_MAIR_ATTR_CODE_IDX        1
26 #define MPU_ARMV8M_MAIR_ATTR_DATA_VAL        0xFF
27 #define MPU_ARMV8M_MAIR_ATTR_DATA_IDX        2
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 #ifdef TFM_PXN_ENABLE
58 enum mpu_armv8m_attr_priv_exec_t {
59     MPU_ARMV8M_PRIV_EXEC_OK,
60     MPU_ARMV8M_PRIV_EXEC_NEVER
61 };
62 #endif
63 
64 struct mpu_armv8m_region_cfg_t {
65     uint32_t region_nr;
66     uint32_t region_base;
67     uint32_t region_limit;
68     uint32_t region_attridx;
69     enum mpu_armv8m_attr_exec_t      attr_exec;
70     enum mpu_armv8m_attr_access_t    attr_access;
71     enum mpu_armv8m_attr_shared_t    attr_sh;
72 #ifdef TFM_PXN_ENABLE
73     enum mpu_armv8m_attr_priv_exec_t attr_pxn;
74 #endif
75 };
76 
77 struct mpu_armv8m_region_cfg_raw_t {
78     uint32_t region_nr;
79     uint32_t region_base;
80     uint32_t region_limit;
81 };
82 
83 
84 /**
85  * \brief Enable MPU
86  *
87  * \param[in] dev            MPU device \ref mpu_armv8m_dev_t
88  * \param[in] privdef_en     privilege default region 1:enable 0:disable
89  * \param[in] hfnmi_en       mpu for hard fault & nmi  1:enable 0:disable
90  *
91  * \return Error code \ref mpu_armv8m_error_t
92  *
93  * \note This function doesn't check if dev is NULL.
94  */
95 FIH_RET_TYPE(enum mpu_armv8m_error_t) mpu_armv8m_enable(
96                                           struct mpu_armv8m_dev_t *dev,
97                                           uint32_t privdef_en,
98                                           uint32_t hfnmi_en);
99 
100 /**
101  * \brief Disable MPU
102  *
103  * \param[in] dev            MPU device \ref mpu_armv8m_dev_t
104  *
105  * \return Error code \ref mpu_armv8m_error_t
106  *
107  * \note This function doesn't check if dev is NULL.
108  */
109 enum mpu_armv8m_error_t mpu_armv8m_disable(struct mpu_armv8m_dev_t *dev);
110 
111 /**
112  * \brief Disable MPU and clean all regions
113  *
114  * \param[in] dev            MPU device \ref mpu_armv8m_dev_t
115  *
116  * \return Error code \ref mpu_armv8m_error_t
117  *
118  * \note This function doesn't check if dev is NULL.
119  */
120 enum mpu_armv8m_error_t mpu_armv8m_clean(struct mpu_armv8m_dev_t *dev);
121 
122 /**
123  * \brief Enable MPU Region
124  *
125  * \param[in] dev            MPU device \ref mpu_armv8m_dev_t
126  * \param[in] region_cfg     MPU region config \ref mpu_armv8m_region_cfg_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 FIH_RET_TYPE(enum mpu_armv8m_error_t) mpu_armv8m_region_enable(
133                                 struct mpu_armv8m_dev_t *dev,
134                                 struct mpu_armv8m_region_cfg_t *region_cfg);
135 
136 /**
137  * \brief Disable MPU Region
138  *
139  * \param[in] dev            MPU device \ref mpu_armv8m_dev_t
140  * \param[in] region_nr            Region number
141  *
142  * \return Error code \ref mpu_armv8m_error_t
143  *
144  * \note This function doesn't check if dev is NULL.
145  */
146 FIH_RET_TYPE(enum mpu_armv8m_error_t) mpu_armv8m_region_disable(
147                                                   struct mpu_armv8m_dev_t *dev,
148                                                   uint32_t region_nr);
149 
150 #ifdef __cplusplus
151 }
152 #endif
153 
154 #endif /* __MPU_ARMV8M_DRV_H__ */
155