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