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