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