1 /*
2 // Copyright (C) 2022 Beken Corporation
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16
17 #include <stdio.h>
18 #include "platform.h"
19 #include <os/os.h>
20 #include "pmp.h"
21
22
23 #define SYS_DELAY_TIME_10US (170UL)
24
25 /* bk7256 */
26 #define MEM_MAPPING_MAX 0xFFFFFFF0
27 #define ADDR_MAPPING_MAX 0x80000000
28 #define DTCM_END 0x20008000
29 #define SRAM_END 0x38080000
30 #define FLASH_END 0x00400000
31
32 /* PMP entry 0 : 0 ~ (_start), lock, TOR range, excutable, no writable, readable */
33 extern char _start;
34
35 /* PMP entry 1(code/RO data section) : (_start) ~ (_data_lmastart), lock, TOR range, excutable, no writable, readable */
36 extern char _data_lmastart;
37
38 /* PMP entry 2(FLASH) : (_data_lmastart) ~ (FLASH_END), lock, TOR range, no excutable, writable, readable */
39
40 /* PMP entry 3(null section) : (FLASH_END) ~ (_itcm_ema_start), lock, TOR range, no excutable, no writable, no readable */
41 extern char _itcm_ema_start;
42
43 /* PMP entry 4(itcm section) : (_itcm_ema_start) ~ (_dtcm_ema_start), lock, TOR range, excutable, no writable, readable */
44 extern char _dtcm_ema_start;
45
46 /* PMP entry 5(dtcm/sram section) : (_dtcm_ema_start) ~ (SRAM_END), lock, TOR range, no excutable, writable, readable */
47
48 /* PMP entry 6(max address section) : (SRAM_END) ~ (ADDR_MAPPING_MAX), lock, TOR range, no excutable, writable, readable */
49
50
51
52 #if (!CONFIG_SLAVE_CORE)
53 const pmp_config_t pmp_tor_config_table[] = {\
54 {ENTRY_PMPADDR0, PMPCFG_ALXWR(PMP_A_TOR, PMP_L_ON, PMP_X_ON, PMP_W_OFF, PMP_R_ON), (void*)(&_start + 4)}, \
55 {ENTRY_PMPADDR1, PMPCFG_ALXWR(PMP_A_TOR, PMP_L_ON, PMP_X_ON, PMP_W_OFF, PMP_R_ON), (void*)(&_data_lmastart + 4) }, \
56 {ENTRY_PMPADDR2, PMPCFG_ALXWR(PMP_A_TOR, PMP_L_ON, PMP_X_OFF, PMP_W_ON, PMP_R_ON), (void*)(FLASH_END + 4) }, \
57 {ENTRY_PMPADDR3, PMPCFG_ALXWR(PMP_A_TOR, PMP_L_ON, PMP_X_OFF, PMP_W_OFF, PMP_R_OFF), (void*)(&_itcm_ema_start + 4) }, \
58 {ENTRY_PMPADDR4, PMPCFG_ALXWR(PMP_A_TOR, PMP_L_ON, PMP_X_ON, PMP_W_OFF, PMP_R_ON), (void*)(&_dtcm_ema_start + 4) }, \
59 {ENTRY_PMPADDR5, PMPCFG_ALXWR(PMP_A_TOR, PMP_L_ON, PMP_X_OFF, PMP_W_ON, PMP_R_ON), (void*)(SRAM_END +4) }, \
60 {ENTRY_PMPADDR6, PMPCFG_ALXWR(PMP_A_TOR, PMP_L_ON, PMP_X_OFF, PMP_W_ON, PMP_R_ON), (void*)(ADDR_MAPPING_MAX+4) } \
61 };
62 #else
63 const pmp_config_t pmp_tor_config_table[] = {\
64 };
65 #endif //#if (!CONFIG_SLAVE_CORE)
66
67 extern void sys_delay_sync(uint32_t time_count );
68
pmp_tor_config(char entry,void * address,char pmp_cfg)69 void pmp_tor_config(char entry, void* address, char pmp_cfg)
70 {
71 long pmpcfg = pmp_cfg & 0xFF;
72
73 void * va = (void *)((((uint32)(address)+3)/4) * 4);
74
75 os_printf("pmp_tor_config[%d]: addr(0x%08x),TOR(0x%08x) cfg(0x%02x).\n", entry, va, TOR(va), pmpcfg);
76 switch (entry) {
77 case ENTRY_PMPADDR0:
78 write_csr(NDS_PMPADDR0, TOR(va));
79 break;
80 case ENTRY_PMPADDR1:
81 write_csr(NDS_PMPADDR1, TOR(va));
82 break;
83 case ENTRY_PMPADDR2:
84 write_csr(NDS_PMPADDR2, TOR(va));
85 break;
86 case ENTRY_PMPADDR3:
87 write_csr(NDS_PMPADDR3, TOR(va));
88 break;
89 case ENTRY_PMPADDR4:
90 write_csr(NDS_PMPADDR4, TOR(va));
91 break;
92 case ENTRY_PMPADDR5:
93 write_csr(NDS_PMPADDR5, TOR(va));
94 break;
95 case ENTRY_PMPADDR6:
96 write_csr(NDS_PMPADDR6, TOR(va));
97 break;
98 case ENTRY_PMPADDR7:
99 write_csr(NDS_PMPADDR7, TOR(va));
100 break;
101 case ENTRY_PMPADDR8:
102 write_csr(NDS_PMPADDR8, TOR(va));
103 break;
104 case ENTRY_PMPADDR9:
105 write_csr(NDS_PMPADDR9, TOR(va));
106 break;
107 case ENTRY_PMPADDR10:
108 write_csr(NDS_PMPADDR10, TOR(va));
109 break;
110 case ENTRY_PMPADDR11:
111 write_csr(NDS_PMPADDR11, TOR(va));
112 break;
113 case ENTRY_PMPADDR12:
114 write_csr(NDS_PMPADDR12, TOR(va));
115 break;
116 case ENTRY_PMPADDR13:
117 write_csr(NDS_PMPADDR13, TOR(va));
118 break;
119 case ENTRY_PMPADDR14:
120 write_csr(NDS_PMPADDR14, TOR(va));
121 break;
122 case ENTRY_PMPADDR15:
123 write_csr(NDS_PMPADDR15, TOR(va));
124 break;
125 }
126
127 #if __riscv_xlen == 64
128 switch (entry >> 3){
129 case ENTRY_PMPCFG0:
130 write_csr(NDS_PMPCFG0, ((read_csr(NDS_PMPCFG0) & (~(0xFFLL << ((long)(entry%8) << 3)))) | (((long)pmpcfg) << ((long)(entry%8) << 3))));
131 break;
132 case ENTRY_PMPCFG1:
133 write_csr(NDS_PMPCFG2, ((read_csr(NDS_PMPCFG2) & (~(0xFFLL << ((long)(entry%8) << 3)))) | (((long)pmpcfg) << ((long)(entry%8) << 3))));
134 break;
135 }
136 #else
137 switch (entry >> 2) {
138 case ENTRY_PMPCFG0:
139 write_csr(NDS_PMPCFG0, ((read_csr(NDS_PMPCFG0) & (~((0xFF) << ((entry%4) << 3)))) | (((long)pmpcfg) << ((entry%4) << 3))));
140 break;
141 case ENTRY_PMPCFG1:
142 write_csr(NDS_PMPCFG1, ((read_csr(NDS_PMPCFG1) & (~((0xFF) << ((entry%4) << 3)))) | (((long)pmpcfg) << ((entry%4) << 3))));
143 break;
144 case ENTRY_PMPCFG2:
145 write_csr(NDS_PMPCFG2, ((read_csr(NDS_PMPCFG2) & (~((0xFF) << ((entry%4) << 3)))) | (((long)pmpcfg) << ((entry%4) << 3))));
146 break;
147 case ENTRY_PMPCFG3:
148 write_csr(NDS_PMPCFG3, ((read_csr(NDS_PMPCFG3) & (~((0xFF) << ((entry%4) << 3)))) | (((long)pmpcfg) << ((entry%4) << 3))));
149 break;
150 }
151 #endif
152 }
153
pmp_napot_config(char entry,void * va,unsigned long size,char pmpcfg)154 void pmp_napot_config(char entry, void* va, unsigned long size, char pmpcfg)
155 {
156 switch (entry) {
157 case ENTRY_PMPADDR0:
158 write_csr(NDS_PMPADDR0, NAPOT(va, size));
159 break;
160 case ENTRY_PMPADDR1:
161 write_csr(NDS_PMPADDR1, NAPOT(va, size));
162 break;
163 case ENTRY_PMPADDR2:
164 write_csr(NDS_PMPADDR2, NAPOT(va, size));
165 break;
166 case ENTRY_PMPADDR3:
167 write_csr(NDS_PMPADDR3, NAPOT(va, size));
168 break;
169 case ENTRY_PMPADDR4:
170 write_csr(NDS_PMPADDR4, NAPOT(va, size));
171 break;
172 case ENTRY_PMPADDR5:
173 write_csr(NDS_PMPADDR5, NAPOT(va, size));
174 break;
175 case ENTRY_PMPADDR6:
176 write_csr(NDS_PMPADDR6, NAPOT(va, size));
177 break;
178 case ENTRY_PMPADDR7:
179 write_csr(NDS_PMPADDR7, NAPOT(va, size));
180 break;
181 case ENTRY_PMPADDR8:
182 write_csr(NDS_PMPADDR8, NAPOT(va, size));
183 break;
184 case ENTRY_PMPADDR9:
185 write_csr(NDS_PMPADDR9, NAPOT(va, size));
186 break;
187 case ENTRY_PMPADDR10:
188 write_csr(NDS_PMPADDR10, NAPOT(va, size));
189 break;
190 case ENTRY_PMPADDR11:
191 write_csr(NDS_PMPADDR11, NAPOT(va, size));
192 break;
193 case ENTRY_PMPADDR12:
194 write_csr(NDS_PMPADDR12, NAPOT(va, size));
195 break;
196 case ENTRY_PMPADDR13:
197 write_csr(NDS_PMPADDR13, NAPOT(va, size));
198 break;
199 case ENTRY_PMPADDR14:
200 write_csr(NDS_PMPADDR14, NAPOT(va, size));
201 break;
202 case ENTRY_PMPADDR15:
203 write_csr(NDS_PMPADDR15, NAPOT(va, size));
204 break;
205 }
206
207 #if __riscv_xlen == 64
208 switch (entry >> 3){
209 case ENTRY_PMPCFG0:
210 write_csr(NDS_PMPCFG0, ((read_csr(NDS_PMPCFG0) & (~(0xFFLL << ((long)(entry%8) << 3)))) | (((long)pmpcfg) << ((long)(entry%8) << 3))));
211 break;
212 case ENTRY_PMPCFG1:
213 write_csr(NDS_PMPCFG2, ((read_csr(NDS_PMPCFG2) & (~(0xFFLL << ((long)(entry%8) << 3)))) | (((long)pmpcfg) << ((long)(entry%8) << 3))));
214 break;
215 }
216 #else
217 switch (entry >> 2) {
218 case ENTRY_PMPCFG0:
219 write_csr(NDS_PMPCFG0, ((read_csr(NDS_PMPCFG0) & (~((0xFF) << ((entry%4) << 3)))) | (((long)pmpcfg) << ((entry%4) << 3))));
220 break;
221 case ENTRY_PMPCFG1:
222 write_csr(NDS_PMPCFG1, ((read_csr(NDS_PMPCFG1) & (~((0xFF) << ((entry%4) << 3)))) | (((long)pmpcfg) << ((entry%4) << 3))));
223 break;
224 case ENTRY_PMPCFG2:
225 write_csr(NDS_PMPCFG2, ((read_csr(NDS_PMPCFG2) & (~((0xFF) << ((entry%4) << 3)))) | (((long)pmpcfg) << ((entry%4) << 3))));
226 break;
227 case ENTRY_PMPCFG3:
228 write_csr(NDS_PMPCFG3, ((read_csr(NDS_PMPCFG3) & (~((0xFF) << ((entry%4) << 3)))) | (((long)pmpcfg) << ((entry%4) << 3))));
229 break;
230 }
231 #endif
232 }
233
234
init_pmp_config()235 void init_pmp_config()
236 {
237 int i = 0;
238 int config_count = 0;
239 /*
240 * Check whether the CPU configured with PMP feature.
241 * Write 0x3 to the pmpcfg0 register, and read it back
242 * to check the number of PMP entries.
243 */
244 write_csr(NDS_PMPCFG0, 0x3);
245 if (!read_csr(NDS_PMPCFG0)) {
246 os_printf("PMP entries is 0, CPU does NOT support PMP.\n");
247 while(1);
248 }
249
250 /* Disable global interrupt but allow exception */
251 clear_csr(NDS_MSTATUS, MSTATUS_MIE);
252
253 #if USE_NAPOT
254
255 os_printf("PMP uses NAPOT scheme!.\n");
256
257 #else /* USE_TOR */
258
259 os_printf("PMP uses TOR scheme!.\n");
260 config_count = sizeof(pmp_tor_config_table)/sizeof(pmp_config_t);
261
262 os_printf("PMP config count(%d).\n", config_count);
263 for (i = 0; i < config_count; i++)
264 {
265 pmp_tor_config(pmp_tor_config_table[i].pmp_entry,
266 pmp_tor_config_table[i].pmp_addr,
267 pmp_tor_config_table[i].pmp_config);
268
269 sys_delay_sync(SYS_DELAY_TIME_10US);
270 }
271
272 #endif
273 }
274
show_pmp_config()275 void show_pmp_config()
276 {
277 os_printf("==========PMP config info===============\r\n");
278
279 int i = 0;
280 int config_count = 0;
281 long pmp_config0 = read_csr(NDS_PMPCFG0);
282 if (!pmp_config0) {
283 os_printf("PMP entries is 0, CPU does NOT support PMP.\n");
284 }
285
286 #if USE_NAPOT
287
288 os_printf("PMP uses NAPOT scheme!.\n");
289
290 #else /* USE_TOR */
291
292 os_printf("PMP uses TOR scheme!.\n");
293 config_count = sizeof(pmp_tor_config_table)/sizeof(pmp_config_t);
294
295 os_printf("PMP user config count(%d).\n", config_count);
296 for (i = 0; i < config_count; i++)
297 {
298 os_printf("PMP config[%d], 0x%08x, 0x%0x.\r\n", i,
299 (void *)pmp_tor_config_table[i].pmp_addr,
300 pmp_tor_config_table[i].pmp_config);
301
302 }
303
304 #endif
305 os_printf("==========PMP actural config:\r\n");
306 os_printf("==========NDS_PMPCFG0: 0x%08x.\r\n", pmp_config0);
307 os_printf("==========NDS_PMPCFG1: 0x%08x.\r\n", read_csr(NDS_PMPCFG1));
308
309 os_printf("==========NDS_PMPADDR0: 0x%08x.\r\n", read_csr(NDS_PMPADDR0));
310 os_printf("==========NDS_PMPADDR1: 0x%08x.\r\n", read_csr(NDS_PMPADDR1));
311 os_printf("==========NDS_PMPADDR2: 0x%08x.\r\n", read_csr(NDS_PMPADDR2));
312 os_printf("==========NDS_PMPADDR3: 0x%08x.\r\n", read_csr(NDS_PMPADDR3));
313 os_printf("==========NDS_PMPADDR4: 0x%08x.\r\n", read_csr(NDS_PMPADDR4));
314 os_printf("==========NDS_PMPADDR5: 0x%08x.\r\n", read_csr(NDS_PMPADDR5));
315 os_printf("==========NDS_PMPADDR6: 0x%08x.\r\n", read_csr(NDS_PMPADDR6));
316 os_printf("==========NDS_PMPADDR7: 0x%08x.\r\n", read_csr(NDS_PMPADDR7));
317
318 }
319