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 * +----------------------+ 0x40
16 * | cpuN sec_entrypoint  |
17 * +----------------------+ 0x3c
18 * |                      |
19 * | mailbox insn. for    |
20 * | cpuN GO sign polling |
21 * |                      |
22 * +----------------------+ 0x10
23 * | mailbox ready        |
24 * +----------------------+ 0x0c
25 * | reserved             |
26 * +----------------------+ 0x08
27 * | cpuN GO signal       |
28 * +----------------------+ 0x04
29 * | cpuN ns_entrypoint   |
30 * +----------------------+ SCU180
31 */
32
33#define SCU_BASE		0x1e6e2000
34#define SCU_PROT_KEY1		(SCU_BASE)
35#define SCU_PROT_KEY2		(SCU_BASE + 0x010)
36#define SCU_REV_ID		(SCU_BASE + 0x014)
37#define SCU_SYSRST_CTRL		(SCU_BASE + 0x040)
38#define SCU_SYSRST_CTRL_CLR	(SCU_BASE + 0x044)
39#define SCU_SYSRST_EVENT	(SCU_BASE + 0x064)
40#define SCU_CLK_STOP_CTRL_CLR	(SCU_BASE + 0x084)
41#define SCU_DEBUG_CTRL		(SCU_BASE + 0x0c8)
42#define SCU_DEBUG_CTRL2		(SCU_BASE + 0x0d8)
43#define SCU_SMP_NS_EP		(SCU_BASE + 0x180)
44#define SCU_SMP_GO		(SCU_BASE + 0x184)
45#define SCU_SMP_READY		(SCU_BASE + 0x18c)
46#define SCU_SMP_POLLINSN	(SCU_BASE + 0x190)
47#define SCU_SMP_S_EP		(SCU_BASE + 0x1bc)
48#define SCU_HPLL_PARAM		(SCU_BASE + 0x200)
49#define SCU_HPLL_PARAM_EXT	(SCU_BASE + 0x204)
50#define SCU_USB_MULTI_FUNC	(SCU_BASE + 0x440)
51#define SCU_HW_STRAP1		(SCU_BASE + 0x500)
52#define SCU_HW_STRAP2		(SCU_BASE + 0x510)
53#define SCU_HW_STRAP3		(SCU_BASE + 0x51c)
54#define SCU_CA7_PARITY_CHK	(SCU_BASE + 0x820)
55#define SCU_CA7_PARITY_CLR	(SCU_BASE + 0x824)
56#define SCU_MMIO_DEC_SET	(SCU_BASE + 0xc24)
57
58#define FMC_BASE		0x1e620000
59#define FMC_CE0_CTRL		(FMC_BASE + 0x010)
60#define FMC_SW_RST_CTRL		(FMC_BASE + 0x050)
61#define FMC_WDT1_CTRL_MODE	(FMC_BASE + 0x060)
62#define FMC_WDT2_CTRL_MODE	(FMC_BASE + 0x064)
63
64#define GPIO_BASE		0x1e780000
65#define GPIOYZ_DATA_VALUE	(GPIO_BASE + 0x1e0)
66
67#define SEC_BASE		0x1e6f2000
68#define SEC_VAULT_KEY_CTRL	(SEC_BASE + 0x80c)
69
70#define REV_ID_AST2600A0	0x05000303
71#define REV_ID_AST2600A1	0x05010303
72#define REV_ID_AST2620A1	0x05010203
73
74.macro scu_unlock
75	movw	r0, #0xa8a8
76	movt	r0, #0x1688	@; magic key to unlock SCU
77
78	ldr	r1, =SCU_PROT_KEY1
79	str	r0, [r1]
80	ldr	r1, =SCU_PROT_KEY2
81	str	r0, [r1]
82.endm
83
84.macro timer_init
85#ifdef CONFIG_FPGA_ASPEED
86	movw	r0, #0x6c00
87	movt	r0, #0x02dc
88#else
89	ldr	r0, =SCU_REV_ID
90	ldr	r0, [r0]
91
92	ldr	r1, =REV_ID_AST2600A0
93	cmp	r0, r1
94
95	beq	timer_init_a0
96
97	ldr	r1, =SCU_HW_STRAP1
98	ldr	r1, [r1]
99	and	r1, #0x700
100	lsr	r1, #0x8
101
102	cmp	r1, #0x0
103	movweq	r0, #0x8c00
104	movteq	r0, #0x4786
105
106	cmp	r1, #0x1
107	movweq	r0, #0x1000
108	movteq	r0, #0x5f5e
109
110	cmp	r1, #0x2
111	movweq	r0, #0x8c00
112	movteq	r0, #0x4786
113
114	cmp	r1, #0x3
115	movweq	r0, #0x1000
116	movteq	r0, #0x5f5e
117
118	cmp	r1, #0x4
119	movwge	r0, #0x0800
120	movtge	r0, #0x2faf
121
122	b	timer_init_out
123
124timer_init_a0:
125	movweq	r0, #0x32c0
126	movteq	r0, #0x4013
127
128timer_init_out:
129#endif
130	mcr	p15, 0, r0, c14, c0, 0	@; update CNTFRQ
131.endm
132
133
134.globl lowlevel_init
135
136lowlevel_init:
137#if defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD)
138	mov	pc, lr
139#else
140	/* setup ARM arch timer frequency */
141	timer_init
142
143	/* reset SMP mailbox as early as possible */
144	mov	r0, #0x0
145	ldr	r1, =SCU_SMP_READY
146	str	r0, [r1]
147
148	/* set ACTLR.SMP to enable cache use */
149	mrc	p15, 0, r0, c1, c0, 1
150	orr	r0, #0x40
151	mcr	p15, 0, r0, c1, c0, 1
152
153	/*
154	 * we treat cpu0 as the primary core and
155	 * put secondary core (cpuN) to sleep
156	 */
157	mrc   p15, 0, r0, c0, c0, 5	@; Read CPU ID register
158	ands  r0, #0xff			@; Mask off, leaving the CPU ID field
159	movw  r4, #0xab00
160	movt  r4, #0xabba
161	orr   r4, r0
162
163	beq   do_primary_core_setup
164
165	/* hold cpuN until SMP mailbox is ready */
166poll_smp_mbox_ready:
167	wfe
168	ldr	r0, =SCU_SMP_READY
169	ldr	r0, [r0]
170	movw	r1, #0xcafe
171	movt	r1, #0xbabe
172	cmp	r1, r0
173	bne	poll_smp_mbox_ready
174
175	/*
176	 * for relocated SMP mailbox insn. use
177	 *  r4 = per-cpu go sign value
178	 *  r5 = SCU_SMP_GO
179	 *  r6 = SCU_SMP_NS_EP
180	 *  r7 = SCU_SMP_S_EP
181	 */
182	ldr	r5, =SCU_SMP_GO
183	ldr	r6, =SCU_SMP_NS_EP
184	ldr	r7, =SCU_SMP_S_EP
185
186	/* no return */
187	ldr	pc, =SCU_SMP_POLLINSN
188
189do_primary_core_setup:
190	/* unlock system control unit */
191	scu_unlock
192
193	/* identify AST2600 A0/A1 */
194	ldr	r0, =SCU_REV_ID
195	ldr	r0, [r0]
196
197	ldr	r1, =REV_ID_AST2600A0
198	cmp	r0, r1
199
200	bne	0f
201
202	/* tune up CPU clocks (A0 only) */
203	ldr	r0, =SCU_HW_STRAP1
204	ldr	r1, [r0]
205	bic	r1, #0x1800
206	orr	r1, #0x1000
207	str	r1, [r0]
208
209	ldr	r0, =SCU_HPLL_PARAM
210	movw	r1, #0x4080
211	movt	r1, #0x1000
212	str	r1, [r0]
213
214	ldr	r0, =SCU_HPLL_PARAM_EXT
215	mov	r1, #0x47
216	str	r1, [r0]
217
218wait_lock:
219	ldr	r1, [r0]
220	tst	r1, #0x80000000
221	beq	wait_lock
222
223	/* skip A1 only area */
224	b 2f
225
2260:
227	/* identify AST2600/AST2620 A1 */
228	ldr	r0, =SCU_REV_ID
229	ldr	r0, [r0]
230
231	ldr	r1, =REV_ID_AST2600A1
232	cmp	r0, r1
233	beq	1f
234
235	ldr	r1, =REV_ID_AST2620A1
236	cmp	r0, r1
237	bne	2f
238
2391:
240	/* LPC/eSPI mode selection by SW (AST2600/AST2620 A1 only) */
241	ldr	r0, =GPIOYZ_DATA_VALUE
242	ldr	r0, [r0]
243	tst	r0, #0x1000
244	beq	2f
245
246	/* switch to LPC mode if GPIOZ[4]=1 */
247	ldr	r0, =SCU_HW_STRAP2
248	ldr	r1, [r0]
249	orr	r1, #0x40
250	str	r1, [r0]
251
2522:
253	/* Enable Vault Key Write Protection */
254	mov	r0, #0x2
255	ldr	r1, =SEC_VAULT_KEY_CTRL
256	str	r0, [r1]
257
258	/* PCIeRC/E2M8 power-on reset comes from SCU040
259	It need set SCU040[18] high to reset PCIeRC/E2M
260	when AC power-on */
261	ldr	r0,  =SCU_SYSRST_EVENT
262	ldr	r1, [r0]
263	tst	r1, #0x1
264	beq	3f
265	ldr     r0, =SCU_SYSRST_CTRL
266	movw    r1, #0x0000
267	movt    r1, #0x0004
268	str     r1, [r0]
2693:
270	/* Fix UART1 route problem on A3 */
271	ldr     r0, =0x1e789098
272	movw    r1, #0x0a30
273	movt    r1, #0x0000
274	str     r1, [r0]
275
276	ldr     r0, =0x1e78909c
277	movw    r1, #0x0000
278	movt    r1, #0x0000
279	str     r1, [r0]
280
281	/* MMIO decode setting */
282	ldr	r0, =SCU_MMIO_DEC_SET
283	mov	r1, #0x2000
284	str	r1, [r0]
285
286	/* enable cache & SRAM parity check */
287	mov	r0, #0
288	ldr	r1, =SCU_CA7_PARITY_CLR
289	str	r0, [r1]
290
291	mov	r0, #0x1
292	ldr	r1, =SCU_CA7_PARITY_CHK
293	str	r0, [r1]
294
295	/* Select USB2.0 Device mode as USB port B */
296	ldr	r0, =0x10000000
297	ldr	r1, =SCU_USB_MULTI_FUNC
298	str	r0, [r1]
299
300	/* enable USB port B PHY clk */
301	mov	r0, #0x80
302	ldr	r1, =SCU_CLK_STOP_CTRL_CLR
303	str	r0, [r1]
304
305#if 0
306	ldr	r1, =FMC_WDT2_CTRL_MODE
307	str	r0, [r1]
308#endif
309
310	/* do not fill FMC50[1] if boot from eMMC */
311	ldr	r0, =SCU_HW_STRAP1
312	ldr	r1, [r0]
313	ands	r1, #0x04
314	bne	skip_fill_wip_bit
315
316	/* fill FMC50[1] for waiting WIP idle */
317	mov	r0, #0x02
318	ldr	r1, =FMC_SW_RST_CTRL
319	str	r0, [r1]
320skip_fill_wip_bit:
321
322#if !defined(CONFIG_ASPEED_DEFAULT_SPI_FREQUENCY)
323	/* tune up SPI clock */
324	movw	r0, #0x0600
325	movt	r0, #0x0000
326	ldr	r1, =FMC_CE0_CTRL
327	str	r0, [r1]
328#endif
329
330	/* disable FMC WDT for SPI address mode detection */
331	mov	r0, #0
332	ldr	r1, =FMC_WDT1_CTRL_MODE
333	str	r0, [r1]
334
335	/* disable backdoor for A1/A2 to align A3 design */
336	ldr	r0, =SCU_HW_STRAP3
337	ldr	r0, [r0]
338	tst	r0, #0x1
339
340	ldr	r0, =SCU_DEBUG_CTRL
341	movwne	r1, #0x0ffd
342	movweq	r1, #0x0fff
343	movt	r1, #0x0000
344	str	r1, [r0]
345
346	ldr	r0, =SCU_DEBUG_CTRL2
347	movne	r1, #0xf7
348	moveq	r1, #0xff
349	str	r1, [r0]
350
351relocate_smp_mbox_start:
352	/* relocate SMP mailbox insn. for cpuN to poll for go signal */
353	adrl	r0, smp_mbox_insn
354	adrl	r1, smp_mbox_insn_end
355	ldr	r2, =SCU_SMP_POLLINSN
356
357relocate_smp_mbox_insn:
358	ldr	r3, [r0], #0x4
359	str	r3, [r2], #0x4
360	cmp	r0, r1
361	bne	relocate_smp_mbox_insn
362
363	/* reset SMP go sign and entrypoints */
364	mov	r0, #0
365	ldr	r1, =SCU_SMP_GO
366	str	r0, [r1]
367	ldr	r1, =SCU_SMP_NS_EP
368	str	r0, [r1]
369	ldr	r1, =SCU_SMP_S_EP
370	str	r0, [r1]
371
372	/* notify cpuN mailbox is ready */
373	movw	r0, #0xcafe
374	movt	r0, #0xbabe
375	ldr	r1, =SCU_SMP_READY
376	str	r0, [r1]
377	sev
378
379	/* back to arch calling code */
380	mov	pc, lr
381
382/*
383 * insn. inside mailbox to poll SMP go signal.
384 *
385 * Note that as this code will be relocated, any
386 * pc-relative assembly should NOT be used.
387 */
388smp_mbox_insn:
389	/*
390	 *  r4 = per-cpu go sign value
391	 *  r5 = SCU_SMP_GO
392	 *  r6 = SCU_SMP_NS_EP
393	 *  r7 = SCU_SMP_S_EP
394	 */
395poll_smp_mbox_go:
396	wfe
397	ldr	r0, [r5]
398	cmp	r0, r4
399	bne	poll_smp_mbox_go
400
401	/* go to secure world if secure entrypoint is specified */
402	ldr	r3, [r7]
403	cmp	r3, #0
404	beq	1f
405
406	ldr	lr, [r6]
407	mov	pc, r3
4081:
409	ldr	pc, [r6]
410
411smp_mbox_insn_end:
412	/* should never reach */
413	b	.
414
415#endif
416