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_SYSRST_EVENT		(AST_SCU_BASE + 0x064)
43#define AST_SCU_DEBUG_CTRL              (AST_SCU_BASE + 0x0C8)
44#define AST_SCU_DEBUG_CTRL2             (AST_SCU_BASE + 0x0D8)
45#define AST_SCU_HPLL_PARAM		(AST_SCU_BASE + 0x200)
46#define AST_SCU_HPLL_PARAM_EXT		(AST_SCU_BASE + 0x204)
47#define AST_SCU_USB_MULTI_FUNC		(AST_SCU_BASE + 0x440)
48#define AST_SCU_HW_STRAP1		(AST_SCU_BASE + 0x500)
49#define AST_SCU_HW_STRAP2		(AST_SCU_BASE + 0x510)
50#define AST_SCU_HW_STRAP3		(AST_SCU_BASE + 0x51C)
51#define AST_SCU_CA7_PARITY_CHK		(AST_SCU_BASE + 0x820)
52#define AST_SCU_CA7_PARITY_CLR		(AST_SCU_BASE + 0x824)
53#define AST_SCU_MMIO_DEC_SET		(AST_SCU_BASE + 0xC24)
54
55#define AST_FMC_BASE		(0x1E620000)
56#define AST_FMC_CE0_CTRL	(AST_FMC_BASE + 0x010)
57#define AST_FMC_SW_RST_CTRL	(AST_FMC_BASE + 0x050)
58#define AST_FMC_WDT1_CTRL_MODE	(AST_FMC_BASE + 0x060)
59#define AST_FMC_WDT2_CTRL_MODE	(AST_FMC_BASE + 0x064)
60
61#define AST_GPIO_BASE		(0x1E780000)
62#define AST_GPIOYZ_DATA_VALUE	(AST_GPIO_BASE + 0x1E0)
63
64/* Revision ID */
65#define REV_ID_AST2600A0	0x05000303
66#define REV_ID_AST2600A1	0x05010303
67#define REV_ID_AST2620A1	0x05010203
68
69.macro scu_unlock
70	movw	r0, #0xA8A8
71	movt	r0, #0x1688	@; magic key to unlock SCU
72
73	ldr	r1, =AST_SCU_PROT_KEY1
74	str	r0, [r1]
75	ldr	r1, =AST_SCU_PROT_KEY2
76	str	r0, [r1]
77.endm
78
79.macro timer_init
80#ifdef CONFIG_FPGA_ASPEED
81	movw	r0, #0x6c00
82	movt	r0, #0x02dc
83#else
84	ldr	r0, =AST_SCU_REV_ID
85	ldr	r0, [r0]
86
87	ldr	r1, =REV_ID_AST2600A0
88	cmp	r0, r1
89
90	beq	timer_init_a0
91
92	ldr	r1, =AST_SCU_HW_STRAP1
93	ldr	r1, [r1]
94	and	r1, #0x700
95	lsr	r1, #0x8
96
97	cmp	r1, #0x0
98	movweq	r0, #0x8c00
99	movteq	r0, #0x4786
100
101	cmp	r1, #0x1
102	movweq	r0, #0x1000
103	movteq	r0, #0x5f5e
104
105	cmp	r1, #0x2
106	movweq	r0, #0x8c00
107	movteq	r0, #0x4786
108
109	cmp	r1, #0x3
110	movweq	r0, #0x1000
111	movteq	r0, #0x5f5e
112
113	cmp	r1, #0x4
114	movwge	r0, #0x0800
115	movtge	r0, #0x2faf
116
117	b	timer_init_out
118
119timer_init_a0:
120	movweq	r0, #0x32c0
121	movteq	r0, #0x4013
122
123timer_init_out:
124#endif
125	mcr	p15, 0, r0, c14, c0, 0	@; update CNTFRQ
126.endm
127
128
129.globl lowlevel_init
130
131lowlevel_init:
132#if defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD)
133	mov	pc, lr
134#else
135	/* setup ARM arch timer frequency */
136	timer_init
137
138	/* reset SMP mailbox as early as possible */
139	mov	r0, #0x0
140	ldr	r1, =AST_SMP_MBOX_FIELD_READY
141	str	r0, [r1]
142
143	/* set ACTLR.SMP to enable cache use */
144	mrc	p15, 0, r0, c1, c0, 1
145	orr	r0, #0x40
146	mcr	p15, 0, r0, c1, c0, 1
147
148	/*
149	 * we treat cpu0 as the primary core and
150	 * put secondary core (cpuN) to sleep
151	 */
152	mrc   p15, 0, r0, c0, c0, 5	@; Read CPU ID register
153	ands  r0, #0xFF			@; Mask off, leaving the CPU ID field
154	movw  r2, #0xAB00
155	movt  r2, #0xABBA
156	orr   r2, r0
157
158	beq   do_primary_core_setup
159
160	/* hold cpuN until mailbox is ready */
161poll_mailbox_ready:
162	wfe
163	ldr	r0, =AST_SMP_MBOX_FIELD_READY
164	ldr	r0, [r0]
165	movw	r1, #0xCAFE
166	movt	r1, #0xBABE
167	cmp	r1, r0
168	bne	poll_mailbox_ready
169
170	/* parameters for relocated SMP go polling insn. */
171	ldr	r0, =AST_SMP_MBOX_FIELD_GOSIGN
172	ldr	r1, =AST_SMP_MBOX_FIELD_ENTRY
173
174	/* no return */
175	ldr	pc, =AST_SMP_MBOX_FIELD_POLLINSN
176
177do_primary_core_setup:
178	/* unlock system control unit */
179	scu_unlock
180
181	/* identify AST2600 A0/A1 */
182	ldr	r0, =AST_SCU_REV_ID
183	ldr	r0, [r0]
184
185	ldr	r1, =REV_ID_AST2600A0
186	cmp	r0, r1
187
188	bne	0f
189
190	/* tune up CPU clocks (A0 only) */
191	ldr	r0, =AST_SCU_HW_STRAP1
192	ldr	r1, [r0]
193	bic	r1, #0x1800
194	orr	r1, #0x1000
195	str	r1, [r0]
196
197	ldr	r0, =AST_SCU_HPLL_PARAM
198	movw	r1, #0x4080
199	movt	r1, #0x1000
200	str	r1, [r0]
201
202	ldr	r0, =AST_SCU_HPLL_PARAM_EXT
203	mov	r1, #0x47
204	str	r1, [r0]
205
206wait_lock:
207	ldr	r1, [r0]
208	tst	r1, #0x80000000
209	beq	wait_lock
210
211	/* skip A1 only area */
212	b 2f
213
2140:
215	/* identify AST2600/AST2620 A1 */
216	ldr	r0, =AST_SCU_REV_ID
217	ldr	r0, [r0]
218
219	ldr	r1, =REV_ID_AST2600A1
220	cmp	r0, r1
221	beq	1f
222
223	ldr	r1, =REV_ID_AST2620A1
224	cmp	r0, r1
225	bne	2f
226
2271:
228	/* LPC/eSPI mode selection by SW (AST2600/AST2620 A1 only) */
229	ldr	r0, =AST_GPIOYZ_DATA_VALUE
230	ldr	r0, [r0]
231	tst	r0, #0x1000
232	beq	2f
233
234	/* switch to LPC mode if GPIOZ[4]=1 */
235	ldr	r0, =AST_SCU_HW_STRAP2
236	ldr	r1, [r0]
237	orr	r1, #0x40
238	str	r1, [r0]
239
2402:
241	/* PCIeRC/E2M8 power-on reset comes from SCU040
242	It need set SCU040[18] high to reset PCIeRC/E2M
243	when AC power-on */
244	ldr	r0,  =AST_SCU_SYSRST_EVENT
245	ldr	r1, [r0]
246	tst	r1, #0x1
247	beq	3f
248	ldr     r0, =AST_SCU_SYSRST_CTRL
249	movw    r1, #0x0000
250	movt    r1, #0x0004
251	str     r1, [r0]
2523:
253	/* Fix UART1 route problem on A3 */
254	ldr     r0, =0x1e789098
255	movw    r1, #0x0a30
256	movt    r1, #0x0000
257	str     r1, [r0]
258
259	ldr     r0, =0x1e78909c
260	movw    r1, #0x0000
261	movt    r1, #0x0000
262	str     r1, [r0]
263
264	/* MMIO decode setting */
265	ldr	r0, =AST_SCU_MMIO_DEC_SET
266	mov	r1, #0x2000
267	str	r1, [r0]
268
269	/* enable cache & SRAM parity check */
270	mov	r0, #0
271	ldr	r1, =AST_SCU_CA7_PARITY_CLR
272	str	r0, [r1]
273
274	mov	r0, #0x1
275	ldr	r1, =AST_SCU_CA7_PARITY_CHK
276	str	r0, [r1]
277
278	/* Select USB2.0 Device mode as USB port B */
279	ldr	r0, =0x10000000
280	ldr	r1, =AST_SCU_USB_MULTI_FUNC
281	str	r0, [r1]
282
283#if 0
284	ldr	r1, =AST_FMC_WDT2_CTRL_MODE
285	str	r0, [r1]
286#endif
287
288	/* do not fill FMC50[1] if boot from eMMC */
289	ldr	r0, =AST_SCU_HW_STRAP1
290	ldr	r1, [r0]
291	ands	r1, #0x04
292	bne	skip_fill_wip_bit
293
294	/* fill FMC50[1] for waiting WIP idle */
295	mov	r0, #0x02
296	ldr	r1, =AST_FMC_SW_RST_CTRL
297	str	r0, [r1]
298skip_fill_wip_bit:
299
300#if !defined(CONFIG_ASPEED_DEFAULT_SPI_FREQUENCY)
301	/* tune up SPI clock */
302	movw	r0, #0x0600
303	movt	r0, #0x0000
304	ldr	r1, =AST_FMC_CE0_CTRL
305	str	r0, [r1]
306#endif
307
308	/* disable FMC WDT for SPI address mode detection */
309	mov	r0, #0
310	ldr	r1, =AST_FMC_WDT1_CTRL_MODE
311	str	r0, [r1]
312
313	/* disable backdoor for A1/A2 to align A3 design */
314	ldr	r0, =AST_SCU_HW_STRAP3
315	ldr	r0, [r0]
316	tst	r0, #0x1
317
318	ldr	r0, =AST_SCU_DEBUG_CTRL
319	movwne	r1, #0x0ffd
320	movweq	r1, #0x0fff
321	movt	r1, #0x0000
322	str	r1, [r0]
323
324	ldr	r0, =AST_SCU_DEBUG_CTRL2
325	movne	r1, #0xf7
326	moveq	r1, #0xff
327	str	r1, [r0]
328
329	/* relocate mailbox insn. for cpuN polling SMP go signal */
330	adrl	r0, mailbox_insn
331	adrl	r1, mailbox_insn_end
332
333	ldr	r2, =#AST_SMP_MBOX_FIELD_POLLINSN
334
335relocate_mailbox_insn:
336	ldr	r3, [r0], #0x4
337	str	r3, [r2], #0x4
338	cmp	r0, r1
339	bne	relocate_mailbox_insn
340
341	/* reset SMP go sign */
342	mov	r0, #0
343	ldr	r1, =AST_SMP_MBOX_FIELD_GOSIGN
344	str	r0, [r1]
345
346	/* notify cpuN mailbox is ready */
347	movw	r0, #0xCAFE
348	movt	r0, #0xBABE
349	ldr	r1, =AST_SMP_MBOX_FIELD_READY
350	str	r0, [r1]
351	sev
352
353	/* back to arch calling code */
354	mov	pc, lr
355
356/*
357 * insn. inside mailbox to poll SMP go signal.
358 *
359 * Note that as this code will be relocated, any
360 * pc-relative assembly should NOT be used.
361 */
362mailbox_insn:
363	/*
364	 * r0 ~ r3 are parameters:
365	 *  r0 = AST_SMP_MBOX_FIELD_GOSIGN
366	 *  r1 = AST_SMP_MBOX_FIELD_ENTRY
367	 *  r2 = per-cpu go sign value
368	 *  r3 = no used now
369	 */
370poll_mailbox_smp_go:
371	wfe
372	ldr	r4, [r0]
373	cmp	r2, r4
374	bne	poll_mailbox_smp_go
375
376	/* SMP GO signal confirmed, release cpuN */
377	ldr	pc, [r1]
378
379mailbox_insn_end:
380	/* should never reach */
381	b	.
382
383#endif
384