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