Merge tag 'u-boot-atmel-fixes-2020.07-a' of https://gitlab.denx.de/u-boot/custodians...
[oweals/u-boot.git] / arch / powerpc / cpu / mpc86xx / cache.S
1 #include <config.h>
2 #include <mpc86xx.h>
3
4 #include <ppc_asm.tmpl>
5 #include <ppc_defs.h>
6
7 #include <asm/cache.h>
8 #include <asm/mmu.h>
9
10 #ifndef CACHE_LINE_SIZE
11 # define CACHE_LINE_SIZE L1_CACHE_BYTES
12 #endif
13
14 #if CACHE_LINE_SIZE == 128
15 #define LG_CACHE_LINE_SIZE 7
16 #elif CACHE_LINE_SIZE == 32
17 #define LG_CACHE_LINE_SIZE 5
18 #elif CACHE_LINE_SIZE == 16
19 #define LG_CACHE_LINE_SIZE 4
20 #elif CACHE_LINE_SIZE == 8
21 #define LG_CACHE_LINE_SIZE 3
22 #else
23 # error "Invalid cache line size!"
24 #endif
25
26 /*
27  * Most of this code is taken from 74xx_7xx/cache.S
28  * and then cleaned up a bit
29  */
30
31 /*
32  * Invalidate L1 instruction cache.
33  */
34 _GLOBAL(invalidate_l1_instruction_cache)
35         /* use invalidate-all bit in HID0 */
36         mfspr   r3,HID0
37         ori     r3,r3,HID0_ICFI
38         mtspr   HID0,r3
39         isync
40         blr
41
42 /*
43  * Invalidate L1 data cache.
44  */
45 _GLOBAL(invalidate_l1_data_cache)
46         mfspr   r3,HID0
47         ori     r3,r3,HID0_DCFI
48         mtspr   HID0,r3
49         isync
50         blr
51
52 /*
53  * Flush data cache.
54  */
55 _GLOBAL(flush_dcache)
56         lis     r3,0
57         lis     r5,CACHE_LINE_SIZE
58 flush:
59         cmp     0,1,r3,r5
60         bge     done
61         lwz     r5,0(r3)
62         lis     r5,CACHE_LINE_SIZE
63         addi    r3,r3,0x4
64         b       flush
65 done:
66         blr
67 /*
68  * Write any modified data cache blocks out to memory
69  * and invalidate the corresponding instruction cache blocks.
70  * This is a no-op on the 601.
71  *
72  * flush_icache_range(unsigned long start, unsigned long stop)
73  */
74 _GLOBAL(flush_icache_range)
75         li      r5,CACHE_LINE_SIZE-1
76         andc    r3,r3,r5
77         subf    r4,r3,r4
78         add     r4,r4,r5
79         srwi.   r4,r4,LG_CACHE_LINE_SIZE
80         beqlr
81         mtctr   r4
82         mr      r6,r3
83 1:      dcbst   0,r3
84         addi    r3,r3,CACHE_LINE_SIZE
85         bdnz    1b
86         sync                            /* wait for dcbst's to get to ram */
87         mtctr   r4
88 2:      icbi    0,r6
89         addi    r6,r6,CACHE_LINE_SIZE
90         bdnz    2b
91         sync                            /* additional sync needed on g4 */
92         isync
93         blr
94 /*
95  * Write any modified data cache blocks out to memory.
96  * Does not invalidate the corresponding cache lines (especially for
97  * any corresponding instruction cache).
98  *
99  * clean_dcache_range(unsigned long start, unsigned long stop)
100  */
101 _GLOBAL(clean_dcache_range)
102         li      r5,CACHE_LINE_SIZE-1
103         andc    r3,r3,r5        /* align r3 down to cache line */
104         subf    r4,r3,r4        /* r4 = offset of stop from start of cache line */
105         add     r4,r4,r5        /* r4 += cache_line_size-1 */
106         srwi.   r4,r4,LG_CACHE_LINE_SIZE  /* r4 = number of cache lines to flush */
107         beqlr                             /* if r4 == 0 return */
108         mtctr   r4                        /* ctr = r4 */
109
110         sync
111 1:      dcbst   0,r3
112         addi    r3,r3,CACHE_LINE_SIZE
113         bdnz    1b
114         sync                            /* wait for dcbst's to get to ram */
115         blr
116
117 /*
118  * Flush a particular page from the data cache to RAM.
119  * Note: this is necessary because the instruction cache does *not*
120  * snoop from the data cache.
121  *
122  *      void __flush_page_to_ram(void *page)
123  */
124 _GLOBAL(__flush_page_to_ram)
125         rlwinm  r3,r3,0,0,19            /* Get page base address */
126         li      r4,4096/CACHE_LINE_SIZE /* Number of lines in a page */
127         mtctr   r4
128         mr      r6,r3
129 0:      dcbst   0,r3                    /* Write line to ram */
130         addi    r3,r3,CACHE_LINE_SIZE
131         bdnz    0b
132         sync
133         mtctr   r4
134 1:      icbi    0,r6
135         addi    r6,r6,CACHE_LINE_SIZE
136         bdnz    1b
137         sync
138         isync
139         blr
140
141 /*
142  * Flush a particular page from the instruction cache.
143  * Note: this is necessary because the instruction cache does *not*
144  * snoop from the data cache.
145  *
146  *      void __flush_icache_page(void *page)
147  */
148 _GLOBAL(__flush_icache_page)
149         li      r4,4096/CACHE_LINE_SIZE /* Number of lines in a page */
150         mtctr   r4
151 1:      icbi    0,r3
152         addi    r3,r3,CACHE_LINE_SIZE
153         bdnz    1b
154         sync
155         isync
156         blr
157
158 /*
159  * Clear a page using the dcbz instruction, which doesn't cause any
160  * memory traffic (except to write out any cache lines which get
161  * displaced).  This only works on cacheable memory.
162  */
163 _GLOBAL(clear_page)
164         li      r0,4096/CACHE_LINE_SIZE
165         mtctr   r0
166 1:      dcbz    0,r3
167         addi    r3,r3,CACHE_LINE_SIZE
168         bdnz    1b
169         blr
170
171 /*
172  * Enable L1 Instruction cache
173  */
174 _GLOBAL(icache_enable)
175         mfspr   r3, HID0
176         li      r5, HID0_ICFI|HID0_ILOCK
177         andc    r3, r3, r5
178         ori     r3, r3, HID0_ICE
179         ori     r5, r3, HID0_ICFI
180         mtspr   HID0, r5
181         mtspr   HID0, r3
182         isync
183         blr
184
185 /*
186  * Disable L1 Instruction cache
187  */
188 _GLOBAL(icache_disable)
189         mflr    r4
190         bl      invalidate_l1_instruction_cache         /* uses r3 */
191         sync
192         mtlr    r4
193         mfspr   r3, HID0
194         li      r5, 0
195         ori     r5, r5, HID0_ICE
196         andc    r3, r3, r5
197         mtspr   HID0, r3
198         isync
199         blr
200
201 /*
202  * Is instruction cache enabled?
203  */
204 _GLOBAL(icache_status)
205         mfspr   r3, HID0
206         andi.   r3, r3, HID0_ICE
207         blr
208
209
210 _GLOBAL(l1dcache_enable)
211         mfspr   r3, HID0
212         li      r5, HID0_DCFI|HID0_DLOCK
213         andc    r3, r3, r5
214         mtspr   HID0, r3                /* no invalidate, unlock */
215         ori     r3, r3, HID0_DCE
216         ori     r5, r3, HID0_DCFI
217         mtspr   HID0, r5                /* enable + invalidate */
218         mtspr   HID0, r3                /* enable */
219         sync
220         blr
221
222 /*
223  * Enable data cache(s) - L1 and optionally L2
224  * Calls l2cache_enable. LR saved in r5
225  */
226 _GLOBAL(dcache_enable)
227         mfspr   r3, HID0
228         li      r5, HID0_DCFI|HID0_DLOCK
229         andc    r3, r3, r5
230         mtspr   HID0, r3                /* no invalidate, unlock */
231         ori     r3, r3, HID0_DCE
232         ori     r5, r3, HID0_DCFI
233         mtspr   HID0, r5                /* enable + invalidate */
234         mtspr   HID0, r3                /* enable */
235         sync
236 #ifdef CONFIG_SYS_L2
237         mflr    r5
238         bl      l2cache_enable          /* uses r3 and r4 */
239         sync
240         mtlr    r5
241 #endif
242         blr
243
244
245 /*
246  * Disable data cache(s) - L1 and optionally L2
247  * Calls flush_dcache and l2cache_disable_no_flush.
248  * LR saved in r4
249  */
250 _GLOBAL(dcache_disable)
251         mflr    r4                      /* save link register */
252         bl      flush_dcache    /* uses r3 and r5 */
253         sync
254         mfspr   r3, HID0
255         li      r5, HID0_DCFI|HID0_DLOCK
256         andc    r3, r3, r5
257         mtspr   HID0, r3                /* no invalidate, unlock */
258         li      r5, HID0_DCE|HID0_DCFI
259         andc    r3, r3, r5              /* no enable, no invalidate */
260         mtspr   HID0, r3
261         sync
262 #ifdef CONFIG_SYS_L2
263         bl      l2cache_disable_no_flush /* uses r3 */
264 #endif
265         mtlr    r4                      /* restore link register */
266         blr
267
268 /*
269  * Is data cache enabled?
270  */
271 _GLOBAL(dcache_status)
272         mfspr   r3, HID0
273         andi.   r3, r3, HID0_DCE
274         blr
275
276 /*
277  * Invalidate L2 cache using L2I, assume L2 is enabled
278  */
279 _GLOBAL(l2cache_invalidate)
280         mfspr   r3, l2cr
281         rlwinm. r3, r3, 0, 0, 0
282         beq     1f
283
284         mfspr   r3, l2cr
285         rlwinm  r3, r3, 0, 1, 31
286
287 #ifdef  CONFIG_ALTIVEC
288         dssall
289 #endif
290         sync
291         mtspr   l2cr, r3
292         sync
293 1:      mfspr   r3, l2cr
294         oris    r3, r3, L2CR_L2I@h
295         mtspr   l2cr, r3
296
297 invl2:
298         mfspr   r3, l2cr
299         andis.  r3, r3, L2CR_L2I@h
300         bne     invl2
301         blr
302
303 /*
304  * Enable L2 cache
305  * Calls l2cache_invalidate. LR is saved in r4
306  */
307 _GLOBAL(l2cache_enable)
308         mflr    r4                      /* save link register */
309         bl      l2cache_invalidate      /* uses r3 */
310         sync
311         lis     r3, L2_ENABLE@h
312         ori     r3, r3, L2_ENABLE@l
313         mtspr   l2cr, r3
314         isync
315         mtlr    r4                      /* restore link register */
316         blr
317
318 /*
319  * Disable L2 cache
320  * Calls flush_dcache. LR is saved in r4
321  */
322 _GLOBAL(l2cache_disable)
323         mflr    r4                      /* save link register */
324         bl      flush_dcache            /* uses r3 and r5 */
325         sync
326         mtlr    r4                      /* restore link register */
327 l2cache_disable_no_flush:               /* provide way to disable L2 w/o flushing */
328         lis     r3, L2_INIT@h
329         ori     r3, r3, L2_INIT@l
330         mtspr   l2cr, r3
331         isync
332         blr