Import 2.3.16
[davej-history.git] / arch / ppc / boot / head.S
blob59e6f2f26df3b2616bb282f2caf29db8bf83dd3e
1 #include "../kernel/ppc_defs.h"
2 #include "../kernel/ppc_asm.tmpl"
3 #include <asm/processor.h>
4 #include <asm/cache.h>
6         .text
8 /*
9  * $Id: head.S,v 1.32 1999/08/12 19:51:12 cort Exp $
10  *      
11  * Boot loader philosophy:
12  *      ROM loads us to some arbitrary location
13  *      Move the boot code to the link address (8M)
14  *      Call decompress_kernel()
15  *         Relocate the initrd, zimage and residual data to 8M
16  *         Decompress the kernel to 0
17  *      Jump to the kernel entry
18  *            -- Cort
19  */
20         .globl  start
21 start:
22         bl      start_
23 start_:
24         mr      r11,r3          /* Save pointer to residual/board data */
25         mr      r25,r5          /* Save OFW pointer */
26         li      r3,MSR_IP       /* Establish default MSR value */
27         mtmsr   r3
29 /* check if we need to relocate ourselves to the link addr or were we
30    loaded there to begin with -- Cort */
31         lis     r4,start@h
32         ori     r4,r4,start@l
33         mflr    r3
34         subi    r3,r3,4         /* we get the nip, not the ip of the branch */
35         mr      r8,r3
36         cmp     0,r3,r4
37         bne     1010f
38 /* compute size of whole image in words.  this should be moved to
39  * start_ldr() -- Cort
40  */
41         lis     r4,start@h
42         ori     r4,r4,start@l
43         lis     r5,end@h
44         ori     r5,r5,end@l
45         addi    r5,r5,3         /* round up */
46         sub     r5,r5,r4
47         srwi    r5,r5,2
48         mr      r7,r5
49         b       start_ldr
50 1010:
51 /* 
52  * no matter where we're loaded, move ourselves to -Ttext address
53  */
54 relocate:
55         mflr    r3              /* Compute code bias */
56         subi    r3,r3,4
57         mr      r8,r3
58         lis     r4,start@h
59         ori     r4,r4,start@l
60         lis     r5,end@h
61         ori     r5,r5,end@l
62         addi    r5,r5,3                 /* Round up - just in case */
63         sub     r5,r5,r4                /* Compute # longwords to move */
64         srwi    r5,r5,2
65         mtctr   r5
66         mr      r7,r5
67         li      r6,0
68         subi    r3,r3,4                 /* Set up for loop */
69         subi    r4,r4,4
70 00:     lwzu    r5,4(r3)
71         stwu    r5,4(r4)
72         xor     r6,r6,r5
73         bdnz    00b
74         lis     r3,start_ldr@h
75         ori     r3,r3,start_ldr@l
76         mtlr    r3                      /* Easiest way to do an absolute jump */
77         blr
78 start_ldr:
79 /* Clear all of BSS */
80         lis     r3,edata@h
81         ori     r3,r3,edata@l
82         lis     r4,end@h
83         ori     r4,r4,end@l
84         subi    r3,r3,4
85         subi    r4,r4,4
86         li      r0,0
87 50:     stwu    r0,4(r3)
88         cmp     0,r3,r4
89         bne     50b
90 90:     mr      r9,r1                   /* Save old stack pointer (in case it matters) */
91         lis     r1,.stack@h
92         ori     r1,r1,.stack@l
93         addi    r1,r1,4096*2
94         subi    r1,r1,256
95         li      r2,0x000F               /* Mask pointer to 16-byte boundary */
96         andc    r1,r1,r2
97 /* Run loader */
98         mr      r3,r8                   /* Load point */
99         mr      r4,r7                   /* Program length */
100         mr      r5,r6                   /* Checksum */
101         mr      r6,r11                  /* Residual data */
102         mr      r7,r25                  /* OFW interfaces */
103         bl      decompress_kernel
104         
105         /* changed to use r3 (as firmware does) for kernel
106            as ptr to residual -- Cort*/
107         lis     r6,cmd_line@h
108         ori     r6,r6,cmd_line@l
109         lwz     r6, 0(r6)
110         subi    r7,r6,1
111 00:     lbzu    r2,1(r7)
112         cmpi    0,r2,0
113         bne     00b
115         /* r4,r5 have initrd_start, size */
116         lis     r2,initrd_start@h
117         ori     r2,r2,initrd_start@l
118         lwz     r4,0(r2)
119         lis     r2,initrd_end@h
120         ori     r2,r2,initrd_end@l
121         lwz     r5,0(r2)
122         
123         /* tell kernel we're prep */
124         /* 
125          * get start address of kernel code which is stored as a coff
126          * entry.  see boot/head.S -- Cort 
127          */
128         li      r9,0x0
129         mtlr    r9
130         lis     r10,0xdeadc0de@h
131         ori     r10,r10,0xdeadc0de@l
132         stw     r10,0(r9)
134  * The Radstone firmware maps PCI memory at 0xc0000000 using BAT2
135  * so disable BATs before setting this to avoid a clash
136  */
137         li      r8,0
138         mtspr   DBAT0U,r8
139         mtspr   DBAT1U,r8
140         mtspr   DBAT2U,r8
141         mtspr   DBAT3U,r8
142         mtspr   IBAT0U,r8
143         mtspr   IBAT1U,r8
144         mtspr   IBAT2U,r8
145         mtspr   IBAT3U,r8
147         blr
148 hang:
149         b       hang    
152  * Delay for a number of microseconds
153  * -- Use the BUS timer (assumes 66MHz)
154  */
155         .globl  udelay
156 udelay:         
157         mfspr   r4,PVR
158         srwi    r4,r4,16
159         cmpi    0,r4,1          /* 601 ? */
160         bne     .udelay_not_601
161 00:     li      r0,86   /* Instructions / microsecond? */
162         mtctr   r0
163 10:     addi    r0,r0,0 /* NOP */
164         bdnz    10b
165         subic.  r3,r3,1
166         bne     00b
167         blr
169 .udelay_not_601:                
170         mulli   r4,r3,1000      /* nanoseconds */
171         addi    r4,r4,59
172         li      r5,60
173         divw    r4,r4,r5        /* BUS ticks */
174 1:      mftbu   r5
175         mftb    r6
176         mftbu   r7
177         cmp     0,r5,r7
178         bne     1b              /* Get [synced] base time */
179         addc    r9,r6,r4        /* Compute end time */
180         addze   r8,r5
181 2:      mftbu   r5
182         cmp     0,r5,r8
183         blt     2b
184         bgt     3f
185         mftb    r6
186         cmp     0,r6,r9
187         blt     2b
188 3:      blr             
190 .globl _get_HID0
191 _get_HID0:              
192         mfspr   r3,HID0
193         blr
195 .globl _put_HID0
196 _put_HID0:              
197         mtspr   HID0,r3
198         blr
199                 
200 .globl _get_MSR
201 _get_MSR:               
202         mfmsr   r3
203         blr
204         
205 .globl _put_MSR
206 _put_MSR:               
207         mtmsr   r3
208         blr
211  * Flush instruction cache
212  * *** I'm really paranoid here!
213  */
214 _GLOBAL(flush_instruction_cache)
215         mflr    r5
216         bl      flush_data_cache
217         mfspr   r3,HID0 /* Caches are controlled by this register */
218         li      r4,0
219         ori     r4,r4,(HID0_ICE|HID0_ICFI)
220         or      r3,r3,r4        /* Need to enable+invalidate to clear */
221         mtspr   HID0,r3
222         andc    r3,r3,r4
223         ori     r3,r3,HID0_ICE  /* Enable cache */
224         mtspr   HID0,r3
225         mtlr    r5
226         blr
227         
228 #define NUM_CACHE_LINES 128*8
229 #define CACHE_LINE_SIZE 32 
230 #define cache_flush_buffer 0x1000
233  * Flush data cache
234  * *** I'm really paranoid here!
235  */
236 _GLOBAL(flush_data_cache)
237         lis     r3,cache_flush_buffer@h
238         ori     r3,r3,cache_flush_buffer@l
239         li      r4,NUM_CACHE_LINES
240         mtctr   r4
241 00:     lwz     r4,0(r3)
242         addi    r3,r3,CACHE_LINE_SIZE   /* Next line, please */
243         bdnz    00b     
244 10:     blr
245         .comm   .stack,4096*2,4