ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / ppc / boot / common / util.S
1 /*
2  * arch/ppc/boot/common/util.S
3  *
4  * Useful bootup functions, which are more easily done in asm than C.
5  *
6  * NOTE:  Be very very careful about the registers you use here.
7  *      We don't follow any ABI calling convention among the
8  *      assembler functions that call each other, especially early
9  *      in the initialization.  Please preserve at least r3 and r4
10  *      for these early functions, as they often contain information
11  *      passed from boot roms into the C decompress function.
12  *
13  * Author: Tom Rini
14  *         trini@mvista.com
15  * Derived from arch/ppc/boot/prep/head.S (Cort Dougan, many others).
16  *
17  * 2001-2004 (c) MontaVista, Software, Inc.  This file is licensed under
18  * the terms of the GNU General Public License version 2.  This program
19  * is licensed "as is" without any warranty of any kind, whether express
20  * or implied.
21  */
22
23 #include <asm/processor.h>
24 #include <asm/cache.h>
25 #include <asm/ppc_asm.h>
26
27
28         .text
29
30         .globl  disable_6xx_mmu
31 disable_6xx_mmu:
32         /* Establish default MSR value, exception prefix 0xFFF.
33          * If necessary, this function must fix up the LR if we
34          * return to a different address space once the MMU is
35          * disabled.
36          */
37         li      r8,MSR_IP|MSR_FP
38         mtmsr   r8
39         isync
40
41         /* Test for a 601 */
42         mfpvr   r10
43         srwi    r10,r10,16
44         cmpi    0,r10,1         /* 601 ? */
45         beq     .clearbats_601
46
47         /* Clear BATs */
48         li      r8,0
49         mtspr   DBAT0U,r8
50         mtspr   DBAT0L,r8
51         mtspr   DBAT1U,r8
52         mtspr   DBAT1L,r8
53         mtspr   DBAT2U,r8
54         mtspr   DBAT2L,r8
55         mtspr   DBAT3U,r8
56         mtspr   DBAT3L,r8
57 .clearbats_601:
58         mtspr   IBAT0U,r8
59         mtspr   IBAT0L,r8
60         mtspr   IBAT1U,r8
61         mtspr   IBAT1L,r8
62         mtspr   IBAT2U,r8
63         mtspr   IBAT2L,r8
64         mtspr   IBAT3U,r8
65         mtspr   IBAT3L,r8
66         isync
67         sync
68         sync
69
70         /* Set segment registers */
71         li      r8,16           /* load up segment register values */
72         mtctr   r8              /* for context 0 */
73         lis     r8,0x2000       /* Ku = 1, VSID = 0 */
74         li      r10,0
75 3:      mtsrin  r8,r10
76         addi    r8,r8,0x111     /* increment VSID */
77         addis   r10,r10,0x1000  /* address of next segment */
78         bdnz    3b
79         blr
80
81         .globl  disable_6xx_l1cache
82 disable_6xx_l1cache:
83         /* Enable, invalidate and then disable the L1 icache/dcache. */
84         li      r8,0
85         ori     r8,r8,(HID0_ICE|HID0_DCE|HID0_ICFI|HID0_DCI)
86         mfspr   r11,HID0
87         or      r11,r11,r8
88         andc    r10,r11,r8
89         isync
90         mtspr   HID0,r8
91         sync
92         isync
93         mtspr   HID0,r10
94         sync
95         isync
96         blr
97
98         .globl  _setup_L2CR
99 _setup_L2CR:
100 /*
101  * We should be skipping this section on CPUs where this results in an
102  * illegal instruction.  If not, please send trini@kernel.crashing.org
103  * the PVR of your CPU.
104  */
105         /* Invalidate/disable L2 cache */
106         sync
107         isync
108         mfspr   r8,L2CR
109         rlwinm  r8,r8,0,1,31
110         oris    r8,r8,L2CR_L2I@h
111         sync
112         isync
113         mtspr   L2CR,r8
114         sync
115         isync
116
117         /* Wait for the invalidation to complete */
118         mfspr   r8,PVR
119         srwi    r8,r8,16
120         cmpli   cr0,r8,0x8000                   /* 7450 */
121         cmpli   cr1,r8,0x8001                   /* 7455 */
122         cmpli   cr2,r8,0x8002                   /* 7457 */
123         cror    4*cr0+eq,4*cr0+eq,4*cr1+eq      /* Now test if any are true. */
124         cror    4*cr0+eq,4*cr0+eq,4*cr2+eq
125         bne     2f
126
127 1:      mfspr   r8,L2CR         /* On 745x, poll L2I bit (bit 10) */
128         rlwinm. r9,r8,0,10,10
129         bne     1b
130         b       3f
131
132 2:      mfspr   r8,L2CR         /* On 75x & 74[01]0, poll L2IP bit (bit 31) */
133         rlwinm. r9,r8,0,31,31
134         bne     2b
135
136 3:      rlwinm  r8,r8,0,11,9    /* Turn off L2I bit */
137         sync
138         isync
139         mtspr   L2CR,r8
140         sync
141         isync
142         blr
143
144         .globl  _setup_L3CR
145 _setup_L3CR:
146         /* Invalidate/disable L3 cache */
147         sync
148         isync
149         mfspr   r8,L3CR
150         rlwinm  r8,r8,0,1,31
151         ori     r8,r8,L3CR_L3I@l
152         sync
153         isync
154         mtspr   L3CR,r8
155         sync
156         isync
157
158         /* Wait for the invalidation to complete */
159 1:      mfspr   r8,L3CR
160         rlwinm. r9,r8,0,21,21
161         bne     1b
162
163         rlwinm  r8,r8,0,22,20           /* Turn off L3I bit */
164         sync
165         isync
166         mtspr   L3CR,r8
167         sync
168         isync
169         blr
170
171
172 /* udelay (on non-601 processors) needs to know the period of the
173  * timebase in nanoseconds.  This used to be hardcoded to be 60ns
174  * (period of 66MHz/4).  Now a variable is used that is initialized to
175  * 60 for backward compatibility, but it can be overridden as necessary
176  * with code something like this:
177  *    extern unsigned long timebase_period_ns;
178  *    timebase_period_ns = 1000000000 / bd->bi_tbfreq;
179  */
180         .data
181         .globl timebase_period_ns
182 timebase_period_ns:
183         .long   60
184
185         .text
186 /*
187  * Delay for a number of microseconds
188  */
189         .globl  udelay
190 udelay:
191         mfspr   r4,PVR
192         srwi    r4,r4,16
193         cmpi    0,r4,1          /* 601 ? */
194         bne     .udelay_not_601
195 00:     li      r0,86   /* Instructions / microsecond? */
196         mtctr   r0
197 10:     addi    r0,r0,0 /* NOP */
198         bdnz    10b
199         subic.  r3,r3,1
200         bne     00b
201         blr
202
203 .udelay_not_601:
204         mulli   r4,r3,1000      /* nanoseconds */
205         /*  Change r4 to be the number of ticks using:  
206          *      (nanoseconds + (timebase_period_ns - 1 )) / timebase_period_ns
207          *  timebase_period_ns defaults to 60 (16.6MHz) */
208         lis     r5,timebase_period_ns@ha
209         lwz     r5,timebase_period_ns@l(r5)
210         add     r4,r4,r5
211         addi    r4,r4,-1
212         divw    r4,r4,r5        /* BUS ticks */
213 1:      mftbu   r5
214         mftb    r6
215         mftbu   r7
216         cmp     0,r5,r7
217         bne     1b              /* Get [synced] base time */
218         addc    r9,r6,r4        /* Compute end time */
219         addze   r8,r5
220 2:      mftbu   r5
221         cmp     0,r5,r8
222         blt     2b
223         bgt     3f
224         mftb    r6
225         cmp     0,r6,r9
226         blt     2b
227 3:      blr
228
229         .section ".relocate_code","xa"
230 /*
231  * Flush and enable instruction cache
232  * First, flush the data cache in case it was enabled and may be
233  * holding instructions for copy back.
234  */
235 _GLOBAL(flush_instruction_cache)
236         mflr    r6
237         bl      flush_data_cache
238
239 #ifdef CONFIG_8xx
240         lis     r3, IDC_INVALL@h
241         mtspr   IC_CST, r3
242         lis     r3, IDC_ENABLE@h
243         mtspr   IC_CST, r3
244         lis     r3, IDC_DISABLE@h
245         mtspr   DC_CST, r3
246 #elif CONFIG_4xx
247         lis     r3,start@h              # r9 = &_start
248         lis     r4,_etext@ha
249         addi    r4,r4,_etext@l          # r8 = &_etext
250 1:      dcbf    r0,r3                   # Flush the data cache
251         icbi    r0,r3                   # Invalidate the instruction cache
252         addi    r3,r3,0x10              # Increment by one cache line
253         cmplwi  cr0,r3,r4               # Are we at the end yet?
254         blt     1b                      # No, keep flushing and invalidating
255 #else
256         /* Enable, invalidate and then disable the L1 icache/dcache. */
257         li      r3,0
258         ori     r3,r3,(HID0_ICE|HID0_DCE|HID0_ICFI|HID0_DCI)
259         mfspr   r4,HID0
260         or      r5,r4,r3
261         isync
262         mtspr   HID0,r5
263         sync
264         isync
265         ori     r5,r4,HID0_ICE  /* Enable cache */
266         mtspr   HID0,r5
267         sync
268         isync
269 #endif
270         mtlr    r6
271         blr
272
273 #define NUM_CACHE_LINES 128*8
274 #define cache_flush_buffer 0x1000
275
276 /*
277  * Flush data cache
278  * Do this by just reading lots of stuff into the cache.
279  */
280 _GLOBAL(flush_data_cache)
281         lis     r3,cache_flush_buffer@h
282         ori     r3,r3,cache_flush_buffer@l
283         li      r4,NUM_CACHE_LINES
284         mtctr   r4
285 00:     lwz     r4,0(r3)
286         addi    r3,r3,L1_CACHE_BYTES    /* Next line, please */
287         bdnz    00b
288 10:     blr
289
290         .previous
291