Merge tag 'trace-printf-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/trace...
[drm/drm-misc.git] / arch / arm / mm / cache-v6.S
blob9f415476e2183dbd1fc8b351f71526341dace87f
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 <linux/cfi_types.h>
12 #include <asm/assembler.h>
13 #include <asm/errno.h>
14 #include <asm/unwind.h>
16 #include "proc-macros.S"
18 #define HARVARD_CACHE
19 #define CACHE_LINE_SIZE         32
20 #define D_CACHE_LINE_SIZE       32
21 #define BTB_FLUSH_SIZE          8
23 .arch armv6
26  *      v6_flush_icache_all()
27  *
28  *      Flush the whole I-cache.
29  *
30  *      ARM1136 erratum 411920 - Invalidate Instruction Cache operation can fail.
31  *      This erratum is present in 1136, 1156 and 1176. It does not affect the
32  *      MPCore.
33  *
34  *      Registers:
35  *      r0 - set to 0
36  *      r1 - corrupted
37  */
38 SYM_TYPED_FUNC_START(v6_flush_icache_all)
39         mov     r0, #0
40 #ifdef CONFIG_ARM_ERRATA_411920
41         mrs     r1, cpsr
42         cpsid   ifa                             @ disable interrupts
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         mcr     p15, 0, r0, c7, c5, 0           @ invalidate entire I-cache
47         msr     cpsr_cx, r1                     @ restore interrupts
48         .rept   11                              @ ARM Ltd recommends at least
49         nop                                     @ 11 NOPs
50         .endr
51 #else
52         mcr     p15, 0, r0, c7, c5, 0           @ invalidate I-cache
53 #endif
54         ret     lr
55 SYM_FUNC_END(v6_flush_icache_all)
58  *      v6_flush_cache_all()
59  *
60  *      Flush the entire cache.
61  *
62  *      It is assumed that:
63  */
64 SYM_TYPED_FUNC_START(v6_flush_kern_cache_all)
65         mov     r0, #0
66 #ifdef HARVARD_CACHE
67         mcr     p15, 0, r0, c7, c14, 0          @ D cache clean+invalidate
68 #ifndef CONFIG_ARM_ERRATA_411920
69         mcr     p15, 0, r0, c7, c5, 0           @ I+BTB cache invalidate
70 #else
71         b       v6_flush_icache_all
72 #endif
73 #else
74         mcr     p15, 0, r0, c7, c15, 0          @ Cache clean+invalidate
75 #endif
76         ret     lr
77 SYM_FUNC_END(v6_flush_kern_cache_all)
80  *      v6_flush_cache_all()
81  *
82  *      Flush all TLB entries in a particular address space
83  *
84  *      - mm    - mm_struct describing address space
85  */
86 SYM_TYPED_FUNC_START(v6_flush_user_cache_all)
87         ret     lr
88 SYM_FUNC_END(v6_flush_user_cache_all)
91  *      v6_flush_cache_range(start, end, flags)
92  *
93  *      Flush a range of TLB entries in the specified address space.
94  *
95  *      - start - start address (may not be aligned)
96  *      - end   - end address (exclusive, may not be aligned)
97  *      - flags - vm_area_struct flags describing address space
98  *
99  *      It is assumed that:
100  *      - we have a VIPT cache.
101  */
102 SYM_TYPED_FUNC_START(v6_flush_user_cache_range)
103         ret     lr
104 SYM_FUNC_END(v6_flush_user_cache_range)
107  *      v6_coherent_kern_range(start,end)
109  *      Ensure that the I and D caches are coherent within specified
110  *      region.  This is typically used when code has been written to
111  *      a memory region, and will be executed.
113  *      - start   - virtual start address of region
114  *      - end     - virtual end address of region
116  *      It is assumed that:
117  *      - the Icache does not read data from the write buffer
118  */
119 SYM_TYPED_FUNC_START(v6_coherent_kern_range)
120 #ifdef CONFIG_CFI_CLANG /* Fallthrough if !CFI */
121         b       v6_coherent_user_range
122 #endif
123 SYM_FUNC_END(v6_coherent_kern_range)
126  *      v6_coherent_user_range(start,end)
128  *      Ensure that the I and D caches are coherent within specified
129  *      region.  This is typically used when code has been written to
130  *      a memory region, and will be executed.
132  *      - start   - virtual start address of region
133  *      - end     - virtual end address of region
135  *      It is assumed that:
136  *      - the Icache does not read data from the write buffer
137  */
138 SYM_TYPED_FUNC_START(v6_coherent_user_range)
139  UNWIND(.fnstart                )
140 #ifdef HARVARD_CACHE
141         bic     r0, r0, #CACHE_LINE_SIZE - 1
143  USER(  mcr     p15, 0, r0, c7, c10, 1  )       @ clean D line
144         add     r0, r0, #CACHE_LINE_SIZE
145         cmp     r0, r1
146         blo     1b
147 #endif
148         mov     r0, #0
149 #ifdef HARVARD_CACHE
150         mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
151 #ifndef CONFIG_ARM_ERRATA_411920
152         mcr     p15, 0, r0, c7, c5, 0           @ I+BTB cache invalidate
153 #else
154         b       v6_flush_icache_all
155 #endif
156 #else
157         mcr     p15, 0, r0, c7, c5, 6           @ invalidate BTB
158 #endif
159         ret     lr
162  * Fault handling for the cache operation above. If the virtual address in r0
163  * isn't mapped, fail with -EFAULT.
164  */
165 9001:
166         mov     r0, #-EFAULT
167         ret     lr
168  UNWIND(.fnend          )
169 SYM_FUNC_END(v6_coherent_user_range)
172  *      v6_flush_kern_dcache_area(void *addr, size_t size)
174  *      Ensure that the data held in the page kaddr is written back
175  *      to the page in question.
177  *      - addr  - kernel address
178  *      - size  - region size
179  */
180 SYM_TYPED_FUNC_START(v6_flush_kern_dcache_area)
181         add     r1, r0, r1
182         bic     r0, r0, #D_CACHE_LINE_SIZE - 1
184 #ifdef HARVARD_CACHE
185         mcr     p15, 0, r0, c7, c14, 1          @ clean & invalidate D line
186 #else
187         mcr     p15, 0, r0, c7, c15, 1          @ clean & invalidate unified line
188 #endif  
189         add     r0, r0, #D_CACHE_LINE_SIZE
190         cmp     r0, r1
191         blo     1b
192 #ifdef HARVARD_CACHE
193         mov     r0, #0
194         mcr     p15, 0, r0, c7, c10, 4
195 #endif
196         ret     lr
197 SYM_FUNC_END(v6_flush_kern_dcache_area)
200  *      v6_dma_inv_range(start,end)
202  *      Invalidate the data cache within the specified region; we will
203  *      be performing a DMA operation in this region and we want to
204  *      purge old data in the cache.
206  *      - start   - virtual start address of region
207  *      - end     - virtual end address of region
208  */
209 v6_dma_inv_range:
210         tst     r0, #D_CACHE_LINE_SIZE - 1
211         bic     r0, r0, #D_CACHE_LINE_SIZE - 1
212 #ifdef HARVARD_CACHE
213         mcrne   p15, 0, r0, c7, c10, 1          @ clean D line
214 #else
215         mcrne   p15, 0, r0, c7, c11, 1          @ clean unified line
216 #endif
217         tst     r1, #D_CACHE_LINE_SIZE - 1
218         bic     r1, r1, #D_CACHE_LINE_SIZE - 1
219 #ifdef HARVARD_CACHE
220         mcrne   p15, 0, r1, c7, c14, 1          @ clean & invalidate D line
221 #else
222         mcrne   p15, 0, r1, c7, c15, 1          @ clean & invalidate unified line
223 #endif
225 #ifdef HARVARD_CACHE
226         mcr     p15, 0, r0, c7, c6, 1           @ invalidate D line
227 #else
228         mcr     p15, 0, r0, c7, c7, 1           @ invalidate unified line
229 #endif
230         add     r0, r0, #D_CACHE_LINE_SIZE
231         cmp     r0, r1
232         blo     1b
233         mov     r0, #0
234         mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
235         ret     lr
238  *      v6_dma_clean_range(start,end)
239  *      - start   - virtual start address of region
240  *      - end     - virtual end address of region
241  */
242 v6_dma_clean_range:
243         bic     r0, r0, #D_CACHE_LINE_SIZE - 1
245 #ifdef HARVARD_CACHE
246         mcr     p15, 0, r0, c7, c10, 1          @ clean D line
247 #else
248         mcr     p15, 0, r0, c7, c11, 1          @ clean unified line
249 #endif
250         add     r0, r0, #D_CACHE_LINE_SIZE
251         cmp     r0, r1
252         blo     1b
253         mov     r0, #0
254         mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
255         ret     lr
258  *      v6_dma_flush_range(start,end)
259  *      - start   - virtual start address of region
260  *      - end     - virtual end address of region
261  */
262 SYM_TYPED_FUNC_START(v6_dma_flush_range)
263         bic     r0, r0, #D_CACHE_LINE_SIZE - 1
265 #ifdef HARVARD_CACHE
266         mcr     p15, 0, r0, c7, c14, 1          @ clean & invalidate D line
267 #else
268         mcr     p15, 0, r0, c7, c15, 1          @ clean & invalidate line
269 #endif
270         add     r0, r0, #D_CACHE_LINE_SIZE
271         cmp     r0, r1
272         blo     1b
273         mov     r0, #0
274         mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
275         ret     lr
276 SYM_FUNC_END(v6_dma_flush_range)
279  *      dma_map_area(start, size, dir)
280  *      - start - kernel virtual start address
281  *      - size  - size of region
282  *      - dir   - DMA direction
283  */
284 SYM_TYPED_FUNC_START(v6_dma_map_area)
285         add     r1, r1, r0
286         teq     r2, #DMA_FROM_DEVICE
287         beq     v6_dma_inv_range
288         b       v6_dma_clean_range
289 SYM_FUNC_END(v6_dma_map_area)
292  *      dma_unmap_area(start, size, dir)
293  *      - start - kernel virtual start address
294  *      - size  - size of region
295  *      - dir   - DMA direction
296  */
297 SYM_TYPED_FUNC_START(v6_dma_unmap_area)
298         add     r1, r1, r0
299         teq     r2, #DMA_TO_DEVICE
300         bne     v6_dma_inv_range
301         ret     lr
302 SYM_FUNC_END(v6_dma_unmap_area)