1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) ASPEED Technology Inc.
4 * Chia-Wei Wang <chiawei_wang@aspeedtech.com>
5 */
6
7#include <config.h>
8#include <version.h>
9#include <asm/secure.h>
10#include <asm/armv7.h>
11#include <linux/linkage.h>
12
13/*
14 *       SMP mailbox
15 * +----------------------+
16 * |                      |
17 * | mailbox insn. for    |
18 * | cpuN polling SMP go  |
19 * |                      |
20 * +----------------------+ 0xC
21 * | mailbox ready signal |
22 * +----------------------+ 0x8
23 * | cpuN GO signal       |
24 * +----------------------+ 0x4
25 * | cpuN entrypoint      |
26 * +----------------------+ AST_SMP_MAILBOX_BASE
27 */
28
29#define AST_SMP_MAILBOX_BASE		(0x1E6E2180)
30#define AST_SMP_MBOX_FIELD_ENTRY	(AST_SMP_MAILBOX_BASE + 0x0)
31#define AST_SMP_MBOX_FIELD_GOSIGN	(AST_SMP_MAILBOX_BASE + 0x4)
32#define AST_SMP_MBOX_FIELD_READY	(AST_SMP_MAILBOX_BASE + 0x8)
33#define AST_SMP_MBOX_FIELD_POLLINSN	(AST_SMP_MAILBOX_BASE + 0xc)
34
35/* AST2600 HW registers */
36#define AST_SCU_BASE		(0x1E6E2000)
37#define AST_SCU_PROT_KEY1	(AST_SCU_BASE)
38#define AST_SCU_PROT_KEY2	(AST_SCU_BASE + 0x010)
39#define AST_SCU_REV_ID		(AST_SCU_BASE + 0x014)
40#define AST_SCU_SYSRST_CTRL	(AST_SCU_BASE + 0x040)
41#define AST_SCU_SYSRST_CTRL_CLR	(AST_SCU_BASE + 0x044)
42#define AST_SCU_HPLL_PARAM	(AST_SCU_BASE + 0x200)
43#define AST_SCU_HPLL_PARAM_EXT	(AST_SCU_BASE + 0x204)
44#define AST_SCU_HW_STRAP1	(AST_SCU_BASE + 0x500)
45#define AST_SCU_HW_STRAP2	(AST_SCU_BASE + 0x510)
46#define AST_SCU_CA7_PARITY_CHK	(AST_SCU_BASE + 0x820)
47#define AST_SCU_CA7_PARITY_CLR	(AST_SCU_BASE + 0x824)
48#define AST_SCU_MMIO_DEC_SET	(AST_SCU_BASE + 0xC24)
49
50#define AST_FMC_BASE		(0x1E620000)
51#define AST_FMC_CE0_CTRL	(AST_FMC_BASE + 0x010)
52#define AST_FMC_WDT1_CTRL_MODE	(AST_FMC_BASE + 0x060)
53#define AST_FMC_WDT2_CTRL_MODE	(AST_FMC_BASE + 0x064)
54
55#define AST_GPIO_BASE		(0x1E780000)
56#define AST_GPIOYZ_DATA_VALUE	(AST_GPIO_BASE + 0x1E0)
57
58/* Revision ID */
59#define REV_ID_AST2600A0	0x05000303
60
61.macro scu_unlock
62	movw	r0, #0xA8A8
63	movt	r0, #0x1688	@; magic key to unlock SCU
64
65	ldr	r1, =AST_SCU_PROT_KEY1
66	str	r0, [r1]
67	ldr	r1, =AST_SCU_PROT_KEY2
68	str	r0, [r1]
69.endm
70
71.macro timer_init
72#ifdef CONFIG_FPGA_ASPEED
73	movw	r0, #0xF080
74	movt	r0, #0x2FA
75#else
76	movw 	r0, #0x32c0
77	movt	r0, #0x4013
78#endif
79	mcr	p15, 0, r0, c14, c0, 0	@; update CNTFRQ
80.endm
81
82
83.globl lowlevel_init
84
85lowlevel_init:
86#if defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD)
87	mov	pc, lr
88#else
89	/* setup ARM arch timer frequency */
90	timer_init
91
92	/* reset SMP mailbox as early as possible */
93	mov	r0, #0x0
94	ldr	r1, =AST_SMP_MBOX_FIELD_READY
95	str	r0, [r1]
96
97	/* set ACTLR.SMP to enable cache use */
98	mrc	p15, 0, r0, c1, c0, 1
99	orr	r0, #0x40
100	mcr	p15, 0, r0, c1, c0, 1
101
102	/*
103	 * we treat cpu0 as the primary core and
104	 * put secondary core (cpuN) to sleep
105	 */
106	mrc   p15, 0, r0, c0, c0, 5	@; Read CPU ID register
107	ands  r0, #0xFF			@; Mask off, leaving the CPU ID field
108	movw  r2, #0xAB00
109	movt  r2, #0xABBA
110	orr   r2, r0
111
112	beq   do_primary_core_setup
113
114	/* hold cpuN until mailbox is ready */
115poll_mailbox_ready:
116	wfe
117	ldr	r0, =AST_SMP_MBOX_FIELD_READY
118	ldr	r0, [r0]
119	movw	r1, #0xCAFE
120	movt	r1, #0xBABE
121	cmp	r1, r0
122	bne	poll_mailbox_ready
123
124	/* parameters for relocated SMP go polling insn. */
125	ldr	r0, =AST_SMP_MBOX_FIELD_GOSIGN
126	ldr	r1, =AST_SMP_MBOX_FIELD_ENTRY
127
128	/* no return */
129	ldr	pc, =AST_SMP_MBOX_FIELD_POLLINSN
130
131do_primary_core_setup:
132	/* unlock system control unit */
133	scu_unlock
134
135	/* tune-up CPU clock for AST2600 A0 */
136	ldr	r0, =AST_SCU_REV_ID
137	ldr	r0, [r0]
138
139	ldr	r1, =REV_ID_AST2600A0
140	cmp	r0, r1
141
142	bne	0f
143
144	/* setup CPU clocks */
145	ldr	r0, =AST_SCU_HW_STRAP1
146	ldr	r1, [r0]
147	bic	r1, #0x1800
148	orr	r1, #0x1000
149	str	r1, [r0]
150
151	ldr	r0, =AST_SCU_HPLL_PARAM
152	movw	r1, #0x4080
153	movt	r1, #0x1000
154	str	r1, [r0]
155
156	ldr	r0, =AST_SCU_HPLL_PARAM_EXT
157	mov	r1, #0x47
158	str	r1, [r0]
159
160wait_lock:
161	ldr	r1, [r0]
162	tst	r1, #0x80000000
163	beq	wait_lock
164
165	b 1f
166
1670:
168	/* LPC/eSPI mode selection for AST2600 A1 */
169	ldr	r0, =AST_GPIOYZ_DATA_VALUE
170	ldr	r0, [r0]
171	tst	r0, #0x1000
172	beq	1f
173
174	/* switch to LPC mode if GPIOZ[4]=1 */
175	ldr	r0, =AST_SCU_HW_STRAP2
176	ldr	r1, [r0]
177	orr	r1, #0x40
178	str	r1, [r0]
179
1801:
181	/* release display port reset */
182	ldr	r0, =AST_SCU_SYSRST_CTRL_CLR
183	movw	r1, #0x0000
184	movt	r1, #0x3000
185	str	r1, [r0]
186
187	/* MMIO decode setting */
188	ldr	r0, =AST_SCU_MMIO_DEC_SET
189	mov	r1, #0x2000
190	str	r1, [r0]
191
192	/* enable cache & SRAM parity check */
193	mov	r0, #0
194	ldr	r1, =AST_SCU_CA7_PARITY_CLR
195	str	r0, [r1]
196
197	mov	r0, #0x11
198	ldr	r1, =AST_SCU_CA7_PARITY_CHK
199	str	r0, [r1]
200
201	/* disable FMC WDT for SPI address mode detection */
202	mov	r0, #0
203	ldr	r1, =AST_FMC_WDT1_CTRL_MODE
204	str	r0, [r1]
205#if 0
206	ldr	r1, =AST_FMC_WDT2_CTRL_MODE
207	str	r0, [r1]
208#endif
209	/* tune up SPI clock */
210	movw	r0, #0x0641
211	movt	r0, #0x203B
212	ldr	r1, =AST_FMC_CE0_CTRL
213	str	r0, [r1]
214
215	/* relocate mailbox insn. for cpuN polling SMP go signal */
216	adrl	r0, mailbox_insn
217	adrl	r1, mailbox_insn_end
218
219	ldr	r2, =#AST_SMP_MBOX_FIELD_POLLINSN
220
221relocate_mailbox_insn:
222	ldr	r3, [r0], #0x4
223	str	r3, [r2], #0x4
224	cmp	r0, r1
225	bne	relocate_mailbox_insn
226
227	/* reset SMP go sign */
228	mov	r0, #0
229	ldr	r1, =AST_SMP_MBOX_FIELD_GOSIGN
230	str	r0, [r1]
231
232	/* notify cpuN mailbox is ready */
233	movw	r0, #0xCAFE
234	movt	r0, #0xBABE
235	ldr	r1, =AST_SMP_MBOX_FIELD_READY
236	str	r0, [r1]
237	sev
238
239	/* back to arch calling code */
240	mov	pc, lr
241
242/*
243 * insn. inside mailbox to poll SMP go signal.
244 *
245 * Note that as this code will be relocated, any
246 * pc-relative assembly should NOT be used.
247 */
248mailbox_insn:
249	/*
250	 * r0 ~ r3 are parameters:
251	 *  r0 = AST_SMP_MBOX_FIELD_GOSIGN
252	 *  r1 = AST_SMP_MBOX_FIELD_ENTRY
253	 *  r2 = per-cpu go sign value
254	 *  r3 = no used now
255	 */
256poll_mailbox_smp_go:
257	wfe
258	ldr	r4, [r0]
259	cmp	r2, r4
260	bne	poll_mailbox_smp_go
261
262	/* SMP GO signal confirmed, release cpuN */
263	ldr	pc, [r1]
264
265mailbox_insn_end:
266	/* should never reach */
267	b	.
268
269#endif
270