de0b53fcce3a2d9e50e842c07d1b7668c05e9966
[3rdparty/ote_partner/tlk.git] / arch / arm / arm / cache-ops.S
1 /*
2  * Copyright (c) 2008-2013 Travis Geiselbrecht
3  * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files
7  * (the "Software"), to deal in the Software without restriction,
8  * including without limitation the rights to use, copy, modify, merge,
9  * publish, distribute, sublicense, and/or sell copies of the Software,
10  * and to permit persons to whom the Software is furnished to do so,
11  * subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 #include <asm.h>
25 #include <arch/ops.h>
26 #include <arch/defines.h>
27
28 .text
29
30 #if ARM_WITH_CACHE
31
32 /* low level cache routines for various cpu families */
33
34 #if ARM_CPU_ARM1136 || ARM_CPU_ARM926
35
36 /* void arch_disable_cache(uint flags) */
37 FUNCTION(arch_disable_cache)
38         mov             r12, #0                 @ zero register
39         mrs             r3, cpsr                @ save the old interrupt state
40 #if ARM_ISA_ARMv6
41         cpsid   iaf                             @ interrupts disabled
42 #else
43         orr             r3, r3, #(1<<7)
44         msr             cpsr, r3
45 #endif
46
47 .Ldcache_disable:
48         tst             r0, #DCACHE
49         beq             .Licache_disable
50         mrc             p15, 0, r1, c1, c0, 0   @ cr1
51         tst             r1, #(1<<2)             @ is the dcache already disabled?
52         beq             .Licache_disable
53
54         bic             r1, #(1<<2)
55         mcr             p15, 0, r1, c1, c0, 0   @ disable dcache
56
57 #if ARM_CPU_ARM1136
58     mcr     p15, 0, r12, c7, c14, 0             @ clean & invalidate dcache
59 #elif ARM_CPU_ARM926
60 0:
61         mrc             p15, 0, r15, c7, c14, 3 @ clean & invalidate dcache
62         bne             0b
63 #else
64 #error whut?
65 #endif
66         mcr             p15, 0, r0, c7, c10, 4  @ data sync barrier (formerly drain write buffer)
67
68 .Licache_disable:
69         tst             r0, #ICACHE
70         beq             .Ldone_disable
71
72         mrc     p15, 0, r1, c1, c0, 0           @ cr1
73         bic             r1, #(1<<12)
74         mcr             p15, 0, r1, c1, c0, 0   @ disable icache
75
76         mcr             p15, 0, r12, c7, c5, 0  @ invalidate icache
77
78 .Ldone_disable:
79         msr             cpsr, r3
80         bx              lr
81
82 /* void arch_enable_cache(uint flags) */
83 FUNCTION(arch_enable_cache)
84         mov             r12, #0                 @ zero register
85         mrs             r3, cpsr                @ save the old interrupt state
86 #if ARM_ISA_ARMv6
87         cpsid iaf                               @ interrupts disabled
88 #else
89         orr             r3, r3, #(1<<7)
90         msr             cpsr, r3
91 #endif
92
93 .Ldcache_enable:
94         tst             r0, #DCACHE
95         beq             .Licache_enable
96         mrc             p15, 0, r1, c1, c0, 0           @ cr1
97         tst             r1, #(1<<2)             @ is the dcache already enabled?
98         bne             .Licache_enable
99
100         mcr             p15, 0, r12, c7, c6, 0          @ invalidate dcache
101
102         orr             r1, #(1<<2)
103         mcr             p15, 0, r1, c1, c0, 0           @ enable dcache
104
105 .Licache_enable:
106         tst             r0, #ICACHE
107         beq             .Ldone_enable
108
109         mcr             p15, 0, r12, c7, c5, 0          @ invalidate icache
110
111         mrc             p15, 0, r1, c1, c0, 0           @ cr1
112         orr             r1, #(1<<12)
113         mcr             p15, 0, r1, c1, c0, 0           @ enable icache
114
115 .Ldone_enable:
116         msr             cpsr, r3
117         bx              lr
118
119 #elif ARM_CPU_CORTEX_A9 || ARM_CPU_CORTEX_A15
120
121 /* void arch_disable_cache(uint flags) */
122 FUNCTION(arch_disable_cache)
123         stmfd   sp!, {r4-r11, lr}
124         mov     r7, r0                          @ save flags
125         mrs     r12, cpsr                       @ save the old interrupt state
126         cpsid   iaf                             @ cpsid iaf, interrupts disabled
127
128 .Ldcache_disable:
129         tst     r7, #DCACHE
130         beq     .Licache_disable
131         mrc     p15, 0, r0, c1, c0, 0           @ system control register
132         tst     r0, #(1<<2)                     @ is the dcache already disabled?
133         beq     .Licache_disable
134
135         dmb
136         bic     r0, #(1<<2)
137         mcr     p15, 0, r0, c1, c0, 0           @ disable dcache
138
139         @ flush and invalidate the dcache
140         @ NOTE: trashes a bunch of registers, can't be spilling stuff to the stack
141         bl      flush_invalidate_cache_v7
142
143 #if ARM_WITH_L2
144         mrc     p15, 0, r0, c1, c0, 1           @ auxiliary control register
145         bic     r0, #(1<<1)
146         mcr     p15, 0, r0, c1, c0, 1           @ disable L2 dcache
147 #endif
148
149 .Licache_disable:
150         tst     r7, #ICACHE
151         beq     .Ldone_disable
152         mrc     p15, 0, r0, c1, c0, 0           @ system control register
153         tst     r0, #(1<<12)                    @ is the icache already disabled?
154         beq     .Ldone_disable
155
156         bic     r0, #(1<<12)
157         mcr     p15, 0, r0, c1, c0, 0           @ disable icache
158         mov     r0, #0
159         mcr     p15, 0, r0, c7, c5, 0           @ invalidate icache to PoU
160
161 .Ldone_disable:
162         mov     r0, #0
163         msr     cpsr, r12
164         ldmfd   sp!, {r4-r11, pc}
165
166 /* void arch_enable_cache(uint flags) */
167 FUNCTION(arch_enable_cache)
168         stmfd   sp!, {r4-r11, lr}
169         mov     r7, r0                          @ save flags
170         mrs     r12, cpsr                       @ save the old interrupt state
171         cpsid   iaf                             @ cpsid iaf, interrupts disabled
172
173 .Ldcache_enable:
174         tst     r7, #DCACHE
175         beq     .Licache_enable
176         mrc     p15, 0, r0, c1, c0, 0           @ system control register
177         tst     r0, #(1<<2)                     @ is the dcache already enabled?
178         bne     .Licache_enable
179
180         @ invalidate L1 and L2
181         @ NOTE: trashes a bunch of registers, can't be spilling stuff to the stack
182 #if ARM_WITH_L2
183         bl      invalidate_cache_v7
184
185         @ enable the L2, if present
186         mrc     p15, 0, r0, c1, c0, 1           @ auxiliary control register
187         orr     r0, #(1<<1)
188         mcr     p15, 0, r0, c1, c0, 1           @ enable L2 dcache
189 #endif
190
191         dmb
192         mrc     p15, 0, r0, c1, c0, 0           @ system control register
193         orr     r0, #(1<<2)
194         dsb
195         mcr     p15, 0, r0, c1, c0, 0           @ enable dcache
196
197 .Licache_enable:
198         tst     r7, #ICACHE
199         beq     .Ldone_enable
200
201 #if ARM_CPU_CORTEX_A9
202         mov     r0, #0
203         mcr     p15, 0, r0, c7, c5, 0           @ invalidate icache to PoU
204 #endif
205         mrc     p15, 0, r0, c1, c0, 0           @ system control register
206         orr     r0, #(1<<12)
207         mcr     p15, 0, r0, c1, c0, 0           @ enable icache
208
209 .Ldone_enable:
210         msr     cpsr, r12
211         ldmfd   sp!, {r4-r11, pc}
212
213 @ flush & invalidate cache routine, trashes r0-r6, r9-r11
214 flush_invalidate_cache_v7:
215 /*
216  * Clean and flush the cache to maintain consistency.
217  * From ARMv7 manual, B2-17
218  *
219  * On exit,
220  *  r1, r2, r3, r9, r10, r11, r12 corrupted
221  * This routine must preserve:
222  *  r4, r6, r7, r8
223  */
224         mrc     p15, 0, r10, c0, c1, 5  @ read ID_MMFR1
225         tst     r10, #0xf << 16         @ hierarchical cache (ARMv7)
226         mov     r10, #0
227         beq     hierarchical
228         mcr     p15, 0, r10, c7, c14, 0 @ clean+invalidate D
229         b       iflush
230 hierarchical:
231         mcr     p15, 0, r10, c7, c10, 5 @ DMB
232         stmfd   sp!, {r0-r7, r9-r11}
233         mrc     p15, 1, r0, c0, c0, 1   @ read clidr
234         ands    r3, r0, #0x7000000      @ extract loc from clidr
235         mov     r3, r3, lsr #23         @ left align loc bit field
236         beq     finished                @ if loc is 0, then no need to clean
237         mov     r10, #0                 @ start clean at cache level 0
238 loop1:
239         add     r2, r10, r10, lsr #1    @ work out 3x current cache level
240         mov     r1, r0, lsr r2          @ extract cache type bits from clidr
241         and     r1, r1, #7              @ mask of the bits for current cache only
242         cmp     r1, #2                  @ see what cache we have at this level
243         blt     skip                    @ skip if no cache, or just i-cache
244         mcr     p15, 2, r10, c0, c0, 0  @ select current cache level in cssr
245         mcr     p15, 0, r10, c7, c5, 4  @ isb to sych the new cssr&csidr
246         mrc     p15, 1, r1, c0, c0, 0   @ read the new csidr
247         and     r2, r1, #7              @ extract the length of the cache lines
248         add     r2, r2, #4              @ add 4 (line length offset)
249         ldr     r4, =0x3ff
250         ands    r4, r4, r1, lsr #3      @ find maximum number on the way size
251         clz     r5, r4                  @ find bit position of way size increment
252         ldr     r7, =0x7fff
253         ands    r7, r7, r1, lsr #13     @ extract max number of the index size
254 loop2:
255         mov     r9, r4                  @ create working copy of max way size
256 loop3:
257         orr     r11, r10, r9, lsl r5    @ factor way and cache number into r11
258         orr     r11, r11, r7, lsl r2    @ factor index number into r11
259         mcr     p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way
260         subs    r9, r9, #1              @ decrement the way
261         bge     loop3
262         subs    r7, r7, #1              @ decrement the index
263         bge     loop2
264 skip:
265         add     r10, r10, #2            @ increment cache number
266         cmp     r3, r10
267         bgt     loop1
268 finished:
269         ldmfd   sp!, {r0-r7, r9-r11}
270         mov     r10, #0                 @ swith back to cache level 0
271         mcr     p15, 2, r10, c0, c0, 0  @ select current cache level in cssr
272         dsb
273         isb
274         mov     pc, lr
275 iflush:
276         mcr     p15, 0, r10, c7, c10, 4 @ DSB
277         mcr     p15, 0, r10, c7, c5, 0  @ invalidate I+BTB
278         mcr     p15, 0, r10, c7, c10, 4 @ DSB
279         mcr     p15, 0, r10, c7, c5, 4  @ ISB
280         mov     pc, lr
281
282 /*
283  *      invalidate_cache_v7
284  *
285  *      Corrupted registers: r0-r7, r9-r11
286  */
287 invalidate_cache_v7:
288         dmb                                     @ ensure ordering with previous memory accesses
289         mrc     p15, 1, r0, c0, c0, 1           @ read clidr
290         ands    r3, r0, #0x7000000              @ extract loc from clidr
291         mov     r3, r3, lsr #23                 @ left align loc bit field
292         beq     1005f                           @ if loc is 0, then no need to clean
293         mov     r10, #0                         @ start clean at cache level 0
294 1001:
295         add     r2, r10, r10, lsr #1            @ work out 3x current cache level
296         mov     r1, r0, lsr r2                  @ extract cache type bits from clidr
297         and     r1, r1, #7                      @ mask of the bits for current cache only
298         cmp     r1, #2                          @ see what cache we have at this level
299         blt     1004f                           @ skip if no cache, or just i-cache
300
301         mcr     p15, 2, r10, c0, c0, 0          @ select current cache level in cssr
302         isb                                     @ isb to sych the new cssr&csidr
303         mrc     p15, 1, r1, c0, c0, 0           @ read the new csidr
304
305         and     r2, r1, #7                      @ extract the length of the cache lines
306         add     r2, r2, #4                      @ add 4 (line length offset)
307         ldr     r4, =0x3ff
308         ands    r4, r4, r1, lsr #3              @ find maximum number on the way size
309         clz     r5, r4                          @ find bit position of way size increment
310         ldr     r7, =0x7fff
311         ands    r7, r7, r1, lsr #13             @ extract max number of the index size
312 1002:
313         mov     r9, r4                          @ create working copy of max way size
314 1003:
315         orr     r11, r10, r9, lsl r5            @ factor way and cache number into r11
316         orr     r11, r11, r7, lsl r2            @ factor index number into r11
317         mcr     p15, 0, r11, c7, c6, 2          @ invalidate by set/way
318         subs    r9, r9, #1                      @ decrement the way
319         bge     1003b
320         subs    r7, r7, #1                      @ decrement the index
321         bge     1002b
322 1004:
323         add     r10, r10, #2                    @ increment cache number
324         cmp     r3, r10
325         bgt     1001b
326 1005:
327         mov     r10, #0                         @ switch back to cache level 0
328         mcr     p15, 2, r10, c0, c0, 0          @ select current cache level in cssr
329         dsb
330         isb
331         mov     pc, lr
332
333 #else
334 #error unhandled cpu
335 #endif
336
337 #if ARM_CPU_ARM926 || ARM_CPU_ARM1136 || ARM_CPU_CORTEX_A8 || ARM_CPU_CORTEX_A9 || ARM_CPU_CORTEX_A15
338 /* shared cache flush routines */
339
340         /* void arch_flush_cache_range(addr_t start, size_t len); */
341 FUNCTION(arch_clean_cache_range)
342 #if ARM_WITH_CP15
343         add             r2, r0, r1                                      // calculate the end address
344         bic             r0, #(CACHE_LINE-1)                     // align the start with a cache line
345 0:
346         mcr             p15, 0, r0, c7, c10, 1          // clean cache to PoC by MVA
347         add             r0, r0, #CACHE_LINE
348         cmp             r0, r2
349         blo             0b
350
351         /* copied from ops.S */
352 #if defined(ARM_CPU_CORTEX_A8) || defined(ARM_CPU_CORTEX_A9) || defined(ARM_CPU_CORTEX_A15)
353         dsb             sy
354 #elif ARM_CPU_ARM1136
355         mov             r0, #0
356         mcr             p15, 0, r0, c7, c10, 4          // data sync barrier
357 #endif
358 #endif
359         bx              lr
360
361         /* void arch_flush_invalidate_cache_range(addr_t start, size_t len); */
362 FUNCTION(arch_clean_invalidate_cache_range)
363 #if ARM_WITH_CP15
364         add             r2, r0, r1                                      // calculate the end address
365         bic             r0, #(CACHE_LINE-1)                     // align the start with a cache line
366 0:
367         mcr             p15, 0, r0, c7, c14, 1          // clean & invalidate dcache to PoC by MVA
368         add             r0, r0, #CACHE_LINE
369         cmp             r0, r2
370         blo             0b
371
372         /* copied from ops.S */
373 #if defined(ARM_CPU_CORTEX_A8) || defined(ARM_CPU_CORTEX_A9) || defined(ARM_CPU_CORTEX_A15)
374         dsb             sy
375 #elif ARM_CPU_ARM1136
376         mov             r0, #0
377         mcr             p15, 0, r0, c7, c10, 4          // data sync barrier
378 #endif
379 #endif
380         bx              lr
381
382         /* void arch_invalidate_cache_range(addr_t start, size_t len); */
383 FUNCTION(arch_invalidate_cache_range)
384 #if ARM_WITH_CP15
385         add             r2, r0, r1                                      // calculate the end address
386         bic             r0, #(CACHE_LINE-1)                     // align the start with a cache line
387 0:
388         mcr             p15, 0, r0, c7, c6, 1           // invalidate dcache to PoC by MVA
389         add             r0, r0, #CACHE_LINE
390         cmp             r0, r2
391         blo             0b
392
393         /* copied from ops.S */
394 #if defined(ARM_CPU_CORTEX_A8) || defined(ARM_CPU_CORTEX_A9) || defined(ARM_CPU_CORTEX_A15)
395         dsb             sy
396 #elif ARM_CPU_ARM1136
397         mov             r0, #0
398         mcr             p15, 0, r0, c7, c10, 4          // data sync barrier
399 #endif
400 #endif
401         bx              lr
402
403         /* void arch_sync_cache_range(addr_t start, size_t len); */
404 FUNCTION(arch_sync_cache_range)
405         push    { r14 }
406         bl      arch_clean_cache_range
407
408         mov     r0, #0
409         mcr     p15, 0, r0, c7, c5, 0       // invalidate icache to PoU
410
411         pop     { pc }
412
413 #endif // ARM_CPU_...
414
415 #else
416
417 /* no cache */
418
419 FUNCTION(arch_disable_cache)
420         bx              lr
421
422 FUNCTION(arch_enable_cache)
423         bx              lr
424
425 FUNCTION(arch_clean_cache_range)
426         bx              lr
427
428 FUNCTION(arch_clean_invalidate_cache_range)
429         bx              lr
430
431 FUNCTION(arch_sync_cache_range)
432         bx              lr
433
434 #endif // ARM_WITH_CACHE
435