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 ****************************************************************************/
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
33 #define HAVE_TEST_AND_CLEAN_CACHE
35 #elif CONFIG_CPU == AS3525
39 #elif CONFIG_CPU == S3C2440
43 #elif CONFIG_CPU == S5L8700 || CONFIG_CPU == S5L8701
47 #elif CONFIG_CPU == IMX233
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)
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))
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)
78 #endif /* CACHE_SIZE */
86 * void ttb_init(void);
88 .section .text.ttb_init, "ax", %progbits
91 .type ttb_init, %function
93 ldr r0, =TTB_BASE_ADDR @
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
98 .size ttb_init, .-ttb_init
101 * void map_section(unsigned int pa, unsigned int va, int mb, int flags);
103 .section .text.map_section, "ax", %progbits
106 .type map_section, %function
113 @ pa |= (flags | 0x412);
115 @ 10: superuser - r/w, user - no access
117 @ 3,2: Cache flags (flags (r3))
118 @ 1: Section signature
123 @ unsigned int* ttbPtr = TTB_BASE + (va >> 20);
124 @ sections are 1MB size
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
132 @ for( ; mb>0; mb--, pa += (1 << 20))
141 add r0, r0, #0x100000
146 .size map_section, .-map_section
149 * void enable_mmu(void);
151 .section .text.enable_mmu, "ax", %progbits
154 .type enable_mmu, %function
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 @
169 .size enable_mmu, .-enable_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);
183 .section .text.commit_discard_dcache_range, "ax", %progbits
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?
193 bic r0, r0, #31 @ Align start to cache line (down)
195 mcr 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
216 mcrhi p15, 0, r0, c7, c14, 1 @ Clean and invalidate line by MVA
221 mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer
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);
229 .section .text.commit_dcache_range, "ax", %progbits
231 .global commit_dcache_range
232 .type commit_dcache_range, %function
234 @ MVA format: 31:5 = Modified virtual address, 4:0 = SBZ
236 add r1, r0, r1 @ size -> end
237 cmp r1, r0 @ end <= start?
239 bic r0, r0, #31 @ Align start to cache line (down)
241 mcr p15, 0, r0, c7, c10, 1 @ Clean line by MVA
244 mcrhi p15, 0, r0, c7, c10, 1 @ Clean line by MVA
247 mcrhi p15, 0, r0, c7, c10, 1 @ Clean line by MVA
250 mcrhi p15, 0, r0, c7, c10, 1 @ Clean line by MVA
253 mcrhi p15, 0, r0, c7, c10, 1 @ Clean line by MVA
256 mcrhi p15, 0, r0, c7, c10, 1 @ Clean line by MVA
259 mcrhi p15, 0, r0, c7, c10, 1 @ Clean line by MVA
262 mcrhi p15, 0, r0, c7, c10, 1 @ Clean line by MVA
265 bhi 1b @clean_start @
267 mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer
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);
276 .section .text.discard_dcache_range, "ax", %progbits
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?
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
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?
298 mcrhi p15, 0, r0, c7, c6, 1 @ Invalidate line by MVA
301 mcrhi p15, 0, r0, c7, c6, 1 @ Invalidate line by MVA
304 mcrhi p15, 0, r0, c7, c6, 1 @ Invalidate line by MVA
307 mcrhi p15, 0, r0, c7, c6, 1 @ Invalidate line by MVA
310 mcrhi p15, 0, r0, c7, c6, 1 @ Invalidate line by MVA
313 mcrhi p15, 0, r0, c7, c6, 1 @ Invalidate line by MVA
316 mcrhi p15, 0, r0, c7, c6, 1 @ Invalidate line by MVA
319 mcrhi p15, 0, r0, c7, c6, 1 @ Invalidate line by MVA
322 bhi 1b @ discard_start @
324 mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer
326 .size discard_dcache_range, .-discard_dcache_range
329 * Write entire DCache back to RAM
330 * void commit_dcache(void);
332 .section .text.commit_dcache, "ax", %progbits
334 .global commit_dcache
335 .type commit_dcache, %function
338 #ifdef HAVE_TEST_AND_CLEAN_CACHE
339 mrc p15, 0, r15, c7, c10, 3 @ test and clean dcache
343 mov r1, #0x00000000 @
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
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
357 .size commit_dcache, .-commit_dcache
360 * Commit and discard entire DCache, will do writeback
361 * void commit_discard_dcache(void);
363 .section .icode.commit_discard_dcache, "ax", %progbits
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
374 mov r1, #0x00000000 @
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
383 adds r1, r1, #0x04000000 @ will wrap to zero at loop end
385 #endif /* HAVE_TEST_AND_CLEAN_CACHE */
386 mcr p15, 0, r1, c7, c10, 4 @ Drain write buffer
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);
394 .section .icode.commit_discard_idcache, "ax", %progbits
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)
404 .size commit_discard_idcache, .-commit_discard_idcache