as3525: use DMA for recording
[kugel-rb.git] / firmware / target / arm / mmu-arm.S
blob2ffc834a0c453c5e9856717151c61b5c9c2aa6e5
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
266  * Dump DCache for this range
267  * will *NOT* do write back except for buffer edges not on a line boundary
268  * void dump_dcache_range(const void *base, unsigned int size);
269  */
270     .section   .text, "ax", %progbits
271     .align      2
272     .global     dump_dcache_range
273     .type       dump_dcache_range, %function
274     @ MVA format: 31:5 = Modified virtual address, 4:0 = SBZ
275  dump_dcache_range:
276     add     r1, r0, r1              @ size -> end
277     cmp     r1, r0                  @ end <= start?
278     bxls    lr                      @
279     tst     r0, #31                 @ Check first line for bits set
280     bicne   r0, r0, #31             @ Clear low five bits (down)
281     mcrne   p15, 0, r0, c7, c14, 1  @ Clean and invalidate line by MVA
282                                     @ if not cache aligned
283     addne   r0, r0, #32             @ Move to the next cache line
284                                     @
285     tst     r1, #31                 @ Check last line for bits set
286     bicne   r1, r1, #31             @ Clear low five bits (down)
287     mcrne   p15, 0, r1, c7, c14, 1  @ Clean and invalidate line by MVA
288                                     @ if not cache aligned
289     cmp     r1, r0                  @ end <= start now?
290 1:  @ dump_start                    @
291     mcrhi   p15, 0, r0, c7, c6, 1   @ Invalidate line by MVA
292     addhi   r0, r0, #32             @
293     cmphi   r1, r0                  @
294     mcrhi   p15, 0, r0, c7, c6, 1   @ Invalidate line by MVA
295     addhi   r0, r0, #32             @
296     cmphi   r1, r0                  @
297     mcrhi   p15, 0, r0, c7, c6, 1   @ Invalidate line by MVA
298     addhi   r0, r0, #32             @
299     cmphi   r1, r0                  @
300     mcrhi   p15, 0, r0, c7, c6, 1   @ Invalidate line by MVA
301     addhi   r0, r0, #32             @
302     cmphi   r1, r0                  @
303     mcrhi   p15, 0, r0, c7, c6, 1   @ Invalidate line by MVA
304     addhi   r0, r0, #32             @
305     cmphi   r1, r0                  @
306     mcrhi   p15, 0, r0, c7, c6, 1   @ Invalidate line by MVA
307     addhi   r0, r0, #32             @
308     cmphi   r1, r0                  @
309     mcrhi   p15, 0, r0, c7, c6, 1   @ Invalidate line by MVA
310     addhi   r0, r0, #32             @
311     cmphi   r1, r0                  @
312     mcrhi   p15, 0, r0, c7, c6, 1   @ Invalidate line by MVA
313     addhi   r0, r0, #32             @
314     cmphi   r1, r0                  @
315     bhi     1b @ dump_start         @
316     mov     r0, #0                  @
317     mcr     p15, 0, r0, c7, c10, 4  @ Drain write buffer
318     bx      lr                      @
319     .size   dump_dcache_range, .-dump_dcache_range
322  * Cleans entire DCache
323  * void clean_dcache(void);
324  */
325     .section   .text, "ax", %progbits
326     .align      2
327     .global     clean_dcache
328     .type       clean_dcache, %function
329     .global     cpucache_flush      @ Alias
330 clean_dcache:
331 cpucache_flush:
332 #ifdef HAVE_TEST_AND_CLEAN_CACHE
333     mrc     p15, 0, r15, c7, c10, 3 @ test and clean dcache
334     bne     clean_dcache
335     mov     r1, #0
336 #else
337     mov     r1, #0x00000000         @
338 1:  @ clean_start                   @
339     mcr     p15, 0, r1, c7, c10, 2  @ Clean entry by index
340     add     r0, r1, #(1<<CACHEALIGN_BITS)
341     mcr     p15, 0, r0, c7, c10, 2  @ Clean entry by index
342 .rept INDEX_STEPS - 2 /* 2 steps already executed */
343     add     r0, r0, #(1<<CACHEALIGN_BITS)
344     mcr     p15, 0, r0, c7, c10, 2  @ Clean entry by index
345 .endr
346     adds    r1, r1, #0x04000000     @ will wrap to zero at loop end
347     bne     1b @ clean_start        @
348 #endif /* HAVE_TEST_AND_CLEAN_CACHE */
349     mcr     p15, 0, r1, c7, c10, 4  @ Drain write buffer
350     bx      lr                      @
351     .size   clean_dcache, .-clean_dcache
354  * Invalidate entire DCache
355  * will do writeback
356  * void invalidate_dcache(void);
357  */
358     .section   .icode, "ax", %progbits
359     .align      2
360     .global     invalidate_dcache
361     .type       invalidate_dcache, %function
362 invalidate_dcache:
363 #ifdef HAVE_TEST_AND_CLEAN_CACHE
364     mrc     p15, 0, r15, c7, c14, 3 @ test, clean and invalidate dcache
365     bne     invalidate_dcache
366     mov     r1, #0
367 #else
368     mov     r1, #0x00000000         @
369 1:  @ inv_start                     @
370     mcr     p15, 0, r1, c7, c14, 2  @ Clean and invalidate entry by index
371     add     r0, r1, #(1<<CACHEALIGN_BITS)
372     mcr     p15, 0, r0, c7, c14, 2  @ Clean and invalidate entry by index
373 .rept INDEX_STEPS - 2 /* 2 steps already executed */
374     add     r0, r0, #(1<<CACHEALIGN_BITS)
375     mcr     p15, 0, r0, c7, c14, 2  @ Clean and invalidate entry by index
376 .endr
377     adds    r1, r1, #0x04000000     @ will wrap to zero at loop end
378     bne     1b @ inv_start          @
379 #endif /* HAVE_TEST_AND_CLEAN_CACHE */
380     mcr     p15, 0, r1, c7, c10, 4  @ Drain write buffer
381     bx      lr                      @
382     .size   invalidate_dcache, .-invalidate_dcache
385  * Invalidate entire ICache and DCache
386  * will do writeback
387  * void invalidate_idcache(void);
388  */
389     .section   .icode, "ax", %progbits
390     .align      2
391     .global     invalidate_idcache
392     .type       invalidate_idcache, %function
393     .global     cpucache_invalidate @ Alias
394 invalidate_idcache:
395 cpucache_invalidate:
396     mov     r2, lr                  @ save lr to r1, call uses r0 only
397     bl      invalidate_dcache       @ Clean and invalidate entire DCache
398     mcr     p15, 0, r1, c7, c5, 0   @ Invalidate ICache (r1=0 from call)
399     mov     pc, r2                  @
400     .size   invalidate_idcache, .-invalidate_idcache