Use real ARM 11 instructions for cache operations. Probably will factor out later.
[kugel-rb.git] / firmware / target / arm / mmu-arm.c
blob5fa05d1dc697ada1cd1cdf0fb689950d71ed2f07
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2006,2007 by Greg White
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
19 #include "cpu.h"
20 #include "mmu-arm.h"
21 #include "panic.h"
23 #define SECTION_ADDRESS_MASK (-1 << 20)
24 #define MB (1 << 20)
26 void ttb_init(void) {
27 unsigned int* ttbPtr;
29 /* must be 16Kb (0x4000) aligned - clear out the TTB */
30 for (ttbPtr=TTB_BASE; ttbPtr<(TTB_SIZE+TTB_BASE); ttbPtr++)
32 *ttbPtr = 0;
35 /* Set the TTB base address */
36 asm volatile("mcr p15, 0, %0, c2, c0, 0" : : "r" (TTB_BASE));
38 /* Set all domains to manager status */
39 asm volatile("mcr p15, 0, %0, c3, c0, 0" : : "r" (0xFFFFFFFF));
42 void map_section(unsigned int pa, unsigned int va, int mb, int cache_flags) {
43 unsigned int* ttbPtr;
44 int i;
45 int section_no;
47 section_no = va >> 20; /* sections are 1Mb size */
48 ttbPtr = TTB_BASE + section_no;
49 pa &= SECTION_ADDRESS_MASK; /* align to 1Mb */
50 for(i=0; i<mb; i++, pa += MB) {
51 *(ttbPtr + i) =
52 pa |
53 1 << 10 | /* superuser - r/w, user - no access */
54 0 << 5 | /* domain 0th */
55 1 << 4 | /* should be "1" */
56 cache_flags |
57 1 << 1; /* Section signature */
61 void enable_mmu(void) {
62 int regread;
64 asm volatile(
65 "MRC p15, 0, %r0, c1, c0, 0\n" /* Read reg1, control register */
66 : /* outputs */
67 "=r"(regread)
68 : /* inputs */
69 : /* clobbers */
70 "r0"
73 if ( !(regread & 0x04) || !(regread & 0x00001000) ) /* Was the ICache or DCache Enabled? */
74 clean_dcache(); /* If so we need to clean the DCache before invalidating below */
76 asm volatile("mov r0, #0\n"
77 "mcr p15, 0, r0, c8, c7, 0\n" /* invalidate TLB */
79 "mcr p15, 0, r0, c7, c7,0\n" /* invalidate both icache and dcache */
81 "mrc p15, 0, r0, c1, c0, 0\n"
82 "orr r0, r0, #1<<0\n" /* enable mmu bit, icache and dcache */
83 "orr r0, r0, #1<<2\n" /* enable dcache */
84 "orr r0, r0, #1<<12\n" /* enable icache */
85 "mcr p15, 0, r0, c1, c0, 0" : : : "r0");
86 asm volatile("nop \n nop \n nop \n nop");
89 #if CONFIG_CPU == IMX31L
90 void __attribute__((naked)) invalidate_dcache_range(const void *base, unsigned int size)
92 asm volatile(
93 "add r1, r1, r0 \n"
94 "mcrr p15, 0, r1, r0, c14 \n"
95 "bx lr \n"
97 (void)base; (void)size;
99 #else
100 /* Invalidate DCache for this range */
101 /* Will do write back */
102 void invalidate_dcache_range(const void *base, unsigned int size) {
103 unsigned int addr = (((int) base) & ~31); /* Align start to cache line*/
104 unsigned int end = ((addr+size) & ~31)+64; /* Align end to cache line, pad */
105 asm volatile(
106 "inv_start: \n"
107 "mcr p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line */
108 "add %0, %0, #32 \n"
109 "cmp %0, %1 \n"
110 "mcrne p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line */
111 "addne %0, %0, #32 \n"
112 "cmpne %0, %1 \n"
113 "mcrne p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line */
114 "addne %0, %0, #32 \n"
115 "cmpne %0, %1 \n"
116 "mcrne p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line */
117 "addne %0, %0, #32 \n"
118 "cmpne %0, %1 \n"
119 "mcrne p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line */
120 "addne %0, %0, #32 \n"
121 "cmpne %0, %1 \n"
122 "mcrne p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line */
123 "addne %0, %0, #32 \n"
124 "cmpne %0, %1 \n"
125 "mcrne p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line */
126 "addne %0, %0, #32 \n"
127 "cmpne %0, %1 \n"
128 "mcrne p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line */
129 "addne %0, %0, #32 \n"
130 "cmpne %0, %1 \n"
131 "bne inv_start \n"
132 "mov %0, #0\n"
133 "mcr p15,0,%0,c7,c10,4\n" /* Drain write buffer */
134 : : "r" (addr), "r" (end));
136 #endif
139 #if CONFIG_CPU == IMX31L
140 void __attribute__((naked)) clean_dcache_range(const void *base, unsigned int size)
142 asm volatile(
143 "add r1, r1, r0 \n"
144 "mcrr p15, 0, r1, r0, c12 \n"
145 "bx lr \n"
147 (void)base; (void)size;
149 #else
150 /* clean DCache for this range */
151 /* forces DCache writeback for the specified range */
152 void clean_dcache_range(const void *base, unsigned int size) {
153 unsigned int addr = (int) base;
154 unsigned int end = addr+size+32;
155 asm volatile(
156 "bic %0, %0, #31 \n"
157 "clean_start: \n"
158 "mcr p15, 0, %0, c7, c10, 1 \n" /* Clean this line */
159 "add %0, %0, #32 \n"
160 "cmp %0, %1 \n"
161 "mcrlo p15, 0, %0, c7, c10, 1 \n" /* Clean this line */
162 "addlo %0, %0, #32 \n"
163 "cmplo %0, %1 \n"
164 "mcrlo p15, 0, %0, c7, c10, 1 \n" /* Clean this line */
165 "addlo %0, %0, #32 \n"
166 "cmplo %0, %1 \n"
167 "mcrlo p15, 0, %0, c7, c10, 1 \n" /* Clean this line */
168 "addlo %0, %0, #32 \n"
169 "cmplo %0, %1 \n"
170 "mcrlo p15, 0, %0, c7, c10, 1 \n" /* Clean this line */
171 "addlo %0, %0, #32 \n"
172 "cmplo %0, %1 \n"
173 "mcrlo p15, 0, %0, c7, c10, 1 \n" /* Clean this line */
174 "addlo %0, %0, #32 \n"
175 "cmplo %0, %1 \n"
176 "mcrlo p15, 0, %0, c7, c10, 1 \n" /* Clean this line */
177 "addlo %0, %0, #32 \n"
178 "cmplo %0, %1 \n"
179 "mcrlo p15, 0, %0, c7, c10, 1 \n" /* Clean this line */
180 "addlo %0, %0, #32 \n"
181 "cmplo %0, %1 \n"
182 "blo clean_start \n"
183 "mov %0, #0\n"
184 "mcr p15,0,%0,c7,c10,4 \n" /* Drain write buffer */
185 : : "r" (addr), "r" (end));
187 #endif
189 #if CONFIG_CPU == IMX31L
190 void __attribute__((naked)) dump_dcache_range(const void *base, unsigned int size)
192 asm volatile(
193 "add r1, r1, r0 \n"
194 "mcrr p15, 0, r1, r0, c6 \n"
195 "bx lr \n"
197 (void)base; (void)size;
199 #else
200 /* Dump DCache for this range */
201 /* Will *NOT* do write back */
202 void dump_dcache_range(const void *base, unsigned int size) {
203 unsigned int addr = (int) base;
204 unsigned int end = addr+size;
205 asm volatile(
206 "tst %0, #31 \n" /* Check to see if low five bits are set */
207 "bic %0, %0, #31 \n" /* Clear them */
208 "mcrne p15, 0, %0, c7, c14, 1 \n" /* Clean and invalidate this line, if those bits were set */
209 "add %0, %0, #32 \n" /* Move to the next cache line */
210 "tst %1, #31 \n" /* Check last line for bits set */
211 "bic %1, %1, #31 \n" /* Clear those bits */
212 "mcrne p15, 0, %1, c7, c14, 1 \n" /* Clean and invalidate this line, if not cache aligned */
213 "dump_start: \n"
214 "mcr p15, 0, %0, c7, c6, 1 \n" /* Invalidate this line */
215 "add %0, %0, #32 \n" /* Next cache line */
216 "cmp %0, %1 \n"
217 "bne dump_start \n"
218 "dump_end: \n"
219 "mcr p15,0,%0,c7,c10,4 \n" /* Drain write buffer */
220 : : "r" (addr), "r" (end));
222 #endif
224 #if CONFIG_CPU == IMX31L
225 void __attribute__((naked)) clean_dcache(void)
227 asm volatile (
228 /* Clean entire data cache */
229 "mov r0, #0 \n"
230 "mcr p15, 0, r0, c7, c10, 0 \n"
231 "bx lr \n"
234 #else
235 /* Cleans entire DCache */
236 void clean_dcache(void)
238 unsigned int index, addr;
240 for(index = 0; index <= 63; index++) {
241 addr = (0 << 5) | (index << 26);
242 asm volatile(
243 "mcr p15, 0, %0, c7, c10, 2 \n" /* Clean this entry by index */
244 : : "r" (addr));
245 addr = (1 << 5) | (index << 26);
246 asm volatile(
247 "mcr p15, 0, %0, c7, c10, 2 \n" /* Clean this entry by index */
248 : : "r" (addr));
249 addr = (2 << 5) | (index << 26);
250 asm volatile(
251 "mcr p15, 0, %0, c7, c10, 2 \n" /* Clean this entry by index */
252 : : "r" (addr));
253 addr = (3 << 5) | (index << 26);
254 asm volatile(
255 "mcr p15, 0, %0, c7, c10, 2 \n" /* Clean this entry by index */
256 : : "r" (addr));
257 addr = (4 << 5) | (index << 26);
258 asm volatile(
259 "mcr p15, 0, %0, c7, c10, 2 \n" /* Clean this entry by index */
260 : : "r" (addr));
261 addr = (5 << 5) | (index << 26);
262 asm volatile(
263 "mcr p15, 0, %0, c7, c10, 2 \n" /* Clean this entry by index */
264 : : "r" (addr));
265 addr = (6 << 5) | (index << 26);
266 asm volatile(
267 "mcr p15, 0, %0, c7, c10, 2 \n" /* Clean this entry by index */
268 : : "r" (addr));
269 addr = (7 << 5) | (index << 26);
270 asm volatile(
271 "mcr p15, 0, %0, c7, c10, 2 \n" /* Clean this entry by index */
272 : : "r" (addr));
275 #endif