summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx31/gigabeat-s/mmu-imx31.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/imx31/gigabeat-s/mmu-imx31.c')
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/mmu-imx31.c237
1 files changed, 237 insertions, 0 deletions
diff --git a/firmware/target/arm/imx31/gigabeat-s/mmu-imx31.c b/firmware/target/arm/imx31/gigabeat-s/mmu-imx31.c
new file mode 100644
index 0000000000..ee86ccc95c
--- /dev/null
+++ b/firmware/target/arm/imx31/gigabeat-s/mmu-imx31.c
@@ -0,0 +1,237 @@
1#include <string.h>
2#include "mmu-imx31.h"
3#include "cpu.h"
4
5static void enable_mmu(void);
6static void set_ttb(void);
7static void set_page_tables(void);
8static void map_section(unsigned int pa, unsigned int va, int mb, int cache_flags);
9
10#define SECTION_ADDRESS_MASK (-1 << 20)
11#define CACHE_ALL (1 << 3 | 1 << 2 )
12#define CACHE_NONE 0
13#define BUFFERED (1 << 2)
14#define MB (1 << 20)
15
16void memory_init(void) {
17 set_ttb();
18 set_page_tables();
19 enable_mmu();
20}
21
22unsigned int* ttb_base = (unsigned int *) TTB_BASE;
23const int ttb_size = 4096;
24
25void set_ttb() {
26 int i;
27 int* ttbPtr;
28 int domain_access;
29
30 /* must be 16Kb (0x4000) aligned */
31 ttb_base = (int*) TTB_BASE;
32 for (i=0; i<ttb_size; i++,ttbPtr++)
33 ttbPtr = 0;
34 asm volatile("mcr p15, 0, %0, c2, c0, 0" : : "r" (ttb_base));
35
36 /* set domain D0 to "client" permission access */
37
38 domain_access = 3;
39 asm volatile("mcr p15, 0, %0, c3, c0, 0" : : "r" (domain_access));
40
41}
42
43void set_page_tables() {
44
45 map_section(0, 0, 0x1000, CACHE_NONE); /* map every memory region to itself */
46 /*This pa *might* change*/
47 map_section(0x80000000, 0, 64, CACHE_ALL); /* map RAM to 0 and enable caching for it */
48 map_section((int)FRAME1, (int)FRAME1, 1, BUFFERED); /* enable buffered writing for the framebuffer */
49 map_section((int)FRAME2, (int)FRAME2, 1, BUFFERED);
50}
51
52void map_section(unsigned int pa, unsigned int va, int mb, int cache_flags) {
53 unsigned int* ttbPtr;
54 int i;
55 int section_no;
56
57 section_no = va >> 20; /* sections are 1Mb size */
58 ttbPtr = ttb_base + section_no;
59 pa &= SECTION_ADDRESS_MASK; /* align to 1Mb */
60 for(i=0; i<mb; i++, pa += MB) {
61 *(ttbPtr + i) =
62 pa |
63 1 << 10 | /* superuser - r/w, user - no access */
64 0 << 5 | /* domain 0th */
65 1 << 4 | /* should be "1" */
66 cache_flags |
67 1 << 1; /* Section signature */
68 }
69}
70
71static void enable_mmu(void) {
72 int regread;
73
74 asm volatile(
75 "MRC p15, 0, %r0, c1, c0, 0\n" /* Read reg1, control register */
76 : /* outputs */
77 "=r"(regread)
78 : /* inputs */
79 : /* clobbers */
80 "r0"
81 );
82
83 if ( !(regread & 0x04) || !(regread & 0x00001000) ) /* Was the ICache or DCache Enabled? */
84 clean_dcache(); /* If so we need to clean the DCache before invalidating below */
85
86 asm volatile("mov r0, #0\n"
87 "mcr p15, 0, r0, c8, c7, 0\n" /* invalidate TLB */
88
89 "mcr p15, 0, r0, c7, c7,0\n" /* invalidate both icache and dcache */
90
91 "mrc p15, 0, r0, c1, c0, 0\n"
92 "orr r0, r0, #1<<0\n" /* enable mmu bit, icache and dcache */
93 "orr r0, r0, #1<<2\n" /* enable dcache */
94 "orr r0, r0, #1<<12\n" /* enable icache */
95 "mcr p15, 0, r0, c1, c0, 0" : : : "r0");
96 asm volatile("nop \n nop \n nop \n nop");
97}
98
99/* Invalidate DCache for this range */
100/* Will do write back */
101void invalidate_dcache_range(const void *base, unsigned int size) {
102 unsigned int addr = (((int) base) & ~31); /* Align start to cache line*/
103 unsigned int end = ((addr+size) & ~31)+64; /* Align end to cache line, pad */
104 asm volatile(
105"inv_start: \n"
106 "mcr p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line */
107 "add %0, %0, #32 \n"
108 "cmp %0, %1 \n"
109 "mcrne p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line */
110 "addne %0, %0, #32 \n"
111 "cmpne %0, %1 \n"
112 "mcrne p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line */
113 "addne %0, %0, #32 \n"
114 "cmpne %0, %1 \n"
115 "mcrne p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line */
116 "addne %0, %0, #32 \n"
117 "cmpne %0, %1 \n"
118 "mcrne p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line */
119 "addne %0, %0, #32 \n"
120 "cmpne %0, %1 \n"
121 "mcrne p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line */
122 "addne %0, %0, #32 \n"
123 "cmpne %0, %1 \n"
124 "mcrne p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line */
125 "addne %0, %0, #32 \n"
126 "cmpne %0, %1 \n"
127 "mcrne p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line */
128 "addne %0, %0, #32 \n"
129 "cmpne %0, %1 \n"
130 "bne inv_start \n"
131 "mov %0, #0\n"
132 "mcr p15,0,%0,c7,c10,4\n" /* Drain write buffer */
133 : : "r" (addr), "r" (end));
134}
135
136/* clean DCache for this range */
137/* forces DCache writeback for the specified range */
138void clean_dcache_range(const void *base, unsigned int size) {
139 unsigned int addr = (int) base;
140 unsigned int end = addr+size+32;
141 asm volatile(
142 "bic %0, %0, #31 \n"
143"clean_start: \n"
144 "mcr p15, 0, %0, c7, c10, 1 \n" /* Clean this line */
145 "add %0, %0, #32 \n"
146 "cmp %0, %1 \n"
147 "mcrlo p15, 0, %0, c7, c10, 1 \n" /* Clean this line */
148 "addlo %0, %0, #32 \n"
149 "cmplo %0, %1 \n"
150 "mcrlo p15, 0, %0, c7, c10, 1 \n" /* Clean this line */
151 "addlo %0, %0, #32 \n"
152 "cmplo %0, %1 \n"
153 "mcrlo p15, 0, %0, c7, c10, 1 \n" /* Clean this line */
154 "addlo %0, %0, #32 \n"
155 "cmplo %0, %1 \n"
156 "mcrlo p15, 0, %0, c7, c10, 1 \n" /* Clean this line */
157 "addlo %0, %0, #32 \n"
158 "cmplo %0, %1 \n"
159 "mcrlo p15, 0, %0, c7, c10, 1 \n" /* Clean this line */
160 "addlo %0, %0, #32 \n"
161 "cmplo %0, %1 \n"
162 "mcrlo p15, 0, %0, c7, c10, 1 \n" /* Clean this line */
163 "addlo %0, %0, #32 \n"
164 "cmplo %0, %1 \n"
165 "mcrlo p15, 0, %0, c7, c10, 1 \n" /* Clean this line */
166 "addlo %0, %0, #32 \n"
167 "cmplo %0, %1 \n"
168 "blo clean_start \n"
169 "mov %0, #0\n"
170 "mcr p15,0,%0,c7,c10,4 \n" /* Drain write buffer */
171 : : "r" (addr), "r" (end));
172}
173
174/* Dump DCache for this range */
175/* Will *NOT* do write back */
176void dump_dcache_range(const void *base, unsigned int size) {
177 unsigned int addr = (int) base;
178 unsigned int end = addr+size;
179 asm volatile(
180 "tst %0, #31 \n" /* Check to see if low five bits are set */
181 "bic %0, %0, #31 \n" /* Clear them */
182 "mcrne p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line, if those bits were set */
183 "add %0, %0, #32 \n" /* Move to the next cache line */
184 "tst %1, #31 \n" /* Check last line for bits set */
185 "bic %1, %1, #31 \n" /* Clear those bits */
186 "mcrne p15, 0, %1, c7, c14, 1 \n" /* Clean and invalidate this line, if not cache aligned */
187"dump_start: \n"
188 "mcr p15, 0, %0, c7, c6, 1 \n" /* Invalidate this line */
189 "add %0, %0, #32 \n" /* Next cache line */
190 "cmp %0, %1 \n"
191 "bne dump_start \n"
192"dump_end: \n"
193 "mcr p15,0,%0,c7,c10,4 \n" /* Drain write buffer */
194 : : "r" (addr), "r" (end));
195}
196/* Cleans entire DCache */
197void clean_dcache(void)
198{
199 unsigned int index, addr;
200
201 for(index = 0; index <= 63; index++) {
202 addr = (0 << 5) | (index << 26);
203 asm volatile(
204 "mcr p15, 0, %0, c7, c10, 2 \n" /* Clean this entry by index */
205 : : "r" (addr));
206 addr = (1 << 5) | (index << 26);
207 asm volatile(
208 "mcr p15, 0, %0, c7, c10, 2 \n" /* Clean this entry by index */
209 : : "r" (addr));
210 addr = (2 << 5) | (index << 26);
211 asm volatile(
212 "mcr p15, 0, %0, c7, c10, 2 \n" /* Clean this entry by index */
213 : : "r" (addr));
214 addr = (3 << 5) | (index << 26);
215 asm volatile(
216 "mcr p15, 0, %0, c7, c10, 2 \n" /* Clean this entry by index */
217 : : "r" (addr));
218 addr = (4 << 5) | (index << 26);
219 asm volatile(
220 "mcr p15, 0, %0, c7, c10, 2 \n" /* Clean this entry by index */
221 : : "r" (addr));
222 addr = (5 << 5) | (index << 26);
223 asm volatile(
224 "mcr p15, 0, %0, c7, c10, 2 \n" /* Clean this entry by index */
225 : : "r" (addr));
226 addr = (6 << 5) | (index << 26);
227 asm volatile(
228 "mcr p15, 0, %0, c7, c10, 2 \n" /* Clean this entry by index */
229 : : "r" (addr));
230 addr = (7 << 5) | (index << 26);
231 asm volatile(
232 "mcr p15, 0, %0, c7, c10, 2 \n" /* Clean this entry by index */
233 : : "r" (addr));
234 }
235}
236
237