summaryrefslogtreecommitdiff
path: root/lib/cpus/aarch64/c1_nano.S
blob: 26828ceb86be9780c0868308ed1efe37cbe4d104 (plain)
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