Merge branch 'master' of git://git.denx.de/u-boot-ubi
[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         move    s2, a2          /* s2 <-- destination address   */
315
316         /*
317          * Fix $gp:
318          *
319          * New $gp = (Old $gp - CONFIG_SYS_MONITOR_BASE) + Destination Address
320          */
321         move    t6, gp
322         sub     gp, CONFIG_SYS_MONITOR_BASE
323         add     gp, a2          /* gp now adjusted              */
324         sub     s1, gp, t6      /* s1 <-- relocation offset     */
325
326         /*
327          * t0 = source address
328          * t1 = target address
329          * t2 = source end address
330          */
331
332         /*
333          * Save destination address and size for later usage in flush_cache()
334          */
335         move    s0, a1          /* save gd in s0                */
336         move    a0, t1          /* a0 <-- destination addr      */
337         sub     a1, t2, t0      /* a1 <-- size                  */
338
339         /* On the purple board we copy the code earlier in a special way
340          * in order to solve flash problems
341          */
342 #ifndef CONFIG_PURPLE
343 1:
344         lw      t3, 0(t0)
345         sw      t3, 0(t1)
346         addu    t0, 4
347         ble     t0, t2, 1b
348         addu    t1, 4           /* delay slot                   */
349 #endif
350
351         /* If caches were enabled, we would have to flush them here.
352          */
353
354         /* a0 & a1 are already set up for flush_cache(start, size) */
355         la      t9, flush_cache
356         jalr    t9
357         nop
358
359         /* Jump to where we've relocated ourselves.
360          */
361         addi    t0, s2, in_ram - _start
362         jr      t0
363         nop
364
365         .word   _gp
366         .word   _GLOBAL_OFFSET_TABLE_
367         .word   uboot_end_data
368         .word   uboot_end
369         .word   num_got_entries
370
371 in_ram:
372         /*
373          * Now we want to update GOT.
374          *
375          * GOT[0] is reserved. GOT[1] is also reserved for the dynamic object
376          * generated by GNU ld. Skip these reserved entries from relocation.
377          */
378         lw      t3, -4(t0)      /* t3 <-- num_got_entries       */
379         lw      t4, -16(t0)     /* t4 <-- _GLOBAL_OFFSET_TABLE_ */
380         lw      t5, -20(t0)     /* t5 <-- _gp   */
381         sub     t4, t5          /* compute offset*/
382         add     t4, t4, gp      /* t4 now holds relocated _GLOBAL_OFFSET_TABLE_ */
383         addi    t4, t4, 8       /* Skipping first two entries.  */
384         li      t2, 2
385 1:
386         lw      t1, 0(t4)
387         beqz    t1, 2f
388         add     t1, s1
389         sw      t1, 0(t4)
390 2:
391         addi    t2, 1
392         blt     t2, t3, 1b
393         addi    t4, 4           /* delay slot                   */
394
395         /* Clear BSS.
396          */
397         lw      t1, -12(t0)     /* t1 <-- uboot_end_data        */
398         lw      t2, -8(t0)      /* t2 <-- uboot_end             */
399         add     t1, s1          /* adjust pointers              */
400         add     t2, s1
401
402         sub     t1, 4
403 1:
404         addi    t1, 4
405         bltl    t1, t2, 1b
406         sw      zero, 0(t1)     /* delay slot                   */
407
408         move    a0, s0          /* a0 <-- gd                    */
409         la      t9, board_init_r
410         jr      t9
411         move    a1, s2          /* delay slot                   */
412
413         .end    relocate_code
414
415         /* Exception handlers.
416          */
417 romReserved:
418         b       romReserved
419
420 romExcHandle:
421         b       romExcHandle