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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
|
/*
* Copyright (c) 2023-2026, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
* TRM: https://developer.arm.com/documentation/107753/latest
* SDEN: https://developer.arm.com/documentation/SDEN-3273788/latest
*/
#include <arch.h>
#include <asm_macros.S>
#include <c1_nano.h>
#include <common/bl_common.h>
#include <cpu_macros.S>
#include <plat_macros.S>
/* Hardware handled coherency */
#if HW_ASSISTED_COHERENCY == 0
#error "Arm C1-Nano must be compiled with HW_ASSISTED_COHERENCY enabled"
#endif
/* 64-bit only core */
#if CTX_INCLUDE_AARCH32_REGS == 1
#error "Arm C1-Nano supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
#endif
cpu_reset_prologue c1_nano
workaround_reset_start c1_nano, ERRATUM(3392149), ERRATA_C1NANO_3392149
sysreg_bit_set C1_NANO_IMP_CPUACTLR3_EL1, BIT(39)
workaround_reset_end c1_nano, ERRATUM(3392149)
check_erratum_ls c1_nano, ERRATUM(3392149), CPU_REV(0, 0)
workaround_reset_start c1_nano, ERRATUM(3419531), ERRATA_C1NANO_3419531
sysreg_bit_set C1_NANO_IMP_CPUACTLR_EL1, BIT(27)
workaround_reset_end c1_nano, ERRATUM(3419531)
check_erratum_ls c1_nano, ERRATUM(3419531), CPU_REV(0, 0)
workaround_reset_start c1_nano, ERRATUM(3437202), ERRATA_C1NANO_3437202
sysreg_bit_set C1_NANO_IMP_CPUACTLR_EL1, BIT(26)
workaround_reset_end c1_nano, ERRATUM(3437202)
check_erratum_ls c1_nano, ERRATUM(3437202), CPU_REV(0, 0)
workaround_reset_start c1_nano, ERRATUM(3516455), ERRATA_C1NANO_3516455
#if ENABLE_SME_FOR_NS
#if ENABLE_SME_FOR_NS == 2
is_feat_sme_present_asm x1
beq 1f
#endif
mov x0, #0
msr C1_NANO_IMP_CPUPSELR_EL3, x0
isb
ldr x0, =0xA0008000
msr C1_NANO_IMP_CPUPOR_EL3, x0
ldr x0, =0xFE808000
msr C1_NANO_IMP_CPUPMR_EL3, x0
ldr x0, =0x7F9
movk x0, #0x20, LSL #32
msr C1_NANO_IMP_CPUPCR_EL3, x0
isb
mov x0, #1
msr C1_NANO_IMP_CPUPSELR_EL3, x0
isb
ldr x0, =0xA4604000
msr C1_NANO_IMP_CPUPOR_EL3, x0
ldr x0, =0xBE604000
msr C1_NANO_IMP_CPUPMR_EL3, x0
ldr x0, =0x7F9
movk x0, #0x20, LSL #32
msr C1_NANO_IMP_CPUPCR_EL3, x0
1:
#endif
workaround_reset_end c1_nano, ERRATUM(3516455)
check_erratum_ls c1_nano, ERRATUM(3516455), CPU_REV(0, 0)
workaround_reset_start c1_nano, ERRATUM(3616450), ERRATA_C1NANO_3616450
#if ENABLE_SME_FOR_NS
#if ENABLE_SME_FOR_NS == 2
is_feat_sme_present_asm x1
beq 1f
#endif
sysreg_bit_set C1_NANO_IMP_CPUACTLR_EL1, BIT(29)
1:
#endif
workaround_reset_end c1_nano, ERRATUM(3616450)
check_erratum_ls c1_nano, ERRATUM(3616450), CPU_REV(0, 0)
workaround_reset_start c1_nano, ERRATUM(3630925), ERRATA_C1NANO_3630925
sysreg_bitfield_insert C1_NANO_IMP_CPUPWRCTLR_EL1, \
C1_NANO_IMP_CPUPWRCTLR_EL1_WFE_RET_CTRL_BIT, \
C1_NANO_IMP_CPUPWRCTLR_EL1_WFE_RET_CTRL_SHIFT, \
C1_NANO_IMP_CPUPWRCTLR_EL1_WFE_RET_CTRL_WIDTH
sysreg_bitfield_insert C1_NANO_IMP_CPUPWRCTLR_EL1, \
C1_NANO_IMP_CPUPWRCTLR_EL1_WFI_RET_CTRL_BIT, \
C1_NANO_IMP_CPUPWRCTLR_EL1_WFI_RET_CTRL_SHIFT, \
C1_NANO_IMP_CPUPWRCTLR_EL1_WFI_RET_CTRL_WIDTH
workaround_reset_end c1_nano, ERRATUM(3630925)
check_erratum_ls c1_nano, ERRATUM(3630925), CPU_REV(0, 0)
workaround_runtime_start c1_nano, ERRATUM(3754876), ERRATA_C1NANO_3754876
tsb_csync
workaround_runtime_end c1_nano, ERRATUM(3754876)
check_erratum_ls c1_nano, ERRATUM(3754876), CPU_REV(0, 1)
.pushsection .data
.align 4
safe_info:
.quad 0x1122334455667788
.quad 0x1122334455667788
.popsection
.global erratum_c1_nano_4497400_wa
workaround_runtime_start c1_nano, ERRATUM(4497400), ERRATA_C1NANO_4497400
adr_l x1, safe_info
mov x0, #4
.balign 16
1:
sb_barrier_insn
ldp x2, x3, [x1, #0]
ldp x2, x3, [x1, #0]
subs x0, x0, #1
sb_barrier_insn
nop
ldp x2, x3, [x1, #0]
ldp x2, x3, [x1, #0]
sb_barrier_insn
ldp x2, x3, [x1, #0]
ldp x2, x3, [x1, #0]
b.ne 1b
sb_barrier_insn
workaround_runtime_end c1_nano, ERRATUM(4497400), NO_ISB
check_erratum_ls c1_nano, ERRATUM(4497400), CPU_REV(0, 2)
cpu_reset_func_start c1_nano
/* ----------------------------------------------------
* Disable speculative loads
* ----------------------------------------------------
*/
msr SSBS, xzr
/* model bug: not cleared on reset */
sysreg_bit_clear C1_NANO_IMP_CPUPWRCTLR_EL1, \
C1_NANO_IMP_CPUPWRCTLR_EL1_CORE_PWRDN_EN_BIT
enable_mpmm
cpu_reset_func_end c1_nano
func c1_nano_core_pwr_dwn
/*
* When software running at lower ELs requests power down without first
* disabling SME, the CME connected to it will reject its power down
* request. Skip setting the PWRDN_EN bit, downgrading the powerdown
* request to a simple WFI wait, to get a minimal amount of power saving
* rather than an instant pabandon.
*/
#if ENABLE_SME_FOR_NS
#if ENABLE_SME_FOR_NS == 2
is_feat_sme_present_asm x1
beq 1f
#endif
mrs x0, SVCR
cbnz x0, c1_nano_skip_pwr_dwn
1:
#endif
/* ---------------------------------------------------
* Enable CPU power down bit in power control register
* ---------------------------------------------------
*/
sysreg_bit_toggle C1_NANO_IMP_CPUPWRCTLR_EL1, \
C1_NANO_IMP_CPUPWRCTLR_EL1_CORE_PWRDN_EN_BIT
isb
apply_erratum c1_nano, ERRATUM(3754876), ERRATA_C1NANO_3754876
c1_nano_skip_pwr_dwn:
signal_pabandon_handled
ret
endfunc c1_nano_core_pwr_dwn
.section .rodata.c1_nano_regs, "aS"
c1_nano_regs: /* The ASCII list of register names to be reported */
.asciz "cpuectlr_el1", ""
func c1_nano_cpu_reg_dump
adr x6, c1_nano_regs
mrs x8, C1_NANO_IMP_CPUECTLR_EL1
ret
endfunc c1_nano_cpu_reg_dump
declare_cpu_ops c1_nano, C1_NANO_MIDR, \
c1_nano_reset_func, \
c1_nano_core_pwr_dwn
|