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_HPLL_PARAM		(AST_SCU_BASE + 0x200)
43#define AST_SCU_HPLL_PARAM_EXT		(AST_SCU_BASE + 0x204)
44#define AST_SCU_HW_STRAP1		(AST_SCU_BASE + 0x500)
45#define AST_SCU_HW_STRAP2		(AST_SCU_BASE + 0x510)
46#define AST_SCU_CA7_CTRL		(AST_SCU_BASE + 0x800)
47#define AST_SCU_CA7_AXI_PREFETCH_START	(AST_SCU_BASE + 0x808)
48#define AST_SCU_CA7_AXI_PREFETCH_END	(AST_SCU_BASE + 0x80C)
49#define AST_SCU_CA7_PARITY_CHK		(AST_SCU_BASE + 0x820)
50#define AST_SCU_CA7_PARITY_CLR		(AST_SCU_BASE + 0x824)
51#define AST_SCU_MMIO_DEC_SET		(AST_SCU_BASE + 0xC24)
52
53#define AST_FMC_BASE		(0x1E620000)
54#define AST_FMC_CE0_CTRL	(AST_FMC_BASE + 0x010)
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
64.macro scu_unlock
65	movw	r0, #0xA8A8
66	movt	r0, #0x1688	@; magic key to unlock SCU
67
68	ldr	r1, =AST_SCU_PROT_KEY1
69	str	r0, [r1]
70	ldr	r1, =AST_SCU_PROT_KEY2
71	str	r0, [r1]
72.endm
73
74.macro timer_init
75#ifdef CONFIG_FPGA_ASPEED
76	movw	r0, #0xF080
77	movt	r0, #0x2FA
78#else
79	ldr	r0, =AST_SCU_REV_ID
80	ldr	r0, [r0]
81
82	ldr	r1, =REV_ID_AST2600A0
83	cmp	r0, r1
84
85	movweq 	r0, #0x32C0
86	movteq	r0, #0x4013
87	movwne	r0, #0x8C00
88	movtne	r0, #0x4786
89#endif
90	mcr	p15, 0, r0, c14, c0, 0	@; update CNTFRQ
91.endm
92
93
94.globl lowlevel_init
95
96lowlevel_init:
97#if defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD)
98	mov	pc, lr
99#else
100	/* setup ARM arch timer frequency */
101	timer_init
102
103	/* reset SMP mailbox as early as possible */
104	mov	r0, #0x0
105	ldr	r1, =AST_SMP_MBOX_FIELD_READY
106	str	r0, [r1]
107
108	/* set ACTLR.SMP to enable cache use */
109	mrc	p15, 0, r0, c1, c0, 1
110	orr	r0, #0x40
111	mcr	p15, 0, r0, c1, c0, 1
112
113	/*
114	 * we treat cpu0 as the primary core and
115	 * put secondary core (cpuN) to sleep
116	 */
117	mrc   p15, 0, r0, c0, c0, 5	@; Read CPU ID register
118	ands  r0, #0xFF			@; Mask off, leaving the CPU ID field
119	movw  r2, #0xAB00
120	movt  r2, #0xABBA
121	orr   r2, r0
122
123	beq   do_primary_core_setup
124
125	/* hold cpuN until mailbox is ready */
126poll_mailbox_ready:
127	wfe
128	ldr	r0, =AST_SMP_MBOX_FIELD_READY
129	ldr	r0, [r0]
130	movw	r1, #0xCAFE
131	movt	r1, #0xBABE
132	cmp	r1, r0
133	bne	poll_mailbox_ready
134
135	/* parameters for relocated SMP go polling insn. */
136	ldr	r0, =AST_SMP_MBOX_FIELD_GOSIGN
137	ldr	r1, =AST_SMP_MBOX_FIELD_ENTRY
138
139	/* no return */
140	ldr	pc, =AST_SMP_MBOX_FIELD_POLLINSN
141
142do_primary_core_setup:
143	/* unlock system control unit */
144	scu_unlock
145
146	/* identify AST2600 A0/A1 */
147	ldr	r0, =AST_SCU_REV_ID
148	ldr	r0, [r0]
149
150	ldr	r1, =REV_ID_AST2600A0
151	cmp	r0, r1
152
153	bne	0f
154
155	/* tune up CPU clocks (A0 only) */
156	ldr	r0, =AST_SCU_HW_STRAP1
157	ldr	r1, [r0]
158	bic	r1, #0x1800
159	orr	r1, #0x1000
160	str	r1, [r0]
161
162	ldr	r0, =AST_SCU_HPLL_PARAM
163	movw	r1, #0x4080
164	movt	r1, #0x1000
165	str	r1, [r0]
166
167	ldr	r0, =AST_SCU_HPLL_PARAM_EXT
168	mov	r1, #0x47
169	str	r1, [r0]
170
171wait_lock:
172	ldr	r1, [r0]
173	tst	r1, #0x80000000
174	beq	wait_lock
175
176	/* skip A1 only area */
177	b 1f
178
1790:
180	/* enable AXI prefetch (A1 only) */
181	ldr	r0, =AST_SCU_CA7_AXI_PREFETCH_START
182	ldr r1, =ASPEED_DRAM_BASE
183	str r1, [r0]
184
185	ldr	r0, =AST_SCU_CA7_AXI_PREFETCH_END
186	ldr	r1, =0xFFFFFFFF
187	str r1, [r0]
188
189	ldr	r0, =AST_SCU_CA7_CTRL
190	ldr	r1, [r0]
191	orr	r1, #0x8000
192	str	r1, [r0]
193
194	/* LPC/eSPI mode selection (A1 only) */
195	ldr	r0, =AST_GPIOYZ_DATA_VALUE
196	ldr	r0, [r0]
197	tst	r0, #0x1000
198	beq	1f
199
200	/* switch to LPC mode if GPIOZ[4]=1 */
201	ldr	r0, =AST_SCU_HW_STRAP2
202	ldr	r1, [r0]
203	orr	r1, #0x40
204	str	r1, [r0]
205
2061:
207	/* release display port reset */
208	ldr	r0, =AST_SCU_SYSRST_CTRL_CLR
209	movw	r1, #0x0000
210	movt	r1, #0x3000
211	str	r1, [r0]
212
213	/* MMIO decode setting */
214	ldr	r0, =AST_SCU_MMIO_DEC_SET
215	mov	r1, #0x2000
216	str	r1, [r0]
217
218	/* enable cache & SRAM parity check */
219	mov	r0, #0
220	ldr	r1, =AST_SCU_CA7_PARITY_CLR
221	str	r0, [r1]
222
223	mov	r0, #0x1
224	ldr	r1, =AST_SCU_CA7_PARITY_CHK
225	str	r0, [r1]
226
227	/* disable FMC WDT for SPI address mode detection */
228	mov	r0, #0
229	ldr	r1, =AST_FMC_WDT1_CTRL_MODE
230	str	r0, [r1]
231#if 0
232	ldr	r1, =AST_FMC_WDT2_CTRL_MODE
233	str	r0, [r1]
234#endif
235	/* tune up SPI clock */
236	movw	r0, #0x0641
237	movt	r0, #0x203B
238	ldr	r1, =AST_FMC_CE0_CTRL
239	str	r0, [r1]
240
241	/* relocate mailbox insn. for cpuN polling SMP go signal */
242	adrl	r0, mailbox_insn
243	adrl	r1, mailbox_insn_end
244
245	ldr	r2, =#AST_SMP_MBOX_FIELD_POLLINSN
246
247relocate_mailbox_insn:
248	ldr	r3, [r0], #0x4
249	str	r3, [r2], #0x4
250	cmp	r0, r1
251	bne	relocate_mailbox_insn
252
253	/* reset SMP go sign */
254	mov	r0, #0
255	ldr	r1, =AST_SMP_MBOX_FIELD_GOSIGN
256	str	r0, [r1]
257
258	/* notify cpuN mailbox is ready */
259	movw	r0, #0xCAFE
260	movt	r0, #0xBABE
261	ldr	r1, =AST_SMP_MBOX_FIELD_READY
262	str	r0, [r1]
263	sev
264
265	/* back to arch calling code */
266	mov	pc, lr
267
268/*
269 * insn. inside mailbox to poll SMP go signal.
270 *
271 * Note that as this code will be relocated, any
272 * pc-relative assembly should NOT be used.
273 */
274mailbox_insn:
275	/*
276	 * r0 ~ r3 are parameters:
277	 *  r0 = AST_SMP_MBOX_FIELD_GOSIGN
278	 *  r1 = AST_SMP_MBOX_FIELD_ENTRY
279	 *  r2 = per-cpu go sign value
280	 *  r3 = no used now
281	 */
282poll_mailbox_smp_go:
283	wfe
284	ldr	r4, [r0]
285	cmp	r2, r4
286	bne	poll_mailbox_smp_go
287
288	/* SMP GO signal confirmed, release cpuN */
289	ldr	pc, [r1]
290
291mailbox_insn_end:
292	/* should never reach */
293	b	.
294
295#endif
296