f6069b3eeaaba98a0c6fdbe77e4363e12d27ff10
[oweals/u-boot.git] / cpu / mips / start.S
1 /*
2  *  Startup Code for MIPS32 CPU-core
3  *
4  *  Copyright (c) 2003  Wolfgang Denk <wd@denx.de>
5  *
6  * See file CREDITS for list of people who contributed to this
7  * project.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation; either version 2 of
12  * the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22  * MA 02111-1307 USA
23  */
24
25 #include <config.h>
26 #include <asm/regdef.h>
27 #include <asm/mipsregs.h>
28
29         /*
30          * For the moment disable interrupts, mark the kernel mode and
31          * set ST0_KX so that the CPU does not spit fire when using
32          * 64-bit addresses.
33          */
34         .macro  setup_c0_status set clr
35         .set    push
36         mfc0    t0, CP0_STATUS
37         or      t0, ST0_CU0 | \set | 0x1f | \clr
38         xor     t0, 0x1f | \clr
39         mtc0    t0, CP0_STATUS
40         .set    noreorder
41         sll     zero, 3                         # ehb
42         .set    pop
43         .endm
44
45         .macro  setup_c0_status_reset
46 #ifdef CONFIG_64BIT
47         setup_c0_status ST0_KX 0
48 #else
49         setup_c0_status 0 0
50 #endif
51         .endm
52
53 #define RVECENT(f,n) \
54    b f; nop
55 #define XVECENT(f,bev) \
56    b f     ;           \
57    li k0,bev
58
59         .set noreorder
60
61         .globl _start
62         .text
63 _start:
64         RVECENT(reset,0)        /* U-boot entry point */
65         RVECENT(reset,1)        /* software reboot */
66 #if defined(CONFIG_INCA_IP)
67         .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */
68         .word 0x00000000           /* phase of the flash                    */
69 #elif defined(CONFIG_PURPLE)
70         .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */
71         .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */
72 #else
73         RVECENT(romReserved,2)
74 #endif
75         RVECENT(romReserved,3)
76         RVECENT(romReserved,4)
77         RVECENT(romReserved,5)
78         RVECENT(romReserved,6)
79         RVECENT(romReserved,7)
80         RVECENT(romReserved,8)
81         RVECENT(romReserved,9)
82         RVECENT(romReserved,10)
83         RVECENT(romReserved,11)
84         RVECENT(romReserved,12)
85         RVECENT(romReserved,13)
86         RVECENT(romReserved,14)
87         RVECENT(romReserved,15)
88         RVECENT(romReserved,16)
89         RVECENT(romReserved,17)
90         RVECENT(romReserved,18)
91         RVECENT(romReserved,19)
92         RVECENT(romReserved,20)
93         RVECENT(romReserved,21)
94         RVECENT(romReserved,22)
95         RVECENT(romReserved,23)
96         RVECENT(romReserved,24)
97         RVECENT(romReserved,25)
98         RVECENT(romReserved,26)
99         RVECENT(romReserved,27)
100         RVECENT(romReserved,28)
101         RVECENT(romReserved,29)
102         RVECENT(romReserved,30)
103         RVECENT(romReserved,31)
104         RVECENT(romReserved,32)
105         RVECENT(romReserved,33)
106         RVECENT(romReserved,34)
107         RVECENT(romReserved,35)
108         RVECENT(romReserved,36)
109         RVECENT(romReserved,37)
110         RVECENT(romReserved,38)
111         RVECENT(romReserved,39)
112         RVECENT(romReserved,40)
113         RVECENT(romReserved,41)
114         RVECENT(romReserved,42)
115         RVECENT(romReserved,43)
116         RVECENT(romReserved,44)
117         RVECENT(romReserved,45)
118         RVECENT(romReserved,46)
119         RVECENT(romReserved,47)
120         RVECENT(romReserved,48)
121         RVECENT(romReserved,49)
122         RVECENT(romReserved,50)
123         RVECENT(romReserved,51)
124         RVECENT(romReserved,52)
125         RVECENT(romReserved,53)
126         RVECENT(romReserved,54)
127         RVECENT(romReserved,55)
128         RVECENT(romReserved,56)
129         RVECENT(romReserved,57)
130         RVECENT(romReserved,58)
131         RVECENT(romReserved,59)
132         RVECENT(romReserved,60)
133         RVECENT(romReserved,61)
134         RVECENT(romReserved,62)
135         RVECENT(romReserved,63)
136         XVECENT(romExcHandle,0x200)     /* bfc00200: R4000 tlbmiss vector */
137         RVECENT(romReserved,65)
138         RVECENT(romReserved,66)
139         RVECENT(romReserved,67)
140         RVECENT(romReserved,68)
141         RVECENT(romReserved,69)
142         RVECENT(romReserved,70)
143         RVECENT(romReserved,71)
144         RVECENT(romReserved,72)
145         RVECENT(romReserved,73)
146         RVECENT(romReserved,74)
147         RVECENT(romReserved,75)
148         RVECENT(romReserved,76)
149         RVECENT(romReserved,77)
150         RVECENT(romReserved,78)
151         RVECENT(romReserved,79)
152         XVECENT(romExcHandle,0x280)     /* bfc00280: R4000 xtlbmiss vector */
153         RVECENT(romReserved,81)
154         RVECENT(romReserved,82)
155         RVECENT(romReserved,83)
156         RVECENT(romReserved,84)
157         RVECENT(romReserved,85)
158         RVECENT(romReserved,86)
159         RVECENT(romReserved,87)
160         RVECENT(romReserved,88)
161         RVECENT(romReserved,89)
162         RVECENT(romReserved,90)
163         RVECENT(romReserved,91)
164         RVECENT(romReserved,92)
165         RVECENT(romReserved,93)
166         RVECENT(romReserved,94)
167         RVECENT(romReserved,95)
168         XVECENT(romExcHandle,0x300)     /* bfc00300: R4000 cache vector */
169         RVECENT(romReserved,97)
170         RVECENT(romReserved,98)
171         RVECENT(romReserved,99)
172         RVECENT(romReserved,100)
173         RVECENT(romReserved,101)
174         RVECENT(romReserved,102)
175         RVECENT(romReserved,103)
176         RVECENT(romReserved,104)
177         RVECENT(romReserved,105)
178         RVECENT(romReserved,106)
179         RVECENT(romReserved,107)
180         RVECENT(romReserved,108)
181         RVECENT(romReserved,109)
182         RVECENT(romReserved,110)
183         RVECENT(romReserved,111)
184         XVECENT(romExcHandle,0x380)     /* bfc00380: R4000 general vector */
185         RVECENT(romReserved,113)
186         RVECENT(romReserved,114)
187         RVECENT(romReserved,115)
188         RVECENT(romReserved,116)
189         RVECENT(romReserved,116)
190         RVECENT(romReserved,118)
191         RVECENT(romReserved,119)
192         RVECENT(romReserved,120)
193         RVECENT(romReserved,121)
194         RVECENT(romReserved,122)
195         RVECENT(romReserved,123)
196         RVECENT(romReserved,124)
197         RVECENT(romReserved,125)
198         RVECENT(romReserved,126)
199         RVECENT(romReserved,127)
200
201         /* We hope there are no more reserved vectors!
202          * 128 * 8 == 1024 == 0x400
203          * so this is address R_VEC+0x400 == 0xbfc00400
204          */
205 #ifdef CONFIG_PURPLE
206 /* 0xbfc00400 */
207         .word   0xdc870000
208         .word   0xfca70000
209         .word   0x20840008
210         .word   0x20a50008
211         .word   0x20c6ffff
212         .word   0x14c0fffa
213         .word   0x00000000
214         .word   0x03e00008
215         .word   0x00000000
216         .word   0x00000000
217 /* 0xbfc00428 */
218         .word   0xdc870000
219         .word   0xfca70000
220         .word   0x20840008
221         .word   0x20a50008
222         .word   0x20c6ffff
223         .word   0x14c0fffa
224         .word   0x00000000
225         .word   0x03e00008
226         .word   0x00000000
227         .word   0x00000000
228 #endif /* CONFIG_PURPLE */
229         .align 4
230 reset:
231
232         /* Clear watch registers.
233          */
234         mtc0    zero, CP0_WATCHLO
235         mtc0    zero, CP0_WATCHHI
236
237         /* WP(Watch Pending), SW0/1 should be cleared. */
238         mtc0    zero, CP0_CAUSE
239
240         setup_c0_status_reset
241
242         /* Init Timer */
243         mtc0    zero, CP0_COUNT
244         mtc0    zero, CP0_COMPARE
245
246 #if !defined(CONFIG_SKIP_LOWLEVEL_INIT)
247         /* CONFIG0 register */
248         li      t0, CONF_CM_UNCACHED
249         mtc0    t0, CP0_CONFIG
250 #endif /* !CONFIG_SKIP_LOWLEVEL_INIT */
251
252         /* Initialize $gp.
253          */
254         bal     1f
255         nop
256         .word   _gp
257 1:
258         lw      gp, 0(ra)
259
260 #if !defined(CONFIG_SKIP_LOWLEVEL_INIT)
261         /* Initialize any external memory.
262          */
263         la      t9, lowlevel_init
264         jalr    t9
265         nop
266
267         /* Initialize caches...
268          */
269         la      t9, mips_cache_reset
270         jalr    t9
271         nop
272
273         /* ... and enable them.
274          */
275         li      t0, CONF_CM_CACHABLE_NONCOHERENT
276         mtc0    t0, CP0_CONFIG
277 #endif /* !CONFIG_SKIP_LOWLEVEL_INIT */
278
279         /* Set up temporary stack.
280          */
281 #ifdef CONFIG_SYS_INIT_RAM_LOCK_MIPS
282         li      a0, CONFIG_SYS_INIT_SP_OFFSET
283         la      t9, mips_cache_lock
284         jalr    t9
285         nop
286 #endif
287
288         li      t0, CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_INIT_SP_OFFSET
289         la      sp, 0(t0)
290
291         la      t9, board_init_f
292         jr      t9
293         nop
294
295 /*
296  * void relocate_code (addr_sp, gd, addr_moni)
297  *
298  * This "function" does not return, instead it continues in RAM
299  * after relocating the monitor code.
300  *
301  * a0 = addr_sp
302  * a1 = gd
303  * a2 = destination address
304  */
305         .globl  relocate_code
306         .ent    relocate_code
307 relocate_code:
308         move    sp, a0          /* Set new stack pointer        */
309
310         li      t0, CONFIG_SYS_MONITOR_BASE
311         la      t3, in_ram
312         lw      t2, -12(t3)     /* t2 <-- uboot_end_data        */
313         move    t1, a2
314
315         /*
316          * Fix $gp:
317          *
318          * New $gp = (Old $gp - CONFIG_SYS_MONITOR_BASE) + Destination Address
319          */
320         move    t6, gp
321         sub     gp, CONFIG_SYS_MONITOR_BASE
322         add     gp, a2          /* gp now adjusted              */
323         sub     t6, gp, t6      /* t6 <-- relocation offset     */
324
325         /*
326          * t0 = source address
327          * t1 = target address
328          * t2 = source end address
329          */
330         /* On the purple board we copy the code earlier in a special way
331          * in order to solve flash problems
332          */
333 #ifndef CONFIG_PURPLE
334 1:
335         lw      t3, 0(t0)
336         sw      t3, 0(t1)
337         addu    t0, 4
338         ble     t0, t2, 1b
339         addu    t1, 4           /* delay slot                   */
340 #endif
341
342         /* If caches were enabled, we would have to flush them here.
343          */
344
345         /* Jump to where we've relocated ourselves.
346          */
347         addi    t0, a2, in_ram - _start
348         jr      t0
349         nop
350
351         .word   _gp
352         .word   _GLOBAL_OFFSET_TABLE_
353         .word   uboot_end_data
354         .word   uboot_end
355         .word   num_got_entries
356
357 in_ram:
358         /*
359          * Now we want to update GOT.
360          *
361          * GOT[0] is reserved. GOT[1] is also reserved for the dynamic object
362          * generated by GNU ld. Skip these reserved entries from relocation.
363          */
364         lw      t3, -4(t0)      /* t3 <-- num_got_entries       */
365         lw      t4, -16(t0)     /* t4 <-- _GLOBAL_OFFSET_TABLE_ */
366         lw      t5, -20(t0)     /* t5 <-- _gp   */
367         sub     t4, t5          /* compute offset*/
368         add     t4, t4, gp      /* t4 now holds relocated _GLOBAL_OFFSET_TABLE_ */
369         addi    t4, t4, 8       /* Skipping first two entries.  */
370         li      t2, 2
371 1:
372         lw      t1, 0(t4)
373         beqz    t1, 2f
374         add     t1, t6
375         sw      t1, 0(t4)
376 2:
377         addi    t2, 1
378         blt     t2, t3, 1b
379         addi    t4, 4           /* delay slot                   */
380
381         /* Clear BSS.
382          */
383         lw      t1, -12(t0)     /* t1 <-- uboot_end_data        */
384         lw      t2, -8(t0)      /* t2 <-- uboot_end             */
385         add     t1, t6          /* adjust pointers              */
386         add     t2, t6
387
388         sub     t1, 4
389 1:
390         addi    t1, 4
391         bltl    t1, t2, 1b
392         sw      zero, 0(t1)     /* delay slot                   */
393
394         move    a0, a1
395         la      t9, board_init_r
396         jr      t9
397         move    a1, a2          /* delay slot                   */
398
399         .end    relocate_code
400
401         /* Exception handlers.
402          */
403 romReserved:
404         b       romReserved
405
406 romExcHandle:
407         b       romExcHandle