1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (C) 2022 MediaTek Inc. All rights reserved.
4 *
5 * Author: Weijie Gao <weijie.gao@mediatek.com>
6 */
7
8#include <asm-offsets.h>
9#include <config.h>
10#include <asm/asm.h>
11#include <asm/regdef.h>
12#include <asm/addrspace.h>
13#include <asm/mipsregs.h>
14#include <asm/cm.h>
15#include "../mt7621.h"
16
17#define SP_ADDR_TEMP		0xbe10dff0
18
19	.set noreorder
20
21	.macro init_wr sel
22	MTC0	zero, CP0_WATCHLO,\sel
23	mtc0	t1, CP0_WATCHHI,\sel
24	.endm
25
26	.macro uhi_mips_exception
27	move	k0, t9		# preserve t9 in k0
28	move	k1, a0		# preserve a0 in k1
29	li	t9, 15		# UHI exception operation
30	li	a0, 0		# Use hard register context
31	sdbbp	1		# Invoke UHI operation
32	.endm
33
34ENTRY(_start)
35	b	reset
36	 mtc0	zero, CP0_COUNT
37
38	/*
39	 * Store TPL size here.
40	 * This will be used by SPL to locate u-boot payload.
41	 */
42	.org	TPL_INFO_OFFSET
43	.word	TPL_INFO_MAGIC
44	.word	__image_copy_len
45
46	/* Exception vector */
47	.org 0x200
48	/* TLB refill, 32 bit task */
49	uhi_mips_exception
50
51	.org 0x280
52	/* XTLB refill, 64 bit task */
53	uhi_mips_exception
54
55	.org 0x300
56	/* Cache error exception */
57	uhi_mips_exception
58
59	.org 0x380
60	/* General exception */
61	uhi_mips_exception
62
63	.org 0x400
64	/* Catch interrupt exceptions */
65	uhi_mips_exception
66
67	.org 0x480
68	/* EJTAG debug exception */
691:	b	1b
70	 nop
71
72	.org 0x500
73
74reset:
75	/* Set KSEG0 to Uncached */
76	mfc0	t0, CP0_CONFIG
77	ins	t0, zero, 0, 3
78	ori	t0, t0, CONF_CM_UNCACHED
79	mtc0	t0, CP0_CONFIG
80	ehb
81
82	/* Check for CPU number */
83	mfc0	t0, CP0_EBASE
84	and	t0, t0, MIPS_EBASE_CPUNUM
85	beqz	t0, 1f
86	 nop
87
88	/* Secondary core goes to specified SPL entry address */
89	li	t0, KSEG1ADDR(SYSCTL_BASE)
90	lw	t0, BOOT_SRAM_BASE_REG(t0)
91	jr	t0
92	 nop
93
94	/* Init CP0 Status */
951:	mfc0	t0, CP0_STATUS
96	and	t0, ST0_IMPL
97	or	t0, ST0_BEV | ST0_ERL
98	mtc0	t0, CP0_STATUS
99	 nop
100
101	/* Clear Watch Status bits and disable watch exceptions */
102	li	t1, 0x7		# Clear I, R and W conditions
103	init_wr	0
104	init_wr	1
105	init_wr	2
106	init_wr	3
107
108	/* Clear WP, IV and SW interrupts */
109	mtc0	zero, CP0_CAUSE
110
111	/* Clear timer interrupt (CP0_COUNT cleared on branch to 'reset') */
112	mtc0	zero, CP0_COMPARE
113
114	/* Setup basic CPS */
115	bal	mips_cm_map
116	 nop
117
118	li	t0, KSEG1ADDR(CONFIG_MIPS_CM_BASE)
119	li	t1, GCR_REG0_BASE_VALUE
120	sw	t1, GCR_REG0_BASE(t0)
121
122	li	t1, ((GCR_REG0_MASK_VALUE << GCR_REGn_MASK_ADDRMASK_SHIFT) | \
123		    GCR_REGn_MASK_CMTGT_IOCU0)
124	sw	t1, GCR_REG0_MASK(t0)
125
126	lw	t1, GCR_BASE(t0)
127	ins	t1, zero, 0, 2		# CM_DEFAULT_TARGET
128	sw	t1, GCR_BASE(t0)
129
130	lw	t1, GCR_CONTROL(t0)
131	li	t2, GCR_CONTROL_SYNCCTL
132	or	t1, t1, t2
133	sw	t1, GCR_CONTROL(t0)
134
135	/* Increase SPI frequency */
136	li	t0, KSEG1ADDR(SPI_BASE)
137	li	t1, 5
138	sw	t1, SPI_SPACE_REG(t0)
139
140	/* Set CPU clock to 500MHz */
141	li	t0, KSEG1ADDR(SYSCTL_BASE)
142	lw	t1, SYSCTL_CLKCFG0_REG(t0)
143	ins	t1, zero, 30, 2		# CPU_CLK_SEL
144	sw	t1, SYSCTL_CLKCFG0_REG(t0)
145
146	/* Set CPU clock divider to 1/1 */
147	li	t0, KSEG1ADDR(RBUS_BASE)
148	li	t1, 0x101
149	sw	t1, RBUS_DYN_CFG0_REG(t0)
150
151	/* Initialize the SRAM */
152	bal	mips_sram_init
153	 nop
154
155	/* Set up initial stack */
156	li	sp, SP_ADDR_TEMP
157
158	bal	tpl_main
159	 nop
160
161	END(_start)
162