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