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#include <system-constants.h>
14
15#ifdef CONFIG_32BIT
16# define STATUS_SET	0
17#endif
18
19#ifdef CONFIG_64BIT
20# define STATUS_SET	ST0_KX
21#endif
22
23	.set noreorder
24
25	.macro init_wr sel
26	MTC0	zero, CP0_WATCHLO,\sel
27	mtc0	t1, CP0_WATCHHI,\sel
28	mfc0	t0, CP0_WATCHHI,\sel
29	bgez	t0, wr_done
30	 nop
31	.endm
32
33	.macro uhi_mips_exception
34	move	k0, t9		# preserve t9 in k0
35	move	k1, a0		# preserve a0 in k1
36	li	t9, 15		# UHI exception operation
37	li	a0, 0		# Use hard register context
38	sdbbp	1		# Invoke UHI operation
39	.endm
40
41	.macro setup_stack_gd
42	li	t0, -16
43	PTR_LI	t1, SYS_INIT_SP_ADDR
44	and	sp, t1, t0		# force 16 byte alignment
45	PTR_SUBU \
46		sp, sp, GD_SIZE		# reserve space for gd
47	and	sp, sp, t0		# force 16 byte alignment
48	move	k0, sp			# save gd pointer
49#if CONFIG_IS_ENABLED(SYS_MALLOC_F) && \
50    !CONFIG_IS_ENABLED(INIT_STACK_WITHOUT_MALLOC_F)
51	li	t2, CONFIG_VAL(SYS_MALLOC_F_LEN)
52	PTR_SUBU \
53		sp, sp, t2		# reserve space for early malloc
54	and	sp, sp, t0		# force 16 byte alignment
55#endif
56	move	fp, sp
57
58	/* Clear gd */
59	move	t0, k0
601:
61	PTR_S	zero, 0(t0)
62	PTR_ADDIU t0, PTRSIZE
63	blt	t0, t1, 1b
64	 nop
65
66#if CONFIG_IS_ENABLED(SYS_MALLOC_F) && \
67    !CONFIG_IS_ENABLED(INIT_STACK_WITHOUT_MALLOC_F)
68	PTR_S	sp, GD_MALLOC_BASE(k0)	# gd->malloc_base offset
69#endif
70	.endm
71
72ENTRY(_start)
73	/*
74	 * U-Boot entry point.
75	 * Do not add instructions to the branch delay slot! Some SoC's
76	 * like Octeon might patch the final U-Boot binary at this location
77	 * with additional boot headers.
78	 */
79	b	reset
80	 nop
81
82#if defined(CONFIG_MIPS_INSERT_BOOT_CONFIG)
83	/*
84	 * Store some board-specific boot configuration. This is used by some
85	 * MIPS systems like Malta.
86	 */
87	.org 0x10
88	.word CONFIG_MIPS_BOOT_CONFIG_WORD0
89	.word CONFIG_MIPS_BOOT_CONFIG_WORD1
90#endif
91
92#if defined(CONFIG_ROM_EXCEPTION_VECTORS)
93	/*
94	 * Exception vector entry points. When running from ROM, an exception
95	 * cannot be handled. Halt execution and transfer control to debugger,
96	 * if one is attached.
97	 */
98	.org 0x200
99	/* TLB refill, 32 bit task */
100	uhi_mips_exception
101
102	.org 0x280
103	/* XTLB refill, 64 bit task */
104	uhi_mips_exception
105
106	.org 0x300
107	/* Cache error exception */
108	uhi_mips_exception
109
110	.org 0x380
111	/* General exception */
112	uhi_mips_exception
113
114	.org 0x400
115	/* Catch interrupt exceptions */
116	uhi_mips_exception
117
118	.org 0x480
119	/* EJTAG debug exception */
1201:	b	1b
121	 nop
122
123	.org 0x500
124#endif
125
126reset:
127	mtc0	zero, CP0_COUNT	# clear cp0 count for most accurate boot timing
128#if __mips_isa_rev >= 6
129	mfc0	t0, CP0_CONFIG, 5
130	and	t0, t0, MIPS_CONF5_VP
131	beqz	t0, 1f
132	 nop
133
134	b	2f
135	 mfc0	t0, CP0_GLOBALNUMBER
136#endif
137
138#ifdef CONFIG_ARCH_BMIPS
1391:	mfc0	t0, CP0_DIAGNOSTIC, 3
140	and	t0, t0, (1 << 31)
141#else
1421:	mfc0	t0, CP0_EBASE
143	and	t0, t0, MIPS_EBASE_CPUNUM
144#endif
145
146	/* Hang if this isn't the first CPU in the system */
1472:	beqz	t0, 4f
148	 nop
1493:	wait
150	b	3b
151	 nop
152
153	/* Init CP0 Status */
1544:	mfc0	t0, CP0_STATUS
155	and	t0, ST0_IMPL
156	or	t0, ST0_BEV | ST0_ERL | STATUS_SET
157	mtc0	t0, CP0_STATUS
158
159	/*
160	 * Check whether CP0 Config1 is implemented. If not continue
161	 * with legacy Watch register initialization.
162	 */
163	mfc0	t0, CP0_CONFIG
164	bgez	t0, wr_legacy
165	 nop
166
167	/*
168	 * Check WR bit in CP0 Config1 to determine if Watch registers
169	 * are implemented.
170	 */
171	mfc0	t0, CP0_CONFIG, 1
172	andi	t0, (1 << 3)
173	beqz	t0, wr_done
174	 nop
175
176	/* Clear Watch Status bits and disable watch exceptions */
177	li	t1, 0x7		# Clear I, R and W conditions
178	init_wr	0
179	init_wr	1
180	init_wr	2
181	init_wr	3
182	init_wr	4
183	init_wr	5
184	init_wr	6
185	init_wr	7
186	b	wr_done
187	 nop
188
189wr_legacy:
190	MTC0	zero, CP0_WATCHLO
191	mtc0	zero, CP0_WATCHHI
192
193wr_done:
194	/* Clear WP, IV and SW interrupts */
195	mtc0	zero, CP0_CAUSE
196
197	/* Clear timer interrupt (CP0_COUNT cleared on branch to 'reset') */
198	mtc0	zero, CP0_COMPARE
199
200#ifdef CONFIG_MIPS_CACHE_DISABLE
201	/* Disable caches */
202	PTR_LA	t9, mips_cache_disable
203	jalr	t9
204	 nop
205#endif
206
207#ifdef CONFIG_MIPS_CM
208	PTR_LA	t9, mips_cm_map
209	jalr	t9
210	 nop
211#endif
212
213#ifdef CONFIG_MIPS_INIT_STACK_IN_SRAM
214#ifdef CONFIG_MIPS_SRAM_INIT
215	/* Initialize the SRAM first */
216	PTR_LA	t9, mips_sram_init
217	jalr	t9
218	 nop
219#endif
220
221	/* Set up initial stack and global data */
222	setup_stack_gd
223
224# ifdef CONFIG_DEBUG_UART
225	/* Earliest point to set up debug uart */
226	PTR_LA	t9, debug_uart_init
227	jalr	t9
228	 nop
229# endif
230#endif
231
232#if !CONFIG_IS_ENABLED(SKIP_LOWLEVEL_INIT)
233# ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
234	/* Initialize any external memory */
235	PTR_LA	t9, lowlevel_init
236	jalr	t9
237	 nop
238# endif
239#endif
240
241#ifdef CONFIG_MIPS_MACH_EARLY_INIT
242	bal	mips_mach_early_init
243	 nop
244#endif
245
246#ifdef CONFIG_MIPS_CACHE_SETUP
247	/* Initialize caches... */
248	PTR_LA	t9, mips_cache_reset
249	jalr	t9
250	 nop
251#endif
252
253#if !CONFIG_IS_ENABLED(SKIP_LOWLEVEL_INIT)
254# ifndef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
255	/* Initialize any external memory */
256	PTR_LA	t9, lowlevel_init
257	jalr	t9
258	 nop
259# endif
260#endif
261
262#ifndef CONFIG_MIPS_INIT_STACK_IN_SRAM
263	/* Set up initial stack and global data */
264	setup_stack_gd
265
266# ifdef CONFIG_DEBUG_UART
267	/* Earliest point to set up debug uart */
268	PTR_LA	t9, debug_uart_init
269	jalr	t9
270	 nop
271# endif
272#endif
273
274	move	a0, zero		# a0 <-- boot_flags = 0
275	PTR_LA	t9, board_init_f
276
277	jr	t9
278	 move	ra, zero
279
280	END(_start)
281