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