1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (c) ASPEED Technology Inc.
4 */
5#include <config.h>
6#include <asm/armv7.h>
7#include <linux/linkage.h>
8#include <asm/arch/scu_ast2600.h>
9
10/* SCU register offsets */
11#define SCU_BASE		0x1e6e2000
12#define SCU_PROT_KEY1		(SCU_BASE + 0x000)
13#define SCU_PROT_KEY2		(SCU_BASE + 0x010)
14#define SCU_SMP_BOOT		(SCU_BASE + 0x180)
15#define SCU_HWSTRAP1		(SCU_BASE + 0x510)
16#define SCU_CA7_PARITY_CHK	(SCU_BASE + 0x820)
17#define SCU_CA7_PARITY_CLR	(SCU_BASE + 0x824)
18#define SCU_MMIO_DEC		(SCU_BASE + 0xc24)
19
20/* FMC SPI register offsets */
21#define FMC_BASE		0x1e620000
22#define FMC_CE0_CTRL		(FMC_BASE + 0x010)
23#define FMC_SW_RST_CTRL		(FMC_BASE + 0x050)
24#define FMC_WDT1_CTRL_MODE	(FMC_BASE + 0x060)
25#define FMC_WDT2_CTRL_MODE	(FMC_BASE + 0x064)
26
27/*
28 * The SMP mailbox provides a space with few instructions in it
29 * for secondary cores to execute on and wait for the signal of
30 * SMP core bring up.
31 *
32 *       SMP mailbox
33 * +----------------------+
34 * |                      |
35 * | mailbox insn. for    |
36 * | cpuN polling SMP go  |
37 * |                      |
38 * +----------------------+ 0xC
39 * | mailbox ready signal |
40 * +----------------------+ 0x8
41 * | cpuN GO signal       |
42 * +----------------------+ 0x4
43 * | cpuN entrypoint      |
44 * +----------------------+ SMP_MAILBOX_BASE
45 */
46#define SMP_MBOX_BASE		(SCU_SMP_BOOT)
47#define SMP_MBOX_FIELD_ENTRY	(SMP_MBOX_BASE + 0x0)
48#define SMP_MBOX_FIELD_GOSIGN	(SMP_MBOX_BASE + 0x4)
49#define SMP_MBOX_FIELD_READY	(SMP_MBOX_BASE + 0x8)
50#define SMP_MBOX_FIELD_POLLINSN	(SMP_MBOX_BASE + 0xc)
51
52.macro scu_unlock
53	movw	r0, #(SCU_UNLOCK_KEY & 0xffff)
54	movt	r0, #(SCU_UNLOCK_KEY >> 16)
55
56	ldr	r1, =SCU_PROT_KEY1
57	str	r0, [r1]
58	ldr	r1, =SCU_PROT_KEY2
59	str	r0, [r1]
60.endm
61
62.macro timer_init
63	ldr	r1, =SCU_HWSTRAP1
64	ldr	r1, [r1]
65	and	r1, #0x700
66	lsr	r1, #0x8
67
68	/* 1.2GHz */
69	cmp	r1, #0x0
70	movweq	r0, #0x8c00
71	movteq	r0, #0x4786
72
73	/* 1.6GHz */
74	cmp	r1, #0x1
75	movweq	r0, #0x1000
76	movteq	r0, #0x5f5e
77
78	/* 1.2GHz */
79	cmp	r1, #0x2
80	movweq	r0, #0x8c00
81	movteq	r0, #0x4786
82
83	/* 1.6GHz */
84	cmp	r1, #0x3
85	movweq	r0, #0x1000
86	movteq	r0, #0x5f5e
87
88	/* 800MHz */
89	cmp	r1, #0x4
90	movwge	r0, #0x0800
91	movtge	r0, #0x2faf
92
93	mcr	p15, 0, r0, c14, c0, 0	@; update CNTFRQ
94.endm
95
96
97.globl lowlevel_init
98
99lowlevel_init:
100#if defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD)
101	mov	pc, lr
102#else
103	/* setup ARM arch timer frequency */
104	timer_init
105
106	/* reset SMP mailbox as early as possible */
107	mov	r0, #0x0
108	ldr	r1, =SMP_MBOX_FIELD_READY
109	str	r0, [r1]
110
111	/* set ACTLR.SMP to enable cache use */
112	mrc	p15, 0, r0, c1, c0, 1
113	orr	r0, #0x40
114	mcr	p15, 0, r0, c1, c0, 1
115
116	/*
117	 * we treat cpu0 as the primary core and
118	 * put secondary core (cpuN) to sleep
119	 */
120	mrc   p15, 0, r0, c0, c0, 5	@; Read CPU ID register
121	ands  r0, #0xff			@; Mask off, leaving the CPU ID field
122	movw  r2, #0xab00
123	movt  r2, #0xabba
124	orr   r2, r0
125
126	beq   do_primary_core_setup
127
128	/* hold cpuN until mailbox is ready */
129poll_mailbox_ready:
130	wfe
131	ldr	r0, =SMP_MBOX_FIELD_READY
132	ldr	r0, [r0]
133	movw	r1, #0xcafe
134	movt	r1, #0xbabe
135	cmp	r1, r0
136	bne	poll_mailbox_ready
137
138	/* parameters for relocated SMP go polling insn. */
139	ldr	r0, =SMP_MBOX_FIELD_GOSIGN
140	ldr	r1, =SMP_MBOX_FIELD_ENTRY
141
142	/* no return */
143	ldr	pc, =SMP_MBOX_FIELD_POLLINSN
144
145do_primary_core_setup:
146	scu_unlock
147
148	/* MMIO decode setting */
149	ldr	r0, =SCU_MMIO_DEC
150	mov	r1, #0x2000
151	str	r1, [r0]
152
153	/* enable CA7 cache parity check */
154	mov	r0, #0
155	ldr	r1, =SCU_CA7_PARITY_CLR
156	str	r0, [r1]
157
158	mov	r0, #0x1
159	ldr	r1, =SCU_CA7_PARITY_CHK
160	str	r0, [r1]
161
162	/* do not fill FMC50[1] if boot from eMMC */
163	ldr	r0, =SCU_HWSTRAP1
164	ldr	r1, [r0]
165	ands	r1, #0x04
166	bne	skip_fill_wip_bit
167
168	/* fill FMC50[1] for waiting WIP idle */
169	mov	r0, #0x02
170	ldr	r1, =FMC_SW_RST_CTRL
171	str	r0, [r1]
172
173skip_fill_wip_bit:
174	/* disable FMC WDT for SPI address mode detection */
175	mov	r0, #0
176	ldr	r1, =FMC_WDT1_CTRL_MODE
177	str	r0, [r1]
178
179	/* relocate mailbox insn. for cpuN polling SMP go signal */
180	adrl	r0, mailbox_insn
181	adrl	r1, mailbox_insn_end
182
183	ldr	r2, =#SMP_MBOX_FIELD_POLLINSN
184
185relocate_mailbox_insn:
186	ldr	r3, [r0], #0x4
187	str	r3, [r2], #0x4
188	cmp	r0, r1
189	bne	relocate_mailbox_insn
190
191	/* reset SMP go sign */
192	mov	r0, #0
193	ldr	r1, =SMP_MBOX_FIELD_GOSIGN
194	str	r0, [r1]
195
196	/* notify cpuN mailbox is ready */
197	movw	r0, #0xCAFE
198	movt	r0, #0xBABE
199	ldr	r1, =SMP_MBOX_FIELD_READY
200	str	r0, [r1]
201	sev
202
203	/* back to arch calling code */
204	mov	pc, lr
205
206/*
207 * insn. inside mailbox to poll SMP go signal.
208 *
209 * Note that as this code will be relocated, any
210 * pc-relative assembly should NOT be used.
211 */
212mailbox_insn:
213	/*
214	 * r0 ~ r3 are parameters:
215	 *  r0 = SMP_MBOX_FIELD_GOSIGN
216	 *  r1 = SMP_MBOX_FIELD_ENTRY
217	 *  r2 = per-cpu go sign value
218	 *  r3 = no used now
219	 */
220poll_mailbox_smp_go:
221	wfe
222	ldr	r4, [r0]
223	cmp	r2, r4
224	bne	poll_mailbox_smp_go
225
226	/* SMP GO signal confirmed, release cpuN */
227	ldr	pc, [r1]
228
229mailbox_insn_end:
230	/* should never reach */
231	b	.
232
233#endif
234