summaryrefslogtreecommitdiff
path: root/arch/mips/mach-mtmips/mt7621/spl/start.S
blob: 6b9f253952a16da6e7c54c866601d6bca0865753 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (C) 2022 MediaTek Inc. All rights reserved.
 *
 * Author: Weijie Gao <weijie.gao@mediatek.com>
 */

#include <asm-offsets.h>
#include <config.h>
#include <asm/asm.h>
#include <asm/regdef.h>
#include <asm/mipsregs.h>
#include <asm/cacheops.h>
#include <asm/addrspace.h>
#include <asm/mipsmtregs.h>
#include <asm/cm.h>
#include "../mt7621.h"
#include "dram.h"

#ifndef CONFIG_SYS_INIT_SP_ADDR
#define CONFIG_SYS_INIT_SP_ADDR	(CFG_SYS_SDRAM_BASE + \
				CONFIG_SYS_INIT_SP_OFFSET)
#endif

#define SP_ADDR_TEMP		0xbe10dff0

	.macro init_wr sel
	MTC0	zero, CP0_WATCHLO,\sel
	mtc0	t1, CP0_WATCHHI,\sel
	.endm

	.macro setup_stack_gd
	li	t0, -16
	PTR_LI	t1, CONFIG_SYS_INIT_SP_ADDR
	and	sp, t1, t0		# force 16 byte alignment
	PTR_SUBU \
		sp, sp, GD_SIZE		# reserve space for gd
	and	sp, sp, t0		# force 16 byte alignment
	move	k0, sp			# save gd pointer
#if CONFIG_VAL(SYS_MALLOC_F_LEN) && \
    !CONFIG_IS_ENABLED(INIT_STACK_WITHOUT_MALLOC_F)
	li	t2, CONFIG_VAL(SYS_MALLOC_F_LEN)
	PTR_SUBU \
		sp, sp, t2		# reserve space for early malloc
	and	sp, sp, t0		# force 16 byte alignment
#endif
	move	fp, sp

	/* Clear gd */
	move	t0, k0
1:
	PTR_S	zero, 0(t0)
	PTR_ADDIU t0, PTRSIZE
	blt	t0, t1, 1b
	 nop

#if CONFIG_VAL(SYS_MALLOC_F_LEN) && \
    !CONFIG_IS_ENABLED(INIT_STACK_WITHOUT_MALLOC_F)
	PTR_S	sp, GD_MALLOC_BASE(k0)	# gd->malloc_base offset
#endif
	.endm

	.set	noreorder

ENTRY(_start)
	b	1f
	 mtc0	zero, CP0_COUNT

	/* Stage header required by BootROM */
	.org	0x8
	.word	0		# ep, filled by mkimage
	.word	0		# stage_size, filled by mkimage
	.word	0		# has_stage2
	.word	0		# next_ep
	.word	0		# next_size
	.word	0		# next_offset

