hm60x/hm801: Buttons rework.
[maemo-rb.git] / firmware / target / arm / mmu-arm.S
blob522aa9f16f7a768ea1b0c75ada9850ec56267f77
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 USE_MMU
49 #define CACHE_SIZE 16
51 #else
52 #error Cache settings unknown for this CPU !
54 #endif /* CPU specific configuration */
56 @ Index format: 31:26 = index, N:5 = segment, remainder = SBZ
57 @ assume 64-way set associative separate I/D caches
58 @ CACHE_SIZE = N (kB) = N*2^10 B
59 @ number of lines = N*2^(10-CACHEALIGN_BITS)
60 @ Index bits = 6
61 @ Segment loops = N*2^(10-CACHEALIGN_BITS-6) = N*2^(4-CACHEALIGN_BITS)
62 @ Segment loops = N/2^(CACHEALIGN_BITS - 4)
63 @ Segment loops = N/(1<<(CACHEALIGN_BITS - 4))
65 #ifdef CACHE_SIZE
67 #if CACHEALIGN_BITS == 4
68 #define INDEX_STEPS CACHE_SIZE
69 #elif CACHEALIGN_BITS == 5
70 #define INDEX_STEPS (CACHE_SIZE/2)
71 #endif /* CACHEALIGN_BITS */
73 @ assume 64-way set associative separate I/D caches (log2(64) == 6)
74 @ Index format: 31:26 = index, M:N = segment, remainder = SBZ
75 @ Segment bits = log2(cache size in bytes / cache line size in byte) - Index bits (== 6)
76 @ N = CACHEALIGN_BITS
78 #endif /* CACHE_SIZE */
81 #ifdef USE_MMU
83 /** MMU setup **/
86  * void ttb_init(void);
87  */
88     .section    .text.ttb_init, "ax", %progbits
89     .align      2
90     .global     ttb_init
91     .type       ttb_init, %function
92 ttb_init:
93     ldr     r0, =TTB_BASE_ADDR      @
94     mvn     r1, #0                  @
95     mcr     p15, 0, r0, c2, c0, 0   @ Set the TTB base address
96     mcr     p15, 0, r1, c3, c0, 0   @ Set all domains to manager status
97     bx      lr                      @
98     .size   ttb_init, .-ttb_init
101  * void map_section(unsigned int pa, unsigned int va, int mb, int flags);
102  */
103     .section    .text.map_section, "ax", %progbits
104     .align      2
105     .global     map_section
106     .type       map_section, %function
107 map_section:
108     @ align to 1MB
109     @ pa &= (-1 << 20);
110     mov     r0, r0, lsr #20
111     mov     r0, r0, lsl #20
113     @ pa |= (flags | 0x412);
114     @ bit breakdown:
115     @  10:  superuser - r/w, user - no access
116     @  4:   should be "1"
117     @  3,2: Cache flags (flags (r3))
118     @  1:   Section signature
119     orr     r0, r0, r3
120     orr     r0, r0, #0x410
121     orr     r0, r0, #0x2
123     @ unsigned int* ttbPtr = TTB_BASE + (va >> 20);
124     @ sections are 1MB size
125     mov     r1, r1, lsr #20
126     ldr     r3, =TTB_BASE_ADDR
127     add     r1, r3, r1, lsl #0x2
129     @ Add MB to pa, flags are already present in pa, but addition
130     @ should not effect them
131     @
132     @ for( ; mb>0; mb--, pa += (1 << 20))
133     @ {
134     @     *(ttbPtr++) = pa;
135     @ }
136     cmp    r2, #0
137     bxle   lr
138     mov    r3, #0x0
139 1:  @ loop
140     str    r0, [r1], #4
141     add    r0, r0, #0x100000
142     add    r3, r3, #0x1
143     cmp    r2, r3
144     bne    1b @ loop
145     bx     lr
146     .size   map_section, .-map_section
149  * void enable_mmu(void);
150  */
151     .section    .text.enable_mmu, "ax", %progbits
152     .align      2
153     .global     enable_mmu
154     .type       enable_mmu, %function
155 enable_mmu:
156     mov     r0, #0                  @
157     mcr     p15, 0, r0, c8, c7, 0   @ invalidate TLB
158     mcr     p15, 0, r0, c7, c7,0    @ invalidate both i and dcache
159     mrc     p15, 0, r0, c1, c0, 0   @
160     orr     r0, r0, #1              @ enable mmu bit, i and dcache
161     orr     r0, r0, #1<<2           @ enable dcache
162     orr     r0, r0, #1<<12          @ enable icache
163     mcr     p15, 0, r0, c1, c0, 0   @
164     nop                             @
165     nop                             @
166     nop                             @
167     nop                             @
168     bx      lr                      @
169     .size   enable_mmu, .-enable_mmu
170     .ltorg
172 #endif  /* USE_MMU */
176 /** Cache coherency **/
179  * Write DCache back to RAM for the given range and remove cache lines
180  * from DCache afterwards
181  * void commit_discard_dcache_range(const void *base, unsigned int size);
182  */
183     .section   .text.commit_discard_dcache_range, "ax", %progbits
184     .align      2
185     .global     commit_discard_dcache_range
186     .type       commit_discard_dcache_range, %function
188     @ MVA format: 31:5 = Modified virtual address, 4:0 = SBZ
189 commit_discard_dcache_range:
190     add     r1, r0, r1              @ size -> end
191     cmp     r1, r0                  @ end <= start?
192     bxls    lr                      @
193     bic     r0, r0, #31             @ Align start to cache line (down)
194 1:  @ inv_start                     @
195     mcr     p15, 0, r0, c7, c14, 1  @ Clean and invalidate line by MVA
196     add     r0, r0, #32             @
197     cmp     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     mcrhi   p15, 0, r0, c7, c14, 1  @ Clean and invalidate line by MVA
214     addhi   r0, r0, #32             @
215     cmphi   r1, r0                  @
216     mcrhi   p15, 0, r0, c7, c14, 1  @ Clean and invalidate line by MVA
217     addhi   r0, r0, #32             @
218     cmphi   r1, r0                  @
219     bhi     1b @ inv_start          @
220     mov     r0, #0                  @
221     mcr     p15, 0, r0, c7, c10, 4  @ Drain write buffer
222     bx      lr                      @
223     .size   commit_discard_dcache_range, .-commit_discard_dcache_range
226  * Write DCache back to RAM for the given range
227  * void commit_dcache_range(const void *base, unsigned int size);
228  */
229     .section   .text.commit_dcache_range, "ax", %progbits
230     .align      2
231     .global     commit_dcache_range
232     .type       commit_dcache_range, %function
234     @ MVA format: 31:5 = Modified virtual address, 4:0 = SBZ
235 commit_dcache_range:
236     add     r1, r0, r1              @ size -> end
237     cmp     r1, r0                  @ end <= start?
238     bxls    lr                      @
239     bic     r0, r0, #31             @ Align start to cache line (down)
240 1:  @ clean_start                   @
241     mcr     p15, 0, r0, c7, c10, 1  @ Clean line by MVA
242     add     r0, r0, #32             @
243     cmp     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     mcrhi   p15, 0, r0, c7, c10, 1  @ Clean line by MVA
260     addhi   r0, r0, #32             @
261     cmphi   r1, r0                  @
262     mcrhi   p15, 0, r0, c7, c10, 1  @ Clean line by MVA
263     addhi   r0, r0, #32             @
264     cmphi   r1, r0                  @
265     bhi     1b @clean_start         @
266     mov     r0, #0                  @
267     mcr     p15, 0, r0, c7, c10, 4  @ Drain write buffer
268     bx      lr                      @
269     .size   commit_dcache_range, .-commit_dcache_range
272  * Remove cache lines for the given range from DCache
273  * will *NOT* do write back except for buffer edges not on a line boundary
274  * void discard_dcache_range(const void *base, unsigned int size);
275  */
276     .section   .text.discard_dcache_range, "ax", %progbits
277     .align      2
278     .global     discard_dcache_range
279     .type       discard_dcache_range, %function
281     @ MVA format: 31:5 = Modified virtual address, 4:0 = SBZ
282 discard_dcache_range:
283     add     r1, r0, r1              @ size -> end
284     cmp     r1, r0                  @ end <= start?
285     bxls    lr                      @
286     tst     r0, #31                 @ Check first line for bits set
287     bicne   r0, r0, #31             @ Clear low five bits (down)
288     mcrne   p15, 0, r0, c7, c14, 1  @ Clean and invalidate line by MVA
289                                     @ if not cache aligned
290     addne   r0, r0, #32             @ Move to the next cache line
291                                     @
292     tst     r1, #31                 @ Check last line for bits set
293     bicne   r1, r1, #31             @ Clear low five bits (down)
294     mcrne   p15, 0, r1, c7, c14, 1  @ Clean and invalidate line by MVA
295                                     @ if not cache aligned
296     cmp     r1, r0                  @ end <= start now?
297 1:  @ discard_start                    @
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     mcrhi   p15, 0, r0, c7, c6, 1   @ Invalidate line by MVA
317     addhi   r0, r0, #32             @
318     cmphi   r1, r0                  @
319     mcrhi   p15, 0, r0, c7, c6, 1   @ Invalidate line by MVA
320     addhi   r0, r0, #32             @
321     cmphi   r1, r0                  @
322     bhi     1b @ discard_start      @
323     mov     r0, #0                  @
324     mcr     p15, 0, r0, c7, c10, 4  @ Drain write buffer
325     bx      lr                      @
326     .size   discard_dcache_range, .-discard_dcache_range
329  * Write entire DCache back to RAM
330  * void commit_dcache(void);
331  */
332     .section   .text.commit_dcache, "ax", %progbits
333     .align      2
334     .global     commit_dcache
335     .type       commit_dcache, %function
337 commit_dcache:
338 #ifdef HAVE_TEST_AND_CLEAN_CACHE
339     mrc     p15, 0, r15, c7, c10, 3 @ test and clean dcache
340     bne     commit_dcache
341     mov     r1, #0
342 #else
343     mov     r1, #0x00000000         @
344 1:  @ commit_start                   @
345     mcr     p15, 0, r1, c7, c10, 2  @ Clean entry by index
346     add     r0, r1, #(1<<CACHEALIGN_BITS)
347     mcr     p15, 0, r0, c7, c10, 2  @ Clean entry by index
348 .rept INDEX_STEPS - 2 /* 2 steps already executed */
349     add     r0, r0, #(1<<CACHEALIGN_BITS)
350     mcr     p15, 0, r0, c7, c10, 2  @ Clean entry by index
351 .endr
352     adds    r1, r1, #0x04000000     @ will wrap to zero at loop end
353     bne     1b @ commit_start        @
354 #endif /* HAVE_TEST_AND_CLEAN_CACHE */
355     mcr     p15, 0, r1, c7, c10, 4  @ Drain write buffer
356     bx      lr                      @
357     .size   commit_dcache, .-commit_dcache
360  * Commit and discard entire DCache, will do writeback
361  * void commit_discard_dcache(void);
362  */
363     .section   .icode.commit_discard_dcache, "ax", %progbits
364     .align      2
365     .global     commit_discard_dcache
366     .type       commit_discard_dcache, %function
368 commit_discard_dcache:
369 #ifdef HAVE_TEST_AND_CLEAN_CACHE
370     mrc     p15, 0, r15, c7, c14, 3 @ test, clean and invalidate dcache
371     bne     commit_discard_dcache
372     mov     r1, #0
373 #else
374     mov     r1, #0x00000000         @
375 1:  @ inv_start                     @
376     mcr     p15, 0, r1, c7, c14, 2  @ Clean and invalidate entry by index
377     add     r0, r1, #(1<<CACHEALIGN_BITS)
378     mcr     p15, 0, r0, c7, c14, 2  @ Clean and invalidate entry by index
379 .rept INDEX_STEPS - 2 /* 2 steps already executed */
380     add     r0, r0, #(1<<CACHEALIGN_BITS)
381     mcr     p15, 0, r0, c7, c14, 2  @ Clean and invalidate entry by index
382 .endr
383     adds    r1, r1, #0x04000000     @ will wrap to zero at loop end
384     bne     1b @ inv_start          @
385 #endif /* HAVE_TEST_AND_CLEAN_CACHE */
386     mcr     p15, 0, r1, c7, c10, 4  @ Drain write buffer
387     bx      lr                      @
388     .size   commit_discard_dcache, .-commit_discard_dcache
391  * Discards the entire ICache, and commit+discards the entire DCache
392  * void commit_discard_idcache(void);
393  */
394     .section   .icode.commit_discard_idcache, "ax", %progbits
395     .align      2
396     .global     commit_discard_idcache
397     .type       commit_discard_idcache, %function
399 commit_discard_idcache:
400     mov     r2, lr                  @ save lr to r1, call uses r0 only
401     bl      commit_discard_dcache   @ commit and discard entire DCache
402     mcr     p15, 0, r1, c7, c5, 0   @ Invalidate ICache (r1=0 from call)
403     bx      r2
404     .size   commit_discard_idcache, .-commit_discard_idcache