]> git.sur5r.net Git - u-boot/blob - arch/powerpc/cpu/mpc86xx/cache.S
Merge branch 'master' of git://www.denx.de/git/u-boot-imx
[u-boot] / 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  * Write any modified data cache blocks out to memory
119  * and invalidate the corresponding instruction cache blocks.
120  *
121  * flush_dcache_range(unsigned long start, unsigned long stop)
122  */
123 _GLOBAL(flush_dcache_range)
124         li      r5,CACHE_LINE_SIZE-1
125         andc    r3,r3,r5
126         subf    r4,r3,r4
127         add     r4,r4,r5
128         srwi.   r4,r4,LG_CACHE_LINE_SIZE
129         beqlr
130         mtctr   r4
131
132         sync
133 1:      dcbf    0,r3
134         addi    r3,r3,CACHE_LINE_SIZE
135         bdnz    1b
136         sync                            /* wait for dcbf's to get to ram */
137         blr
138
139 /*
140  * Like above, but invalidate the D-cache.  This is used by the 8xx
141  * to invalidate the cache so the PPC core doesn't get stale data
142  * from the CPM (no cache snooping here :-).
143  *
144  * invalidate_dcache_range(unsigned long start, unsigned long stop)
145  */
146 _GLOBAL(invalidate_dcache_range)
147         li      r5,CACHE_LINE_SIZE-1
148         andc    r3,r3,r5
149         subf    r4,r3,r4
150         add     r4,r4,r5
151         srwi.   r4,r4,LG_CACHE_LINE_SIZE
152         beqlr
153         mtctr   r4
154
155         sync
156 1:      dcbi    0,r3
157         addi    r3,r3,CACHE_LINE_SIZE
158         bdnz    1b
159         sync                            /* wait for dcbi's to get to ram */
160         blr
161
162 /*
163  * Flush a particular page from the data cache to RAM.
164  * Note: this is necessary because the instruction cache does *not*
165  * snoop from the data cache.
166  *
167  *      void __flush_page_to_ram(void *page)
168  */
169 _GLOBAL(__flush_page_to_ram)
170         rlwinm  r3,r3,0,0,19            /* Get page base address */
171         li      r4,4096/CACHE_LINE_SIZE /* Number of lines in a page */
172         mtctr   r4
173         mr      r6,r3
174 0:      dcbst   0,r3                    /* Write line to ram */
175         addi    r3,r3,CACHE_LINE_SIZE
176         bdnz    0b
177         sync
178         mtctr   r4
179 1:      icbi    0,r6
180         addi    r6,r6,CACHE_LINE_SIZE
181         bdnz    1b
182         sync
183         isync
184         blr
185
186 /*
187  * Flush a particular page from the instruction cache.
188  * Note: this is necessary because the instruction cache does *not*
189  * snoop from the data cache.
190  *
191  *      void __flush_icache_page(void *page)
192  */
193 _GLOBAL(__flush_icache_page)
194         li      r4,4096/CACHE_LINE_SIZE /* Number of lines in a page */
195         mtctr   r4
196 1:      icbi    0,r3
197         addi    r3,r3,CACHE_LINE_SIZE
198         bdnz    1b
199         sync
200         isync
201         blr
202
203 /*
204  * Clear a page using the dcbz instruction, which doesn't cause any
205  * memory traffic (except to write out any cache lines which get
206  * displaced).  This only works on cacheable memory.
207  */
208 _GLOBAL(clear_page)
209         li      r0,4096/CACHE_LINE_SIZE
210         mtctr   r0
211 1:      dcbz    0,r3
212         addi    r3,r3,CACHE_LINE_SIZE
213         bdnz    1b
214         blr
215
216 /*
217  * Enable L1 Instruction cache
218  */
219 _GLOBAL(icache_enable)
220         mfspr   r3, HID0
221         li      r5, HID0_ICFI|HID0_ILOCK
222         andc    r3, r3, r5
223         ori     r3, r3, HID0_ICE
224         ori     r5, r3, HID0_ICFI
225         mtspr   HID0, r5
226         mtspr   HID0, r3
227         isync
228         blr
229
230 /*
231  * Disable L1 Instruction cache
232  */
233 _GLOBAL(icache_disable)
234         mflr    r4
235         bl      invalidate_l1_instruction_cache         /* uses r3 */
236         sync
237         mtlr    r4
238         mfspr   r3, HID0
239         li      r5, 0
240         ori     r5, r5, HID0_ICE
241         andc    r3, r3, r5
242         mtspr   HID0, r3
243         isync
244         blr
245
246 /*
247  * Is instruction cache enabled?
248  */
249 _GLOBAL(icache_status)
250         mfspr   r3, HID0
251         andi.   r3, r3, HID0_ICE
252         blr
253
254
255 _GLOBAL(l1dcache_enable)
256         mfspr   r3, HID0
257         li      r5, HID0_DCFI|HID0_DLOCK
258         andc    r3, r3, r5
259         mtspr   HID0, r3                /* no invalidate, unlock */
260         ori     r3, r3, HID0_DCE
261         ori     r5, r3, HID0_DCFI
262         mtspr   HID0, r5                /* enable + invalidate */
263         mtspr   HID0, r3                /* enable */
264         sync
265         blr
266
267 /*
268  * Enable data cache(s) - L1 and optionally L2
269  * Calls l2cache_enable. LR saved in r5
270  */
271 _GLOBAL(dcache_enable)
272         mfspr   r3, HID0
273         li      r5, HID0_DCFI|HID0_DLOCK
274         andc    r3, r3, r5
275         mtspr   HID0, r3                /* no invalidate, unlock */
276         ori     r3, r3, HID0_DCE
277         ori     r5, r3, HID0_DCFI
278         mtspr   HID0, r5                /* enable + invalidate */
279         mtspr   HID0, r3                /* enable */
280         sync
281 #ifdef CONFIG_SYS_L2
282         mflr    r5
283         bl      l2cache_enable          /* uses r3 and r4 */
284         sync
285         mtlr    r5
286 #endif
287         blr
288
289
290 /*
291  * Disable data cache(s) - L1 and optionally L2
292  * Calls flush_dcache and l2cache_disable_no_flush.
293  * LR saved in r4
294  */
295 _GLOBAL(dcache_disable)
296         mflr    r4                      /* save link register */
297         bl      flush_dcache    /* uses r3 and r5 */
298         sync
299         mfspr   r3, HID0
300         li      r5, HID0_DCFI|HID0_DLOCK
301         andc    r3, r3, r5
302         mtspr   HID0, r3                /* no invalidate, unlock */
303         li      r5, HID0_DCE|HID0_DCFI
304         andc    r3, r3, r5              /* no enable, no invalidate */
305         mtspr   HID0, r3
306         sync
307 #ifdef CONFIG_SYS_L2
308         bl      l2cache_disable_no_flush /* uses r3 */
309 #endif
310         mtlr    r4                      /* restore link register */
311         blr
312
313 /*
314  * Is data cache enabled?
315  */
316 _GLOBAL(dcache_status)
317         mfspr   r3, HID0
318         andi.   r3, r3, HID0_DCE
319         blr
320
321 /*
322  * Invalidate L2 cache using L2I, assume L2 is enabled
323  */
324 _GLOBAL(l2cache_invalidate)
325         mfspr   r3, l2cr
326         rlwinm. r3, r3, 0, 0, 0
327         beq     1f
328
329         mfspr   r3, l2cr
330         rlwinm  r3, r3, 0, 1, 31
331
332 #ifdef  CONFIG_ALTIVEC
333         dssall
334 #endif
335         sync
336         mtspr   l2cr, r3
337         sync
338 1:      mfspr   r3, l2cr
339         oris    r3, r3, L2CR_L2I@h
340         mtspr   l2cr, r3
341
342 invl2:
343         mfspr   r3, l2cr
344         andis.  r3, r3, L2CR_L2I@h
345         bne     invl2
346         blr
347
348 /*
349  * Enable L2 cache
350  * Calls l2cache_invalidate. LR is saved in r4
351  */
352 _GLOBAL(l2cache_enable)
353         mflr    r4                      /* save link register */
354         bl      l2cache_invalidate      /* uses r3 */
355         sync
356         lis     r3, L2_ENABLE@h
357         ori     r3, r3, L2_ENABLE@l
358         mtspr   l2cr, r3
359         isync
360         mtlr    r4                      /* restore link register */
361         blr
362
363 /*
364  * Disable L2 cache
365  * Calls flush_dcache. LR is saved in r4
366  */
367 _GLOBAL(l2cache_disable)
368         mflr    r4                      /* save link register */
369         bl      flush_dcache            /* uses r3 and r5 */
370         sync
371         mtlr    r4                      /* restore link register */
372 l2cache_disable_no_flush:               /* provide way to disable L2 w/o flushing */
373         lis     r3, L2_INIT@h
374         ori     r3, r3, L2_INIT@l
375         mtspr   l2cr, r3
376         isync
377         blr