]> git.sur5r.net Git - u-boot/blob - arch/arm/cpu/armv7/cache_v7_asm.S
bd27ab219c6a752043148ff21798727b725986f8
[u-boot] / arch / arm / cpu / armv7 / cache_v7_asm.S
1 /*
2  * SPDX-License-Identifier:     GPL-2.0+
3  */
4
5 #include <config.h>
6 #include <linux/linkage.h>
7 #include <linux/sizes.h>
8 #include <asm/system.h>
9
10 #if CONFIG_IS_ENABLED(SYS_THUMB_BUILD)
11 #define ARM(x...)
12 #define THUMB(x...)     x
13 #else
14 #define ARM(x...)       x
15 #define THUMB(x...)
16 #endif
17
18 /*
19  *      v7_flush_dcache_all()
20  *
21  *      Flush the whole D-cache.
22  *
23  *      Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode)
24  *
25  *      Note: copied from arch/arm/mm/cache-v7.S of Linux 4.4
26  */
27 ENTRY(__v7_flush_dcache_all)
28         dmb                                     @ ensure ordering with previous memory accesses
29         mrc     p15, 1, r0, c0, c0, 1           @ read clidr
30         mov     r3, r0, lsr #23                 @ move LoC into position
31         ands    r3, r3, #7 << 1                 @ extract LoC*2 from clidr
32         beq     finished                        @ if loc is 0, then no need to clean
33 start_flush_levels:
34         mov     r10, #0                         @ start clean at cache level 0
35 flush_levels:
36         add     r2, r10, r10, lsr #1            @ work out 3x current cache level
37         mov     r1, r0, lsr r2                  @ extract cache type bits from clidr
38         and     r1, r1, #7                      @ mask of the bits for current cache only
39         cmp     r1, #2                          @ see what cache we have at this level
40         blt     skip                            @ skip if no cache, or just i-cache
41         mcr     p15, 2, r10, c0, c0, 0          @ select current cache level in cssr
42         isb                                     @ isb to sych the new cssr&csidr
43         mrc     p15, 1, r1, c0, c0, 0           @ read the new csidr
44         and     r2, r1, #7                      @ extract the length of the cache lines
45         add     r2, r2, #4                      @ add 4 (line length offset)
46         movw    r4, #0x3ff
47         ands    r4, r4, r1, lsr #3              @ find maximum number on the way size
48         clz     r5, r4                          @ find bit position of way size increment
49         movw    r7, #0x7fff
50         ands    r7, r7, r1, lsr #13             @ extract max number of the index size
51 loop1:
52         mov     r9, r7                          @ create working copy of max index
53 loop2:
54  ARM(   orr     r11, r10, r4, lsl r5    )       @ factor way and cache number into r11
55  THUMB( lsl     r6, r4, r5              )
56  THUMB( orr     r11, r10, r6            )       @ factor way and cache number into r11
57  ARM(   orr     r11, r11, r9, lsl r2    )       @ factor index number into r11
58  THUMB( lsl     r6, r9, r2              )
59  THUMB( orr     r11, r11, r6            )       @ factor index number into r11
60         mcr     p15, 0, r11, c7, c14, 2         @ clean & invalidate by set/way
61         subs    r9, r9, #1                      @ decrement the index
62         bge     loop2
63         subs    r4, r4, #1                      @ decrement the way
64         bge     loop1
65 skip:
66         add     r10, r10, #2                    @ increment cache number
67         cmp     r3, r10
68         bgt     flush_levels
69 finished:
70         mov     r10, #0                         @ swith back to cache level 0
71         mcr     p15, 2, r10, c0, c0, 0          @ select current cache level in cssr
72         dsb     st
73         isb
74         bx      lr
75 ENDPROC(__v7_flush_dcache_all)
76
77 ENTRY(v7_flush_dcache_all)
78  ARM(   stmfd   sp!, {r4-r5, r7, r9-r11, lr}    )
79  THUMB( stmfd   sp!, {r4-r7, r9-r11, lr}        )
80         bl      __v7_flush_dcache_all
81  ARM(   ldmfd   sp!, {r4-r5, r7, r9-r11, lr}    )
82  THUMB( ldmfd   sp!, {r4-r7, r9-r11, lr}        )
83         bx      lr
84 ENDPROC(v7_flush_dcache_all)
85
86 /*
87  *      v7_invalidate_dcache_all()
88  *
89  *      Invalidate the whole D-cache.
90  *
91  *      Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode)
92  *
93  *      Note: copied from __v7_flush_dcache_all above with
94  *      mcr     p15, 0, r11, c7, c14, 2
95  *      Replaced with:
96  *      mcr     p15, 0, r11, c7, c6, 2
97  */
98 ENTRY(__v7_invalidate_dcache_all)
99         dmb                                     @ ensure ordering with previous memory accesses
100         mrc     p15, 1, r0, c0, c0, 1           @ read clidr
101         mov     r3, r0, lsr #23                 @ move LoC into position
102         ands    r3, r3, #7 << 1                 @ extract LoC*2 from clidr
103         beq     inval_finished                  @ if loc is 0, then no need to clean
104         mov     r10, #0                         @ start clean at cache level 0
105 inval_levels:
106         add     r2, r10, r10, lsr #1            @ work out 3x current cache level
107         mov     r1, r0, lsr r2                  @ extract cache type bits from clidr
108         and     r1, r1, #7                      @ mask of the bits for current cache only
109         cmp     r1, #2                          @ see what cache we have at this level
110         blt     inval_skip                      @ skip if no cache, or just i-cache
111         mcr     p15, 2, r10, c0, c0, 0          @ select current cache level in cssr
112         isb                                     @ isb to sych the new cssr&csidr
113         mrc     p15, 1, r1, c0, c0, 0           @ read the new csidr
114         and     r2, r1, #7                      @ extract the length of the cache lines
115         add     r2, r2, #4                      @ add 4 (line length offset)
116         movw    r4, #0x3ff
117         ands    r4, r4, r1, lsr #3              @ find maximum number on the way size
118         clz     r5, r4                          @ find bit position of way size increment
119         movw    r7, #0x7fff
120         ands    r7, r7, r1, lsr #13             @ extract max number of the index size
121 inval_loop1:
122         mov     r9, r7                          @ create working copy of max index
123 inval_loop2:
124  ARM(   orr     r11, r10, r4, lsl r5    )       @ factor way and cache number into r11
125  THUMB( lsl     r6, r4, r5              )
126  THUMB( orr     r11, r10, r6            )       @ factor way and cache number into r11
127  ARM(   orr     r11, r11, r9, lsl r2    )       @ factor index number into r11
128  THUMB( lsl     r6, r9, r2              )
129  THUMB( orr     r11, r11, r6            )       @ factor index number into r11
130         mcr     p15, 0, r11, c7, c6, 2          @ invalidate by set/way
131         subs    r9, r9, #1                      @ decrement the index
132         bge     inval_loop2
133         subs    r4, r4, #1                      @ decrement the way
134         bge     inval_loop1
135 inval_skip:
136         add     r10, r10, #2                    @ increment cache number
137         cmp     r3, r10
138         bgt     inval_levels
139 inval_finished:
140         mov     r10, #0                         @ swith back to cache level 0
141         mcr     p15, 2, r10, c0, c0, 0          @ select current cache level in cssr
142         dsb     st
143         isb
144         bx      lr
145 ENDPROC(__v7_invalidate_dcache_all)
146
147 ENTRY(v7_invalidate_dcache_all)
148  ARM(   stmfd   sp!, {r4-r5, r7, r9-r11, lr}    )
149  THUMB( stmfd   sp!, {r4-r7, r9-r11, lr}        )
150         bl      __v7_invalidate_dcache_all
151  ARM(   ldmfd   sp!, {r4-r5, r7, r9-r11, lr}    )
152  THUMB( ldmfd   sp!, {r4-r7, r9-r11, lr}        )
153         bx      lr
154 ENDPROC(v7_invalidate_dcache_all)