0119b2613343773ba0c4dc4cad1959f0826244f9
[kugel-rb.git] / firmware / target / arm / mmu-arm.S
blob0119b2613343773ba0c4dc4cad1959f0826244f9
1 /***************************************************************************
2  *             __________               __   ___.
3  *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
4  *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
5  *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
6  *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
7  *                     \/            \/     \/    \/            \/
8  * $Id$
9  *
10  * Copyright (C) 2006,2007 by Greg White
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18  * KIND, either express or implied.
19  *
20  ****************************************************************************/
21 #include "config.h"
22 #include "cpu.h"
24 /* Used by ARMv4 & ARMv5 CPUs with cp15 register and MMU */
26 #if CONFIG_CPU == TCC7801 || CONFIG_CPU == AT91SAM9260
27 /* MMU present but unused */
28 #define HAVE_TEST_AND_CLEAN_CACHE
30 #elif CONFIG_CPU == DM320 || CONFIG_CPU == AS3525v2
31 #define USE_MMU
32 #define HAVE_TEST_AND_CLEAN_CACHE
34 #elif CONFIG_CPU == AS3525
35 #define USE_MMU
36 #define CACHE_SIZE 8
38 #elif CONFIG_CPU == S3C2440
39 #define USE_MMU
40 #define CACHE_SIZE 16
42 #elif CONFIG_CPU == S5L8701
43 /* MMU not present */
44 #define CACHE_SIZE 4
46 #else
47 #error Cache settings unknown for this CPU !
49 #endif /* CPU specific configuration */
51 @ Index format: 31:26 = index, N:5 = segment, remainder = SBZ
52 @ assume 64-way set associative separate I/D caches
53 @ CACHE_SIZE = N (kB) = N*2^10 B
54 @ number of lines = N*2^(10-CACHEALIGN_BITS)
55 @ Index bits = 6
56 @ Segment loops = N*2^(10-CACHEALIGN_BITS-6) = N*2^(4-CACHEALIGN_BITS)
57 @ Segment loops = N/2^(CACHEALIGN_BITS - 4)
58 @ Segment loops = N/(1<<(CACHEALIGN_BITS - 4))
60 #ifdef CACHE_SIZE
62 #if CACHEALIGN_BITS == 4
63 #define INDEX_STEPS CACHE_SIZE
64 #elif CACHEALIGN_BITS == 5
65 #define INDEX_STEPS (CACHE_SIZE/2)
66 #endif /* CACHEALIGN_BITS */
68 @ assume 64-way set associative separate I/D caches (log2(64) == 6)
69 @ Index format: 31:26 = index, M:N = segment, remainder = SBZ
70 @ Segment bits = log2(cache size in bytes / cache line size in byte) - Index bits (== 6)
71 @ N = CACHEALIGN_BITS
73 #endif /* CACHE_SIZE */
76 #ifdef USE_MMU
78 /** MMU setup **/
81  * void ttb_init(void);
82  */
83     .section    .text, "ax", %progbits
84     .align      2
85     .global     ttb_init
86     .type       ttb_init, %function
87 ttb_init:
88     ldr     r0, =TTB_BASE_ADDR      @
89     mvn     r1, #0                  @
90     mcr     p15, 0, r0, c2, c0, 0   @ Set the TTB base address
91     mcr     p15, 0, r1, c3, c0, 0   @ Set all domains to manager status
92     bx      lr                      @
93     .size   ttb_init, .-ttb_init
96  * void map_section(unsigned int pa, unsigned int va, int mb, int flags);
97  */
98     .section    .text, "ax", %progbits
99     .align      2
100     .global     map_section
101     .type       map_section, %function
102 map_section:
103     @ align to 1MB
104     @ pa &= (-1 << 20);
105     mov     r0, r0, lsr #20
106     mov     r0, r0, lsl #20
108     @ pa |= (flags | 0x412);
109     @ bit breakdown:
110     @  10:  superuser - r/w, user - no access
111     @  4:   should be "1"
112     @  3,2: Cache flags (flags (r3))
113     @  1:   Section signature
114     orr     r0, r0, r3
115     orr     r0, r0, #0x410
116     orr     r0, r0, #0x2
118     @ unsigned int* ttbPtr = TTB_BASE + (va >> 20);
119     @ sections are 1MB size
120     mov     r1, r1, lsr #20
121     ldr     r3, =TTB_BASE_ADDR
122     add     r1, r3, r1, lsl #0x2
124     @ Add MB to pa, flags are already present in pa, but addition
125     @ should not effect them
126     @
127     @ for( ; mb>0; mb--, pa += (1 << 20))
128     @ {
129     @     *(ttbPtr++) = pa;
130     @ }
131     cmp    r2, #0
132     bxle   lr
133     mov    r3, #0x0
134 1:  @ loop
135     str    r0, [r1], #4
136     add    r0, r0, #0x100000
137     add    r3, r3, #0x1
138     cmp    r2, r3
139     bne    1b @ loop
140     bx     lr
141     .size   map_section, .-map_section
144  * void enable_mmu(void);
145  */
146     .section    .text, "ax", %progbits
147     .align      2
148     .global     enable_mmu
149     .type       enable_mmu, %function
150 enable_mmu:
151     mov     r0, #0                  @
152     mcr     p15, 0, r0, c8, c7, 0   @ invalidate TLB
153     mcr     p15, 0, r0, c7, c7,0    @ invalidate both i and dcache
154     mrc     p15, 0, r0, c1, c0, 0   @
155     orr     r0, r0, #1              @ enable mmu bit, i and dcache
156     orr     r0, r0, #1<<2           @ enable dcache
157     orr     r0, r0, #1<<12          @ enable icache
158     mcr     p15, 0, r0, c1, c0, 0   @
159     nop                             @
160     nop                             @
161     nop                             @
162     nop                             @
163     bx      lr                      @
164     .size   enable_mmu, .-enable_mmu
165     .ltorg
167 #endif  /* USE_MMU */
171 /** Cache coherency **/
174  * Invalidate DCache for this range
175  * will do write back
176  * void invalidate_dcache_range(const void *base, unsigned int size);
177  */
178     .section   .text, "ax", %progbits
179     .align      2
180     .global     invalidate_dcache_range
181     .type       invalidate_dcache_range, %function
182     @ MVA format: 31:5 = Modified virtual address, 4:0 = SBZ
183 invalidate_dcache_range:
184     add     r1, r0, r1              @ size -> end
185     cmp     r1, r0                  @ end <= start?
186     bxls    lr                      @
187     bic     r0, r0, #31             @ Align start to cache line (down)
188 1:  @ inv_start                     @
189     mcr     p15, 0, r0, c7, c14, 1  @ Clean and invalidate line by MVA
190     add     r0, r0, #32             @
191     cmp     r1, r0                  @
192     mcrhi   p15, 0, r0, c7, c14, 1  @ Clean and invalidate line by MVA
193     addhi   r0, r0, #32             @
194     cmphi   r1, r0                  @
195     mcrhi   p15, 0, r0, c7, c14, 1  @ Clean and invalidate line by MVA
196     addhi   r0, r0, #32             @
197     cmphi   r1, r0                  @
198     mcrhi   p15, 0, r0, c7, c14, 1  @ Clean and invalidate line by MVA
199     addhi   r0, r0, #32             @
200     cmphi   r1, r0                  @
201     mcrhi   p15, 0, r0, c7, c14, 1  @ Clean and invalidate line by MVA
202     addhi   r0, r0, #32             @
203     cmphi   r1, r0                  @
204     mcrhi   p15, 0, r0, c7, c14, 1  @ Clean and invalidate line by MVA
205     addhi   r0, r0, #32             @
206     cmphi   r1, r0                  @
207     mcrhi   p15, 0, r0, c7, c14, 1  @ Clean and invalidate line by MVA
208     addhi   r0, r0, #32             @
209     cmphi   r1, r0                  @
210     mcrhi   p15, 0, r0, c7, c14, 1  @ Clean and invalidate line by MVA
211     addhi   r0, r0, #32             @
212     cmphi   r1, r0                  @
213     bhi     1b @ inv_start          @
214     mov     r0, #0                  @
215     mcr     p15, 0, r0, c7, c10, 4  @ Drain write buffer
216     bx      lr                      @
217     .size   invalidate_dcache_range, .-invalidate_dcache_range
220  * clean DCache for this range
221  * forces DCache writeback for the specified range
222  * void clean_dcache_range(const void *base, unsigned int size);
223  */
224     .section   .text, "ax", %progbits
225     .align      2
226     .global     clean_dcache_range
227     .type       clean_dcache_range, %function
228     @ MVA format: 31:5 = Modified virtual address, 4:0 = SBZ
229 clean_dcache_range:
230     add     r1, r0, r1              @ size -> end
231     cmp     r1, r0                  @ end <= start?
232     bxls    lr                      @
233     bic     r0, r0, #31             @ Align start to cache line (down)
234 1:  @ clean_start                   @
235     mcr     p15, 0, r0, c7, c10, 1  @ Clean line by MVA
236     add     r0, r0, #32             @
237     cmp     r1, r0                  @
238     mcrhi   p15, 0, r0, c7, c10, 1  @ Clean line by MVA
239     addhi   r0, r0, #32             @
240     cmphi   r1, r0                  @
241     mcrhi   p15, 0, r0, c7, c10, 1  @ Clean line by MVA
242     addhi   r0, r0, #32             @
243     cmphi   r1, r0                  @
244     mcrhi   p15, 0, r0, c7, c10, 1  @ Clean line by MVA
245     addhi   r0, r0, #32             @
246     cmphi   r1, r0                  @
247     mcrhi   p15, 0, r0, c7, c10, 1  @ Clean line by MVA
248     addhi   r0, r0, #32             @
249     cmphi   r1, r0                  @
250     mcrhi   p15, 0, r0, c7, c10, 1  @ Clean line by MVA
251     addhi   r0, r0, #32             @
252     cmphi   r1, r0                  @
253     mcrhi   p15, 0, r0, c7, c10, 1  @ Clean line by MVA
254     addhi   r0, r0, #32             @
255     cmphi   r1, r0                  @
256     mcrhi   p15, 0, r0, c7, c10, 1  @ Clean line by MVA
257     addhi   r0, r0, #32             @
258     cmphi   r1, r0                  @
259     bhi     1b @clean_start         @
260     mov     r0, #0                  @
261     mcr     p15, 0, r0, c7, c10, 4  @ Drain write buffer
262     bx      lr                      @
263     .size   clean_dcache_range, .-clean_dcache_range
265 #if 0 /* unused */
267  * Dump DCache for this range
268  * will *NOT* do write back except for buffer edges not on a line boundary
269  * void dump_dcache_range(const void *base, unsigned int size);
270  */
271     .section   .text, "ax", %progbits
272     .align      2
273     .global     dump_dcache_range
274     .type       dump_dcache_range, %function
275     @ MVA format: 31:5 = Modified virtual address, 4:0 = SBZ
276  dump_dcache_range:
277     add     r1, r0, r1              @ size -> end
278     cmp     r1, r0                  @ end <= start?
279     bxls    lr                      @
280     tst     r0, #31                 @ Check first line for bits set
281     bicne   r0, r0, #31             @ Clear low five bits (down)
282     mcrne   p15, 0, r0, c7, c14, 1  @ Clean and invalidate line by MVA
283                                     @ if not cache aligned
284     addne   r0, r0, #32             @ Move to the next cache line
285                                     @
286     tst     r1, #31                 @ Check last line for bits set
287     bicne   r1, r1, #31             @ Clear low five bits (down)
288     mcrne   p15, 0, r1, c7, c14, 1  @ Clean and invalidate line by MVA
289                                     @ if not cache aligned
290     cmp     r1, r0                  @ end <= start now?
291 1:  @ dump_start                    @
292     mcrhi   p15, 0, r0, c7, c6, 1   @ Invalidate line by MVA
293     addhi   r0, r0, #32             @
294     cmphi   r1, r0                  @
295     mcrhi   p15, 0, r0, c7, c6, 1   @ Invalidate line by MVA
296     addhi   r0, r0, #32             @
297     cmphi   r1, r0                  @
298     mcrhi   p15, 0, r0, c7, c6, 1   @ Invalidate line by MVA
299     addhi   r0, r0, #32             @
300     cmphi   r1, r0                  @
301     mcrhi   p15, 0, r0, c7, c6, 1   @ Invalidate line by MVA
302     addhi   r0, r0, #32             @
303     cmphi   r1, r0                  @
304     mcrhi   p15, 0, r0, c7, c6, 1   @ Invalidate line by MVA
305     addhi   r0, r0, #32             @
306     cmphi   r1, r0                  @
307     mcrhi   p15, 0, r0, c7, c6, 1   @ Invalidate line by MVA
308     addhi   r0, r0, #32             @
309     cmphi   r1, r0                  @
310     mcrhi   p15, 0, r0, c7, c6, 1   @ Invalidate line by MVA
311     addhi   r0, r0, #32             @
312     cmphi   r1, r0                  @
313     mcrhi   p15, 0, r0, c7, c6, 1   @ Invalidate line by MVA
314     addhi   r0, r0, #32             @
315     cmphi   r1, r0                  @
316     bhi     1b @ dump_start         @
317     mov     r0, #0                  @
318     mcr     p15, 0, r0, c7, c10, 4  @ Drain write buffer
319     bx      lr                      @
320     .size   dump_dcache_range, .-dump_dcache_range
321 #endif /* unused function */
324  * Cleans entire DCache
325  * void clean_dcache(void);
326  */
327     .section   .text, "ax", %progbits
328     .align      2
329     .global     clean_dcache
330     .type       clean_dcache, %function
331     .global     cpucache_flush      @ Alias
332 clean_dcache:
333 cpucache_flush:
334 #ifdef HAVE_TEST_AND_CLEAN_CACHE
335     mrc     p15, 0, r15, c7, c10, 3 @ test and clean dcache
336     bne     clean_dcache
337     mov     r1, #0
338 #else
339     mov     r1, #0x00000000         @
340 1:  @ clean_start                   @
341     mcr     p15, 0, r1, c7, c10, 2  @ Clean entry by index
342     add     r0, r1, #(1<<CACHEALIGN_BITS)
343     mcr     p15, 0, r0, c7, c10, 2  @ Clean entry by index
344 .rept INDEX_STEPS - 2 /* 2 steps already executed */
345     add     r0, r0, #(1<<CACHEALIGN_BITS)
346     mcr     p15, 0, r0, c7, c10, 2  @ Clean entry by index
347 .endr
348     adds    r1, r1, #0x04000000     @ will wrap to zero at loop end
349     bne     1b @ clean_start        @
350 #endif /* HAVE_TEST_AND_CLEAN_CACHE */
351     mcr     p15, 0, r1, c7, c10, 4  @ Drain write buffer
352     bx      lr                      @
353     .size   clean_dcache, .-clean_dcache
356  * Invalidate entire DCache
357  * will do writeback
358  * void invalidate_dcache(void);
359  */
360     .section   .icode, "ax", %progbits
361     .align      2
362     .global     invalidate_dcache
363     .type       invalidate_dcache, %function
364 invalidate_dcache:
365 #ifdef HAVE_TEST_AND_CLEAN_CACHE
366     mrc     p15, 0, r15, c7, c14, 3 @ test, clean and invalidate dcache
367     bne     invalidate_dcache
368     mov     r1, #0
369 #else
370     mov     r1, #0x00000000         @
371 1:  @ inv_start                     @
372     mcr     p15, 0, r1, c7, c14, 2  @ Clean and invalidate entry by index
373     add     r0, r1, #(1<<CACHEALIGN_BITS)
374     mcr     p15, 0, r0, c7, c14, 2  @ Clean and invalidate entry by index
375 .rept INDEX_STEPS - 2 /* 2 steps already executed */
376     add     r0, r0, #(1<<CACHEALIGN_BITS)
377     mcr     p15, 0, r0, c7, c14, 2  @ Clean and invalidate entry by index
378 .endr
379     adds    r1, r1, #0x04000000     @ will wrap to zero at loop end
380     bne     1b @ inv_start          @
381 #endif /* HAVE_TEST_AND_CLEAN_CACHE */
382     mcr     p15, 0, r1, c7, c10, 4  @ Drain write buffer
383     bx      lr                      @
384     .size   invalidate_dcache, .-invalidate_dcache
387  * Invalidate entire ICache and DCache
388  * will do writeback
389  * void invalidate_idcache(void);
390  */
391     .section   .icode, "ax", %progbits
392     .align      2
393     .global     invalidate_idcache
394     .type       invalidate_idcache, %function
395     .global     cpucache_invalidate @ Alias
396 invalidate_idcache:
397 cpucache_invalidate:
398     mov     r2, lr                  @ save lr to r1, call uses r0 only
399     bl      invalidate_dcache       @ Clean and invalidate entire DCache
400     mcr     p15, 0, r1, c7, c5, 0   @ Invalidate ICache (r1=0 from call)
401     mov     pc, r2                  @
402     .size   invalidate_idcache, .-invalidate_idcache