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