1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) ASPEED Technology Inc.
*/
#include <config.h>
#include <linux/linkage.h>
/*
* SMP mailbox
* +-----------------------+ 0x40
* | |
* | mailbox insn. for |
* | cpuN GO sign polling |
* | |
* +-----------------------+ 0x20
* | cpu3 entrypoint |
* +-----------------------+ 0x18
* | cpu2 entrypoint |
* +-----------------------+ 0x10
* | cpu1 entrypoint |
* +-----------------------+ 0x8
* | reserved |
* +-----------------------+ 0x4
* | mailbox ready |
* +-----------------------+ SCU_CPU + 0x780
*/
#define SCU_CPU_BASE 0x12c02000
#define SCU_CPU_SMP_READY (SCU_CPU_BASE + 0x780)
#define SCU_CPU_SMP_EP1 (SCU_CPU_BASE + 0x788)
#define SCU_CPU_SMP_EP2 (SCU_CPU_BASE + 0x790)
#define SCU_CPU_SMP_EP3 (SCU_CPU_BASE + 0x798)
#define SCU_CPU_SMP_POLLINSN (SCU_CPU_BASE + 0x7a0)
ENTRY(lowlevel_init)
/* backup LR */
mov x29, lr
#if !CONFIG_IS_ENABLED(SKIP_LOWLEVEL_INIT)
/* reset SMP mailbox ASAP */
ldr x0, =SCU_CPU_SMP_READY
str wzr, [x0]
/*
* get cpu core id
*
* ast2700 has 1-cluster, 4-cores CPU topology.
* Affinity level 0 in MPIDR is sufficient.
*/
mrs x4, mpidr_el1
ands x4, x4, #0xff
/* cpu0 is the primary core to setup SMP mailbox */
beq do_primary_core_setup
/* hold cpuN until mailbox is ready */
ldr x0, =SCU_CPU_SMP_READY
movz w1, #0xcafe
movk w1, #0xbabe, lsl #16
poll_mailbox_ready:
wfe
ldr w2, [x0]
cmp w1, w2
bne poll_mailbox_ready
/*
* parameters for relocated SMP go polling insn.
* x4 = cpu id
* x5 = SCU_CPU_SMP_EPx
*/
add x5, x0, x4, lsl #3
/* jump to the polling loop in SMP mailbox, no return */
ldr x0, =SCU_CPU_SMP_POLLINSN
br x0
do_primary_core_setup:
/* relocate mailbox insn. for cpuN to poll for SMP go signal */
adr x0, smp_mbox_insn
adr x1, smp_mbox_insn_end
ldr x2, =SCU_CPU_SMP_POLLINSN
relocate_smp_mbox_insn:
ldr w3, [x0], #0x4
str w3, [x2], #0x4
cmp x0, x1
bne relocate_smp_mbox_insn
/* reset cpuN entrypoints */
ldr x0, =SCU_CPU_SMP_EP1
str xzr, [x0], #8
str xzr, [x0], #8
str xzr, [x0]
/* notify cpuN that SMP mailbox is ready */
movz w0, #0xcafe
movk w0, #0xbabe, lsl #16
ldr x1, =SCU_CPU_SMP_READY
str w0, [x1]
sev
#endif /* !CONFIG_IS_ENABLED(SKIP_LOWLEVEL_INIT) */
/* back to arch calling code */
mov lr, x29
ret
ENDPROC(lowlevel_init)
/*
* insn. inside mailbox to poll SMP go signal.
*
* Note that this code will be relocated, any absolute
* addressing should NOT be used.
*/
smp_mbox_insn:
/*
* x4 = cpu id
* x5 = SCU_CPU_SMP_EPx
*/
poll_smp_mbox_go:
wfe
ldr x0, [x5]
cmp x0, xzr
beq poll_smp_mbox_go
/* jump to secondary core entrypoint */
br x0
smp_mbox_insn_end:
/* should never reach */
b .
|