1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2006,2007 by Greg White
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.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
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
32 #define HAVE_TEST_AND_CLEAN_CACHE
34 #elif CONFIG_CPU == AS3525
38 #elif CONFIG_CPU == S3C2440
42 #elif CONFIG_CPU == S5L8700 || CONFIG_CPU == S5L8701
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)
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))
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)
73 #endif /* CACHE_SIZE */
81 * void ttb_init(void);
83 .section .text, "ax", %progbits
86 .type ttb_init, %function
88 ldr r0, =TTB_BASE_ADDR @
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
93 .size ttb_init, .-ttb_init
96 * void map_section(unsigned int pa, unsigned int va, int mb, int flags);
98 .section .text, "ax", %progbits
101 .type map_section, %function
108 @ pa |= (flags | 0x412);
110 @ 10: superuser - r/w, user - no access
112 @ 3,2: Cache flags (flags (r3))
113 @ 1: Section signature
118 @ unsigned int* ttbPtr = TTB_BASE + (va >> 20);
119 @ sections are 1MB size
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
127 @ for( ; mb>0; mb--, pa += (1 << 20))
136 add r0, r0, #0x100000
141 .size map_section, .-map_section
144 * void enable_mmu(void);
146 .section .text, "ax", %progbits
149 .type enable_mmu, %function
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 @
164 .size enable_mmu, .-enable_mmu
171 /** Cache coherency **/
174 * Write DCache back to RAM for the given range and remove cache lines
175 * from DCache afterwards
176 * void commit_discard_dcache_range(const void *base, unsigned int size);
178 .section .text, "ax", %progbits
180 .global commit_discard_dcache_range
181 .type commit_discard_dcache_range, %function
182 .global invalidate_dcache_range @ Alias, deprecated
184 @ MVA format: 31:5 = Modified virtual address, 4:0 = SBZ
185 commit_discard_dcache_range:
186 invalidate_dcache_range:
187 add r1, r0, r1 @ size -> end
188 cmp r1, r0 @ end <= start?
190 bic r0, r0, #31 @ Align start to cache line (down)
192 mcr p15, 0, r0, c7, c14, 1 @ Clean and invalidate line by MVA
195 mcrhi p15, 0, r0, c7, c14, 1 @ Clean and invalidate line by MVA
198 mcrhi p15, 0, r0, c7, c14, 1 @ Clean and invalidate line by MVA
201 mcrhi p15, 0, r0, c7, c14, 1 @ Clean and invalidate line by MVA
204 mcrhi p15, 0, r0, c7, c14, 1 @ Clean and invalidate line by MVA
207 mcrhi p15, 0, r0, c7, c14, 1 @ Clean and invalidate line by MVA
210 mcrhi p15, 0, r0, c7, c14, 1 @ Clean and invalidate line by MVA
213 mcrhi p15, 0, r0, c7, c14, 1 @ Clean and invalidate line by MVA
218 mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer
220 .size commit_discard_dcache_range, .-commit_discard_dcache_range
223 * Write DCache back to RAM for the given range
224 * void commit_dcache_range(const void *base, unsigned int size);
226 .section .text, "ax", %progbits
228 .global commit_dcache_range
229 .type commit_dcache_range, %function
230 .global clean_dcache_range @ Alias, deprecated
232 @ MVA format: 31:5 = Modified virtual address, 4:0 = SBZ
235 add r1, r0, r1 @ size -> end
236 cmp r1, r0 @ end <= start?
238 bic r0, r0, #31 @ Align start to cache line (down)
240 mcr p15, 0, r0, c7, c10, 1 @ Clean line by MVA
243 mcrhi p15, 0, r0, c7, c10, 1 @ Clean line by MVA
246 mcrhi p15, 0, r0, c7, c10, 1 @ Clean line by MVA
249 mcrhi p15, 0, r0, c7, c10, 1 @ Clean line by MVA
252 mcrhi p15, 0, r0, c7, c10, 1 @ Clean line by MVA
255 mcrhi p15, 0, r0, c7, c10, 1 @ Clean line by MVA
258 mcrhi p15, 0, r0, c7, c10, 1 @ Clean line by MVA
261 mcrhi p15, 0, r0, c7, c10, 1 @ Clean line by MVA
264 bhi 1b @clean_start @
266 mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer
268 .size commit_dcache_range, .-commit_dcache_range
271 * Remove cache lines for the given range from DCache
272 * will *NOT* do write back except for buffer edges not on a line boundary
273 * void discard_dcache_range(const void *base, unsigned int size);
275 .section .text, "ax", %progbits
277 .global discard_dcache_range
278 .type discard_dcache_range, %function
279 .global dump_dcache_range @ Alias, deprecated
281 @ MVA format: 31:5 = Modified virtual address, 4:0 = SBZ
282 discard_dcache_range:
284 add r1, r0, r1 @ size -> end
285 cmp r1, r0 @ end <= start?
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
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?
299 mcrhi p15, 0, r0, c7, c6, 1 @ Invalidate line by MVA
302 mcrhi p15, 0, r0, c7, c6, 1 @ Invalidate line by MVA
305 mcrhi p15, 0, r0, c7, c6, 1 @ Invalidate line by MVA
308 mcrhi p15, 0, r0, c7, c6, 1 @ Invalidate line by MVA
311 mcrhi p15, 0, r0, c7, c6, 1 @ Invalidate line by MVA
314 mcrhi p15, 0, r0, c7, c6, 1 @ Invalidate line by MVA
317 mcrhi p15, 0, r0, c7, c6, 1 @ Invalidate line by MVA
320 mcrhi p15, 0, r0, c7, c6, 1 @ Invalidate line by MVA
323 bhi 1b @ discard_start @
325 mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer
327 .size discard_dcache_range, .-discard_dcache_range
330 * Write entire DCache back to RAM
331 * void commit_dcache(void);
333 .section .text, "ax", %progbits
335 .global commit_dcache
336 .type commit_dcache, %function
337 .global cpucache_commit @ Alias
338 .global clean_dcache @ Alias, deprecated
339 .global cpucache_flush @ Alias, deprecated
345 #ifdef HAVE_TEST_AND_CLEAN_CACHE
346 mrc p15, 0, r15, c7, c10, 3 @ test and clean dcache
350 mov r1, #0x00000000 @
352 mcr p15, 0, r1, c7, c10, 2 @ Clean entry by index
353 add r0, r1, #(1<<CACHEALIGN_BITS)
354 mcr p15, 0, r0, c7, c10, 2 @ Clean entry by index
355 .rept INDEX_STEPS - 2 /* 2 steps already executed */
356 add r0, r0, #(1<<CACHEALIGN_BITS)
357 mcr p15, 0, r0, c7, c10, 2 @ Clean entry by index
359 adds r1, r1, #0x04000000 @ will wrap to zero at loop end
360 bne 1b @ commit_start @
361 #endif /* HAVE_TEST_AND_CLEAN_CACHE */
362 mcr p15, 0, r1, c7, c10, 4 @ Drain write buffer
364 .size commit_dcache, .-commit_dcache
367 * Commit and discard entire DCache, will do writeback
368 * void commit_discard_dcache(void);
370 .section .icode, "ax", %progbits
372 .global commit_discard_dcache
373 .type commit_discard_dcache, %function
374 .global invalidate_dcache @ Alias, deprecated
376 commit_discard_dcache:
378 #ifdef HAVE_TEST_AND_CLEAN_CACHE
379 mrc p15, 0, r15, c7, c14, 3 @ test, clean and invalidate dcache
380 bne commit_discard_dcache
383 mov r1, #0x00000000 @
385 mcr p15, 0, r1, c7, c14, 2 @ Clean and invalidate entry by index
386 add r0, r1, #(1<<CACHEALIGN_BITS)
387 mcr p15, 0, r0, c7, c14, 2 @ Clean and invalidate entry by index
388 .rept INDEX_STEPS - 2 /* 2 steps already executed */
389 add r0, r0, #(1<<CACHEALIGN_BITS)
390 mcr p15, 0, r0, c7, c14, 2 @ Clean and invalidate entry by index
392 adds r1, r1, #0x04000000 @ will wrap to zero at loop end
394 #endif /* HAVE_TEST_AND_CLEAN_CACHE */
395 mcr p15, 0, r1, c7, c10, 4 @ Drain write buffer
397 .size commit_discard_dcache, .-commit_discard_dcache
400 * Discards the entire ICache, and commit+discards the entire DCache
401 * void commit_discard_idcache(void);
403 .section .icode, "ax", %progbits
405 .global commit_discard_idcache
406 .type commit_discard_idcache, %function
407 .global cpucache_commit_discard @ Alias
408 .global invalidate_idcache @ Alias, deprecated
409 .global cpucache_invalidate @ Alias, deprecated
411 commit_discard_idcache:
412 cpucache_commit_discard:
415 mov r2, lr @ save lr to r1, call uses r0 only
416 bl commit_discard_dcache @ commit and discard entire DCache
417 mcr p15, 0, r1, c7, c5, 0 @ Invalidate ICache (r1=0 from call)
419 .size commit_discard_idcache, .-commit_discard_idcache