source: rtems/c/src/lib/libcpu/powerpc/mpc6xx/mmu/mmuAsm.S @ c499856

4.115
Last change on this file since c499856 was c499856, checked in by Chris Johns <chrisj@…>, on 03/20/14 at 21:10:47

Change all references of rtems.com to rtems.org.

  • Property mode set to 100644
File size: 13.1 KB
Line 
1/*
2 *  mmuAsm.S
3 *
4 *  Copyright (C) 1999 Eric Valette (valette@crf.canon.fr)
5 *
6 *  This file contains the low-level support for various MMU
7 *  features.
8 *
9 *  The license and distribution terms for this file may be
10 *  found in the file LICENSE in this distribution or at
11 *  http://www.rtems.org/license/LICENSE.
12 *
13 *  T. Straumann - 11/2001: added support for 7400 (no AltiVec yet)
14 *  S.K. Feng    - 10/2003: added support for 7455 (no AltiVec yet)
15 *
16 */
17
18#include <rtems/asm.h>
19#include <rtems/score/cpu.h>
20#include <libcpu/io.h>
21#include <libcpu/bat.h>
22
23/* Unfortunately, the CPU types defined in cpu.h are
24 * an 'enum' type and hence not available :-(
25 */
26#define PPC_601   0x1
27#define PPC_603   0x3
28#define PPC_604   0x4
29#define PPC_603e  0x6
30#define PPC_603ev 0x7
31#define PPC_750   0x8
32#define PPC_604e  0x9
33#define PPC_604r  0xA
34#define PPC_7400  0xC
35#define PPC_7455  0x8001
36#define PPC_7457  0x8002
37#define PPC_620   0x16
38#define PPC_860   0x50
39#define PPC_821   PPC_860
40#define PPC_8260  0x81
41#define PPC_8240  PPC_8260
42
43/* ALTIVEC instructions (not recognized by off-the shelf gcc yet) */
44#define DSSALL  .long   0x7e00066c              /* DSSALL altivec instruction opcode */
45
46/* A couple of defines to make the code more readable */
47#define CACHE_LINE_SIZE 32
48
49#ifndef MSSCR0
50#define MSSCR0   1014
51#endif
52
53#define DL1HWF  (1<<(31-8))
54#define L2HWF   (1<<(31-20))
55
56#FIXME Should really move this to C code
57
58        .globl L1_caches_enables
59        .type  L1_caches_enables, @function
60
61L1_caches_enables:
62        /*
63         * Enable caches and 604-specific features if necessary.
64         */
65        mfspr   r9,PPC_PVR
66        rlwinm  r9,r9,16,16,31
67        cmpi    0,r9,PPC_601
68        beq     4f                      /* not needed for 601 */
69        mfspr   r11,HID0
70        andi.   r0,r11,HID0_DCE
71        ori     r11,r11,HID0_ICE|HID0_DCE
72        ori     r8,r11,HID0_ICFI
73        bne     3f                      /* don't invalidate the D-cache */
74        ori     r8,r8,HID0_DCI          /* unless it wasn't enabled */
753:
76        sync
77        mtspr   HID0,r8                 /* enable and invalidate caches */
78        sync
79        mtspr   HID0,r11                /* enable caches */
80        sync
81        isync
82        cmpi    1,r9,PPC_604    /* check for 604 */
83        cmpi    2,r9,PPC_604e   /* or 604e */
84        cmpi    3,r9,PPC_604r   /* or mach5 */
85        cror    6,6,10
86        cror    6,6,14
87        cmpi    2,r9,PPC_750    /* or 750 */
88        cror    6,6,10
89        cmpi    2,r9,PPC_7400   /* or 7400 */
90        cror    6,6,10
91        cmpli   0,r9,PPC_7455   /* or 7455 */
92        beq     1f
93        cmpli   0,r9,PPC_7457   /* or 7457 */
94        bne             2f
951:
96        /* 7455:link register stack,branch folding &
97         * TBEN : enable the time base and decrementer.
98         * EMCP bit is defined in HID1. However, it's not used
99         * in mvme5500 board because of GT64260 (e.g. it's connected
100         * pull-up).
101         */
102        oris    r11,r11,(HID0_LRSTK|HID0_FOLD|HID0_TBEN)@h
103        ori     r11,r11,(HID0_LRSTK|HID0_FOLD|HID0_TBEN)@l
1042:      cror    2,2,10
105        bne     3f
106        ori     r11,r11,HID0_BTIC       /* enable branch tgt cache on 7400 , 7455 , 7457 */
1073:      cror    2,2,6
108        bne     4f
109        /* on 7400 SIED is actually SGE (store gathering enable) */
110        ori     r11,r11,HID0_SIED|HID0_BHTE /* for 604[e], enable */
111        bne     2,5f
112        ori     r11,r11,HID0_BTCD
1135:      mtspr   HID0,r11                /* superscalar exec & br history tbl */
114        sync                 /* for SGE bit */
115        isync                /* P2-17 to 2-22 in MPC7450UM */
1164:
117        blr
118
119        .globl get_L1CR
120.type  get_L1CR, @function
121get_L1CR:
122        mfspr   r3,HID0
123        blr
124
125        .globl get_L2CR
126        .type  get_L2CR, @function
127get_L2CR:
128        /* Make sure this is a > 750 chip */
129        mfspr   r3,PPC_PVR
130        rlwinm  r3,r3,16,16,31
131        cmplwi  r3,PPC_750      /* it's a 750 */
132        beq     1f
133        cmplwi  r3,PPC_7400     /* it's a 7400 */
134        beq     1f
135        cmplwi  r3,PPC_7455     /* it's a 7455 */
136        beq     1f
137        cmplwi  r3,PPC_7457     /* it's a 7457 */
138        beq     1f
139        li      r3,-1
140        blr
141
1421:
143        /* Return the L2CR contents */
144        mfspr   r3,L2CR
145        blr
146
147        .globl set_L2CR
148        .type  set_L2CR, @function
149set_L2CR:
150        /* Usage:
151         * When setting the L2CR register, you must do a few special things.
152         * If you are enabling the cache, you must perform a global invalidate.
153         * If you are disabling the cache, you must flush the cache contents first.
154         * This routine takes care of doing these things.  When first
155         * enabling the cache, make sure you pass in the L2CR you want, as well as
156         * passing in the global invalidate bit set.  A global invalidate will
157         * only be performed if the L2I bit is set in applyThis.  When enabling
158         * the cache, you should also set the L2E bit in applyThis.  If you
159         * want to modify the L2CR contents after the cache has been enabled,
160         * the recommended procedure is to first call __setL2CR(0) to disable
161         * the cache and then call it again with the new values for L2CR.  Examples:
162         *
163         *      _setL2CR(0)             -       disables the cache
164         *      _setL2CR(0xb9A14000)    -       enables my G3 MCP750 card:
165         *                              -       L2E set to turn on the cache
166         *                              -       L2SIZ set to 1MB
167         *                              -       L2CLK set to %2
168         *                              -       L2RAM set to pipelined syncronous late-write
169         *                              -       L2I set to perform a global invalidation
170         *                              -       L2OH set to 1 nS
171         *
172         * A similar call should work for your card.  You need to know the correct
173         * setting for your card and then place them in the fields I have outlined
174         * above.  Other fields support optional features, such as L2DO which caches
175         * only data, or L2TS which causes cache pushes from the L1 cache to go to
176         *the L2 cache instead of to main memory.
177         */
178
179        /* Make sure this is a > 750 chip */
180        mfspr   r0,PPC_PVR
181        rlwinm  r0,r0,16,16,31
182        cmplwi  r0,PPC_750
183        beq     thisIs750
184        cmplwi  r0,PPC_7400
185        beq     thisIs750
186        cmplwi  r0,PPC_7455
187        beq     thisIs750
188        cmplwi  r0,PPC_7457
189        beq     thisIs750
190        li      r3,-1
191        blr
192
193thisIs750:
194        /* Get the current enable bit of the L2CR into r4 */
195        mfspr   r4,L2CR
196        rlwinm  r4,r4,0,0,0
197
198        /* See if we want to perform a global inval this time. */
199        rlwinm  r6,r3,0,10,10           /* r6 contains the new invalidate bit */
200        rlwinm. r5,r3,0,0,0             /* r5 contains the new enable bit */
201        rlwinm  r3,r3,0,11,9            /* Turn off the invalidate bit */
202        rlwinm  r3,r3,0,1,31            /* Turn off the enable bit */
203        or      r3,r3,r4                /* Keep the enable bit the same as it was for now. */
204        mfmsr   r7                      /* shut off interrupts around critical flush/invalidate sections */
205        rlwinm  r4,r7,0,17,15           /* Turn off EE bit - an external exception while we are flushing
206                                                                   the cache is fatal (comment this line and see!) */
207        mtmsr   r4
208        bne     dontDisableCache        /* Only disable the cache if L2CRApply has the enable bit off */
209
210        cmplwi  r0,PPC_7400             /* 7400 ? */
211        bne     disableCache            /* use traditional method */
212
213        /* On the 7400, they recommend using the hardware flush feature */
214        DSSALL                                          /* stop all data streams */
215        sync
216        /* we wouldn't have to flush L1, but for sake of consistency with the other code we do it anyway */
217        mfspr   r4, MSSCR0
218        oris    r4, r4, DL1HWF@h
219        mtspr   MSSCR0, r4
220        sync
221        /* L1 flushed */
222        mfspr   r4, L2CR
223        ori     r4, r4, L2HWF
224        mtspr   L2CR, r4
225        sync
226        /* L2 flushed */
227        b       flushDone
228
229disableCache:
230        /* Disable the cache.  First, we turn off data relocation. */
231        rlwinm  r4,r4,0,28,26           /* Turn off DR bit */
232        cmplwi  r0,PPC_7455             /* 7455 ? */
233        beq     1f
234        cmplwi  r0,PPC_7457             /* 7457 ? */
235        bne     not745x
2361:
237        /* 745x:L1 Load/Flush, L2, L3 :  hardware flush */
238        DSSALL
239        mtmsr   r4
240        sync
241        isync
242        mfspr   r4, MSSCR0
243        rlwinm  r4,r4,0,29,0            /* Turn off the L2PFE bits */
244        mtspr   MSSCR0, r4
245        sync
246        /* flush L1 first */
247        lis     r4,0x0001
248        mtctr   r4
249        li      r4,0
250        li      r0,0
251loadFlush:
252        lwzx    r0,r0,r4
253        dcbf    r0,r4
254        addi    r4,r4,CACHE_LINE_SIZE   /* Go to start of next cache line */
255        bdnz    loadFlush
256        sync
257        /* Set the L2CR[L2IO & L2DO] bits to completely lock the L2 cache */
258        mfspr   r0, L2CR
259        lis     r4,L2CR_LOCK_745x@h
260        ori     r4,r4,L2CR_LOCK_745x@l
261        or      r4,r0,r4
262        rlwinm  r4,r4,0,11,9           /* make sure the invalidate bit off */
263        mtspr   L2CR, r4
264        sync
265        ori     r4, r4, L2HWF
266        mtspr   L2CR, r4
267        sync
268        /* L2 flushed,L2IO & L2DO got cleared in the dontDisableCache:  */
269        b       reenableDR
270
271not745x:
272        sync
273        mtmsr   r4
274        isync
275        /*
276                Now, read the first 2MB of memory to put new data in the cache.
277                (Actually we only need the size of the L2 cache plus
278                the size of the L1 cache, but 2MB will cover everything just to be safe).
279        */
280        lis     r4,0x0001
281        mtctr   r4
282        li      r4,0
283loadLoop:
284        lwzx    r0,r0,r4
285        addi    r4,r4,CACHE_LINE_SIZE   /* Go to start of next cache line */
286        bdnz    loadLoop
287
288        /* Now, flush the first 2MB of memory */
289        lis             r4,0x0001
290        mtctr   r4
291        li              r4,0
292        sync
293flushLoop:
294        dcbf    r0,r4
295        addi    r4,r4,CACHE_LINE_SIZE   /* Go to start of next cache line */
296        bdnz    flushLoop
297reenableDR:
298        rlwinm  r4,r7,0,17,15           /* still mask EE but reenable data relocation */
299        sync
300        mtmsr   r4
301        isync
302
303flushDone:
304
305        /* Turn off the L2CR enable bit. */
306        rlwinm  r3,r3,0,1,31
307
308dontDisableCache:
309        /* Set up the L2CR configuration bits */
310        sync
311        mtspr   L2CR,r3
312        sync
313        cmplwi  r6,0
314        beq     noInval
315
316        /* Perform a global invalidation */
317        oris    r3,r3,0x0020
318        sync
319        mtspr   L2CR,r3
320        sync
321invalCompleteLoop:                              /* Wait for the invalidation to complete */
322        mfspr   r3,L2CR
323        rlwinm. r4,r3,0,31,31
324        bne     invalCompleteLoop
325
326        rlwinm  r3,r3,0,11,9;           /* Turn off the L2I bit */
327        sync
328        mtspr   L2CR,r3
329
330noInval:
331        sync
332        /* re-enable interrupts, i.e. restore original MSR */
333        mtmsr   r7                                      /* (no sync needed) */
334        /* See if we need to enable the cache */
335        cmplwi  r5,0
336        beqlr
337
338enableCache:
339        /* Enable the cache */
340        oris    r3,r3,0x8000
341        mtspr   L2CR,r3
342        sync
343        blr
344
345
346        .globl get_L3CR
347        .type  get_L3CR, @function
348get_L3CR:
349        /* Make sure this is a 7455 chip */
350        mfspr   r3,PPC_PVR
351        rlwinm  r3,r3,16,16,31
352        cmplwi  r3,PPC_7455     /* it's a 7455 */
353        beq     1f
354        cmplwi  r3,PPC_7457     /* it's a 7457 */
355        beq     1f
356        li      r3,-1
357        blr
358
3591:
360        /* Return the L3CR contents */
361        mfspr   r3,L3CR
362        blr
363
364        .globl set_L3CR
365        .type  set_L3CR, @function
366set_L3CR:
367        /* Usage:
368         * When setting the L3CR register, you must do a few special things.
369         * If you are enabling the cache, you must perform a global invalidate.
370         * Then call cpu_enable_l3cr(l3cr).
371         * If you are disabling the cache, you must flush the cache contents first.
372         * This routine takes care of doing these things.  If you
373         * want to modify the L3CR contents after the cache has been enabled,
374         * the recommended procedure is to first call __setL3CR(0) to disable
375         * the cache and then call cpu_enable_l3cr with the new values for
376         * L3CR.
377         */
378
379        /* Make sure this is a 7455 chip */
380        mfspr   r0,PPC_PVR
381        rlwinm  r0,r0,16,16,31
382        cmplwi  r0,PPC_7455
383        beq     thisIs7455
384        cmplwi  r0,PPC_7457
385        beq     thisIs7455
386        li      r3,-1
387        blr
388
389thisIs7455:
390        /* Get the current enable bit of the L3CR into r4 */
391        mfspr   r4,L3CR
392        rlwinm  r4,r4,0,0,0
393
394        /* See if we want to perform a global inval this time. */
395        rlwinm  r6,r3,0,10,10           /* r6 contains the new invalidate bit */
396        rlwinm. r5,r3,0,0,0             /* r5 contains the new enable bit */
397        rlwinm  r3,r3,0,11,9            /* Turn off the invalidate bit */
398        rlwinm  r3,r3,0,1,31            /* Turn off the enable bit */
399        or      r3,r3,r4                /* Keep the enable bit the same as it was for now. */
400        mfmsr   r7                      /* shut off interrupts around critical flush/invalidate sections */
401        rlwinm  r4,r7,0,17,15           /* Turn off EE bit - an external exception while we are flushing
402                                                                   the cache is fatal (comment this line and see!) */
403        mtmsr   r4
404        bne     dontDisableL3Cache      /* Only disable the cache if L3CRApply has the enable bit off */
405        /* Before the L3 is disabled, it must be flused to prevent coherency problems */
406        /* First, we turn off data relocation. */
407        rlwinm  r4,r4,0,28,26           /* Turn off DR bit */
408        DSSALL
409        sync
410        mtmsr   r4
411        isync                           /* make sure memory accesses have completed */
412        /* 7455: L3 :    hardware flush
413         * Set the L3CR[L3IO & L3DO] bits to completely lock the L3 cache */
414        mfspr   r0, L3CR
415        lis     r4, L3CR_LOCK_745x@h
416        ori     r4,r4, L3CR_LOCK_745x@l
417        or      r4,r0,r4
418        rlwinm  r4,r4,0,11,9           /* make sure the invalidate bit off */
419        mtspr   L3CR, r4
420        sync
421        ori     r4, r4, L3CR_L3HWF
422        mtspr   L3CR, r4
423        sync
424        /* L3 flushed,L3IO & L3DO got cleared in the dontDisableL3Cache:  */
425        rlwinm  r4,r7,0,17,15           /* still mask EE but reenable data relocation */
426        sync
427        mtmsr   r4
428        isync
429
430        /* Turn off the L3CR enable bit. */
431        rlwinm  r3,r3,0,1,31
432
433dontDisableL3Cache:
434        /* Set up the L3CR configuration bits */
435        sync
436        mtspr   L3CR,r3
437        sync
438ifL3Inval:
439        cmplwi  r6,0
440        beq     noL3Inval
441
442        /* Perform a global invalidation */
443        oris    r3,r3,0x0020
444        sync
445        mtspr   L3CR,r3
446        sync
447invalCompleteL3:                                /* Wait for the invalidation to complete */
448        mfspr   r3,L3CR
449        rlwinm. r4,r3,0,31,31
450        bne     invalCompleteL3
451
452        rlwinm  r3,r3,0,11,9;           /* Turn off the L3I bit */
453        sync
454        mtspr   L3CR,r3
455        sync
456
457noL3Inval:
458        /* re-enable interrupts, i.e. restore original MSR */
459        mtmsr   r7                                      /* (no sync needed) */
460        /* See if we need to enable the cache */
461        cmplwi  r5,0
462        beqlr
463
464enableL3Cache:
465        /* Enable the cache */
466        oris    r3,r3,0x8000
467        mtspr   L3CR,r3
468        sync
469        blr
470
471/*
472 * An undocumented "feature" of 604e requires that the v bit
473 * be cleared before changing BAT values.
474 *
475 * Also, newer IBM firmware does not clear bat3 and 4 so
476 * this makes sure it's done.
477 *  -- Cort
478 */
479        .globl  CPU_clear_bats_early
480        .type   CPU_clear_bats_early,@function
481CPU_clear_bats_early:
482        li              r3,0
483        mfspr   r4,PPC_PVR
484        rlwinm  r4,r4,16,16,31          /* r4 = 1 for 601, 4 for 604 */
485        cmpwi   r4, 1
486        sync
487        isync
488        beq     1f
489        cmplwi  r4,0x8001                       /* 7445, 7455 (0x8001), 7447, 7457 (0x8002)      */
490        blt 2f                                          /* 7447a (0x8003) and 7448 (0x8004) have 16 bats */
491        cmplwi  r4,0x8004
492        bgt 2f
493        mtspr   DBAT4U,r3
494        mtspr   DBAT4L,r3
495        mtspr   DBAT5U,r3
496        mtspr   DBAT5L,r3
497        mtspr   DBAT6U,r3
498        mtspr   DBAT6L,r3
499        mtspr   DBAT7U,r3
500        mtspr   DBAT7L,r3
501        mtspr   IBAT4U,r3
502        mtspr   IBAT4L,r3
503        mtspr   IBAT5U,r3
504        mtspr   IBAT5L,r3
505        mtspr   IBAT6U,r3
506        mtspr   IBAT6L,r3
507        mtspr   IBAT7U,r3
508        mtspr   IBAT7L,r3
5092:
510        mtspr   DBAT0U,r3
511        mtspr   DBAT0L,r3
512        mtspr   DBAT1U,r3
513        mtspr   DBAT1L,r3
514        mtspr   DBAT2U,r3
515        mtspr   DBAT2L,r3
516        mtspr   DBAT3U,r3
517        mtspr   DBAT3L,r3
5181:
519        mtspr   IBAT0U,r3
520        mtspr   IBAT0L,r3
521        mtspr   IBAT1U,r3
522        mtspr   IBAT1L,r3
523        mtspr   IBAT2U,r3
524        mtspr   IBAT2L,r3
525        mtspr   IBAT3U,r3
526        mtspr   IBAT3L,r3
527        sync
528        isync
529        blr
530
Note: See TracBrowser for help on using the repository browser.