xref: /rk3399_rockchip-uboot/arch/mips/cpu/start.S (revision 345490fcd68d830adef7fcfa4ef5bf5681c29546)
1/*
2 *  Startup Code for MIPS32 CPU-core
3 *
4 *  Copyright (c) 2003	Wolfgang Denk <wd@denx.de>
5 *
6 * SPDX-License-Identifier:	GPL-2.0+
7 */
8
9#include <asm-offsets.h>
10#include <config.h>
11#include <asm/asm.h>
12#include <asm/regdef.h>
13#include <asm/mipsregs.h>
14
15#ifndef CONFIG_SYS_INIT_SP_ADDR
16#define CONFIG_SYS_INIT_SP_ADDR	(CONFIG_SYS_SDRAM_BASE + \
17				CONFIG_SYS_INIT_SP_OFFSET)
18#endif
19
20#ifdef CONFIG_32BIT
21# define MIPS_RELOC	3
22# define STATUS_SET	0
23#endif
24
25#ifdef CONFIG_64BIT
26# ifdef CONFIG_SYS_LITTLE_ENDIAN
27#  define MIPS64_R_INFO(ssym, r_type3, r_type2, r_type) \
28	(((r_type) << 24) | ((r_type2) << 16) | ((r_type3) << 8) | (ssym))
29# else
30#  define MIPS64_R_INFO(ssym, r_type3, r_type2, r_type) \
31	((r_type) | ((r_type2) << 8) | ((r_type3) << 16) | (ssym) << 24)
32# endif
33# define MIPS_RELOC	MIPS64_R_INFO(0x00, 0x00, 0x12, 0x03)
34# define STATUS_SET	ST0_KX
35#endif
36
37	/*
38	 * For the moment disable interrupts, mark the kernel mode and
39	 * set ST0_KX so that the CPU does not spit fire when using
40	 * 64-bit addresses.
41	 */
42	.macro	setup_c0_status set clr
43	.set	push
44	mfc0	t0, CP0_STATUS
45	or	t0, ST0_CU0 | \set | 0x1f | \clr
46	xor	t0, 0x1f | \clr
47	mtc0	t0, CP0_STATUS
48	.set	noreorder
49	sll	zero, 3				# ehb
50	.set	pop
51	.endm
52
53	.set noreorder
54
55	.macro uhi_mips_exception
56	move	k0, t9		# preserve t9 in k0
57	move	k1, a0		# preserve a0 in k1
58	li	t9, 15		# UHI exception operation
59	li	a0, 0		# Use hard register context
60	sdbbp	1		# Invoke UHI operation
61	.endm
62
63ENTRY(_start)
64	/* U-Boot entry point */
65	b	reset
66	 nop
67
68#if defined(CONFIG_SYS_XWAY_EBU_BOOTCFG)
69	/*
70	 * Almost all Lantiq XWAY SoC devices have an external bus unit (EBU) to
71	 * access external NOR flashes. If the board boots from NOR flash the
72	 * internal BootROM does a blind read at address 0xB0000010 to read the
73	 * initial configuration for that EBU in order to access the flash
74	 * device with correct parameters. This config option is board-specific.
75	 */
76	.org 0x10
77	.word CONFIG_SYS_XWAY_EBU_BOOTCFG
78	.word 0x0
79#endif
80#if defined(CONFIG_MALTA)
81	/*
82	 * Linux expects the Board ID here.
83	 */
84	.org 0x10
85	.word 0x00000420	# 0x420 (Malta Board with CoreLV)
86	.word 0x00000000
87#endif
88
89#if defined(CONFIG_ROM_EXCEPTION_VECTORS)
90	/*
91	 * Exception vector entry points. When running from ROM, an exception
92	 * cannot be handled. Halt execution and transfer control to debugger,
93	 * if one is attached.
94	 */
95	.org 0x200
96	/* TLB refill, 32 bit task */
97	uhi_mips_exception
98
99	.org 0x280
100	/* XTLB refill, 64 bit task */
101	uhi_mips_exception
102
103	.org 0x300
104	/* Cache error exception */
105	uhi_mips_exception
106
107	.org 0x380
108	/* General exception */
109	uhi_mips_exception
110
111	.org 0x400
112	/* Catch interrupt exceptions */
113	uhi_mips_exception
114
115	.org 0x480
116	/* EJTAG debug exception */
1171:	b	1b
118	 nop
119
120	.org 0x500
121#endif
122
123reset:
124#if __mips_isa_rev >= 6
125	mfc0	t0, CP0_CONFIG, 5
126	and	t0, t0, MIPS_CONF5_VP
127	beqz	t0, 1f
128	 nop
129
130	b	2f
131	 mfc0	t0, CP0_GLOBALNUMBER
132#endif
133
1341:	mfc0	t0, CP0_EBASE
135	and	t0, t0, EBASE_CPUNUM
136
137	/* Hang if this isn't the first CPU in the system */
1382:	beqz	t0, 4f
139	 nop
1403:	wait
141	b	3b
142	 nop
143
144	/* Clear watch registers */
1454:	MTC0	zero, CP0_WATCHLO
146	mtc0	zero, CP0_WATCHHI
147
148	/* WP(Watch Pending), SW0/1 should be cleared */
149	mtc0	zero, CP0_CAUSE
150
151	setup_c0_status STATUS_SET 0
152
153	/* Init Timer */
154	mtc0	zero, CP0_COUNT
155	mtc0	zero, CP0_COMPARE
156
157#ifndef CONFIG_SKIP_LOWLEVEL_INIT
158	mfc0	t0, CP0_CONFIG
159	and	t0, t0, MIPS_CONF_IMPL
160	or	t0, t0, CONF_CM_UNCACHED
161	mtc0	t0, CP0_CONFIG
162	ehb
163#endif
164
165	/*
166	 * Initialize $gp, force pointer sized alignment of bal instruction to
167	 * forbid the compiler to put nop's between bal and _gp. This is
168	 * required to keep _gp and ra aligned to 8 byte.
169	 */
170	.align	PTRLOG
171	bal	1f
172	 nop
173	PTR	_gp
1741:
175	PTR_L	gp, 0(ra)
176
177#ifdef CONFIG_MIPS_CM
178	PTR_LA	t9, mips_cm_map
179	jalr	t9
180	 nop
181#endif
182
183#ifndef CONFIG_SKIP_LOWLEVEL_INIT
184# ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
185	/* Initialize any external memory */
186	PTR_LA	t9, lowlevel_init
187	jalr	t9
188	 nop
189# endif
190
191	/* Initialize caches... */
192	PTR_LA	t9, mips_cache_reset
193	jalr	t9
194	 nop
195
196# ifndef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
197	/* Initialize any external memory */
198	PTR_LA	t9, lowlevel_init
199	jalr	t9
200	 nop
201# endif
202#endif
203
204	/* Set up temporary stack */
205	li	t0, -16
206	PTR_LI	t1, CONFIG_SYS_INIT_SP_ADDR
207	and	sp, t1, t0		# force 16 byte alignment
208	PTR_SUBU \
209		sp, sp, GD_SIZE		# reserve space for gd
210	and	sp, sp, t0		# force 16 byte alignment
211	move	k0, sp			# save gd pointer
212#ifdef CONFIG_SYS_MALLOC_F_LEN
213	li	t2, CONFIG_SYS_MALLOC_F_LEN
214	PTR_SUBU \
215		sp, sp, t2		# reserve space for early malloc
216	and	sp, sp, t0		# force 16 byte alignment
217#endif
218	move	fp, sp
219
220	/* Clear gd */
221	move	t0, k0
2221:
223	PTR_S	zero, 0(t0)
224	blt	t0, t1, 1b
225	 PTR_ADDIU t0, PTRSIZE
226
227#ifdef CONFIG_SYS_MALLOC_F_LEN
228	PTR_S	sp, GD_MALLOC_BASE(k0)	# gd->malloc_base offset
229#endif
230
231	move	a0, zero		# a0 <-- boot_flags = 0
232	PTR_LA	t9, board_init_f
233
234	jr	t9
235	 move	ra, zero
236
237	END(_start)
238
239/*
240 * void relocate_code (addr_sp, gd, addr_moni)
241 *
242 * This "function" does not return, instead it continues in RAM
243 * after relocating the monitor code.
244 *
245 * a0 = addr_sp
246 * a1 = gd
247 * a2 = destination address
248 */
249ENTRY(relocate_code)
250	move	sp, a0			# set new stack pointer
251	move	fp, sp
252
253	move	s0, a1			# save gd in s0
254	move	s2, a2			# save destination address in s2
255
256	PTR_LI	t0, CONFIG_SYS_MONITOR_BASE
257	PTR_SUB	s1, s2, t0		# s1 <-- relocation offset
258
259	PTR_LA	t2, __image_copy_end
260	move	t1, a2
261
262	/*
263	 * t0 = source address
264	 * t1 = target address
265	 * t2 = source end address
266	 */
2671:
268	PTR_L	t3, 0(t0)
269	PTR_S	t3, 0(t1)
270	PTR_ADDU t0, PTRSIZE
271	blt	t0, t2, 1b
272	 PTR_ADDU t1, PTRSIZE
273
274	/*
275	 * Now we want to update GOT.
276	 *
277	 * GOT[0] is reserved. GOT[1] is also reserved for the dynamic object
278	 * generated by GNU ld. Skip these reserved entries from relocation.
279	 */
280	PTR_LA	t3, num_got_entries
281	PTR_LA	t8, _GLOBAL_OFFSET_TABLE_
282	PTR_ADD	t8, s1			# t8 now holds relocated _G_O_T_
283	PTR_ADDIU t8, t8, 2 * PTRSIZE	# skipping first two entries
284	PTR_LI	t2, 2
2851:
286	PTR_L	t1, 0(t8)
287	beqz	t1, 2f
288	 PTR_ADD t1, s1
289	PTR_S	t1, 0(t8)
2902:
291	PTR_ADDIU t2, 1
292	blt	t2, t3, 1b
293	 PTR_ADDIU t8, PTRSIZE
294
295	/* Update dynamic relocations */
296	PTR_LA	t1, __rel_dyn_start
297	PTR_LA	t2, __rel_dyn_end
298
299	b	2f			# skip first reserved entry
300	 PTR_ADDIU t1, 2 * PTRSIZE
301
3021:
303	lw	t8, -4(t1)		# t8 <-- relocation info
304
305	PTR_LI	t3, MIPS_RELOC
306	bne	t8, t3, 2f		# skip non-MIPS_RELOC entries
307	 nop
308
309	PTR_L	t3, -(2 * PTRSIZE)(t1)	# t3 <-- location to fix up in FLASH
310
311	PTR_L	t8, 0(t3)		# t8 <-- original pointer
312	PTR_ADD	t8, s1			# t8 <-- adjusted pointer
313
314	PTR_ADD	t3, s1			# t3 <-- location to fix up in RAM
315	PTR_S	t8, 0(t3)
316
3172:
318	blt	t1, t2, 1b
319	 PTR_ADDIU t1, 2 * PTRSIZE	# each rel.dyn entry is 2*PTRSIZE bytes
320
321	/*
322	 * Flush caches to ensure our newly modified instructions are visible
323	 * to the instruction cache. We're still running with the old GOT, so
324	 * apply the reloc offset to the start address.
325	 */
326	PTR_LA	a0, __text_start
327	PTR_LA	a1, __text_end
328	PTR_SUB	a1, a1, a0
329	PTR_LA	t9, flush_cache
330	jalr	t9
331	 PTR_ADD	a0, s1
332
333	PTR_ADD	gp, s1			# adjust gp
334
335	/*
336	 * Clear BSS
337	 *
338	 * GOT is now relocated. Thus __bss_start and __bss_end can be
339	 * accessed directly via $gp.
340	 */
341	PTR_LA	t1, __bss_start		# t1 <-- __bss_start
342	PTR_LA	t2, __bss_end		# t2 <-- __bss_end
343
3441:
345	PTR_S	zero, 0(t1)
346	blt	t1, t2, 1b
347	 PTR_ADDIU t1, PTRSIZE
348
349	move	a0, s0			# a0 <-- gd
350	move	a1, s2
351	PTR_LA	t9, board_init_r
352	jr	t9
353	 move	ra, zero
354
355	END(relocate_code)
356