1:
	/* Init CP0 Status */
	mfc0	t0, CP0_STATUS
	and	t0, ST0_IMPL
	or	t0, ST0_BEV | ST0_ERL
	mtc0	t0, CP0_STATUS
	ehb

	/* Clear Watch Status bits and disable watch exceptions */
	li	t1, 0x7		# Clear I, R and W conditions
	init_wr	0
	init_wr	1
	init_wr	2
	init_wr	3

	/* Clear WP, IV and SW interrupts */
	mtc0	zero, CP0_CAUSE

	/* Clear timer interrupt (CP0_COUNT cleared on branch to 'reset') */
	mtc0	zero, CP0_COMPARE

	/* VPE1 goes to wait code directly */
	mfc0	t0, CP0_TCBIND
	andi	t0, TCBIND_CURVPE
	bnez	t0, launch_vpe_entry
	 nop

	/* Core1 goes to specific launch entry */
	PTR_LI	t0, KSEG1ADDR(CONFIG_MIPS_CM_BASE)
	lw	t1, GCR_Cx_ID(t0)
	bnez	t1, launch_core_entry
	 nop

	/* MT7530 reset */
	li	t0, KSEG1ADDR(SYSCTL_BASE)
	lw	t1, SYSCTL_RSTCTL_REG(t0)
	ori	t1, MCM_RST
	sw	t1, SYSCTL_RSTCTL_REG(t0)

	/* Disable DMA route for PSE SRAM set by BootROM */
	PTR_LI	t0, KSEG1ADDR(DMA_CFG_ARB_BASE)
	sw	zero, DMA_ROUTE_REG(t0)

	/* Set CPU clock to 500MHz (Required if boot from NAND) */
	li	t0, KSEG1ADDR(SYSCTL_BASE)
	lw	t1, SYSCTL_CLKCFG0_REG(t0)
	ins	t1, zero, 30, 2		# CPU_CLK_SEL
	sw	t1, SYSCTL_CLKCFG0_REG(t0)

	/* Set CPU clock divider to 1/1 */
	li	t0, KSEG1ADDR(RBUS_BASE)
	li	t1, 0x101
	sw	t1, RBUS_DYN_CFG0_REG(t0)

	/* (Re-)initialize the SRAM */
	bal	mips_sram_init
	 nop

	/* Set up temporary stack */
	li	sp, SP_ADDR_TEMP

	/* Setup full CPS */
	bal	mips_cm_map
	 nop

	bal	mt7621_cps_init
	 nop

	/* Prepare for CPU/DDR initialization binary blob */
	bal	prepare_stage_bin
	 nop

	/* Call CPU/DDR initialization binary blob */
	li	t9, STAGE_LOAD_ADDR
	jalr	t9
	 nop

	/* Switch CPU PLL source */
	li	t0, KSEG1ADDR(SYSCTL_BASE)
	lw	t1, SYSCTL_CLKCFG0_REG(t0)
	li	t2, 1
	ins	t1, t2, CPU_CLK_SEL_S, 2
	sw	t1, SYSCTL_CLKCFG0_REG(t0)

	/*
	 * Currently SPL is running on locked L2 cache (on KSEG0).
	 * To reset the entire cache, we have to writeback SPL to DRAM first.
	 * Cache flush won't work here. Use memcpy instead.
	 */

	la	a0, __text_start
	move	a1, a0
	la	a2, __image_copy_end
	sub	a2, a2, a1
	li	a3, 5
	ins	a0, a3, 29, 3	# convert to KSEG1

	bal	memcpy
	 nop

	/* Disable caches */
	bal	mips_cache_disable
	 nop

	/* Reset caches */
	bal	mips_cache_reset
	 nop

	/* Disable SRAM */
	li	t0, KSEG1ADDR(FE_BASE)
	li	t1, FE_PSE_RESET
	sw	t1, FE_RST_GLO_REG(t0)

	/* Clear the .bss section */
	la	a0, __bss_start
	la	a1, __bss_end
1:	sw	zero, 0(a0)
	addiu	a0, 4
	ble	a0, a1, 1b
	 nop

	/* Set up initial stack and global data */
	setup_stack_gd

#if CONFIG_IS_ENABLED(INIT_STACK_WITHOUT_MALLOC_F)
	/* Set malloc base */
	li	t0, (CONFIG_SYS_INIT_SP_ADDR + 15) & (~15)
	PTR_S	t0, GD_MALLOC_BASE(k0)	# gd->malloc_base offset
#endif

#if defined(CONFIG_DEBUG_UART) && defined(CONFIG_SPL_SERIAL)
	/* Earliest point to set up debug uart */
	bal	debug_uart_init
	 nop
#endif

	/* Setup timer */
	bal	set_timer_freq_simple
	 nop

	/* Bootup secondary CPUs */
	bal	secondary_cpu_init
	 nop

	move	a0, zero		# a0 <-- boot_flags = 0
	bal board_init_f
	 move	ra, zero

	END(_start)