xref: /nrf52832-nimble/rt-thread/libcpu/arm/zynq7000/mmu.c (revision 104654410c56c573564690304ae786df310c91fc)
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  * 2013-07-20     Bernard      first version
9*10465441SEvalZero  */
10*10465441SEvalZero 
11*10465441SEvalZero #include <rtthread.h>
12*10465441SEvalZero #include <rthw.h>
13*10465441SEvalZero #include <board.h>
14*10465441SEvalZero 
15*10465441SEvalZero #include "cp15.h"
16*10465441SEvalZero 
17*10465441SEvalZero #define DESC_SEC       (0x2)
18*10465441SEvalZero #define CB             (3<<2)  //cache_on, write_back
19*10465441SEvalZero #define CNB            (2<<2)  //cache_on, write_through
20*10465441SEvalZero #define NCB            (1<<2)  //cache_off,WR_BUF on
21*10465441SEvalZero #define NCNB           (0<<2)  //cache_off,WR_BUF off
22*10465441SEvalZero #define AP_RW          (3<<10) //supervisor=RW, user=RW
23*10465441SEvalZero #define AP_RO          (2<<10) //supervisor=RW, user=RO
24*10465441SEvalZero #define XN             (1<<4)  //eXecute Never
25*10465441SEvalZero 
26*10465441SEvalZero #define DOMAIN_FAULT   (0x0)
27*10465441SEvalZero #define DOMAIN_CHK     (0x1)
28*10465441SEvalZero #define DOMAIN_NOTCHK  (0x3)
29*10465441SEvalZero #define DOMAIN0        (0x0<<5)
30*10465441SEvalZero #define DOMAIN1        (0x1<<5)
31*10465441SEvalZero 
32*10465441SEvalZero #define DOMAIN0_ATTR   (DOMAIN_CHK<<0)
33*10465441SEvalZero #define DOMAIN1_ATTR   (DOMAIN_FAULT<<2)
34*10465441SEvalZero 
35*10465441SEvalZero /* Read/Write, cache, write back */
36*10465441SEvalZero #define RW_CB          (AP_RW|DOMAIN0|CB|DESC_SEC)
37*10465441SEvalZero /* Read/Write, cache, write through */
38*10465441SEvalZero #define RW_CNB         (AP_RW|DOMAIN0|CNB|DESC_SEC)
39*10465441SEvalZero /* Read/Write, device type */
40*10465441SEvalZero #define RW_NCB         (AP_RW|DOMAIN0|NCB|DESC_SEC)
41*10465441SEvalZero /* Read/Write strongly ordered type */
42*10465441SEvalZero #define RW_NCNB        (AP_RW|DOMAIN0|NCNB|DESC_SEC)
43*10465441SEvalZero /* Read/Write without cache and write buffer, no execute */
44*10465441SEvalZero #define RW_NCNBXN      (AP_RW|DOMAIN0|NCNB|DESC_SEC|XN)
45*10465441SEvalZero /* Read/Write without cache and write buffer */
46*10465441SEvalZero #define RW_FAULT       (AP_RW|DOMAIN1|NCNB|DESC_SEC)
47*10465441SEvalZero 
rt_hw_cpu_dump_page_table(rt_uint32_t * ptb)48*10465441SEvalZero void rt_hw_cpu_dump_page_table(rt_uint32_t *ptb)
49*10465441SEvalZero {
50*10465441SEvalZero     int i;
51*10465441SEvalZero     int fcnt = 0;
52*10465441SEvalZero 
53*10465441SEvalZero     rt_kprintf("page table@%p\n", ptb);
54*10465441SEvalZero     for (i = 0; i < 1024*4; i++)
55*10465441SEvalZero     {
56*10465441SEvalZero         rt_uint32_t pte1 = ptb[i];
57*10465441SEvalZero         if ((pte1 & 0x3) == 0)
58*10465441SEvalZero         {
59*10465441SEvalZero             rt_kprintf("%03x: ", i);
60*10465441SEvalZero             fcnt++;
61*10465441SEvalZero             if (fcnt == 16)
62*10465441SEvalZero             {
63*10465441SEvalZero                 rt_kprintf("fault\n");
64*10465441SEvalZero                 fcnt = 0;
65*10465441SEvalZero             }
66*10465441SEvalZero             continue;
67*10465441SEvalZero         }
68*10465441SEvalZero         if (fcnt != 0)
69*10465441SEvalZero         {
70*10465441SEvalZero             rt_kprintf("fault\n");
71*10465441SEvalZero             fcnt = 0;
72*10465441SEvalZero         }
73*10465441SEvalZero 
74*10465441SEvalZero         rt_kprintf("%03x: %08x: ", i, pte1);
75*10465441SEvalZero         if ((pte1 & 0x3) == 0x3)
76*10465441SEvalZero         {
77*10465441SEvalZero             rt_kprintf("LPAE\n");
78*10465441SEvalZero         }
79*10465441SEvalZero         else if ((pte1 & 0x3) == 0x1)
80*10465441SEvalZero         {
81*10465441SEvalZero             rt_kprintf("pte,ns:%d,domain:%d\n",
82*10465441SEvalZero                        (pte1 >> 3) & 0x1, (pte1 >> 5) & 0xf);
83*10465441SEvalZero             /*
84*10465441SEvalZero              *rt_hw_cpu_dump_page_table_2nd((void*)((pte1 & 0xfffffc000)
85*10465441SEvalZero              *                               - 0x80000000 + 0xC0000000));
86*10465441SEvalZero              */
87*10465441SEvalZero         }
88*10465441SEvalZero         else if (pte1 & (1 << 18))
89*10465441SEvalZero         {
90*10465441SEvalZero             rt_kprintf("super section,ns:%d,ap:%x,xn:%d,texcb:%02x\n",
91*10465441SEvalZero                        (pte1 >> 19) & 0x1,
92*10465441SEvalZero                        ((pte1 >> 13) | (pte1 >> 10))& 0xf,
93*10465441SEvalZero                        (pte1 >> 4) & 0x1,
94*10465441SEvalZero                        ((pte1 >> 10) | (pte1 >> 2)) & 0x1f);
95*10465441SEvalZero         }
96*10465441SEvalZero         else
97*10465441SEvalZero         {
98*10465441SEvalZero             rt_kprintf("section,ns:%d,ap:%x,"
99*10465441SEvalZero                        "xn:%d,texcb:%02x,domain:%d\n",
100*10465441SEvalZero                        (pte1 >> 19) & 0x1,
101*10465441SEvalZero                        ((pte1 >> 13) | (pte1 >> 10))& 0xf,
102*10465441SEvalZero                        (pte1 >> 4) & 0x1,
103*10465441SEvalZero                        (((pte1 & (0x7 << 12)) >> 10) |
104*10465441SEvalZero                         ((pte1 &        0x0c) >>  2)) & 0x1f,
105*10465441SEvalZero                        (pte1 >> 5) & 0xf);
106*10465441SEvalZero         }
107*10465441SEvalZero     }
108*10465441SEvalZero }
109*10465441SEvalZero 
110*10465441SEvalZero /* level1 page table, each entry for 1MB memory. */
111*10465441SEvalZero /* MMUTable is the name used by codes of Xilinx */
112*10465441SEvalZero volatile unsigned long MMUTable[4*1024] SECTION("mmu_tbl") __attribute__((aligned(16*1024)));
rt_hw_mmu_setmtt(rt_uint32_t vaddrStart,rt_uint32_t vaddrEnd,rt_uint32_t paddrStart,rt_uint32_t attr)113*10465441SEvalZero void rt_hw_mmu_setmtt(rt_uint32_t vaddrStart,
114*10465441SEvalZero                       rt_uint32_t vaddrEnd,
115*10465441SEvalZero                       rt_uint32_t paddrStart,
116*10465441SEvalZero                       rt_uint32_t attr)
117*10465441SEvalZero {
118*10465441SEvalZero     volatile rt_uint32_t *pTT;
119*10465441SEvalZero     volatile int i, nSec;
120*10465441SEvalZero     pTT  = (rt_uint32_t *)MMUTable + (vaddrStart >> 20);
121*10465441SEvalZero     nSec = (vaddrEnd >> 20) - (vaddrStart >> 20);
122*10465441SEvalZero     for(i = 0; i <= nSec; i++)
123*10465441SEvalZero     {
124*10465441SEvalZero         *pTT = attr | (((paddrStart >> 20) + i) << 20);
125*10465441SEvalZero         pTT++;
126*10465441SEvalZero     }
127*10465441SEvalZero }
128*10465441SEvalZero 
rt_hw_set_domain_register(unsigned long domain_val)129*10465441SEvalZero unsigned long rt_hw_set_domain_register(unsigned long domain_val)
130*10465441SEvalZero {
131*10465441SEvalZero     unsigned long old_domain;
132*10465441SEvalZero 
133*10465441SEvalZero     asm volatile ("mrc p15, 0, %0, c3, c0\n" : "=r" (old_domain));
134*10465441SEvalZero     asm volatile ("mcr p15, 0, %0, c3, c0\n" : :"r" (domain_val) : "memory");
135*10465441SEvalZero 
136*10465441SEvalZero     return old_domain;
137*10465441SEvalZero }
138*10465441SEvalZero 
rt_hw_mmu_init(void)139*10465441SEvalZero void rt_hw_mmu_init(void)
140*10465441SEvalZero {
141*10465441SEvalZero     extern rt_uint32_t __text_start;
142*10465441SEvalZero     rt_hw_cpu_dcache_disable();
143*10465441SEvalZero     rt_hw_cpu_icache_disable();
144*10465441SEvalZero     rt_cpu_mmu_disable();
145*10465441SEvalZero 
146*10465441SEvalZero     /* set page table */
147*10465441SEvalZero     /* no access to the memory below .text */
148*10465441SEvalZero     /* 128M cached DDR memory */
149*10465441SEvalZero     rt_hw_mmu_setmtt((rt_uint32_t)&__text_start, 0x20000000-1,
150*10465441SEvalZero                      0x1ff00000, RW_CB);
151*10465441SEvalZero     /* PL region */
152*10465441SEvalZero     rt_hw_mmu_setmtt(0x40000000, 0xBFFFFFFF, 0x40000000, RW_NCNBXN);
153*10465441SEvalZero     /* IOP registers */
154*10465441SEvalZero     rt_hw_mmu_setmtt(0xE0000000, 0xE02FFFFF, 0xE0000000, RW_NCNBXN);
155*10465441SEvalZero     /* no access to the SMC memory(enable it if you want) */
156*10465441SEvalZero     /* SLCR, PS and CPU private registers, note we map more memory space as the
157*10465441SEvalZero      * entry is 1MB in size. */
158*10465441SEvalZero     rt_hw_mmu_setmtt(0xF8000000, 0xF8FFFFFF, 0xF8000000, RW_NCNBXN);
159*10465441SEvalZero 
160*10465441SEvalZero     /*rt_hw_cpu_dump_page_table(MMUTable);*/
161*10465441SEvalZero 
162*10465441SEvalZero     /* become clients for all domains */
163*10465441SEvalZero     rt_hw_set_domain_register(0x55555555);
164*10465441SEvalZero 
165*10465441SEvalZero     rt_cpu_tlb_set(MMUTable);
166*10465441SEvalZero 
167*10465441SEvalZero     rt_cpu_mmu_enable();
168*10465441SEvalZero 
169*10465441SEvalZero     rt_hw_cpu_icache_enable();
170*10465441SEvalZero     rt_hw_cpu_dcache_enable();
171*10465441SEvalZero }
172*10465441SEvalZero 
173