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-fa.S
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  *  linux/arch/arm/mm/cache-fa.S
4  *
5  *  Copyright (C) 2005 Faraday Corp.
6  *  Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
7  *
8  * Based on cache-v4wb.S:
9  *  Copyright (C) 1997-2002 Russell king
10  *
11  *  Processors: FA520 FA526 FA626       
12  */
13 #include <linux/linkage.h>
14 #include <linux/init.h>
15 #include <asm/assembler.h>
16 #include <asm/page.h>
17
18 #include "proc-macros.S"
19
20 /*
21  * The size of one data cache line.
22  */
23 #define CACHE_DLINESIZE 16
24
25 /*
26  * The total size of the data cache.
27  */
28 #ifdef CONFIG_ARCH_GEMINI
29 #define CACHE_DSIZE     8192
30 #else
31 #define CACHE_DSIZE     16384 
32 #endif 
33
34 /* FIXME: put optimal value here. Current one is just estimation */
35 #define CACHE_DLIMIT    (CACHE_DSIZE * 2)
36
37 /*
38  *      flush_icache_all()
39  *
40  *      Unconditionally clean and invalidate the entire icache.
41  */
42 ENTRY(fa_flush_icache_all)
43         mov     r0, #0
44         mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
45         ret     lr
46 ENDPROC(fa_flush_icache_all)
47
48 /*
49  *      flush_user_cache_all()
50  *
51  *      Clean and invalidate all cache entries in a particular address
52  *      space.
53  */
54 ENTRY(fa_flush_user_cache_all)
55         /* FALLTHROUGH */
56 /*
57  *      flush_kern_cache_all()
58  *
59  *      Clean and invalidate the entire cache.
60  */
61 ENTRY(fa_flush_kern_cache_all)
62         mov     ip, #0
63         mov     r2, #VM_EXEC
64 __flush_whole_cache:
65         mcr     p15, 0, ip, c7, c14, 0          @ clean/invalidate D cache
66         tst     r2, #VM_EXEC
67         mcrne   p15, 0, ip, c7, c5, 0           @ invalidate I cache
68         mcrne   p15, 0, ip, c7, c5, 6           @ invalidate BTB
69         mcrne   p15, 0, ip, c7, c10, 4          @ drain write buffer
70         mcrne   p15, 0, ip, c7, c5, 4           @ prefetch flush
71         ret     lr
72
73 /*
74  *      flush_user_cache_range(start, end, flags)
75  *
76  *      Invalidate a range of cache entries in the specified
77  *      address space.
78  *
79  *      - start - start address (inclusive, page aligned)
80  *      - end   - end address (exclusive, page aligned)
81  *      - flags - vma_area_struct flags describing address space
82  */
83 ENTRY(fa_flush_user_cache_range)
84         mov     ip, #0
85         sub     r3, r1, r0                      @ calculate total size
86         cmp     r3, #CACHE_DLIMIT               @ total size >= limit?
87         bhs     __flush_whole_cache             @ flush whole D cache
88
89 1:      tst     r2, #VM_EXEC
90         mcrne   p15, 0, r0, c7, c5, 1           @ invalidate I line
91         mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate D entry
92         add     r0, r0, #CACHE_DLINESIZE
93         cmp     r0, r1
94         blo     1b
95         tst     r2, #VM_EXEC
96         mcrne   p15, 0, ip, c7, c5, 6           @ invalidate BTB
97         mcrne   p15, 0, ip, c7, c10, 4          @ data write barrier
98         mcrne   p15, 0, ip, c7, c5, 4           @ prefetch flush
99         ret     lr
100
101 /*
102  *      coherent_kern_range(start, end)
103  *
104  *      Ensure coherency between the Icache and the Dcache in the
105  *      region described by start.  If you have non-snooping
106  *      Harvard caches, you need to implement this function.
107  *
108  *      - start  - virtual start address
109  *      - end    - virtual end address
110  */
111 ENTRY(fa_coherent_kern_range)
112         /* fall through */
113
114 /*
115  *      coherent_user_range(start, end)
116  *
117  *      Ensure coherency between the Icache and the Dcache in the
118  *      region described by start.  If you have non-snooping
119  *      Harvard caches, you need to implement this function.
120  *
121  *      - start  - virtual start address
122  *      - end    - virtual end address
123  */
124 ENTRY(fa_coherent_user_range)
125         bic     r0, r0, #CACHE_DLINESIZE - 1
126 1:      mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate D entry
127         mcr     p15, 0, r0, c7, c5, 1           @ invalidate I entry
128         add     r0, r0, #CACHE_DLINESIZE
129         cmp     r0, r1
130         blo     1b
131         mov     r0, #0
132         mcr     p15, 0, r0, c7, c5, 6           @ invalidate BTB
133         mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
134         mcr     p15, 0, r0, c7, c5, 4           @ prefetch flush
135         ret     lr
136
137 /*
138  *      flush_kern_dcache_area(void *addr, size_t size)
139  *
140  *      Ensure that the data held in the page kaddr is written back
141  *      to the page in question.
142  *
143  *      - addr  - kernel address
144  *      - size  - size of region
145  */
146 ENTRY(fa_flush_kern_dcache_area)
147         add     r1, r0, r1
148 1:      mcr     p15, 0, r0, c7, c14, 1          @ clean & invalidate D line
149         add     r0, r0, #CACHE_DLINESIZE
150         cmp     r0, r1
151         blo     1b
152         mov     r0, #0
153         mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
154         mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
155         ret     lr
156
157 /*
158  *      dma_inv_range(start, end)
159  *
160  *      Invalidate (discard) the specified virtual address range.
161  *      May not write back any entries.  If 'start' or 'end'
162  *      are not cache line aligned, those lines must be written
163  *      back.
164  *
165  *      - start  - virtual start address
166  *      - end    - virtual end address
167  */
168 fa_dma_inv_range:
169         tst     r0, #CACHE_DLINESIZE - 1
170         bic     r0, r0, #CACHE_DLINESIZE - 1
171         mcrne   p15, 0, r0, c7, c14, 1          @ clean & invalidate D entry
172         tst     r1, #CACHE_DLINESIZE - 1
173         bic     r1, r1, #CACHE_DLINESIZE - 1
174         mcrne   p15, 0, r1, c7, c14, 1          @ clean & invalidate D entry
175 1:      mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry
176         add     r0, r0, #CACHE_DLINESIZE
177         cmp     r0, r1
178         blo     1b
179         mov     r0, #0
180         mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
181         ret     lr
182
183 /*
184  *      dma_clean_range(start, end)
185  *
186  *      Clean (write back) the specified virtual address range.
187  *
188  *      - start  - virtual start address
189  *      - end    - virtual end address
190  */
191 fa_dma_clean_range:
192         bic     r0, r0, #CACHE_DLINESIZE - 1
193 1:      mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
194         add     r0, r0, #CACHE_DLINESIZE
195         cmp     r0, r1
196         blo     1b
197         mov     r0, #0  
198         mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
199         ret     lr
200
201 /*
202  *      dma_flush_range(start,end)
203  *      - start   - virtual start address of region
204  *      - end     - virtual end address of region
205  */
206 ENTRY(fa_dma_flush_range)
207         bic     r0, r0, #CACHE_DLINESIZE - 1
208 1:      mcr     p15, 0, r0, c7, c14, 1          @ clean & invalidate D entry
209         add     r0, r0, #CACHE_DLINESIZE
210         cmp     r0, r1
211         blo     1b
212         mov     r0, #0  
213         mcr     p15, 0, r0, c7, c10, 4          @ drain write buffer
214         ret     lr
215
216 /*
217  *      dma_map_area(start, size, dir)
218  *      - start - kernel virtual start address
219  *      - size  - size of region
220  *      - dir   - DMA direction
221  */
222 ENTRY(fa_dma_map_area)
223         add     r1, r1, r0
224         cmp     r2, #DMA_TO_DEVICE
225         beq     fa_dma_clean_range
226         bcs     fa_dma_inv_range
227         b       fa_dma_flush_range
228 ENDPROC(fa_dma_map_area)
229
230 /*
231  *      dma_unmap_area(start, size, dir)
232  *      - start - kernel virtual start address
233  *      - size  - size of region
234  *      - dir   - DMA direction
235  */
236 ENTRY(fa_dma_unmap_area)
237         ret     lr
238 ENDPROC(fa_dma_unmap_area)
239
240         .globl  fa_flush_kern_cache_louis
241         .equ    fa_flush_kern_cache_louis, fa_flush_kern_cache_all
242
243         __INITDATA
244
245         @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
246         define_cache_functions fa