xref: /rk3399_ARM-atf/include/lib/cpus/aarch32/cpu_macros.S (revision 9a905a7d86867bab8a5d9befd40a67a6ab9aaea2)
1/*
2 * Copyright (c) 2016-2023, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6#ifndef CPU_MACROS_S
7#define CPU_MACROS_S
8
9#include <arch.h>
10#include <lib/cpus/errata_report.h>
11
12#if defined(IMAGE_BL1) || defined(IMAGE_BL32)  \
13	|| (defined(IMAGE_BL2) && RESET_TO_BL2)
14#define IMAGE_AT_EL3
15#endif
16
17#define CPU_IMPL_PN_MASK	(MIDR_IMPL_MASK << MIDR_IMPL_SHIFT) | \
18				(MIDR_PN_MASK << MIDR_PN_SHIFT)
19
20/* The number of CPU operations allowed */
21#define CPU_MAX_PWR_DWN_OPS		2
22
23/* Special constant to specify that CPU has no reset function */
24#define CPU_NO_RESET_FUNC		0
25
26/* Word size for 32-bit CPUs */
27#define CPU_WORD_SIZE			4
28
29/*
30 * Whether errata status needs reporting. Errata status is printed in debug
31 * builds for both BL1 and BL32 images.
32 */
33#if (defined(IMAGE_BL1) || defined(IMAGE_BL32)) && DEBUG
34# define REPORT_ERRATA	1
35#else
36# define REPORT_ERRATA	0
37#endif
38
39
40	.equ	CPU_MIDR_SIZE, CPU_WORD_SIZE
41	.equ	CPU_RESET_FUNC_SIZE, CPU_WORD_SIZE
42	.equ	CPU_PWR_DWN_OPS_SIZE, CPU_WORD_SIZE * CPU_MAX_PWR_DWN_OPS
43	.equ	CPU_ERRATA_FUNC_SIZE, CPU_WORD_SIZE
44	.equ	CPU_ERRATA_LOCK_SIZE, CPU_WORD_SIZE
45	.equ	CPU_ERRATA_PRINTED_SIZE, CPU_WORD_SIZE
46
47#ifndef IMAGE_AT_EL3
48	.equ	CPU_RESET_FUNC_SIZE, 0
49#endif
50
51/* The power down core and cluster is needed only in BL32 */
52#ifndef IMAGE_BL32
53	.equ	CPU_PWR_DWN_OPS_SIZE, 0
54#endif
55
56/* Fields required to print errata status  */
57#if !REPORT_ERRATA
58	.equ	CPU_ERRATA_FUNC_SIZE, 0
59#endif
60
61/* Only BL32 requires mutual exclusion and printed flag. */
62#if !(REPORT_ERRATA && defined(IMAGE_BL32))
63	.equ	CPU_ERRATA_LOCK_SIZE, 0
64	.equ	CPU_ERRATA_PRINTED_SIZE, 0
65#endif
66
67
68/*
69 * Define the offsets to the fields in cpu_ops structure.
70 * Every offset is defined based on the offset and size of the previous
71 * field.
72 */
73	.equ	CPU_MIDR, 0
74	.equ	CPU_RESET_FUNC, CPU_MIDR + CPU_MIDR_SIZE
75	.equ	CPU_PWR_DWN_OPS, CPU_RESET_FUNC + CPU_RESET_FUNC_SIZE
76	.equ	CPU_ERRATA_FUNC, CPU_PWR_DWN_OPS + CPU_PWR_DWN_OPS_SIZE
77	.equ	CPU_ERRATA_LOCK, CPU_ERRATA_FUNC + CPU_ERRATA_FUNC_SIZE
78	.equ	CPU_ERRATA_PRINTED, CPU_ERRATA_LOCK + CPU_ERRATA_LOCK_SIZE
79	.equ	CPU_OPS_SIZE, CPU_ERRATA_PRINTED + CPU_ERRATA_PRINTED_SIZE
80
81	/*
82	 * Write given expressions as words
83	 *
84	 * _count:
85	 *	Write at least _count words. If the given number of expressions
86	 *	is less than _count, repeat the last expression to fill _count
87	 *	words in total
88	 * _rest:
89	 *	Optional list of expressions. _this is for parameter extraction
90	 *	only, and has no significance to the caller
91	 *
92	 * Invoked as:
93	 *	fill_constants 2, foo, bar, blah, ...
94	 */
95	.macro fill_constants _count:req, _this, _rest:vararg
96	  .ifgt \_count
97	    /* Write the current expression */
98	    .ifb \_this
99	      .error "Nothing to fill"
100	    .endif
101	    .word \_this
102
103	    /* Invoke recursively for remaining expressions */
104	    .ifnb \_rest
105	      fill_constants \_count-1, \_rest
106	    .else
107	      fill_constants \_count-1, \_this
108	    .endif
109	  .endif
110	.endm
111
112	/*
113	 * Declare CPU operations
114	 *
115	 * _name:
116	 *	Name of the CPU for which operations are being specified
117	 * _midr:
118	 *	Numeric value expected to read from CPU's MIDR
119	 * _resetfunc:
120	 *	Reset function for the CPU. If there's no CPU reset function,
121	 *	specify CPU_NO_RESET_FUNC
122	 * _power_down_ops:
123	 *	Comma-separated list of functions to perform power-down
124	 *	operatios on the CPU. At least one, and up to
125	 *	CPU_MAX_PWR_DWN_OPS number of functions may be specified.
126	 *	Starting at power level 0, these functions shall handle power
127	 *	down at subsequent power levels. If there aren't exactly
128	 *	CPU_MAX_PWR_DWN_OPS functions, the last specified one will be
129	 *	used to handle power down at subsequent levels
130	 */
131	.macro declare_cpu_ops _name:req, _midr:req, _resetfunc:req, \
132		_power_down_ops:vararg
133	.section .cpu_ops, "a"
134	.align 2
135	.type cpu_ops_\_name, %object
136	.word \_midr
137#if defined(IMAGE_AT_EL3)
138	.word \_resetfunc
139#endif
140#ifdef IMAGE_BL32
141	/* Insert list of functions */
142	fill_constants CPU_MAX_PWR_DWN_OPS, \_power_down_ops
143#endif
144
145#if REPORT_ERRATA
146	.ifndef \_name\()_cpu_str
147	  /*
148	   * Place errata reported flag, and the spinlock to arbitrate access to
149	   * it in the data section.
150	   */
151	  .pushsection .data
152	  define_asm_spinlock \_name\()_errata_lock
153	  \_name\()_errata_reported:
154	  .word	0
155	  .popsection
156
157	  /* Place CPU string in rodata */
158	  .pushsection .rodata
159	  \_name\()_cpu_str:
160	  .asciz "\_name"
161	  .popsection
162	.endif
163
164	/*
165	 * Mandatory errata status printing function for CPUs of
166	 * this class.
167	 */
168	.word \_name\()_errata_report
169
170#ifdef IMAGE_BL32
171	/* Pointers to errata lock and reported flag */
172	.word \_name\()_errata_lock
173	.word \_name\()_errata_reported
174#endif
175#endif
176	.endm
177
178#if REPORT_ERRATA
179	/*
180	 * Print status of a CPU errata
181	 *
182	 * _chosen:
183	 *	Identifier indicating whether or not a CPU errata has been
184	 *	compiled in.
185	 * _cpu:
186	 *	Name of the CPU
187	 * _id:
188	 *	Errata identifier
189	 * _rev_var:
190	 *	Register containing the combined value CPU revision and variant
191	 *	- typically the return value of cpu_get_rev_var
192	 */
193	.macro report_errata _chosen, _cpu, _id, _rev_var=r4
194	/* Stash a string with errata ID */
195	.pushsection .rodata
196	\_cpu\()_errata_\_id\()_str:
197	.asciz	"\_id"
198	.popsection
199
200	/* Check whether errata applies */
201	mov	r0, \_rev_var
202	bl	check_errata_\_id
203
204	.ifeq \_chosen
205	/*
206	 * Errata workaround has not been compiled in. If the errata would have
207	 * applied had it been compiled in, print its status as missing.
208	 */
209	cmp	r0, #0
210	movne	r0, #ERRATA_MISSING
211	.endif
212	ldr	r1, =\_cpu\()_cpu_str
213	ldr	r2, =\_cpu\()_errata_\_id\()_str
214	bl	errata_print_msg
215	.endm
216#endif
217	/*
218	 * Helper macro that reads the part number of the current CPU and jumps
219	 * to the given label if it matches the CPU MIDR provided.
220	 *
221	 * Clobbers: r0-r1
222	 */
223	.macro  jump_if_cpu_midr _cpu_midr, _label
224	ldcopr	r0, MIDR
225	ubfx	r0, r0, #MIDR_PN_SHIFT, #12
226	ldr	r1, =((\_cpu_midr >> MIDR_PN_SHIFT) & MIDR_PN_MASK)
227	cmp	r0, r1
228	beq	\_label
229	.endm
230
231#endif /* CPU_MACROS_S */
232