• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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