]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/mips/cpu/xburst/start.S
Merge branch 'master' of git://git.denx.de/u-boot-mips
[karo-tx-uboot.git] / arch / mips / cpu / xburst / start.S
1 /*
2  *  Startup Code for MIPS32 XBURST CPU-core
3  *
4  *  Copyright (c) 2010 Xiangfu Liu <xiangfu@sharism.cc>
5  *
6  * SPDX-License-Identifier:     GPL-2.0+
7  */
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
25 1:
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
47 relocate_code:
48         move    sp, a0                  # set new stack pointer
49
50         move    s0, a1                  # save gd in s0
51         move    s2, a2                  # save destination address in s2
52
53         li      t0, CONFIG_SYS_MONITOR_BASE
54         sub     s1, s2, t0              # s1 <-- relocation offset
55
56         la      t3, in_ram
57         lw      t2, -12(t3)             # t2 <-- __image_copy_end
58         move    t1, a2
59
60         add     gp, s1                  # adjust gp
61
62         /*
63          * t0 = source address
64          * t1 = target address
65          * t2 = source end address
66          */
67 1:
68         lw      t3, 0(t0)
69         sw      t3, 0(t1)
70         addu    t0, 4
71         blt     t0, t2, 1b
72          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
79 2:
80         cache   INDEX_WRITEBACK_INV_D, 0(t0)
81         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
89 3:
90         cache   INDEX_INVALIDATE_I, 0(t0)
91         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 */
102         addi    t0, s2, in_ram - _start
103         jr      t0
104          nop
105
106         .word   __rel_dyn_end
107         .word   __rel_dyn_start
108         .word   __image_copy_end
109         .word   _GLOBAL_OFFSET_TABLE_
110         .word   num_got_entries
111
112 in_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
120         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
123         li      t2, 2
124 1:
125         lw      t1, 0(t8)
126         beqz    t1, 2f
127          add    t1, s1
128         sw      t1, 0(t8)
129 2:
130         addi    t2, 1
131         blt     t2, t3, 1b
132          addi   t8, 4
133
134         /* 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
141 1:
142         lw      t8, -4(t1)              # t8 <-- relocation info
143
144         li      t3, 3
145         bne     t8, t3, 2f              # skip non R_MIPS_REL32 entries
146          nop
147
148         lw      t3, -8(t1)              # t3 <-- location to fix up in FLASH
149
150         lw      t8, 0(t3)               # t8 <-- original pointer
151         add     t8, s1                  # t8 <-- adjusted pointer
152
153         add     t3, s1                  # t3 <-- location to fix up in RAM
154         sw      t8, 0(t3)
155
156 2:
157         blt     t1, t2, 1b
158          addi   t1, 8                   # each rel.dyn entry is 8 bytes
159
160         /*
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
168
169 1:
170         sw      zero, 0(t1)
171         blt     t1, t2, 1b
172          addi   t1, 4
173
174         move    a0, s0                  # a0 <-- gd
175         la      t9, board_init_r
176         jr      t9
177          move   a1, s2
178
179         .end    relocate_code