xref: /openbmc/u-boot/arch/mips/cpu/start.S (revision 7d2a0534)
1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 *  Startup Code for MIPS32 CPU-core
4 *
5 *  Copyright (c) 2003	Wolfgang Denk <wd@denx.de>
6 */
7
8#include <asm-offsets.h>
9#include <config.h>
10#include <asm/asm.h>
11#include <asm/regdef.h>
12#include <asm/mipsregs.h>
13
14#ifndef CONFIG_SYS_INIT_SP_ADDR
15#define CONFIG_SYS_INIT_SP_ADDR	(CONFIG_SYS_SDRAM_BASE + \
16				CONFIG_SYS_INIT_SP_OFFSET)
17#endif
18
19#ifdef CONFIG_32BIT
20# define MIPS_RELOC	3
21# define STATUS_SET	0
22#endif
23
24#ifdef CONFIG_64BIT
25# ifdef CONFIG_SYS_LITTLE_ENDIAN
26#  define MIPS64_R_INFO(ssym, r_type3, r_type2, r_type) \
27	(((r_type) << 24) | ((r_type2) << 16) | ((r_type3) << 8) | (ssym))
28# else
29#  define MIPS64_R_INFO(ssym, r_type3, r_type2, r_type) \
30	((r_type) | ((r_type2) << 8) | ((r_type3) << 16) | (ssym) << 24)
31# endif
32# define MIPS_RELOC	MIPS64_R_INFO(0x00, 0x00, 0x12, 0x03)
33# define STATUS_SET	ST0_KX
34#endif
35
36	.set noreorder
37
38	.macro init_wr sel
39	MTC0	zero, CP0_WATCHLO,\sel
40	mtc0	t1, CP0_WATCHHI,\sel
41	mfc0	t0, CP0_WATCHHI,\sel
42	bgez	t0, wr_done
43	 nop
44	.endm
45
46	.macro uhi_mips_exception
47	move	k0, t9		# preserve t9 in k0
48	move	k1, a0		# preserve a0 in k1
49	li	t9, 15		# UHI exception operation
50	li	a0, 0		# Use hard register context
51	sdbbp	1		# Invoke UHI operation
52	.endm
53
54	.macro setup_stack_gd
55	li	t0, -16
56	PTR_LI	t1, CONFIG_SYS_INIT_SP_ADDR
57	and	sp, t1, t0		# force 16 byte alignment
58	PTR_SUBU \
59		sp, sp, GD_SIZE		# reserve space for gd
60	and	sp, sp, t0		# force 16 byte alignment
61	move	k0, sp			# save gd pointer
62#if CONFIG_VAL(SYS_MALLOC_F_LEN)
63	li	t2, CONFIG_VAL(SYS_MALLOC_F_LEN)
64	PTR_SUBU \
65		sp, sp, t2		# reserve space for early malloc
66	and	sp, sp, t0		# force 16 byte alignment
67#endif
68	move	fp, sp
69
70	/* Clear gd */
71	move	t0, k0
721:
73	PTR_S	zero, 0(t0)
74	blt	t0, t1, 1b
75	 PTR_ADDIU t0, PTRSIZE
76
77#if CONFIG_VAL(SYS_MALLOC_F_LEN)
78	PTR_S	sp, GD_MALLOC_BASE(k0)	# gd->malloc_base offset
79#endif
80	.endm
81
82ENTRY(_start)
83	/* U-Boot entry point */
84	b	reset
85	 mtc0	zero, CP0_COUNT	# clear cp0 count for most accurate boot timing
86
87#if defined(CONFIG_MIPS_INSERT_BOOT_CONFIG)
88	/*
89	 * Store some board-specific boot configuration. This is used by some
90	 * MIPS systems like Malta.
91	 */
92	.org 0x10
93	.word CONFIG_MIPS_BOOT_CONFIG_WORD0
94	.word CONFIG_MIPS_BOOT_CONFIG_WORD1
95#endif
96
97#if defined(CONFIG_ROM_EXCEPTION_VECTORS)
98	/*
99	 * Exception vector entry points. When running from ROM, an exception
100	 * cannot be handled. Halt execution and transfer control to debugger,
101	 * if one is attached.
102	 */
103	.org 0x200
104	/* TLB refill, 32 bit task */
105	uhi_mips_exception
106
107	.org 0x280
108	/* XTLB refill, 64 bit task */
109	uhi_mips_exception
110
111	.org 0x300
112	/* Cache error exception */
113	uhi_mips_exception
114
115	.org 0x380
116	/* General exception */
117	uhi_mips_exception
118
119	.org 0x400
120	/* Catch interrupt exceptions */
121	uhi_mips_exception
122
123	.org 0x480
124	/* EJTAG debug exception */
1251:	b	1b
126	 nop
127
128	.org 0x500
129#endif
130
131reset:
132#if __mips_isa_rev >= 6
133	mfc0	t0, CP0_CONFIG, 5
134	and	t0, t0, MIPS_CONF5_VP
135	beqz	t0, 1f
136	 nop
137
138	b	2f
139	 mfc0	t0, CP0_GLOBALNUMBER
140#endif
141
142#ifdef CONFIG_ARCH_BMIPS
1431:	mfc0	t0, CP0_DIAGNOSTIC, 3
144	and	t0, t0, (1 << 31)
145#else
1461:	mfc0	t0, CP0_EBASE
147	and	t0, t0, EBASE_CPUNUM
148#endif
149
150	/* Hang if this isn't the first CPU in the system */
1512:	beqz	t0, 4f
152	 nop
1533:	wait
154	b	3b
155	 nop
156
157	/* Init CP0 Status */
1584:	mfc0	t0, CP0_STATUS
159	and	t0, ST0_IMPL
160	or	t0, ST0_BEV | ST0_ERL | STATUS_SET
161	mtc0	t0, CP0_STATUS
162
163	/*
164	 * Check whether CP0 Config1 is implemented. If not continue
165	 * with legacy Watch register initialization.
166	 */
167	mfc0	t0, CP0_CONFIG
168	bgez	t0, wr_legacy
169	 nop
170
171	/*
172	 * Check WR bit in CP0 Config1 to determine if Watch registers
173	 * are implemented.
174	 */
175	mfc0	t0, CP0_CONFIG, 1
176	andi	t0, (1 << 3)
177	beqz	t0, wr_done
178	 nop
179
180	/* Clear Watch Status bits and disable watch exceptions */
181	li	t1, 0x7		# Clear I, R and W conditions
182	init_wr	0
183	init_wr	1
184	init_wr	2
185	init_wr	3
186	init_wr	4
187	init_wr	5
188	init_wr	6
189	init_wr	7
190	b	wr_done
191	 nop
192
193wr_legacy:
194	MTC0	zero, CP0_WATCHLO
195	mtc0	zero, CP0_WATCHHI
196
197wr_done:
198	/* Clear WP, IV and SW interrupts */
199	mtc0	zero, CP0_CAUSE
200
201	/* Clear timer interrupt (CP0_COUNT cleared on branch to 'reset') */
202	mtc0	zero, CP0_COMPARE
203
204#ifndef CONFIG_SKIP_LOWLEVEL_INIT
205	mfc0	t0, CP0_CONFIG
206	and	t0, t0, MIPS_CONF_IMPL
207	or	t0, t0, CONF_CM_UNCACHED
208	mtc0	t0, CP0_CONFIG
209	ehb
210#endif
211
212#ifdef CONFIG_MIPS_CM
213	PTR_LA	t9, mips_cm_map
214	jalr	t9
215	 nop
216#endif
217
218#ifdef CONFIG_MIPS_INIT_STACK_IN_SRAM
219	/* Set up initial stack and global data */
220	setup_stack_gd
221
222# ifdef CONFIG_DEBUG_UART
223	/* Earliest point to set up debug uart */
224	PTR_LA	t9, debug_uart_init
225	jalr	t9
226	 nop
227# endif
228#endif
229
230#ifndef CONFIG_SKIP_LOWLEVEL_INIT
231# ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
232	/* Initialize any external memory */
233	PTR_LA	t9, lowlevel_init
234	jalr	t9
235	 nop
236# endif
237
238	/* Initialize caches... */
239	PTR_LA	t9, mips_cache_reset
240	jalr	t9
241	 nop
242
243# ifndef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
244	/* Initialize any external memory */
245	PTR_LA	t9, lowlevel_init
246	jalr	t9
247	 nop
248# endif
249#endif
250
251#ifndef CONFIG_MIPS_INIT_STACK_IN_SRAM
252	/* Set up initial stack and global data */
253	setup_stack_gd
254
255# ifdef CONFIG_DEBUG_UART
256	/* Earliest point to set up debug uart */
257	PTR_LA	t9, debug_uart_init
258	jalr	t9
259	 nop
260# endif
261#endif
262
263	move	a0, zero		# a0 <-- boot_flags = 0
264	PTR_LA	t9, board_init_f
265
266	jr	t9
267	 move	ra, zero
268
269	END(_start)
270