blob: 10dffb4a5cb84c1c740663f3a83c694e0ffdde0a [file] [log] [blame]
Xiangfu Liu80421fc2011-10-12 12:24:06 +08001/*
2 * Startup Code for MIPS32 XBURST CPU-core
3 *
4 * Copyright (c) 2010 Xiangfu Liu <xiangfu@sharism.cc>
5 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02006 * SPDX-License-Identifier: GPL-2.0+
Xiangfu Liu80421fc2011-10-12 12:24:06 +08007 */
8
9#include <config.h>
10#include <version.h>
11#include <asm/regdef.h>
12#include <asm/mipsregs.h>
13#include <asm/addrspace.h>
14#include <asm/cacheops.h>
15
16 .set noreorder
17
18 .globl _start
19 .text
20_start:
21 /* Initialize $gp */
22 bal 1f
23 nop
24 .word _gp
251:
26 lw gp, 0(ra)
27
28 /* Set up temporary stack */
29 li sp, CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_INIT_SP_OFFSET
30
31 la t9, board_init_f
32 jr t9
33 nop
34
35/*
36 * void relocate_code (addr_sp, gd, addr_moni)
37 *
38 * This "function" does not return, instead it continues in RAM
39 * after relocating the monitor code.
40 *
41 * a0 = addr_sp
42 * a1 = gd
43 * a2 = destination address
44 */
45 .globl relocate_code
46 .ent relocate_code
47relocate_code:
48 move sp, a0 # set new stack pointer
49
Gabor Juhosf01d6932013-06-13 12:59:31 +020050 move s0, a1 # save gd in s0
Gabor Juhos9a28e0d2013-06-13 12:59:29 +020051 move s2, a2 # save destination address in s2
52
Xiangfu Liu80421fc2011-10-12 12:24:06 +080053 li t0, CONFIG_SYS_MONITOR_BASE
Gabor Juhosba9cf072013-06-13 12:59:30 +020054 sub s1, s2, t0 # s1 <-- relocation offset
Gabor Juhos6d862272013-01-30 04:51:06 +000055
Xiangfu Liu80421fc2011-10-12 12:24:06 +080056 la t3, in_ram
Daniel Schwierzeck28875e22013-02-12 22:22:13 +010057 lw t2, -12(t3) # t2 <-- __image_copy_end
Xiangfu Liu80421fc2011-10-12 12:24:06 +080058 move t1, a2
59
Gabor Juhosba9cf072013-06-13 12:59:30 +020060 add gp, s1 # adjust gp
Xiangfu Liu80421fc2011-10-12 12:24:06 +080061
62 /*
63 * t0 = source address
64 * t1 = target address
65 * t2 = source end address
66 */
671:
68 lw t3, 0(t0)
69 sw t3, 0(t1)
70 addu t0, 4
Gabor Juhos5b7dd812013-01-24 06:27:51 +000071 blt t0, t2, 1b
Xiangfu Liu80421fc2011-10-12 12:24:06 +080072 addu t1, 4
73
74 /* If caches were enabled, we would have to flush them here. */
75
76 /* flush d-cache */
77 li t0, KSEG0
78 addi t1, t0, CONFIG_SYS_DCACHE_SIZE
792:
Zhi-zhou Zhangcb0a6a12012-10-16 15:02:08 +020080 cache INDEX_WRITEBACK_INV_D, 0(t0)
Xiangfu Liu80421fc2011-10-12 12:24:06 +080081 bne t0, t1, 2b
82 addi t0, CONFIG_SYS_CACHELINE_SIZE
83
84 sync
85
86 /* flush i-cache */
87 li t0, KSEG0
88 addi t1, t0, CONFIG_SYS_ICACHE_SIZE
893:
Zhi-zhou Zhangcb0a6a12012-10-16 15:02:08 +020090 cache INDEX_INVALIDATE_I, 0(t0)
Xiangfu Liu80421fc2011-10-12 12:24:06 +080091 bne t0, t1, 3b
92 addi t0, CONFIG_SYS_CACHELINE_SIZE
93
94 /* Invalidate BTB */
95 mfc0 t0, CP0_CONFIG, 7
96 nop
97 ori t0, 2
98 mtc0 t0, CP0_CONFIG, 7
99 nop
100
101 /* Jump to where we've relocated ourselves */
Gabor Juhos9a28e0d2013-06-13 12:59:29 +0200102 addi t0, s2, in_ram - _start
Xiangfu Liu80421fc2011-10-12 12:24:06 +0800103 jr t0
104 nop
105
Gabor Juhos04380c62013-02-12 22:22:13 +0100106 .word __rel_dyn_end
107 .word __rel_dyn_start
Daniel Schwierzeck28875e22013-02-12 22:22:13 +0100108 .word __image_copy_end
Xiangfu Liu80421fc2011-10-12 12:24:06 +0800109 .word _GLOBAL_OFFSET_TABLE_
Xiangfu Liu80421fc2011-10-12 12:24:06 +0800110 .word num_got_entries
111
112in_ram:
113 /*
114 * Now we want to update GOT.
115 *
116 * GOT[0] is reserved. GOT[1] is also reserved for the dynamic object
117 * generated by GNU ld. Skip these reserved entries from relocation.
118 */
119 lw t3, -4(t0) # t3 <-- num_got_entries
Gabor Juhose5c868a2013-06-13 12:59:32 +0200120 lw t8, -8(t0) # t8 <-- _GLOBAL_OFFSET_TABLE_
121 add t8, s1 # t8 now holds relocated _G_O_T_
122 addi t8, t8, 8 # skipping first two entries
Xiangfu Liu80421fc2011-10-12 12:24:06 +0800123 li t2, 2
1241:
Gabor Juhose5c868a2013-06-13 12:59:32 +0200125 lw t1, 0(t8)
Xiangfu Liu80421fc2011-10-12 12:24:06 +0800126 beqz t1, 2f
Gabor Juhosba9cf072013-06-13 12:59:30 +0200127 add t1, s1
Gabor Juhose5c868a2013-06-13 12:59:32 +0200128 sw t1, 0(t8)
Xiangfu Liu80421fc2011-10-12 12:24:06 +08001292:
130 addi t2, 1
131 blt t2, t3, 1b
Gabor Juhose5c868a2013-06-13 12:59:32 +0200132 addi t8, 4
Xiangfu Liu80421fc2011-10-12 12:24:06 +0800133
Gabor Juhos04380c62013-02-12 22:22:13 +0100134 /* Update dynamic relocations */
135 lw t1, -16(t0) # t1 <-- __rel_dyn_start
136 lw t2, -20(t0) # t2 <-- __rel_dyn_end
137
138 b 2f # skip first reserved entry
139 addi t1, 8
140
1411:
Gabor Juhosd707e5b2013-06-14 14:47:10 +0200142 lw t8, -4(t1) # t8 <-- relocation info
Gabor Juhos04380c62013-02-12 22:22:13 +0100143
Gabor Juhosd707e5b2013-06-14 14:47:10 +0200144 li t3, 3
145 bne t8, t3, 2f # skip non R_MIPS_REL32 entries
Gabor Juhos04380c62013-02-12 22:22:13 +0100146 nop
147
148 lw t3, -8(t1) # t3 <-- location to fix up in FLASH
149
Gabor Juhose5c868a2013-06-13 12:59:32 +0200150 lw t8, 0(t3) # t8 <-- original pointer
151 add t8, s1 # t8 <-- adjusted pointer
Gabor Juhos04380c62013-02-12 22:22:13 +0100152
Gabor Juhosba9cf072013-06-13 12:59:30 +0200153 add t3, s1 # t3 <-- location to fix up in RAM
Gabor Juhose5c868a2013-06-13 12:59:32 +0200154 sw t8, 0(t3)
Gabor Juhos04380c62013-02-12 22:22:13 +0100155
1562:
157 blt t1, t2, 1b
158 addi t1, 8 # each rel.dyn entry is 8 bytes
159
Daniel Schwierzeck696a3b22013-02-12 22:22:13 +0100160 /*
161 * Clear BSS
162 *
163 * GOT is now relocated. Thus __bss_start and __bss_end can be
164 * accessed directly via $gp.
165 */
166 la t1, __bss_start # t1 <-- __bss_start
167 la t2, __bss_end # t2 <-- __bss_end
Xiangfu Liu80421fc2011-10-12 12:24:06 +0800168
Daniel Schwierzeck696a3b22013-02-12 22:22:13 +01001691:
170 sw zero, 0(t1)
171 blt t1, t2, 1b
172 addi t1, 4
Xiangfu Liu80421fc2011-10-12 12:24:06 +0800173
Gabor Juhosf01d6932013-06-13 12:59:31 +0200174 move a0, s0 # a0 <-- gd
Xiangfu Liu80421fc2011-10-12 12:24:06 +0800175 la t9, board_init_r
176 jr t9
Gabor Juhos9a28e0d2013-06-13 12:59:29 +0200177 move a1, s2
Xiangfu Liu80421fc2011-10-12 12:24:06 +0800178
179 .end relocate_code