1 /*
2 * Copyright (c) 2021-2022 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7 #include "riscv/riscv_core.h"
8 #include "hpm_pmp_drv.h"
9 #include "hpm_csr_regs.h"
10
read_pmp_cfg(uint32_t idx)11 uint32_t read_pmp_cfg(uint32_t idx)
12 {
13 uint32_t pmp_cfg = 0;
14 switch (idx) {
15 case 0:
16 pmp_cfg = read_csr(CSR_PMPCFG0);
17 break;
18 case 1:
19 pmp_cfg = read_csr(CSR_PMPCFG1);
20 break;
21 case 2:
22 pmp_cfg = read_csr(CSR_PMPCFG2);
23 break;
24 case 3:
25 pmp_cfg = read_csr(CSR_PMPCFG3);
26 break;
27 default:
28 /* Do nothing */
29 break;
30 }
31 return pmp_cfg;
32 }
33
read_pma_cfg(uint32_t idx)34 uint32_t read_pma_cfg(uint32_t idx)
35 {
36 uint32_t pma_cfg = 0;
37 switch (idx) {
38 case 0:
39 pma_cfg = read_csr(CSR_PMACFG0);
40 break;
41 case 1:
42 pma_cfg = read_csr(CSR_PMACFG1);
43 break;
44 case 2:
45 pma_cfg = read_csr(CSR_PMACFG2);
46 break;
47 case 3:
48 pma_cfg = read_csr(CSR_PMACFG3);
49 break;
50 default:
51 /* Do nothing */
52 break;
53 }
54 return pma_cfg;
55 }
56
write_pmp_cfg(uint32_t value,uint32_t idx)57 void write_pmp_cfg(uint32_t value, uint32_t idx)
58 {
59 switch (idx) {
60 case 0:
61 write_csr(CSR_PMPCFG0, value);
62 break;
63 case 1:
64 write_csr(CSR_PMPCFG1, value);
65 break;
66 case 2:
67 write_csr(CSR_PMPCFG2, value);
68 break;
69 case 3:
70 write_csr(CSR_PMPCFG3, value);
71 break;
72 default:
73 /* Do nothing */
74 break;
75 }
76 }
77
write_pma_cfg(uint32_t value,uint32_t idx)78 void write_pma_cfg(uint32_t value, uint32_t idx)
79 {
80 switch (idx) {
81 case 0:
82 write_csr(CSR_PMACFG0, value);
83 break;
84 case 1:
85 write_csr(CSR_PMACFG1, value);
86 break;
87 case 2:
88 write_csr(CSR_PMACFG2, value);
89 break;
90 case 3:
91 write_csr(CSR_PMACFG3, value);
92 break;
93 default:
94 /* Do nothing */
95 break;
96 }
97 }
98
write_pmp_addr(uint32_t value,uint32_t idx)99 void write_pmp_addr(uint32_t value, uint32_t idx)
100 {
101 switch (idx) {
102 case 0:
103 write_csr(CSR_PMPADDR0, value);
104 break;
105 case 1:
106 write_csr(CSR_PMPADDR1, value);
107 break;
108 case 2:
109 write_csr(CSR_PMPADDR2, value);
110 break;
111 case 3:
112 write_csr(CSR_PMPADDR3, value);
113 break;
114 case 4:
115 write_csr(CSR_PMPADDR4, value);
116 break;
117 case 5:
118 write_csr(CSR_PMPADDR5, value);
119 break;
120 case 6:
121 write_csr(CSR_PMPADDR6, value);
122 break;
123 case 7:
124 write_csr(CSR_PMPADDR7, value);
125 break;
126 case 8:
127 write_csr(CSR_PMPADDR8, value);
128 break;
129 case 9:
130 write_csr(CSR_PMPADDR9, value);
131 break;
132 case 10:
133 write_csr(CSR_PMPADDR10, value);
134 break;
135 case 11:
136 write_csr(CSR_PMPADDR11, value);
137 break;
138 case 12:
139 write_csr(CSR_PMPADDR12, value);
140 break;
141 case 13:
142 write_csr(CSR_PMPADDR13, value);
143 break;
144 case 14:
145 write_csr(CSR_PMPADDR14, value);
146 break;
147 case 15:
148 write_csr(CSR_PMPADDR15, value);
149 break;
150 default:
151 /* Do nothing */
152 break;
153 }
154 }
155
write_pma_addr(uint32_t value,uint32_t idx)156 void write_pma_addr(uint32_t value, uint32_t idx)
157 {
158 switch (idx) {
159 case 0:
160 write_csr(CSR_PMAADDR0, value);
161 break;
162 case 1:
163 write_csr(CSR_PMAADDR1, value);
164 break;
165 case 2:
166 write_csr(CSR_PMAADDR2, value);
167 break;
168 case 3:
169 write_csr(CSR_PMAADDR3, value);
170 break;
171 case 4:
172 write_csr(CSR_PMAADDR4, value);
173 break;
174 case 5:
175 write_csr(CSR_PMAADDR5, value);
176 break;
177 case 6:
178 write_csr(CSR_PMAADDR6, value);
179 break;
180 case 7:
181 write_csr(CSR_PMAADDR7, value);
182 break;
183 case 8:
184 write_csr(CSR_PMAADDR8, value);
185 break;
186 case 9:
187 write_csr(CSR_PMAADDR9, value);
188 break;
189 case 10:
190 write_csr(CSR_PMAADDR10, value);
191 break;
192 case 11:
193 write_csr(CSR_PMAADDR11, value);
194 break;
195 case 12:
196 write_csr(CSR_PMAADDR12, value);
197 break;
198 case 13:
199 write_csr(CSR_PMAADDR13, value);
200 break;
201 case 14:
202 write_csr(CSR_PMAADDR14, value);
203 break;
204 case 15:
205 write_csr(CSR_PMAADDR15, value);
206 break;
207 default:
208 /* Do nothing */
209 break;
210 }
211 }
212
read_pmp_addr(uint32_t idx)213 uint32_t read_pmp_addr(uint32_t idx)
214 {
215 uint32_t ret_val = 0;
216 switch (idx) {
217 case 0:
218 ret_val = read_csr(CSR_PMPADDR0);
219 break;
220 case 1:
221 ret_val = read_csr(CSR_PMPADDR1);
222 break;
223 case 2:
224 ret_val = read_csr(CSR_PMPADDR2);
225 break;
226 case 3:
227 ret_val = read_csr(CSR_PMPADDR3);
228 break;
229 case 4:
230 ret_val = read_csr(CSR_PMPADDR4);
231 break;
232 case 5:
233 ret_val = read_csr(CSR_PMPADDR5);
234 break;
235 case 6:
236 ret_val = read_csr(CSR_PMPADDR6);
237 break;
238 case 7:
239 ret_val = read_csr(CSR_PMPADDR7);
240 break;
241 case 8:
242 ret_val = read_csr(CSR_PMPADDR8);
243 break;
244 case 9:
245 ret_val = read_csr(CSR_PMPADDR9);
246 break;
247 case 10:
248 ret_val = read_csr(CSR_PMPADDR10);
249 break;
250 case 11:
251 ret_val = read_csr(CSR_PMPADDR11);
252 break;
253 case 12:
254 ret_val = read_csr(CSR_PMPADDR12);
255 break;
256 case 13:
257 ret_val = read_csr(CSR_PMPADDR13);
258 break;
259 case 14:
260 ret_val = read_csr(CSR_PMPADDR14);
261 break;
262 case 15:
263 ret_val = read_csr(CSR_PMPADDR15);
264 break;
265 default:
266 /* Do nothing */
267 break;
268 }
269 return ret_val;
270 }
271
read_pma_addr(uint32_t idx)272 uint32_t read_pma_addr(uint32_t idx)
273 {
274 uint32_t ret_val = 0;
275 switch (idx) {
276 case 0:
277 ret_val = read_csr(CSR_PMAADDR0);
278 break;
279 case 1:
280 ret_val = read_csr(CSR_PMAADDR1);
281 break;
282 case 2:
283 ret_val = read_csr(CSR_PMAADDR2);
284 break;
285 case 3:
286 ret_val = read_csr(CSR_PMAADDR3);
287 break;
288 case 4:
289 ret_val = read_csr(CSR_PMAADDR4);
290 break;
291 case 5:
292 ret_val = read_csr(CSR_PMAADDR5);
293 break;
294 case 6:
295 ret_val = read_csr(CSR_PMAADDR6);
296 break;
297 case 7:
298 ret_val = read_csr(CSR_PMAADDR7);
299 break;
300 case 8:
301 ret_val = read_csr(CSR_PMAADDR8);
302 break;
303 case 9:
304 ret_val = read_csr(CSR_PMAADDR9);
305 break;
306 case 10:
307 ret_val = read_csr(CSR_PMAADDR10);
308 break;
309 case 11:
310 ret_val = read_csr(CSR_PMAADDR11);
311 break;
312 case 12:
313 ret_val = read_csr(CSR_PMAADDR12);
314 break;
315 case 13:
316 ret_val = read_csr(CSR_PMAADDR13);
317 break;
318 case 14:
319 ret_val = read_csr(CSR_PMAADDR14);
320 break;
321 case 15:
322 ret_val = read_csr(CSR_PMAADDR15);
323 break;
324 default:
325 /* Do nothing */
326 break;
327 }
328 return ret_val;
329 }
330
pmp_config_entry(const pmp_entry_t * entry,uint32_t entry_index)331 hpm_stat_t pmp_config_entry(const pmp_entry_t *entry, uint32_t entry_index)
332 {
333 hpm_stat_t status = status_invalid_argument;
334 do {
335 HPM_BREAK_IF((entry == NULL) || (entry_index > 15U));
336
337 uint32_t idx = entry_index / 4;
338 uint32_t offset = (entry_index * 8) & 0x1F;
339
340 uint32_t pmp_cfg = read_pmp_cfg(idx);
341 pmp_cfg &= ~(0xFFUL << offset);
342 pmp_cfg |= ((uint32_t) entry->pmp_cfg.val) << offset;
343 uint32_t pma_cfg = read_pma_cfg(idx);
344 pma_cfg &= ~(0xFFUL << offset);
345 pma_cfg |= ((uint32_t) entry->pma_cfg.val) << offset;
346
347 write_pmp_addr(entry->pmp_addr, entry_index);
348 write_pma_addr(entry->pma_addr, entry_index);
349
350 write_pma_cfg(pma_cfg, idx);
351 write_pmp_cfg(pmp_cfg, idx);
352 fencei();
353
354 status = status_success;
355
356 } while (false);
357
358 return status;
359 }
360
pmp_config(const pmp_entry_t * entry,uint32_t num_of_entries)361 hpm_stat_t pmp_config(const pmp_entry_t *entry, uint32_t num_of_entries)
362 {
363 hpm_stat_t status = status_invalid_argument;
364 do {
365 HPM_BREAK_IF((entry == NULL) || (num_of_entries < 1U) || (num_of_entries > 15U));
366
367 for (uint32_t i = 0; i < num_of_entries; i++) {
368 uint32_t idx = i / 4;
369 uint32_t offset = (i * 8) & 0x1F;
370
371 uint32_t pmp_cfg = read_pmp_cfg(idx);
372 pmp_cfg &= ~(0xFFUL << offset);
373 pmp_cfg |= ((uint32_t) entry->pmp_cfg.val) << offset;
374 uint32_t pma_cfg = read_pma_cfg(idx);
375 pma_cfg &= ~(0xFFUL << offset);
376 pma_cfg |= ((uint32_t) entry->pma_cfg.val) << offset;
377
378 write_pmp_addr(entry->pmp_addr, i);
379 write_pma_addr(entry->pma_addr, i);
380
381 write_pma_cfg(pma_cfg, idx);
382 write_pmp_cfg(pmp_cfg, idx);
383
384 ++entry;
385 }
386 fencei();
387
388 status = status_success;
389
390 } while (false);
391
392 return status;
393 }
394
pmp_disable(void)395 void pmp_disable(void)
396 {
397 /* Disable caches */
398 fencei();
399 uint32_t mcache_ctl = read_csr(CSR_MCACHE_CTL);
400 write_csr(CSR_MCACHE_CTL, 0x0);
401 fencei();
402 write_csr(CSR_PMACFG0, 0);
403 write_csr(CSR_PMACFG1, 0);
404 write_csr(CSR_PMACFG2, 0);
405 write_csr(CSR_PMACFG3, 0);
406 write_csr(CSR_PMPCFG0, 0);
407 write_csr(CSR_PMPCFG1, 0);
408 write_csr(CSR_PMPCFG2, 0);
409 write_csr(CSR_PMPCFG3, 0);
410
411 write_csr(CSR_PMAADDR0, 0);
412 write_csr(CSR_PMAADDR1, 0);
413 write_csr(CSR_PMAADDR2, 0);
414 write_csr(CSR_PMAADDR3, 0);
415 write_csr(CSR_PMAADDR4, 0);
416 write_csr(CSR_PMAADDR5, 0);
417 write_csr(CSR_PMAADDR6, 0);
418 write_csr(CSR_PMAADDR7, 0);
419 write_csr(CSR_PMAADDR8, 0);
420 write_csr(CSR_PMAADDR9, 0);
421 write_csr(CSR_PMAADDR10, 0);
422 write_csr(CSR_PMAADDR11, 0);
423 write_csr(CSR_PMAADDR12, 0);
424 write_csr(CSR_PMAADDR13, 0);
425 write_csr(CSR_PMAADDR14, 0);
426 write_csr(CSR_PMAADDR15, 0);
427 fencei();
428 write_csr(CSR_MCACHE_CTL, mcache_ctl);
429 fencei();
430 }
431