1*10465441SEvalZero /*
2*10465441SEvalZero * Copyright (c) 2006-2018, RT-Thread Development Team
3*10465441SEvalZero *
4*10465441SEvalZero * SPDX-License-Identifier: Apache-2.0
5*10465441SEvalZero *
6*10465441SEvalZero * Change Logs:
7*10465441SEvalZero * Date Author Notes
8*10465441SEvalZero * 2015-04-15 ArdaFu Add code for IAR
9*10465441SEvalZero */
10*10465441SEvalZero
11*10465441SEvalZero #include "mmu.h"
12*10465441SEvalZero
13*10465441SEvalZero /*----- Keil -----------------------------------------------------------------*/
14*10465441SEvalZero #ifdef __CC_ARM
mmu_setttbase(rt_uint32_t i)15*10465441SEvalZero void mmu_setttbase(rt_uint32_t i)
16*10465441SEvalZero {
17*10465441SEvalZero register rt_uint32_t value;
18*10465441SEvalZero
19*10465441SEvalZero /* Invalidates all TLBs.Domain access is selected as
20*10465441SEvalZero * client by configuring domain access register,
21*10465441SEvalZero * in that case access controlled by permission value
22*10465441SEvalZero * set by page table entry
23*10465441SEvalZero */
24*10465441SEvalZero value = 0;
25*10465441SEvalZero __asm volatile{ mcr p15, 0, value, c8, c7, 0 }
26*10465441SEvalZero value = 0x55555555;
27*10465441SEvalZero __asm volatile { mcr p15, 0, value, c3, c0, 0 }
28*10465441SEvalZero __asm volatile { mcr p15, 0, i, c2, c0, 0 }
29*10465441SEvalZero }
30*10465441SEvalZero
mmu_set_domain(rt_uint32_t i)31*10465441SEvalZero void mmu_set_domain(rt_uint32_t i)
32*10465441SEvalZero {
33*10465441SEvalZero __asm volatile { mcr p15, 0, i, c3, c0, 0 }
34*10465441SEvalZero }
35*10465441SEvalZero
mmu_enable()36*10465441SEvalZero void mmu_enable()
37*10465441SEvalZero {
38*10465441SEvalZero register rt_uint32_t value;
39*10465441SEvalZero
40*10465441SEvalZero __asm volatile
41*10465441SEvalZero {
42*10465441SEvalZero mrc p15, 0, value, c1, c0, 0
43*10465441SEvalZero orr value, value, #0x01
44*10465441SEvalZero mcr p15, 0, value, c1, c0, 0
45*10465441SEvalZero }
46*10465441SEvalZero }
47*10465441SEvalZero
mmu_disable()48*10465441SEvalZero void mmu_disable()
49*10465441SEvalZero {
50*10465441SEvalZero register rt_uint32_t value;
51*10465441SEvalZero
52*10465441SEvalZero __asm volatile
53*10465441SEvalZero {
54*10465441SEvalZero mrc p15, 0, value, c1, c0, 0
55*10465441SEvalZero bic value, value, #0x01
56*10465441SEvalZero mcr p15, 0, value, c1, c0, 0
57*10465441SEvalZero }
58*10465441SEvalZero }
59*10465441SEvalZero
mmu_enable_icache()60*10465441SEvalZero void mmu_enable_icache()
61*10465441SEvalZero {
62*10465441SEvalZero register rt_uint32_t value;
63*10465441SEvalZero
64*10465441SEvalZero __asm volatile
65*10465441SEvalZero {
66*10465441SEvalZero mrc p15, 0, value, c1, c0, 0
67*10465441SEvalZero orr value, value, #0x1000
68*10465441SEvalZero mcr p15, 0, value, c1, c0, 0
69*10465441SEvalZero }
70*10465441SEvalZero }
71*10465441SEvalZero
mmu_enable_dcache()72*10465441SEvalZero void mmu_enable_dcache()
73*10465441SEvalZero {
74*10465441SEvalZero register rt_uint32_t value;
75*10465441SEvalZero
76*10465441SEvalZero __asm volatile
77*10465441SEvalZero {
78*10465441SEvalZero mrc p15, 0, value, c1, c0, 0
79*10465441SEvalZero orr value, value, #0x04
80*10465441SEvalZero mcr p15, 0, value, c1, c0, 0
81*10465441SEvalZero }
82*10465441SEvalZero }
83*10465441SEvalZero
mmu_disable_icache()84*10465441SEvalZero void mmu_disable_icache()
85*10465441SEvalZero {
86*10465441SEvalZero register rt_uint32_t value;
87*10465441SEvalZero
88*10465441SEvalZero __asm volatile
89*10465441SEvalZero {
90*10465441SEvalZero mrc p15, 0, value, c1, c0, 0
91*10465441SEvalZero bic value, value, #0x1000
92*10465441SEvalZero mcr p15, 0, value, c1, c0, 0
93*10465441SEvalZero }
94*10465441SEvalZero }
95*10465441SEvalZero
mmu_disable_dcache()96*10465441SEvalZero void mmu_disable_dcache()
97*10465441SEvalZero {
98*10465441SEvalZero register rt_uint32_t value;
99*10465441SEvalZero
100*10465441SEvalZero __asm volatile
101*10465441SEvalZero {
102*10465441SEvalZero mrc p15, 0, value, c1, c0, 0
103*10465441SEvalZero bic value, value, #0x04
104*10465441SEvalZero mcr p15, 0, value, c1, c0, 0
105*10465441SEvalZero }
106*10465441SEvalZero }
107*10465441SEvalZero
mmu_enable_alignfault()108*10465441SEvalZero void mmu_enable_alignfault()
109*10465441SEvalZero {
110*10465441SEvalZero register rt_uint32_t value;
111*10465441SEvalZero
112*10465441SEvalZero __asm volatile
113*10465441SEvalZero {
114*10465441SEvalZero mrc p15, 0, value, c1, c0, 0
115*10465441SEvalZero orr value, value, #0x02
116*10465441SEvalZero mcr p15, 0, value, c1, c0, 0
117*10465441SEvalZero }
118*10465441SEvalZero }
119*10465441SEvalZero
mmu_disable_alignfault()120*10465441SEvalZero void mmu_disable_alignfault()
121*10465441SEvalZero {
122*10465441SEvalZero register rt_uint32_t value;
123*10465441SEvalZero
124*10465441SEvalZero __asm volatile
125*10465441SEvalZero {
126*10465441SEvalZero mrc p15, 0, value, c1, c0, 0
127*10465441SEvalZero bic value, value, #0x02
128*10465441SEvalZero mcr p15, 0, value, c1, c0, 0
129*10465441SEvalZero }
130*10465441SEvalZero }
131*10465441SEvalZero
mmu_clean_invalidated_cache_index(int index)132*10465441SEvalZero void mmu_clean_invalidated_cache_index(int index)
133*10465441SEvalZero {
134*10465441SEvalZero __asm volatile { mcr p15, 0, index, c7, c14, 2 }
135*10465441SEvalZero }
136*10465441SEvalZero
mmu_clean_invalidated_dcache(rt_uint32_t buffer,rt_uint32_t size)137*10465441SEvalZero void mmu_clean_invalidated_dcache(rt_uint32_t buffer, rt_uint32_t size)
138*10465441SEvalZero {
139*10465441SEvalZero unsigned int ptr;
140*10465441SEvalZero
141*10465441SEvalZero ptr = buffer & ~(CACHE_LINE_SIZE - 1);
142*10465441SEvalZero
143*10465441SEvalZero while(ptr < buffer + size)
144*10465441SEvalZero {
145*10465441SEvalZero __asm volatile { MCR p15, 0, ptr, c7, c14, 1 }
146*10465441SEvalZero ptr += CACHE_LINE_SIZE;
147*10465441SEvalZero }
148*10465441SEvalZero }
149*10465441SEvalZero
mmu_clean_dcache(rt_uint32_t buffer,rt_uint32_t size)150*10465441SEvalZero void mmu_clean_dcache(rt_uint32_t buffer, rt_uint32_t size)
151*10465441SEvalZero {
152*10465441SEvalZero unsigned int ptr;
153*10465441SEvalZero
154*10465441SEvalZero ptr = buffer & ~(CACHE_LINE_SIZE - 1);
155*10465441SEvalZero
156*10465441SEvalZero while (ptr < buffer + size)
157*10465441SEvalZero {
158*10465441SEvalZero __asm volatile { MCR p15, 0, ptr, c7, c10, 1 }
159*10465441SEvalZero ptr += CACHE_LINE_SIZE;
160*10465441SEvalZero }
161*10465441SEvalZero }
162*10465441SEvalZero
mmu_invalidate_dcache(rt_uint32_t buffer,rt_uint32_t size)163*10465441SEvalZero void mmu_invalidate_dcache(rt_uint32_t buffer, rt_uint32_t size)
164*10465441SEvalZero {
165*10465441SEvalZero unsigned int ptr;
166*10465441SEvalZero
167*10465441SEvalZero ptr = buffer & ~(CACHE_LINE_SIZE - 1);
168*10465441SEvalZero
169*10465441SEvalZero while (ptr < buffer + size)
170*10465441SEvalZero {
171*10465441SEvalZero __asm volatile { MCR p15, 0, ptr, c7, c6, 1 }
172*10465441SEvalZero ptr += CACHE_LINE_SIZE;
173*10465441SEvalZero }
174*10465441SEvalZero }
175*10465441SEvalZero
mmu_invalidate_tlb()176*10465441SEvalZero void mmu_invalidate_tlb()
177*10465441SEvalZero {
178*10465441SEvalZero register rt_uint32_t value;
179*10465441SEvalZero
180*10465441SEvalZero value = 0;
181*10465441SEvalZero __asm volatile { mcr p15, 0, value, c8, c7, 0 }
182*10465441SEvalZero }
183*10465441SEvalZero
mmu_invalidate_icache()184*10465441SEvalZero void mmu_invalidate_icache()
185*10465441SEvalZero {
186*10465441SEvalZero register rt_uint32_t value;
187*10465441SEvalZero
188*10465441SEvalZero value = 0;
189*10465441SEvalZero
190*10465441SEvalZero __asm volatile { mcr p15, 0, value, c7, c5, 0 }
191*10465441SEvalZero }
192*10465441SEvalZero
193*10465441SEvalZero
mmu_invalidate_dcache_all()194*10465441SEvalZero void mmu_invalidate_dcache_all()
195*10465441SEvalZero {
196*10465441SEvalZero register rt_uint32_t value;
197*10465441SEvalZero
198*10465441SEvalZero value = 0;
199*10465441SEvalZero
200*10465441SEvalZero __asm volatile { mcr p15, 0, value, c7, c6, 0 }
201*10465441SEvalZero }
202*10465441SEvalZero /*----- GNU ------------------------------------------------------------------*/
203*10465441SEvalZero #elif defined(__GNUC__) || defined(__ICCARM__)
mmu_setttbase(register rt_uint32_t i)204*10465441SEvalZero void mmu_setttbase(register rt_uint32_t i)
205*10465441SEvalZero {
206*10465441SEvalZero register rt_uint32_t value;
207*10465441SEvalZero
208*10465441SEvalZero /* Invalidates all TLBs.Domain access is selected as
209*10465441SEvalZero * client by configuring domain access register,
210*10465441SEvalZero * in that case access controlled by permission value
211*10465441SEvalZero * set by page table entry
212*10465441SEvalZero */
213*10465441SEvalZero value = 0;
214*10465441SEvalZero asm volatile ("mcr p15, 0, %0, c8, c7, 0"::"r"(value));
215*10465441SEvalZero
216*10465441SEvalZero value = 0x55555555;
217*10465441SEvalZero asm volatile ("mcr p15, 0, %0, c3, c0, 0"::"r"(value));
218*10465441SEvalZero
219*10465441SEvalZero asm volatile ("mcr p15, 0, %0, c2, c0, 0"::"r"(i));
220*10465441SEvalZero
221*10465441SEvalZero }
222*10465441SEvalZero
mmu_set_domain(register rt_uint32_t i)223*10465441SEvalZero void mmu_set_domain(register rt_uint32_t i)
224*10465441SEvalZero {
225*10465441SEvalZero asm volatile ("mcr p15,0, %0, c3, c0, 0": :"r" (i));
226*10465441SEvalZero }
227*10465441SEvalZero
mmu_enable()228*10465441SEvalZero void mmu_enable()
229*10465441SEvalZero {
230*10465441SEvalZero asm volatile
231*10465441SEvalZero (
232*10465441SEvalZero "mrc p15, 0, r0, c1, c0, 0 \n"
233*10465441SEvalZero "orr r0, r0, #0x1 \n"
234*10465441SEvalZero "mcr p15, 0, r0, c1, c0, 0 \n"
235*10465441SEvalZero :::"r0"
236*10465441SEvalZero );
237*10465441SEvalZero }
238*10465441SEvalZero
mmu_disable()239*10465441SEvalZero void mmu_disable()
240*10465441SEvalZero {
241*10465441SEvalZero asm volatile
242*10465441SEvalZero (
243*10465441SEvalZero "mrc p15, 0, r0, c1, c0, 0 \n"
244*10465441SEvalZero "bic r0, r0, #0x1 \n"
245*10465441SEvalZero "mcr p15, 0, r0, c1, c0, 0 \n"
246*10465441SEvalZero :::"r0"
247*10465441SEvalZero );
248*10465441SEvalZero
249*10465441SEvalZero }
250*10465441SEvalZero
mmu_enable_icache()251*10465441SEvalZero void mmu_enable_icache()
252*10465441SEvalZero {
253*10465441SEvalZero asm volatile
254*10465441SEvalZero (
255*10465441SEvalZero "mrc p15, 0, r0, c1, c0, 0 \n"
256*10465441SEvalZero "orr r0, r0, #(1<<12) \n"
257*10465441SEvalZero "mcr p15, 0, r0, c1, c0, 0 \n"
258*10465441SEvalZero :::"r0"
259*10465441SEvalZero );
260*10465441SEvalZero }
261*10465441SEvalZero
mmu_enable_dcache()262*10465441SEvalZero void mmu_enable_dcache()
263*10465441SEvalZero {
264*10465441SEvalZero asm volatile
265*10465441SEvalZero (
266*10465441SEvalZero "mrc p15, 0, r0, c1, c0, 0 \n"
267*10465441SEvalZero "orr r0, r0, #(1<<2) \n"
268*10465441SEvalZero "mcr p15, 0, r0, c1, c0, 0 \n"
269*10465441SEvalZero :::"r0"
270*10465441SEvalZero );
271*10465441SEvalZero
272*10465441SEvalZero }
273*10465441SEvalZero
mmu_disable_icache()274*10465441SEvalZero void mmu_disable_icache()
275*10465441SEvalZero {
276*10465441SEvalZero asm volatile
277*10465441SEvalZero (
278*10465441SEvalZero "mrc p15, 0, r0, c1, c0, 0 \n"
279*10465441SEvalZero "bic r0, r0, #(1<<12) \n"
280*10465441SEvalZero "mcr p15, 0, r0, c1, c0, 0 \n"
281*10465441SEvalZero :::"r0"
282*10465441SEvalZero );
283*10465441SEvalZero
284*10465441SEvalZero }
285*10465441SEvalZero
mmu_disable_dcache()286*10465441SEvalZero void mmu_disable_dcache()
287*10465441SEvalZero {
288*10465441SEvalZero asm volatile
289*10465441SEvalZero (
290*10465441SEvalZero "mrc p15, 0, r0, c1, c0, 0 \n"
291*10465441SEvalZero "bic r0, r0, #(1<<2) \n"
292*10465441SEvalZero "mcr p15, 0, r0, c1, c0, 0 \n"
293*10465441SEvalZero :::"r0"
294*10465441SEvalZero );
295*10465441SEvalZero
296*10465441SEvalZero }
297*10465441SEvalZero
mmu_enable_alignfault()298*10465441SEvalZero void mmu_enable_alignfault()
299*10465441SEvalZero {
300*10465441SEvalZero asm volatile
301*10465441SEvalZero (
302*10465441SEvalZero "mrc p15, 0, r0, c1, c0, 0 \n"
303*10465441SEvalZero "orr r0, r0, #1 \n"
304*10465441SEvalZero "mcr p15, 0, r0, c1, c0, 0 \n"
305*10465441SEvalZero :::"r0"
306*10465441SEvalZero );
307*10465441SEvalZero
308*10465441SEvalZero }
309*10465441SEvalZero
mmu_disable_alignfault()310*10465441SEvalZero void mmu_disable_alignfault()
311*10465441SEvalZero {
312*10465441SEvalZero asm volatile
313*10465441SEvalZero (
314*10465441SEvalZero "mrc p15, 0, r0, c1, c0, 0 \n"
315*10465441SEvalZero "bic r0, r0, #1 \n"
316*10465441SEvalZero "mcr p15, 0, r0, c1, c0, 0 \n"
317*10465441SEvalZero :::"r0"
318*10465441SEvalZero );
319*10465441SEvalZero
320*10465441SEvalZero }
321*10465441SEvalZero
mmu_clean_invalidated_cache_index(int index)322*10465441SEvalZero void mmu_clean_invalidated_cache_index(int index)
323*10465441SEvalZero {
324*10465441SEvalZero asm volatile ("mcr p15, 0, %0, c7, c14, 2": :"r" (index));
325*10465441SEvalZero }
326*10465441SEvalZero
mmu_clean_invalidated_dcache(rt_uint32_t buffer,rt_uint32_t size)327*10465441SEvalZero void mmu_clean_invalidated_dcache(rt_uint32_t buffer, rt_uint32_t size)
328*10465441SEvalZero {
329*10465441SEvalZero unsigned int ptr;
330*10465441SEvalZero
331*10465441SEvalZero ptr = buffer & ~(CACHE_LINE_SIZE - 1);
332*10465441SEvalZero
333*10465441SEvalZero while(ptr < buffer + size)
334*10465441SEvalZero {
335*10465441SEvalZero asm volatile ("mcr p15, 0, %0, c7, c14, 1": :"r" (ptr));
336*10465441SEvalZero
337*10465441SEvalZero ptr += CACHE_LINE_SIZE;
338*10465441SEvalZero }
339*10465441SEvalZero }
340*10465441SEvalZero
341*10465441SEvalZero
mmu_clean_dcache(rt_uint32_t buffer,rt_uint32_t size)342*10465441SEvalZero void mmu_clean_dcache(rt_uint32_t buffer, rt_uint32_t size)
343*10465441SEvalZero {
344*10465441SEvalZero unsigned int ptr;
345*10465441SEvalZero
346*10465441SEvalZero ptr = buffer & ~(CACHE_LINE_SIZE - 1);
347*10465441SEvalZero
348*10465441SEvalZero while (ptr < buffer + size)
349*10465441SEvalZero {
350*10465441SEvalZero asm volatile ("mcr p15, 0, %0, c7, c10, 1": :"r" (ptr));
351*10465441SEvalZero
352*10465441SEvalZero ptr += CACHE_LINE_SIZE;
353*10465441SEvalZero }
354*10465441SEvalZero }
355*10465441SEvalZero
mmu_invalidate_dcache(rt_uint32_t buffer,rt_uint32_t size)356*10465441SEvalZero void mmu_invalidate_dcache(rt_uint32_t buffer, rt_uint32_t size)
357*10465441SEvalZero {
358*10465441SEvalZero unsigned int ptr;
359*10465441SEvalZero
360*10465441SEvalZero ptr = buffer & ~(CACHE_LINE_SIZE - 1);
361*10465441SEvalZero
362*10465441SEvalZero while (ptr < buffer + size)
363*10465441SEvalZero {
364*10465441SEvalZero asm volatile ("mcr p15, 0, %0, c7, c6, 1": :"r" (ptr));
365*10465441SEvalZero
366*10465441SEvalZero ptr += CACHE_LINE_SIZE;
367*10465441SEvalZero }
368*10465441SEvalZero }
369*10465441SEvalZero
mmu_invalidate_tlb()370*10465441SEvalZero void mmu_invalidate_tlb()
371*10465441SEvalZero {
372*10465441SEvalZero asm volatile ("mcr p15, 0, %0, c8, c7, 0": :"r" (0));
373*10465441SEvalZero
374*10465441SEvalZero }
375*10465441SEvalZero
mmu_invalidate_icache()376*10465441SEvalZero void mmu_invalidate_icache()
377*10465441SEvalZero {
378*10465441SEvalZero asm volatile ("mcr p15, 0, %0, c7, c5, 0": :"r" (0));
379*10465441SEvalZero
380*10465441SEvalZero }
381*10465441SEvalZero
mmu_invalidate_dcache_all()382*10465441SEvalZero void mmu_invalidate_dcache_all()
383*10465441SEvalZero {
384*10465441SEvalZero asm volatile ("mcr p15, 0, %0, c7, c6, 0": :"r" (0));
385*10465441SEvalZero
386*10465441SEvalZero }
387*10465441SEvalZero #endif
388*10465441SEvalZero
389*10465441SEvalZero /* level1 page table */
390*10465441SEvalZero #if defined(__ICCARM__)
391*10465441SEvalZero #pragma data_alignment=(16*1024)
392*10465441SEvalZero static volatile rt_uint32_t _page_table[4*1024];
393*10465441SEvalZero #else
394*10465441SEvalZero static volatile rt_uint32_t _page_table[4*1024] \
395*10465441SEvalZero __attribute__((aligned(16*1024)));
396*10465441SEvalZero #endif
397*10465441SEvalZero
mmu_setmtt(rt_uint32_t vaddrStart,rt_uint32_t vaddrEnd,rt_uint32_t paddrStart,rt_uint32_t attr)398*10465441SEvalZero void mmu_setmtt(rt_uint32_t vaddrStart, rt_uint32_t vaddrEnd,
399*10465441SEvalZero rt_uint32_t paddrStart, rt_uint32_t attr)
400*10465441SEvalZero {
401*10465441SEvalZero volatile rt_uint32_t *pTT;
402*10465441SEvalZero volatile int nSec;
403*10465441SEvalZero int i = 0;
404*10465441SEvalZero pTT=(rt_uint32_t *)_page_table+(vaddrStart>>20);
405*10465441SEvalZero nSec=(vaddrEnd>>20)-(vaddrStart>>20);
406*10465441SEvalZero for(i=0; i<=nSec; i++)
407*10465441SEvalZero {
408*10465441SEvalZero *pTT = attr |(((paddrStart>>20)+i)<<20);
409*10465441SEvalZero pTT++;
410*10465441SEvalZero }
411*10465441SEvalZero }
412*10465441SEvalZero
rt_hw_mmu_init(struct mem_desc * mdesc,rt_uint32_t size)413*10465441SEvalZero void rt_hw_mmu_init(struct mem_desc *mdesc, rt_uint32_t size)
414*10465441SEvalZero {
415*10465441SEvalZero /* disable I/D cache */
416*10465441SEvalZero mmu_disable_dcache();
417*10465441SEvalZero mmu_disable_icache();
418*10465441SEvalZero mmu_disable();
419*10465441SEvalZero mmu_invalidate_tlb();
420*10465441SEvalZero
421*10465441SEvalZero /* set page table */
422*10465441SEvalZero for (; size > 0; size--)
423*10465441SEvalZero {
424*10465441SEvalZero mmu_setmtt(mdesc->vaddr_start, mdesc->vaddr_end,
425*10465441SEvalZero mdesc->paddr_start, mdesc->attr);
426*10465441SEvalZero mdesc++;
427*10465441SEvalZero }
428*10465441SEvalZero
429*10465441SEvalZero /* set MMU table address */
430*10465441SEvalZero mmu_setttbase((rt_uint32_t)_page_table);
431*10465441SEvalZero
432*10465441SEvalZero /* enables MMU */
433*10465441SEvalZero mmu_enable();
434*10465441SEvalZero
435*10465441SEvalZero /* enable Instruction Cache */
436*10465441SEvalZero mmu_enable_icache();
437*10465441SEvalZero
438*10465441SEvalZero /* enable Data Cache */
439*10465441SEvalZero mmu_enable_dcache();
440*10465441SEvalZero
441*10465441SEvalZero mmu_invalidate_icache();
442*10465441SEvalZero mmu_invalidate_dcache_all();
443*10465441SEvalZero }
444