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