]>
Commit | Line | Data |
---|---|---|
c021880a WD |
1 | /* |
2 | * Startup Code for MIPS32 CPU-core | |
3 | * | |
4 | * Copyright (c) 2003 Wolfgang Denk <wd@denx.de> | |
5 | * | |
1a459660 | 6 | * SPDX-License-Identifier: GPL-2.0+ |
c021880a WD |
7 | */ |
8 | ||
25ddd1fb | 9 | #include <asm-offsets.h> |
c021880a | 10 | #include <config.h> |
c021880a WD |
11 | #include <asm/regdef.h> |
12 | #include <asm/mipsregs.h> | |
13 | ||
ab2a98b1 DS |
14 | #ifndef CONFIG_SYS_MIPS_CACHE_MODE |
15 | #define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT | |
16 | #endif | |
17 | ||
decaba6f SK |
18 | /* |
19 | * For the moment disable interrupts, mark the kernel mode and | |
20 | * set ST0_KX so that the CPU does not spit fire when using | |
21 | * 64-bit addresses. | |
22 | */ | |
23 | .macro setup_c0_status set clr | |
24 | .set push | |
25 | mfc0 t0, CP0_STATUS | |
26 | or t0, ST0_CU0 | \set | 0x1f | \clr | |
27 | xor t0, 0x1f | \clr | |
28 | mtc0 t0, CP0_STATUS | |
29 | .set noreorder | |
30 | sll zero, 3 # ehb | |
31 | .set pop | |
32 | .endm | |
33 | ||
c021880a WD |
34 | .set noreorder |
35 | ||
36 | .globl _start | |
37 | .text | |
38 | _start: | |
8b1c7345 DS |
39 | /* U-boot entry point */ |
40 | b reset | |
41 | nop | |
42 | ||
43 | .org 0x10 | |
7185adb4 DS |
44 | #ifdef CONFIG_SYS_XWAY_EBU_BOOTCFG |
45 | /* | |
46 | * Almost all Lantiq XWAY SoC devices have an external bus unit (EBU) to | |
47 | * access external NOR flashes. If the board boots from NOR flash the | |
48 | * internal BootROM does a blind read at address 0xB0000010 to read the | |
49 | * initial configuration for that EBU in order to access the flash | |
50 | * device with correct parameters. This config option is board-specific. | |
51 | */ | |
52 | .word CONFIG_SYS_XWAY_EBU_BOOTCFG | |
8b1c7345 | 53 | .word 0x0 |
c021880a | 54 | #endif |
8bde7f77 | 55 | |
8b1c7345 DS |
56 | .org 0x200 |
57 | /* TLB refill, 32 bit task */ | |
58 | 1: b 1b | |
59 | nop | |
60 | ||
61 | .org 0x280 | |
62 | /* XTLB refill, 64 bit task */ | |
63 | 1: b 1b | |
64 | nop | |
65 | ||
66 | .org 0x300 | |
67 | /* Cache error exception */ | |
68 | 1: b 1b | |
69 | nop | |
70 | ||
71 | .org 0x380 | |
72 | /* General exception */ | |
73 | 1: b 1b | |
74 | nop | |
75 | ||
76 | .org 0x400 | |
77 | /* Catch interrupt exceptions */ | |
78 | 1: b 1b | |
79 | nop | |
80 | ||
81 | .org 0x480 | |
82 | /* EJTAG debug exception */ | |
83 | 1: b 1b | |
84 | nop | |
85 | ||
c021880a WD |
86 | .align 4 |
87 | reset: | |
88 | ||
7aa1f198 | 89 | /* Clear watch registers */ |
c021880a WD |
90 | mtc0 zero, CP0_WATCHLO |
91 | mtc0 zero, CP0_WATCHHI | |
92 | ||
7aa1f198 | 93 | /* WP(Watch Pending), SW0/1 should be cleared */ |
d43d43ef SK |
94 | mtc0 zero, CP0_CAUSE |
95 | ||
4dc7412a | 96 | setup_c0_status 0 0 |
c021880a | 97 | |
c021880a WD |
98 | /* Init Timer */ |
99 | mtc0 zero, CP0_COUNT | |
100 | mtc0 zero, CP0_COMPARE | |
101 | ||
7aa1f198 | 102 | #ifndef CONFIG_SKIP_LOWLEVEL_INIT |
c021880a WD |
103 | /* CONFIG0 register */ |
104 | li t0, CONF_CM_UNCACHED | |
105 | mtc0 t0, CP0_CONFIG | |
7aa1f198 | 106 | #endif |
c021880a | 107 | |
7aa1f198 | 108 | /* Initialize $gp */ |
03c031d5 | 109 | bal 1f |
7aa1f198 | 110 | nop |
22069215 | 111 | .word _gp |
03c031d5 | 112 | 1: |
16664f72 | 113 | lw gp, 0(ra) |
c75eba3b | 114 | |
7aa1f198 SK |
115 | #ifndef CONFIG_SKIP_LOWLEVEL_INIT |
116 | /* Initialize any external memory */ | |
03c031d5 SK |
117 | la t9, lowlevel_init |
118 | jalr t9 | |
7aa1f198 | 119 | nop |
c021880a | 120 | |
7aa1f198 | 121 | /* Initialize caches... */ |
03c031d5 SK |
122 | la t9, mips_cache_reset |
123 | jalr t9 | |
7aa1f198 | 124 | nop |
c021880a | 125 | |
7aa1f198 | 126 | /* ... and enable them */ |
ab2a98b1 | 127 | li t0, CONFIG_SYS_MIPS_CACHE_MODE |
c021880a | 128 | mtc0 t0, CP0_CONFIG |
7aa1f198 | 129 | #endif |
c021880a | 130 | |
7aa1f198 | 131 | /* Set up temporary stack */ |
f321b0f9 | 132 | li sp, CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_INIT_SP_OFFSET |
c021880a | 133 | |
c021880a | 134 | la t9, board_init_f |
43c50925 | 135 | jr t9 |
7aa1f198 | 136 | nop |
c021880a | 137 | |
c021880a WD |
138 | /* |
139 | * void relocate_code (addr_sp, gd, addr_moni) | |
140 | * | |
141 | * This "function" does not return, instead it continues in RAM | |
142 | * after relocating the monitor code. | |
143 | * | |
144 | * a0 = addr_sp | |
145 | * a1 = gd | |
146 | * a2 = destination address | |
147 | */ | |
148 | .globl relocate_code | |
149 | .ent relocate_code | |
150 | relocate_code: | |
7aa1f198 | 151 | move sp, a0 # set new stack pointer |
c021880a | 152 | |
b2fe86f8 GJ |
153 | move s0, a1 # save gd in s0 |
154 | move s2, a2 # save destination address in s2 | |
155 | ||
6d0f6bcf | 156 | li t0, CONFIG_SYS_MONITOR_BASE |
248fe03f GJ |
157 | sub s1, s2, t0 # s1 <-- relocation offset |
158 | ||
27b207fd | 159 | la t3, in_ram |
28875e2c | 160 | lw t2, -12(t3) # t2 <-- __image_copy_end |
27b207fd WD |
161 | move t1, a2 |
162 | ||
248fe03f | 163 | add gp, s1 # adjust gp |
8bde7f77 | 164 | |
c021880a WD |
165 | /* |
166 | * t0 = source address | |
167 | * t1 = target address | |
168 | * t2 = source end address | |
169 | */ | |
170 | 1: | |
171 | lw t3, 0(t0) | |
172 | sw t3, 0(t1) | |
173 | addu t0, 4 | |
5b7dd816 | 174 | blt t0, t2, 1b |
7aa1f198 | 175 | addu t1, 4 |
c021880a | 176 | |
7aa1f198 | 177 | /* If caches were enabled, we would have to flush them here. */ |
67d80c9f | 178 | sub a1, t1, s2 # a1 <-- size |
71fa0714 SR |
179 | la t9, flush_cache |
180 | jalr t9 | |
67d80c9f | 181 | move a0, s2 # a0 <-- destination address |
71fa0714 | 182 | |
7aa1f198 | 183 | /* Jump to where we've relocated ourselves */ |
71fa0714 | 184 | addi t0, s2, in_ram - _start |
43c50925 | 185 | jr t0 |
7aa1f198 | 186 | nop |
c021880a | 187 | |
04380c65 GJ |
188 | .word __rel_dyn_end |
189 | .word __rel_dyn_start | |
28875e2c | 190 | .word __image_copy_end |
0f8c62a1 | 191 | .word _GLOBAL_OFFSET_TABLE_ |
c021880a WD |
192 | .word num_got_entries |
193 | ||
194 | in_ram: | |
22069215 SK |
195 | /* |
196 | * Now we want to update GOT. | |
197 | * | |
198 | * GOT[0] is reserved. GOT[1] is also reserved for the dynamic object | |
199 | * generated by GNU ld. Skip these reserved entries from relocation. | |
c021880a | 200 | */ |
7aa1f198 | 201 | lw t3, -4(t0) # t3 <-- num_got_entries |
28875e2c | 202 | lw t4, -8(t0) # t4 <-- _GLOBAL_OFFSET_TABLE_ |
025f2b33 | 203 | add t4, s1 # t4 now holds relocated _G_O_T_ |
7aa1f198 | 204 | addi t4, t4, 8 # skipping first two entries |
c021880a WD |
205 | li t2, 2 |
206 | 1: | |
207 | lw t1, 0(t4) | |
208 | beqz t1, 2f | |
7aa1f198 | 209 | add t1, s1 |
c021880a WD |
210 | sw t1, 0(t4) |
211 | 2: | |
212 | addi t2, 1 | |
213 | blt t2, t3, 1b | |
7aa1f198 | 214 | addi t4, 4 |
c021880a | 215 | |
04380c65 GJ |
216 | /* Update dynamic relocations */ |
217 | lw t1, -16(t0) # t1 <-- __rel_dyn_start | |
218 | lw t2, -20(t0) # t2 <-- __rel_dyn_end | |
219 | ||
220 | b 2f # skip first reserved entry | |
221 | addi t1, 8 | |
222 | ||
223 | 1: | |
224 | lw t3, -4(t1) # t3 <-- relocation info | |
225 | ||
226 | sub t3, 3 | |
227 | bnez t3, 2f # skip non R_MIPS_REL32 entries | |
228 | nop | |
229 | ||
230 | lw t3, -8(t1) # t3 <-- location to fix up in FLASH | |
231 | ||
232 | lw t4, 0(t3) # t4 <-- original pointer | |
233 | add t4, s1 # t4 <-- adjusted pointer | |
234 | ||
235 | add t3, s1 # t3 <-- location to fix up in RAM | |
236 | sw t4, 0(t3) | |
237 | ||
238 | 2: | |
239 | blt t1, t2, 1b | |
240 | addi t1, 8 # each rel.dyn entry is 8 bytes | |
241 | ||
696a3b2a DS |
242 | /* |
243 | * Clear BSS | |
244 | * | |
245 | * GOT is now relocated. Thus __bss_start and __bss_end can be | |
246 | * accessed directly via $gp. | |
247 | */ | |
248 | la t1, __bss_start # t1 <-- __bss_start | |
249 | la t2, __bss_end # t2 <-- __bss_end | |
c021880a | 250 | |
03c031d5 | 251 | 1: |
696a3b2a DS |
252 | sw zero, 0(t1) |
253 | blt t1, t2, 1b | |
254 | addi t1, 4 | |
8bde7f77 | 255 | |
7aa1f198 | 256 | move a0, s0 # a0 <-- gd |
c021880a | 257 | la t9, board_init_r |
43c50925 | 258 | jr t9 |
7aa1f198 | 259 | move a1, s2 |
c021880a WD |
260 | |
261 | .end relocate_code |