Prepare new maemo release
[maemo-rb.git] / firmware / target / arm / mmu-arm.S
blob2458118186a3b6578d2a779ce22a8af300bb49d6
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 #define ASM
22 #include "config.h"
23 #include "cpu.h"
25 /* Used by ARMv4 & ARMv5 CPUs with cp15 register and MMU */
27 #if CONFIG_CPU == TCC7801 || CONFIG_CPU == AT91SAM9260
28 /* MMU present but unused */
29 #define HAVE_TEST_AND_CLEAN_CACHE
31 #elif CONFIG_CPU == DM320 || CONFIG_CPU == AS3525v2 || CONFIG_CPU == S5L8702
32 #define USE_MMU
33 #define HAVE_TEST_AND_CLEAN_CACHE
35 #elif CONFIG_CPU == AS3525
36 #define USE_MMU
37 #define CACHE_SIZE 8
39 #elif CONFIG_CPU == S3C2440
40 #define USE_MMU
41 #define CACHE_SIZE 16
43 #elif CONFIG_CPU == S5L8700 || CONFIG_CPU == S5L8701
44 /* MMU not present */
45 #define CACHE_SIZE 4
47 #elif CONFIG_CPU == IMX233
48 #define HAVE_TEST_AND_CLEAN_CACHE
49 #define USE_MMU
50 #define CACHE_SIZE 16
52 #else
53 #error Cache settings unknown for this CPU !
55 #endif /* CPU specific configuration */
57 @ Index format: 31:26 = index, N:5 = segment, remainder = SBZ
58 @ assume 64-way set associative separate I/D caches
59 @ CACHE_SIZE = N (kB) = N*2^10 B
60 @ number of lines = N*2^(10-CACHEALIGN_BITS)
61 @ Index bits = 6
62 @ Segment loops = N*2^(10-CACHEALIGN_BITS-6) = N*2^(4-CACHEALIGN_BITS)
63 @ Segment loops = N/2^(CACHEALIGN_BITS - 4)
64 @ Segment loops = N/(1<<(CACHEALIGN_BITS - 4))
66 #ifdef CACHE_SIZE
68 #if CACHEALIGN_BITS == 4
69 #define INDEX_STEPS CACHE_SIZE
70 #elif CACHEALIGN_BITS == 5
71 #define INDEX_STEPS (CACHE_SIZE/2)
72 #endif /* CACHEALIGN_BITS */
74 @ assume 64-way set associative separate I/D caches (log2(64) == 6)
75 @ Index format: 31:26 = index, M:N = segment, remainder = SBZ
76 @ Segment bits = log2(cache size in bytes / cache line size in byte) - Index bits (== 6)
77 @ N = CACHEALIGN_BITS
79 #endif /* CACHE_SIZE */
82 #ifdef USE_MMU
84 /** MMU setup **/
87  * void ttb_init(void);
88  */
89     .section    .text.ttb_init, "ax", %progbits
90     .align      2
91     .global     ttb_init
92     .type       ttb_init, %function
93 ttb_init:
94     ldr     r0, =TTB_BASE_ADDR      @
95     mvn     r1, #0                  @
96     mcr     p15, 0, r0, c2, c0, 0   @ Set the TTB base address
97     mcr     p15, 0, r1, c3, c0, 0   @ Set all domains to manager status
98     bx      lr                      @
99     .size   ttb_init, .-ttb_init
102  * void map_section(unsigned int pa, unsigned int va, int mb, int flags);
103  */
104     .section    .text.map_section, "ax", %progbits
105     .align      2
106     .global     map_section
107     .type       map_section, %function
108 map_section:
109     @ align to 1MB
110     @ pa &= (-1 << 20);
111     mov     r0, r0, lsr #20
112     mov     r0, r0, lsl #20
114     @ pa |= (flags | 0x412);
115     @ bit breakdown:
116     @  10:  superuser - r/w, user - no access
117     @  4:   should be "1"
118     @  3,2: Cache flags (flags (r3))
119     @  1:   Section signature
120     orr     r0, r0, r3
121     orr     r0, r0, #0x410
122     orr     r0, r0, #0x2
124     @ unsigned int* ttbPtr = TTB_BASE + (va >> 20);
125     @ sections are 1MB size
126     mov     r1, r1, lsr #20
127     ldr     r3, =TTB_BASE_ADDR
128     add     r1, r3, r1, lsl #0x2
130     @ Add MB to pa, flags are already present in pa, but addition
131     @ should not effect them
132     @
133     @ for( ; mb>0; mb--, pa += (1 << 20))
134     @ {
135     @     *(ttbPtr++) = pa;
136     @ }
137     cmp    r2, #0
138     bxle   lr
139     mov    r3, #0x0
140 1:  @ loop
141     str    r0, [r1], #4
142     add    r0, r0, #0x100000
143     add    r3, r3, #0x1
144     cmp    r2, r3
145     bne    1b @ loop
146     bx     lr
147     .size   map_section, .-map_section
150  * void enable_mmu(void);
151  */
152     .section    .text.enable_mmu, "ax", %progbits
153     .align      2
154     .global     enable_mmu
155     .type       enable_mmu, %function
156 enable_mmu:
157     mov     r0, #0                  @
158     mcr     p15, 0, r0, c8, c7, 0   @ invalidate TLB
159     mcr     p15, 0, r0, c7, c7,0    @ invalidate both i and dcache
160     mrc     p15, 0, r0, c1, c0, 0   @
161     orr     r0, r0, #1              @ enable mmu bit, i and dcache
162     orr     r0, r0, #1<<2           @ enable dcache
163     orr     r0, r0, #1<<12          @ enable icache
164     mcr     p15, 0, r0, c1, c0, 0   @
165     nop                             @
166     nop                             @
167     nop                             @
168     nop                             @
169     bx      lr                      @
170     .size   enable_mmu, .-enable_mmu
171     .ltorg
173 #endif  /* USE_MMU */
177 /** Cache coherency **/
180  * Write DCache back to RAM for the given range and remove cache lines
181  * from DCache afterwards
182  * void commit_discard_dcache_range(const void *base, unsigned int size);
183  */
184     .section   .text.commit_discard_dcache_range, "ax", %progbits
185     .align      2
186     .global     commit_discard_dcache_range
187     .type       commit_discard_dcache_range, %function
189     @ MVA format: 31:5 = Modified virtual address, 4:0 = SBZ
190 commit_discard_dcache_range:
191     add     r1, r0, r1              @ size -> end
192     cmp     r1, r0                  @ end <= start?
193     bxls    lr                      @
194     bic     r0, r0, #31             @ Align start to cache line (down)
195 1:  @ inv_start                     @
196     mcr     p15, 0, r0, c7, c14, 1  @ Clean and invalidate line by MVA
197     add     r0, r0, #32             @
198     cmp     r1, r0                  @
199     mcrhi   p15, 0, r0, c7, c14, 1  @ Clean and invalidate line by MVA
200     addhi   r0, r0, #32             @
201     cmphi   r1, r0                  @
202     mcrhi   p15, 0, r0, c7, c14, 1  @ Clean and invalidate line by MVA
203     addhi   r0, r0, #32             @
204     cmphi   r1, r0                  @
205     mcrhi   p15, 0, r0, c7, c14, 1  @ Clean and invalidate line by MVA
206     addhi   r0, r0, #32             @
207     cmphi   r1, r0                  @
208     mcrhi   p15, 0, r0, c7, c14, 1  @ Clean and invalidate line by MVA
209     addhi   r0, r0, #32             @
210     cmphi   r1, r0                  @
211     mcrhi   p15, 0, r0, c7, c14, 1  @ Clean and invalidate line by MVA
212     addhi   r0, r0, #32             @
213     cmphi   r1, r0                  @
214     mcrhi   p15, 0, r0, c7, c14, 1  @ Clean and invalidate line by MVA
215     addhi   r0, r0, #32             @
216     cmphi   r1, r0                  @
217     mcrhi   p15, 0, r0, c7, c14, 1  @ Clean and invalidate line by MVA
218     addhi   r0, r0, #32             @
219     cmphi   r1, r0                  @
220     bhi     1b @ inv_start          @
221     mov     r0, #0                  @
222     mcr     p15, 0, r0, c7, c10, 4  @ Drain write buffer
223     bx      lr                      @
224     .size   commit_discard_dcache_range, .-commit_discard_dcache_range
227  * Write DCache back to RAM for the given range
228  * void commit_dcache_range(const void *base, unsigned int size);
229  */
230     .section   .text.commit_dcache_range, "ax", %progbits
231     .align      2
232     .global     commit_dcache_range
233     .type       commit_dcache_range, %function
235     @ MVA format: 31:5 = Modified virtual address, 4:0 = SBZ
236 commit_dcache_range:
237     add     r1, r0, r1              @ size -> end
238     cmp     r1, r0                  @ end <= start?
239     bxls    lr                      @
240     bic     r0, r0, #31             @ Align start to cache line (down)
241 1:  @ clean_start                   @
242     mcr     p15, 0, r0, c7, c10, 1  @ Clean line by MVA
243     add     r0, r0, #32             @
244     cmp     r1, r0                  @
245     mcrhi   p15, 0, r0, c7, c10, 1  @ Clean line by MVA
246     addhi   r0, r0, #32             @
247     cmphi   r1, r0                  @
248     mcrhi   p15, 0, r0, c7, c10, 1  @ Clean line by MVA
249     addhi   r0, r0, #32             @
250     cmphi   r1, r0                  @
251     mcrhi   p15, 0, r0, c7, c10, 1  @ Clean line by MVA
252     addhi   r0, r0, #32             @
253     cmphi   r1, r0                  @
254     mcrhi   p15, 0, r0, c7, c10, 1  @ Clean line by MVA
255     addhi   r0, r0, #32             @
256     cmphi   r1, r0                  @
257     mcrhi   p15, 0, r0, c7, c10, 1  @ Clean line by MVA
258     addhi   r0, r0, #32             @
259     cmphi   r1, r0                  @
260     mcrhi   p15, 0, r0, c7, c10, 1  @ Clean line by MVA
261     addhi   r0, r0, #32             @
262     cmphi   r1, r0                  @
263     mcrhi   p15, 0, r0, c7, c10, 1  @ Clean line by MVA
264     addhi   r0, r0, #32             @
265     cmphi   r1, r0                  @
266     bhi     1b @clean_start         @
267     mov     r0, #0                  @
268     mcr     p15, 0, r0, c7, c10, 4  @ Drain write buffer
269     bx      lr                      @
270     .size   commit_dcache_range, .-commit_dcache_range
273  * Remove cache lines for the given range from DCache
274  * will *NOT* do write back except for buffer edges not on a line boundary
275  * void discard_dcache_range(const void *base, unsigned int size);
276  */
277     .section   .text.discard_dcache_range, "ax", %progbits
278     .align      2
279     .global     discard_dcache_range
280     .type       discard_dcache_range, %function
282     @ MVA format: 31:5 = Modified virtual address, 4:0 = SBZ
283 discard_dcache_range:
284     add     r1, r0, r1              @ size -> end
285     cmp     r1, r0                  @ end <= start?
286     bxls    lr                      @
287     tst     r0, #31                 @ Check first line for bits set
288     bicne   r0, r0, #31             @ Clear low five bits (down)
289     mcrne   p15, 0, r0, c7, c14, 1  @ Clean and invalidate line by MVA
290                                     @ if not cache aligned
291     addne   r0, r0, #32             @ Move to the next cache line
292                                     @
293     tst     r1, #31                 @ Check last line for bits set
294     bicne   r1, r1, #31             @ Clear low five bits (down)
295     mcrne   p15, 0, r1, c7, c14, 1  @ Clean and invalidate line by MVA
296                                     @ if not cache aligned
297     cmp     r1, r0                  @ end <= start now?
298 1:  @ discard_start                    @
299     mcrhi   p15, 0, r0, c7, c6, 1   @ Invalidate line by MVA
300     addhi   r0, r0, #32             @
301     cmphi   r1, r0                  @
302     mcrhi   p15, 0, r0, c7, c6, 1   @ Invalidate line by MVA
303     addhi   r0, r0, #32             @
304     cmphi   r1, r0                  @
305     mcrhi   p15, 0, r0, c7, c6, 1   @ Invalidate line by MVA
306     addhi   r0, r0, #32             @
307     cmphi   r1, r0                  @
308     mcrhi   p15, 0, r0, c7, c6, 1   @ Invalidate line by MVA
309     addhi   r0, r0, #32             @
310     cmphi   r1, r0                  @
311     mcrhi   p15, 0, r0, c7, c6, 1   @ Invalidate line by MVA
312     addhi   r0, r0, #32             @
313     cmphi   r1, r0                  @
314     mcrhi   p15, 0, r0, c7, c6, 1   @ Invalidate line by MVA
315     addhi   r0, r0, #32             @
316     cmphi   r1, r0                  @
317     mcrhi   p15, 0, r0, c7, c6, 1   @ Invalidate line by MVA
318     addhi   r0, r0, #32             @
319     cmphi   r1, r0                  @
320     mcrhi   p15, 0, r0, c7, c6, 1   @ Invalidate line by MVA
321     addhi   r0, r0, #32             @
322     cmphi   r1, r0                  @
323     bhi     1b @ discard_start      @
324     mov     r0, #0                  @
325     mcr     p15, 0, r0, c7, c10, 4  @ Drain write buffer
326     bx      lr                      @
327     .size   discard_dcache_range, .-discard_dcache_range
330  * Write entire DCache back to RAM
331  * void commit_dcache(void);
332  */
333     .section   .text.commit_dcache, "ax", %progbits
334     .align      2
335     .global     commit_dcache
336     .type       commit_dcache, %function
338 commit_dcache:
339 #ifdef HAVE_TEST_AND_CLEAN_CACHE
340     mrc     p15, 0, r15, c7, c10, 3 @ test and clean dcache
341     bne     commit_dcache
342     mov     r1, #0
343 #else
344     mov     r1, #0x00000000         @
345 1:  @ commit_start                   @
346     mcr     p15, 0, r1, c7, c10, 2  @ Clean entry by index
347     add     r0, r1, #(1<<CACHEALIGN_BITS)
348     mcr     p15, 0, r0, c7, c10, 2  @ Clean entry by index
349 .rept INDEX_STEPS - 2 /* 2 steps already executed */
350     add     r0, r0, #(1<<CACHEALIGN_BITS)
351     mcr     p15, 0, r0, c7, c10, 2  @ Clean entry by index
352 .endr
353     adds    r1, r1, #0x04000000     @ will wrap to zero at loop end
354     bne     1b @ commit_start        @
355 #endif /* HAVE_TEST_AND_CLEAN_CACHE */
356     mcr     p15, 0, r1, c7, c10, 4  @ Drain write buffer
357     bx      lr                      @
358     .size   commit_dcache, .-commit_dcache
361  * Commit and discard entire DCache, will do writeback
362  * void commit_discard_dcache(void);
363  */
364     .section   .icode.commit_discard_dcache, "ax", %progbits
365     .align      2
366     .global     commit_discard_dcache
367     .type       commit_discard_dcache, %function
369 commit_discard_dcache:
370 #ifdef HAVE_TEST_AND_CLEAN_CACHE
371     mrc     p15, 0, r15, c7, c14, 3 @ test, clean and invalidate dcache
372     bne     commit_discard_dcache
373     mov     r1, #0
374 #else
375     mov     r1, #0x00000000         @
376 1:  @ inv_start                     @
377     mcr     p15, 0, r1, c7, c14, 2  @ Clean and invalidate entry by index
378     add     r0, r1, #(1<<CACHEALIGN_BITS)
379     mcr     p15, 0, r0, c7, c14, 2  @ Clean and invalidate entry by index
380 .rept INDEX_STEPS - 2 /* 2 steps already executed */
381     add     r0, r0, #(1<<CACHEALIGN_BITS)
382     mcr     p15, 0, r0, c7, c14, 2  @ Clean and invalidate entry by index
383 .endr
384     adds    r1, r1, #0x04000000     @ will wrap to zero at loop end
385     bne     1b @ inv_start          @
386 #endif /* HAVE_TEST_AND_CLEAN_CACHE */
387     mcr     p15, 0, r1, c7, c10, 4  @ Drain write buffer
388     bx      lr                      @
389     .size   commit_discard_dcache, .-commit_discard_dcache
392  * Discards the entire ICache, and commit+discards the entire DCache
393  * void commit_discard_idcache(void);
394  */
395     .section   .icode.commit_discard_idcache, "ax", %progbits
396     .align      2
397     .global     commit_discard_idcache
398     .type       commit_discard_idcache, %function
400 commit_discard_idcache:
401     mov     r2, lr                  @ save lr to r1, call uses r0 only
402     bl      commit_discard_dcache   @ commit and discard entire DCache
403     mcr     p15, 0, r1, c7, c5, 0   @ Invalidate ICache (r1=0 from call)
404     bx      r2
405     .size   commit_discard_idcache, .-commit_discard_idcache