1 /*
2  * Copyright (c) 2006-2021, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2012-01-10     bernard      porting to AM1808
9  * 2019-07-28     zdzn         add smp support
10  */
11 
12 #include "mmu.h"
13 
14 /* dump 2nd level page table */
rt_hw_cpu_dump_page_table_2nd(rt_uint32_t * ptb)15 void rt_hw_cpu_dump_page_table_2nd(rt_uint32_t *ptb)
16 {
17     int i;
18     int fcnt = 0;
19 
20     for (i = 0; i < 256; i++)
21     {
22         rt_uint32_t pte2 = ptb[i];
23         if ((pte2 & 0x3) == 0)
24         {
25             if (fcnt == 0)
26                 rt_kprintf("    ");
27             rt_kprintf("%04x: ", i);
28             fcnt++;
29             if (fcnt == 16)
30             {
31                 rt_kprintf("fault\n");
32                 fcnt = 0;
33             }
34             continue;
35         }
36         if (fcnt != 0)
37         {
38             rt_kprintf("fault\n");
39             fcnt = 0;
40         }
41 
42         rt_kprintf("    %04x: %x: ", i, pte2);
43         if ((pte2 & 0x3) == 0x1)
44         {
45             rt_kprintf("L,ap:%x,xn:%d,texcb:%02x\n",
46                        ((pte2 >> 7) | (pte2 >> 4))& 0xf,
47                        (pte2 >> 15) & 0x1,
48                        ((pte2 >> 10) | (pte2 >> 2)) & 0x1f);
49         }
50         else
51         {
52             rt_kprintf("S,ap:%x,xn:%d,texcb:%02x\n",
53                        ((pte2 >> 7) | (pte2 >> 4))& 0xf, pte2 & 0x1,
54                        ((pte2 >> 4) | (pte2 >> 2)) & 0x1f);
55         }
56     }
57 }
58 
rt_hw_cpu_dump_page_table(rt_uint32_t * ptb)59 void rt_hw_cpu_dump_page_table(rt_uint32_t *ptb)
60 {
61     int i;
62     int fcnt = 0;
63 
64     rt_kprintf("page table@%p\n", ptb);
65     for (i = 0; i < 1024*4; i++)
66     {
67         rt_uint32_t pte1 = ptb[i];
68         if ((pte1 & 0x3) == 0)
69         {
70             rt_kprintf("%03x: ", i);
71             fcnt++;
72             if (fcnt == 16)
73             {
74                 rt_kprintf("fault\n");
75                 fcnt = 0;
76             }
77             continue;
78         }
79         if (fcnt != 0)
80         {
81             rt_kprintf("fault\n");
82             fcnt = 0;
83         }
84 
85         rt_kprintf("%03x: %08x: ", i, pte1);
86         if ((pte1 & 0x3) == 0x3)
87         {
88             rt_kprintf("LPAE\n");
89         }
90         else if ((pte1 & 0x3) == 0x1)
91         {
92             rt_kprintf("pte,ns:%d,domain:%d\n",
93                        (pte1 >> 3) & 0x1, (pte1 >> 5) & 0xf);
94             /*
95              *rt_hw_cpu_dump_page_table_2nd((void*)((pte1 & 0xfffffc000)
96              *                               - 0x80000000 + 0xC0000000));
97              */
98         }
99         else if (pte1 & (1 << 18))
100         {
101             rt_kprintf("super section,ns:%d,ap:%x,xn:%d,texcb:%02x\n",
102                        (pte1 >> 19) & 0x1,
103                        ((pte1 >> 13) | (pte1 >> 10))& 0xf,
104                        (pte1 >> 4) & 0x1,
105                        ((pte1 >> 10) | (pte1 >> 2)) & 0x1f);
106         }
107         else
108         {
109             rt_kprintf("section,ns:%d,ap:%x,"
110                        "xn:%d,texcb:%02x,domain:%d\n",
111                        (pte1 >> 19) & 0x1,
112                        ((pte1 >> 13) | (pte1 >> 10))& 0xf,
113                        (pte1 >> 4) & 0x1,
114                        (((pte1 & (0x7 << 12)) >> 10) |
115                         ((pte1 &        0x0c) >>  2)) & 0x1f,
116                        (pte1 >> 5) & 0xf);
117         }
118     }
119 }
120 
121 /* level1 page table, each entry for 1MB memory. */
122 volatile static unsigned long MMUTable[4*1024] __attribute__((aligned(16*1024)));
rt_hw_mmu_setmtt(rt_uint32_t vaddrStart,rt_uint32_t vaddrEnd,rt_uint32_t paddrStart,rt_uint32_t attr)123 void rt_hw_mmu_setmtt(rt_uint32_t vaddrStart,
124                       rt_uint32_t vaddrEnd,
125                       rt_uint32_t paddrStart,
126                       rt_uint32_t attr)
127 {
128     volatile rt_uint32_t *pTT;
129     volatile int i, nSec;
130     pTT  = (rt_uint32_t *)MMUTable + (vaddrStart >> 20);
131     nSec = (vaddrEnd >> 20) - (vaddrStart >> 20);
132     for (i = 0; i <= nSec; i++)
133     {
134         *pTT = attr | (((paddrStart >> 20) + i) << 20);
135         pTT++;
136     }
137 }
138 
rt_hw_set_domain_register(unsigned long domain_val)139 unsigned long rt_hw_set_domain_register(unsigned long domain_val)
140 {
141     unsigned long old_domain;
142 
143     asm volatile ("mrc p15, 0, %0, c3, c0\n" : "=r" (old_domain));
144     asm volatile ("mcr p15, 0, %0, c3, c0\n" : :"r" (domain_val) : "memory");
145 
146     return old_domain;
147 }
148 
rt_hw_init_mmu_table()149 void rt_hw_init_mmu_table()
150 {
151     /* set page table */
152     /* 4G 1:1 memory */
153     rt_hw_mmu_setmtt(0x00000000, 0x3effffff, 0x00000000, NORMAL_MEM);
154     /* IO memory region */
155     rt_hw_mmu_setmtt(0x3f000000, 0x40010000, 0x3f000000, DEVICE_MEM);
156 }
157 
rt_hw_change_mmu_table(rt_uint32_t vaddrStart,rt_uint32_t size,rt_uint32_t paddrStart,rt_uint32_t attr)158 void rt_hw_change_mmu_table(rt_uint32_t vaddrStart,
159                       rt_uint32_t size,
160                       rt_uint32_t paddrStart, rt_uint32_t attr)
161 {
162     rt_hw_mmu_setmtt(vaddrStart, vaddrStart+size-1, paddrStart, attr);
163 #ifndef RT_USING_SMP
164     rt_cpu_dcache_clean_flush();
165     rt_cpu_icache_flush();
166 #endif
167 }
168 
169 
rt_hw_mmu_init(void)170 void rt_hw_mmu_init(void)
171 {
172     rt_cpu_dcache_clean_flush();
173     rt_cpu_icache_flush();
174     rt_hw_cpu_dcache_disable();
175     rt_hw_cpu_icache_disable();
176     rt_cpu_mmu_disable();
177 
178     /*rt_hw_cpu_dump_page_table(MMUTable);*/
179     rt_hw_set_domain_register(0x55555555);
180 
181     rt_cpu_tlb_set(MMUTable);
182 
183     rt_cpu_mmu_enable();
184 
185     rt_hw_cpu_icache_enable();
186     rt_hw_cpu_dcache_enable();
187 }
188 
189