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