1 /*
2 * Copyright (C) 2017-2024 Alibaba Group Holding Limited
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 #include <soc.h>
20 #include <csi_core.h>
21 #include <drv/tick.h>
22 #include <drv/porting.h>
23 #include <drv/irq.h>
24 #include "riscv_csr.h"
25
26 #if (defined(CONFIG_KERNEL_RHINO) || defined(CONFIG_KERNEL_FREERTOS) || defined(CONFIG_KERNEL_RTTHREAD)) && defined(CONFIG_KERNEL_NONE)
27 #error "Please check the current system is baremetal or not!!!"
28 #endif
29
30 #if !defined(CONFIG_SMP) || (defined(CONFIG_SMP) && !CONFIG_SMP)
31 #if CONFIG_NR_CPUS > 1
32 #error "Please define CONFIG_NR_CPUS as 1 or do not need define."
33 #endif
34 #endif
35
36 #if CONFIG_ECC_L2_ENABLE
37 static csi_dev_t ecc_l2_dev;
38 #endif
39
40 extern void section_data_copy(void);
41 extern void section_ram_code_copy(void);
42 extern void section_bss_clear(void);
43
44 #ifdef CONFIG_RISCV_SMODE
45 extern unsigned long __Vectors;
46 unsigned long page_table_l2[512] __attribute__ ((aligned(4096)));
47 unsigned long page_table_l1[512] __attribute__ ((aligned(4096)));
48 unsigned long page_table_l0[512] __attribute__ ((aligned(4096)));
49
50 void _mmu_init(void) __attribute__((noinline));
_mmu_init(void)51 void _mmu_init(void)
52 {
53 #if CONFIG_CPU_XUANTIE_C906 || CONFIG_CPU_XUANTIE_C906FD || CONFIG_CPU_XUANTIE_C906FDV \
54 || CONFIG_CPU_XUANTIE_C908 || CONFIG_CPU_XUANTIE_C908V || CONFIG_CPU_XUANTIE_C908I \
55 || CONFIG_CPU_XUANTIE_R910 || CONFIG_CPU_XUANTIE_R920
56 unsigned long status = __get_MXSTATUS();
57 /* open MAEE for thead-mmu extension */
58 status |= (1 << 21);
59 __set_MXSTATUS(status);
60
61 page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10;
62 page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10;
63 /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */
64 for (unsigned long i = 0; i < 256; i++) {
65 page_table_l0[i] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | i << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1;
66 }
67
68 /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */
69 for (unsigned long i = 1; i < 512; i++) {
70 page_table_l1[i] = (UPPER_ATTRS(ATTR_SO | ATTR_SH) | i << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1;
71 }
72
73 /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */
74 page_table_l2[1] = (UPPER_ATTRS(ATTR_CA | ATTR_SH) | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1;
75 #elif CONFIG_CPU_XUANTIE_C907_RV32 || CONFIG_CPU_XUANTIE_C907FD_RV32 || CONFIG_CPU_XUANTIE_C907FDV_RV32 || CONFIG_CPU_XUANTIE_C907FDVM_RV32
76 unsigned long envcfgh = __get_MENVCFGH();
77 /* enable svpbmt */
78 envcfgh |= (1 << 30);
79 __set_MENVCFGH(envcfgh);
80
81 page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10;
82 /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */
83 for (unsigned long i = 0; i < 256; i++) {
84 page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1;
85 }
86
87 /* setup mmu VA(4M ~ 1G-1) <==> PA(4M ~ 1G-1) */
88 for (unsigned long i = 1; i < 256; i++) {
89 page_table_l1[i] = (SVPBMT_IO | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1;
90 }
91
92 /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */
93 for (unsigned long i = 256; i < 512; i++) {
94 page_table_l1[i] = (SVPBMT_PMA | (i) << 20 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1;
95 }
96 #else
97 unsigned long envcfg = __get_MENVCFG();
98 /* enable svpbmt */
99 envcfg |= (1ull << 62);
100 __set_MENVCFG(envcfg);
101
102 page_table_l2[0] = 0x1 | ((unsigned long)page_table_l1 >> 12) << 10;
103 page_table_l1[0] = 0x1 | ((unsigned long)page_table_l0 >> 12) << 10;
104 /* setup mmu VA(0M ~ 1M-1) <==> PA(0M ~ 1M-1) */
105 for (unsigned long i = 0; i < 256; i++) {
106 page_table_l0[i] = (SVPBMT_PMA | (i) << 10 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1;
107 }
108
109 /* setup mmu VA(2M ~ 1G-1) <==> PA(2M ~ 1G-1) */
110 for (unsigned long i = 1; i < 512; i++) {
111 page_table_l1[i] = (SVPBMT_IO | (i) << 19 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1;
112 }
113
114 /* setup mmu VA(1G ~ 2G-1) <==> PA(1G ~ 2G-1) */
115 page_table_l2[1] = (SVPBMT_PMA | (1) << 28 | LOWER_ATTRS(DIRTY_FLAG | ACCESS_FLAG | AP_X | AP_W | AP_R | GLOBAL_FLAG)) | 0x1;
116 #endif
117
118 #if __riscv_xlen == 64
119 csi_dcache_clean_range((unsigned long *)&page_table_l2, sizeof(page_table_l2));
120 #endif
121 csi_dcache_clean_range((unsigned long *)&page_table_l1, sizeof(page_table_l1));
122 csi_dcache_clean_range((unsigned long *)&page_table_l0, sizeof(page_table_l0));
123 csi_mmu_invalid_tlb_all();
124 #if __riscv_xlen == 64
125 __set_SATP(((unsigned long)&page_table_l2 >> 12));
126 csi_mmu_set_mode(MMU_MODE_39);
127 csi_mmu_enable();
128 #else
129 __set_SATP(((unsigned long)&page_table_l1 >> 12));
130 csi_mmu_set_mode(MMU_MODE_32);
131 csi_mmu_enable();
132 #endif
133 }
134
_system_switchto_smode(void)135 void _system_switchto_smode(void)
136 {
137 unsigned long m_status = __get_MSTATUS();
138 m_status &= ~MSTATUS_TVM_MASK;
139 m_status &= ~MSTATUS_MPP_MASK;
140 m_status |= MSTATUS_MPP_S;
141 __set_MSTATUS(m_status);
142
143 /* setup S-Mode csr regs */
144 __set_STVEC((unsigned long)(&__Vectors) | 0x1);
145 //FIXME:
146 __ASM("auipc a0, 0");
147 __ASM("addi a0, a0, 14");
148 __ASM("csrw mepc, a0");
149 __ASM("mret");
150 }
151
_system_init_for_smode(void)152 void _system_init_for_smode(void)
153 {
154 _system_switchto_smode();
155 }
156
smode_init(void)157 void smode_init(void)
158 {
159 /* may be not clear after reset on FPGA */
160 csi_mmu_disable();
161 _mmu_init();
162 _system_init_for_smode();
163 }
164 #endif
165
166 /**
167 * @brief initialize pmp
168 * @param None
169 * @return None
170 */
pmp_init(void)171 static void pmp_init(void)
172 {
173 long addr;
174
175 addr = 0x90000000UL >> 2;
176 __set_PMPADDR0(addr);
177 __set_PMPxCFG(0, 0x8f);
178 }
179
interrupt_init(void)180 static void interrupt_init(void)
181 {
182 int i;
183
184 for (i = 0; i < CONFIG_IRQ_NUM; i++) {
185 PLIC->PLIC_PRIO[i] = 31;
186 }
187
188 for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) {
189 PLIC->PLIC_IP[i] = 0;
190 }
191
192 for (i = 0; i < (CONFIG_IRQ_NUM + 32) / 32; i++) {
193 PLIC->PLIC_H0_MIE[i] = 0;
194 PLIC->PLIC_H0_SIE[i] = 0;
195 }
196
197 /* set hart threshold 0, enable all interrupt */
198 PLIC->PLIC_H0_MTH = 0;
199 PLIC->PLIC_H0_STH = 0;
200
201 for (i = 0; i < CONFIG_IRQ_NUM; i++) {
202 PLIC->PLIC_H0_MCLAIM = i;
203 PLIC->PLIC_H0_SCLAIM = i;
204 }
205
206 /* set PLIC_PER */
207 PLIC->PLIC_PER = 0x1;
208
209 /* enable MEIE & MTIE & MSIE */
210 uint32_t mie = __get_MIE();
211 mie |= (1 << 11 | 1 << 7 | 1 << 3);
212 #if CONFIG_ECC_L1_ENABLE
213 mie |= (1 << 16);
214 #endif
215 __set_MIE(mie);
216 }
217
section_init(void)218 static void section_init(void)
219 {
220 #if CONFIG_XIP
221 section_data_copy();
222 section_ram_code_copy();
223 csi_dcache_clean();
224 csi_icache_invalid();
225 #endif
226
227 section_bss_clear();
228 }
229
cache_init(void)230 static void cache_init(void)
231 {
232 /* enable cache */
233 csi_dcache_enable();
234 csi_icache_enable();
235 }
236
237 /**
238 * @brief initialize the system
239 * Initialize the psr and vbr.
240 * @param None
241 * @return None
242 */
SystemInit(void)243 void SystemInit(void)
244 {
245 #if CONFIG_CPU_XUANTIE_C910V3_CP || CONFIG_CPU_XUANTIE_C920V3_CP
246 /* disable theadisaee & enable MM */
247 unsigned long status = __get_MXSTATUS();
248 status &= ~(1 << 22);
249 status |= (1 << 24 | 1 << 15);
250 __set_MXSTATUS(status);
251 #else
252 /* enable theadisaee & MM */
253 unsigned long status = __get_MXSTATUS();
254 status |= (1 << 22 | 1 << 15);
255 __set_MXSTATUS(status);
256 #endif
257
258 #if __riscv_flen == 64
259 /* enable float ISA */
260 status = __get_MSTATUS();
261 status |= (1 << MSTATUS_FS_SHIFT);
262 __set_MSTATUS(status);
263 #endif
264 #ifdef __riscv_vector
265 /* enable vector ISA */
266 status = __get_MSTATUS();
267 status |= (1 << MSTATUS_VS_SHIFT);
268 __set_MSTATUS(status);
269 #endif
270
271 #if CONFIG_ECC_L1_ENABLE
272 /* enable L1 cache ecc */
273 uint64_t mhint = __get_MHINT();
274 mhint |= (0x1 << 19);
275 __set_MHINT(mhint);
276 #endif
277
278 #if CONFIG_ECC_L2_ENABLE
279 /* enable L2 cache ecc */
280 uint64_t mccr2 = __get_MCCR2();
281 mccr2 |= (0x1 << 1);
282 __set_MCCR2(mccr2);
283 #endif
284
285 #ifdef CONFIG_RISCV_SMODE
286 /* enable ecall delegate */
287 unsigned long medeleg = __get_MEDELEG();
288 medeleg |= (1 << 9);
289 __set_MEDELEG(medeleg);
290
291 /* enable interrupt delegate */
292 unsigned long mideleg = __get_MIDELEG();
293 mideleg |= 0x222;
294 __set_MIDELEG(mideleg);
295 #endif
296
297 #ifdef CONFIG_RISCV_SMODE
298 /* enable mcounteren for s-mode */
299 __set_MCOUNTEREN(0xffffffff);
300
301 #if CBO_INSN_SUPPORT
302 unsigned long envcfg = __get_MENVCFG();
303 /* enable CBIE & CBCFE & CBZE on lower priviledge */
304 envcfg |= (3 << 4 | 1 << 6 | 1 << 7);
305 __set_MENVCFG(envcfg);
306 #endif
307 #endif
308
309 cache_init();
310 section_init();
311 pmp_init();
312
313 interrupt_init();
314 soc_set_sys_freq(20000000);
315 csi_tick_init();
316
317 #if CONFIG_ECC_L2_ENABLE
318 extern void ecc_l2_irqhandler(void *arg);
319 /* l2 cache ecc interrupt register */
320 ecc_l2_dev.irq_num = L2_CACHE_ECC_IRQn;
321 csi_irq_attach(ecc_l2_dev.irq_num, ecc_l2_irqhandler, &ecc_l2_dev);
322 csi_irq_enable(ecc_l2_dev.irq_num);
323 #endif
324 }
325