1 /*******************************************************************************
2 * Copyright 2019-2021 Microchip FPGA Embedded Systems Solutions.
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 * MPFS HAL Embedded Software
7 *
8 */
9 /*******************************************************************************
10 * @file mss_mpu.c
11 * @author Microchip-FPGA Embedded Systems Solutions
12 * @brief PolarFire SoC MSS MPU driver for configuring access regions for the
13 * external masters.
14 *
15 */
16 /*=========================================================================*//**
17
18 *//*=========================================================================*/
19 #include <stdio.h>
20 #include <string.h>
21 #include "mpfs_hal/mss_hal.h"
22
23 #ifndef SIFIVE_HIFIVE_UNLEASHED
24
25 static uint64_t pmp_get_napot_base_and_range(uint64_t reg, uint64_t *range);
26
27 uint8_t num_pmp_lut[10U] = {16U,16U,8U,4U,8U,8U,4U,4U,8U,2U};
28
29 /**
30 * \brief MPU configuration from Libero for FIC0
31 *
32 */
33 const uint64_t mpu_fic0_values[] = {
34 LIBERO_SETTING_FIC0_MPU_CFG_PMP0,
35 LIBERO_SETTING_FIC0_MPU_CFG_PMP1,
36 LIBERO_SETTING_FIC0_MPU_CFG_PMP2,
37 LIBERO_SETTING_FIC0_MPU_CFG_PMP3,
38 LIBERO_SETTING_FIC0_MPU_CFG_PMP4,
39 LIBERO_SETTING_FIC0_MPU_CFG_PMP5,
40 LIBERO_SETTING_FIC0_MPU_CFG_PMP6,
41 LIBERO_SETTING_FIC0_MPU_CFG_PMP7,
42 LIBERO_SETTING_FIC0_MPU_CFG_PMP8,
43 LIBERO_SETTING_FIC0_MPU_CFG_PMP9,
44 LIBERO_SETTING_FIC0_MPU_CFG_PMP10,
45 LIBERO_SETTING_FIC0_MPU_CFG_PMP11,
46 LIBERO_SETTING_FIC0_MPU_CFG_PMP12,
47 LIBERO_SETTING_FIC0_MPU_CFG_PMP13,
48 LIBERO_SETTING_FIC0_MPU_CFG_PMP14,
49 LIBERO_SETTING_FIC0_MPU_CFG_PMP15
50 };
51
52 /**
53 * \brief MPU configuration from Libero for FIC1
54 *
55 */
56 const uint64_t mpu_fic1_values[] = {
57 LIBERO_SETTING_FIC1_MPU_CFG_PMP0,
58 LIBERO_SETTING_FIC1_MPU_CFG_PMP1,
59 LIBERO_SETTING_FIC1_MPU_CFG_PMP2,
60 LIBERO_SETTING_FIC1_MPU_CFG_PMP3,
61 LIBERO_SETTING_FIC1_MPU_CFG_PMP4,
62 LIBERO_SETTING_FIC1_MPU_CFG_PMP5,
63 LIBERO_SETTING_FIC1_MPU_CFG_PMP6,
64 LIBERO_SETTING_FIC1_MPU_CFG_PMP7,
65 LIBERO_SETTING_FIC1_MPU_CFG_PMP8,
66 LIBERO_SETTING_FIC1_MPU_CFG_PMP9,
67 LIBERO_SETTING_FIC1_MPU_CFG_PMP10,
68 LIBERO_SETTING_FIC1_MPU_CFG_PMP11,
69 LIBERO_SETTING_FIC1_MPU_CFG_PMP12,
70 LIBERO_SETTING_FIC1_MPU_CFG_PMP13,
71 LIBERO_SETTING_FIC1_MPU_CFG_PMP14,
72 LIBERO_SETTING_FIC1_MPU_CFG_PMP15
73 };
74
75 /**
76 * \brief MPU configuration from Libero for FIC2
77 *
78 */
79 const uint64_t mpu_fic2_values[] = {
80 LIBERO_SETTING_FIC2_MPU_CFG_PMP0,
81 LIBERO_SETTING_FIC2_MPU_CFG_PMP1,
82 LIBERO_SETTING_FIC2_MPU_CFG_PMP2,
83 LIBERO_SETTING_FIC2_MPU_CFG_PMP3,
84 LIBERO_SETTING_FIC2_MPU_CFG_PMP4,
85 LIBERO_SETTING_FIC2_MPU_CFG_PMP5,
86 LIBERO_SETTING_FIC2_MPU_CFG_PMP6,
87 LIBERO_SETTING_FIC2_MPU_CFG_PMP7,
88 };
89
90 /**
91 * \brief MPU configuration from Libero for ATHENA
92 *
93 */
94 const uint64_t mpu_crypto_values[] = {
95 LIBERO_SETTING_CRYPTO_MPU_CFG_PMP0,
96 LIBERO_SETTING_CRYPTO_MPU_CFG_PMP1,
97 LIBERO_SETTING_CRYPTO_MPU_CFG_PMP2,
98 LIBERO_SETTING_CRYPTO_MPU_CFG_PMP3,
99 };
100
101 /**
102 * \brief MPU configuration from Libero for GEM0
103 *
104 */
105 const uint64_t mpu_gem0_values[] = {
106 LIBERO_SETTING_GEM0_MPU_CFG_PMP0,
107 LIBERO_SETTING_GEM0_MPU_CFG_PMP1,
108 LIBERO_SETTING_GEM0_MPU_CFG_PMP2,
109 LIBERO_SETTING_GEM0_MPU_CFG_PMP3,
110 LIBERO_SETTING_GEM0_MPU_CFG_PMP4,
111 LIBERO_SETTING_GEM0_MPU_CFG_PMP5,
112 LIBERO_SETTING_GEM0_MPU_CFG_PMP6,
113 LIBERO_SETTING_GEM0_MPU_CFG_PMP7,
114 };
115
116 /**
117 * \brief MPU configuration from Libero for GEM1
118 *
119 */
120 const uint64_t mpu_gem1_values[] = {
121 LIBERO_SETTING_GEM1_MPU_CFG_PMP0,
122 LIBERO_SETTING_GEM1_MPU_CFG_PMP1,
123 LIBERO_SETTING_GEM1_MPU_CFG_PMP2,
124 LIBERO_SETTING_GEM1_MPU_CFG_PMP3,
125 LIBERO_SETTING_GEM1_MPU_CFG_PMP4,
126 LIBERO_SETTING_GEM1_MPU_CFG_PMP5,
127 LIBERO_SETTING_GEM1_MPU_CFG_PMP6,
128 LIBERO_SETTING_GEM1_MPU_CFG_PMP7,
129 };
130
131 /**
132 * \brief MPU configuration from Libero for MMC
133 *
134 */
135 const uint64_t mpu_mmc_values[] = {
136 LIBERO_SETTING_MMC_MPU_CFG_PMP0,
137 LIBERO_SETTING_MMC_MPU_CFG_PMP1,
138 LIBERO_SETTING_MMC_MPU_CFG_PMP2,
139 LIBERO_SETTING_MMC_MPU_CFG_PMP3,
140 };
141
142 /**
143 * \brief MPU configuration from Libero for SCB
144 *
145 */
146 const uint64_t mpu_scb_values[] = {
147 LIBERO_SETTING_SCB_MPU_CFG_PMP0,
148 LIBERO_SETTING_SCB_MPU_CFG_PMP1,
149 LIBERO_SETTING_SCB_MPU_CFG_PMP2,
150 LIBERO_SETTING_SCB_MPU_CFG_PMP3,
151 LIBERO_SETTING_SCB_MPU_CFG_PMP4,
152 LIBERO_SETTING_SCB_MPU_CFG_PMP5,
153 LIBERO_SETTING_SCB_MPU_CFG_PMP6,
154 LIBERO_SETTING_SCB_MPU_CFG_PMP7,
155 };
156
157 /**
158 * \brief MPU configuration from Libero for USB
159 *
160 */
161 const uint64_t mpu_usb_values[] = {
162 LIBERO_SETTING_USB_MPU_CFG_PMP0,
163 LIBERO_SETTING_USB_MPU_CFG_PMP1,
164 LIBERO_SETTING_USB_MPU_CFG_PMP2,
165 LIBERO_SETTING_USB_MPU_CFG_PMP3,
166 };
167
168 /**
169 * \brief MPU configuration from Libero for TRACE
170 *
171 */
172 const uint64_t mpu_trace_values[] = {
173 LIBERO_SETTING_TRACE_MPU_CFG_PMP0,
174 LIBERO_SETTING_TRACE_MPU_CFG_PMP1,
175 };
176
177
178 /***************************************************************************//**
179 * MSS_MPU_auto_configure()
180 * Set MPU's up with configuration from Libero
181 *
182 *
183 * @return
184 */
mpu_configure(void)185 uint8_t mpu_configure(void)
186 {
187 config_64_copy((void *)(&(MSS_MPU(MSS_MPU_FIC0)->PMPCFG)),
188 &(mpu_fic0_values),
189 sizeof(mpu_fic0_values));
190
191 config_64_copy((void *)(&(MSS_MPU(MSS_MPU_FIC1)->PMPCFG)),
192 &(mpu_fic1_values),
193 sizeof(mpu_fic1_values));
194
195 config_64_copy((void *)(&(MSS_MPU(MSS_MPU_FIC2)->PMPCFG)),
196 &(mpu_fic2_values),
197 sizeof(mpu_fic2_values));
198
199 config_64_copy((void *)(&(MSS_MPU(MSS_MPU_CRYPTO)->PMPCFG)),
200 &(mpu_crypto_values),
201 sizeof(mpu_crypto_values));
202
203 config_64_copy((void *)(&(MSS_MPU(MSS_MPU_GEM0)->PMPCFG)),
204 &(mpu_gem0_values),
205 sizeof(mpu_gem0_values));
206
207 config_64_copy((void *)(&(MSS_MPU(MSS_MPU_GEM1)->PMPCFG)),
208 &(mpu_gem1_values),
209 sizeof(mpu_gem1_values));
210
211 config_64_copy((void *)(&(MSS_MPU(MSS_MPU_USB)->PMPCFG)),
212 &(mpu_usb_values),
213 sizeof(mpu_usb_values));
214
215 config_64_copy((void *)(&(MSS_MPU(MSS_MPU_MMC)->PMPCFG)),
216 &(mpu_mmc_values),
217 sizeof(mpu_mmc_values));
218
219 config_64_copy((void *)(&(MSS_MPU(MSS_MPU_SCB)->PMPCFG)),
220 &(mpu_scb_values),
221 sizeof(mpu_scb_values));
222
223 config_64_copy((void *)(&(MSS_MPU(MSS_MPU_TRACE)->PMPCFG)),
224 &(mpu_trace_values),
225 sizeof(mpu_trace_values));
226
227 return(0);
228 }
229
230
231
232
233
234 /***************************************************************************//**
235 */
MSS_MPU_configure(mss_mpu_mport_t master_port,mss_mpu_pmp_region_t pmp_region,uint64_t base,uint64_t size,uint8_t permission,mss_mpu_addrm_t matching_mode,uint8_t lock_en)236 uint8_t MSS_MPU_configure(mss_mpu_mport_t master_port,
237 mss_mpu_pmp_region_t pmp_region,
238 uint64_t base,
239 uint64_t size,
240 uint8_t permission,
241 mss_mpu_addrm_t matching_mode,
242 uint8_t lock_en)
243 {
244 uint64_t temp = size, cnt=0ULL;
245 uint64_t range;
246
247 /*size must be minimum 4k
248 Size must be power of 2
249 different masters have different number of regions*/
250 if((size >= 4096ULL) && (0U == (size & (size - 1U))) && (pmp_region < num_pmp_lut[master_port]))
251 {
252 while((0 == (temp & 0x01U)))
253 {
254 cnt++;
255 temp >>= 1U;
256 }
257
258 range = (1ULL << (cnt-1U))-1U;
259
260 MSS_MPU(master_port)->PMPCFG[pmp_region].raw = (base | range) >> 2U;
261
262 MSS_MPU(master_port)->PMPCFG[pmp_region].MPUCFG_TypeDef.mode = (uint8_t)(permission |
263 (uint8_t)(matching_mode << 3U) |
264 (lock_en << 0x7U));
265
266 return ((uint8_t)0);
267 }
268 else
269 {
270 return ((uint8_t)1);
271 }
272 }
273
MSS_MPU_get_config(mss_mpu_mport_t master_port,mss_mpu_pmp_region_t pmp_region,uint64_t * base,uint64_t * size,uint8_t * permission,mss_mpu_addrm_t * matching_mode,uint8_t * lock_en)274 uint8_t MSS_MPU_get_config(mss_mpu_mport_t master_port,
275 mss_mpu_pmp_region_t pmp_region,
276 uint64_t* base,
277 uint64_t* size,
278 uint8_t* permission,
279 mss_mpu_addrm_t* matching_mode,
280 uint8_t* lock_en)
281 {
282 uint64_t reg;
283
284 /*All AXI external masters dont have same number of PMP regions*/
285 if(pmp_region < num_pmp_lut[master_port])
286 {
287 reg = MSS_MPU(master_port)->PMPCFG[pmp_region].MPUCFG_TypeDef.pmp;
288 *base = pmp_get_napot_base_and_range(reg, size);
289
290 reg = MSS_MPU(master_port)->PMPCFG[pmp_region].MPUCFG_TypeDef.mode;
291 *lock_en = ( reg >> 0x7U) & 0x1U;
292 *matching_mode = (mss_mpu_addrm_t)( (reg >> 3ULL) & 0x3U);
293 *permission = reg & 0x7U;
294
295 return ((uint8_t)0);
296 }
297 else
298 {
299 return ((uint8_t)1);
300 }
301 }
302
pmp_get_napot_base_and_range(uint64_t reg,uint64_t * range)303 static uint64_t pmp_get_napot_base_and_range(uint64_t reg, uint64_t *range)
304 {
305 /* construct a mask of all bits bar the top bit */
306 uint64_t mask = 0U;
307 uint64_t base = reg;
308 uint64_t numbits = (sizeof(uint64_t) * 8U) + 2U;
309 mask = (mask - 1U) >> 1U;
310
311 while (mask)
312 {
313 if ((reg & mask) == mask)
314 {
315 /* this is the mask to use */
316 base = reg & ~mask;
317 break;
318 }
319 mask >>= 1U;
320 numbits--;
321 }
322
323 *range = (1LU << numbits);
324 return (base << 2U);
325 }
326
327 #endif
328