Merge tag 'powerpc-6.6-5' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc...
[platform/kernel/linux-starfive.git] / arch / arm / mm / cache-v6.S
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  *  linux/arch/arm/mm/cache-v6.S
4  *
5  *  Copyright (C) 2001 Deep Blue Solutions Ltd.
6  *
7  *  This is the "shell" of the ARMv6 processor support.
8  */
9 #include <linux/linkage.h>
10 #include <linux/init.h>
11 #include <asm/assembler.h>
12 #include <asm/errno.h>
13 #include <asm/unwind.h>
14
15 #include "proc-macros.S"
16
17 #define HARVARD_CACHE
18 #define CACHE_LINE_SIZE         32
19 #define D_CACHE_LINE_SIZE       32
20 #define BTB_FLUSH_SIZE          8
21
22 .arch armv6
23
24 /*
25  *      v6_flush_icache_all()
26  *
27  *      Flush the whole I-cache.
28  *
29  *      ARM1136 erratum 411920 - Invalidate Instruction Cache operation can fail.
30  *      This erratum is present in 1136, 1156 and 1176. It does not affect the
31  *      MPCore.
32  *
33  *      Registers:
34  *      r0 - set to 0
35  *      r1 - corrupted
36  */
37 ENTRY(v6_flush_icache_all)
38         mov     r0, #0
39 #ifdef CONFIG_ARM_ERRATA_411920
40         mrs     r1, cpsr
41         cpsid   ifa                             @ disable interrupts
42         mcr     p15, 0, r0, c7, c5, 0           @ invalidate entire I-cache
43         mcr     p15, 0, r0, c7, c5, 0           @ invalidate entire I-cache
44         mcr     p15, 0, r0, c7, c5, 0           @ invalidate entire I-cache
45         mcr     p15, 0, r0, c7, c5, 0           @ invalidate entire I-cache
46         msr     cpsr_cx, r1                     @ restore interrupts
47         .rept   11                              @ ARM Ltd recommends at least
48         nop                                     @ 11 NOPs
49         .endr
50 #else
51         mcr     p15, 0, r0, c7, c5, 0           @ invalidate I-cache
52 #endif
53         ret     lr
54 ENDPROC(v6_flush_icache_all)
55
56 /*
57  *      v6_flush_cache_all()
58  *
59  *      Flush the entire cache.
60  *
61  *      It is assumed that:
62  */
63 ENTRY(v6_flush_kern_cache_all)
64         mov     r0, #0
65 #ifdef HARVARD_CACHE
66         mcr     p15, 0, r0, c7, c14, 0          @ D cache clean+invalidate
67 #ifndef CONFIG_ARM_ERRATA_411920
68         mcr     p15, 0, r0, c7, c5, 0           @ I+BTB cache invalidate
69 #else
70         b       v6_flush_icache_all
71 #endif
72 #else
73         mcr     p15, 0, r0, c7, c15, 0          @ Cache clean+invalidate
74 #endif
75         ret     lr
76
77 /*
78  *      v6_flush_cache_all()
79  *
80  *      Flush all TLB entries in a particular address space
81  *
82  *      - mm    - mm_struct describing address space
83  */
84 ENTRY(v6_flush_user_cache_all)
85         /*FALLTHROUGH*/
86
87 /*
88  *      v6_flush_cache_range(start, end, flags)
89  *
90  *      Flush a range of TLB entries in the specified address space.
91  *
92  *      - start - start address (may not be aligned)
93  *      - end   - end address (exclusive, may not be aligned)
94  *      - flags - vm_area_struct flags describing address space
95  *
96  *      It is assumed that:
97  *      - we have a VIPT cache.
98  */
99 ENTRY(v6_flush_user_cache_range)
100         ret     lr
101
102 /*
103  *      v6_coherent_kern_range(start,end)
104  *
105  *      Ensure that the I and D caches are coherent within specified
106  *      region.  This is typically used when code has been written to
107  *      a memory region, and will be executed.
108  *
109  *      - start   - virtual start address of region
110  *      - end     - virtual end address of region
111  *
112  *      It is assumed that:
113  *      - the Icache does not read data from the write buffer
114  */
115 ENTRY(v6_coherent_kern_range)
116         /* FALLTHROUGH */
117
118 /*
119  *      v6_coherent_user_range(start,end)
120  *
121  *      Ensure that the I and D caches are coherent within specified
122  *      region.  This is typically used when code has been written to
123  *      a memory region, and will be executed.
124  *
125  *      - start   - virtual start address of region
126  *      - end     - virtual end address of region
127  *
128  *      It is assumed that:
129  *      - the Icache does not read data from the write buffer
130  */
131 ENTRY(v6_coherent_user_range)
132  UNWIND(.fnstart                )
133 #ifdef HARVARD_CACHE
134         bic     r0, r0, #CACHE_LINE_SIZE - 1
135 1:
136  USER(  mcr     p15, 0, r0, c7, c10, 1  )       @ clean D line
137         add     r0, r0, #CACHE_LINE_SIZE
138         cmp     r0, r1
139         blo     1b
140 #endif
141         mov     r0, #0
142 #ifdef HARVARD_CACHE
143         mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
144 #ifndef CONFIG_ARM_ERRATA_411920
145         mcr     p15, 0, r0, c7, c5, 0           @ I+BTB cache invalidate
146 #else
147         b       v6_flush_icache_all
148 #endif
149 #else
150         mcr     p15, 0, r0, c7, c5, 6           @ invalidate BTB
151 #endif
152         ret     lr
153
154 /*
155  * Fault handling for the cache operation above. If the virtual address in r0
156  * isn't mapped, fail with -EFAULT.
157  */
158 9001:
159         mov     r0, #-EFAULT
160         ret     lr
161  UNWIND(.fnend          )
162 ENDPROC(v6_coherent_user_range)
163 ENDPROC(v6_coherent_kern_range)
164
165 /*
166  *      v6_flush_kern_dcache_area(void *addr, size_t size)
167  *
168  *      Ensure that the data held in the page kaddr is written back
169  *      to the page in question.
170  *
171  *      - addr  - kernel address
172  *      - size  - region size
173  */
174 ENTRY(v6_flush_kern_dcache_area)
175         add     r1, r0, r1
176         bic     r0, r0, #D_CACHE_LINE_SIZE - 1
177 1:
178 #ifdef HARVARD_CACHE
179         mcr     p15, 0, r0, c7, c14, 1          @ clean & invalidate D line
180 #else
181         mcr     p15, 0, r0, c7, c15, 1          @ clean & invalidate unified line
182 #endif  
183         add     r0, r0, #D_CACHE_LINE_SIZE
184         cmp     r0, r1
185         blo     1b
186 #ifdef HARVARD_CACHE
187         mov     r0, #0
188         mcr     p15, 0, r0, c7, c10, 4
189 #endif
190         ret     lr
191
192
193 /*
194  *      v6_dma_inv_range(start,end)
195  *
196  *      Invalidate the data cache within the specified region; we will
197  *      be performing a DMA operation in this region and we want to
198  *      purge old data in the cache.
199  *
200  *      - start   - virtual start address of region
201  *      - end     - virtual end address of region
202  */
203 v6_dma_inv_range:
204 #ifdef CONFIG_DMA_CACHE_RWFO
205         ldrb    r2, [r0]                        @ read for ownership
206         strb    r2, [r0]                        @ write for ownership
207 #endif
208         tst     r0, #D_CACHE_LINE_SIZE - 1
209         bic     r0, r0, #D_CACHE_LINE_SIZE - 1
210 #ifdef HARVARD_CACHE
211         mcrne   p15, 0, r0, c7, c10, 1          @ clean D line
212 #else
213         mcrne   p15, 0, r0, c7, c11, 1          @ clean unified line
214 #endif
215         tst     r1, #D_CACHE_LINE_SIZE - 1
216 #ifdef CONFIG_DMA_CACHE_RWFO
217         ldrbne  r2, [r1, #-1]                   @ read for ownership
218         strbne  r2, [r1, #-1]                   @ write for ownership
219 #endif
220         bic     r1, r1, #D_CACHE_LINE_SIZE - 1
221 #ifdef HARVARD_CACHE
222         mcrne   p15, 0, r1, c7, c14, 1          @ clean & invalidate D line
223 #else
224         mcrne   p15, 0, r1, c7, c15, 1          @ clean & invalidate unified line
225 #endif
226 1:
227 #ifdef HARVARD_CACHE
228         mcr     p15, 0, r0, c7, c6, 1           @ invalidate D line
229 #else
230         mcr     p15, 0, r0, c7, c7, 1           @ invalidate unified line
231 #endif
232         add     r0, r0, #D_CACHE_LINE_SIZE
233         cmp     r0, r1
234 #ifdef CONFIG_DMA_CACHE_RWFO
235         ldrlo   r2, [r0]                        @ read for ownership
236         strlo   r2, [r0]                        @ write for ownership
237 #endif
238         blo     1b
239         mov     r0, #0
240         mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
241         ret     lr
242
243 /*
244  *      v6_dma_clean_range(start,end)
245  *      - start   - virtual start address of region
246  *      - end     - virtual end address of region
247  */
248 v6_dma_clean_range:
249         bic     r0, r0, #D_CACHE_LINE_SIZE - 1
250 1:
251 #ifdef CONFIG_DMA_CACHE_RWFO
252         ldr     r2, [r0]                        @ read for ownership
253 #endif
254 #ifdef HARVARD_CACHE
255         mcr     p15, 0, r0, c7, c10, 1          @ clean D line
256 #else
257         mcr     p15, 0, r0, c7, c11, 1          @ clean unified line
258 #endif
259         add     r0, r0, #D_CACHE_LINE_SIZE
260         cmp     r0, r1
261         blo     1b
262         mov     r0, #0
263         mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
264         ret     lr
265
266 /*
267  *      v6_dma_flush_range(start,end)
268  *      - start   - virtual start address of region
269  *      - end     - virtual end address of region
270  */
271 ENTRY(v6_dma_flush_range)
272 #ifdef CONFIG_DMA_CACHE_RWFO
273         ldrb    r2, [r0]                @ read for ownership
274         strb    r2, [r0]                @ write for ownership
275 #endif
276         bic     r0, r0, #D_CACHE_LINE_SIZE - 1
277 1:
278 #ifdef HARVARD_CACHE
279         mcr     p15, 0, r0, c7, c14, 1          @ clean & invalidate D line
280 #else
281         mcr     p15, 0, r0, c7, c15, 1          @ clean & invalidate line
282 #endif
283         add     r0, r0, #D_CACHE_LINE_SIZE
284         cmp     r0, r1
285 #ifdef CONFIG_DMA_CACHE_RWFO
286         ldrblo  r2, [r0]                        @ read for ownership
287         strblo  r2, [r0]                        @ write for ownership
288 #endif
289         blo     1b
290         mov     r0, #0
291         mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
292         ret     lr
293
294 /*
295  *      dma_map_area(start, size, dir)
296  *      - start - kernel virtual start address
297  *      - size  - size of region
298  *      - dir   - DMA direction
299  */
300 ENTRY(v6_dma_map_area)
301         add     r1, r1, r0
302         teq     r2, #DMA_FROM_DEVICE
303         beq     v6_dma_inv_range
304 #ifndef CONFIG_DMA_CACHE_RWFO
305         b       v6_dma_clean_range
306 #else
307         teq     r2, #DMA_TO_DEVICE
308         beq     v6_dma_clean_range
309         b       v6_dma_flush_range
310 #endif
311 ENDPROC(v6_dma_map_area)
312
313 /*
314  *      dma_unmap_area(start, size, dir)
315  *      - start - kernel virtual start address
316  *      - size  - size of region
317  *      - dir   - DMA direction
318  */
319 ENTRY(v6_dma_unmap_area)
320 #ifndef CONFIG_DMA_CACHE_RWFO
321         add     r1, r1, r0
322         teq     r2, #DMA_TO_DEVICE
323         bne     v6_dma_inv_range
324 #endif
325         ret     lr
326 ENDPROC(v6_dma_unmap_area)
327
328         .globl  v6_flush_kern_cache_louis
329         .equ    v6_flush_kern_cache_louis, v6_flush_kern_cache_all
330
331         __INITDATA
332
333         @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
334         define_cache_functions v6