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