xref: /rk3399_ARM-atf/include/lib/cpus/aarch32/cpu_macros.S (revision a8a5d39d6e8805eee74aecedf140cdc87e387065)
1/*
2 * Copyright (c) 2016-2025, 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 <lib/cpus/cpu_ops.h>
10#include <lib/cpus/errata.h>
11
12	/*
13	 * Write given expressions as words
14	 *
15	 * _count:
16	 *	Write at least _count words. If the given number of expressions
17	 *	is less than _count, repeat the last expression to fill _count
18	 *	words in total
19	 * _rest:
20	 *	Optional list of expressions. _this is for parameter extraction
21	 *	only, and has no significance to the caller
22	 *
23	 * Invoked as:
24	 *	fill_constants 2, foo, bar, blah, ...
25	 */
26	.macro fill_constants _count:req, _this, _rest:vararg
27	  .ifgt \_count
28	    /* Write the current expression */
29	    .ifb \_this
30	      .error "Nothing to fill"
31	    .endif
32	    .word \_this
33
34	    /* Invoke recursively for remaining expressions */
35	    .ifnb \_rest
36	      fill_constants \_count-1, \_rest
37	    .else
38	      fill_constants \_count-1, \_this
39	    .endif
40	  .endif
41	.endm
42
43	/*
44	 * Declare CPU operations
45	 *
46	 * _name:
47	 *	Name of the CPU for which operations are being specified
48	 * _midr:
49	 *	Numeric value expected to read from CPU's MIDR
50	 * _resetfunc:
51	 *	Reset function for the CPU
52	 * _power_down_ops:
53	 *	Comma-separated list of functions to perform power-down
54	 *	operatios on the CPU. At least one, and up to
55	 *	CPU_MAX_PWR_DWN_OPS number of functions may be specified.
56	 *	Starting at power level 0, these functions shall handle power
57	 *	down at subsequent power levels. If there aren't exactly
58	 *	CPU_MAX_PWR_DWN_OPS functions, the last specified one will be
59	 *	used to handle power down at subsequent levels
60	 */
61	.macro declare_cpu_ops _name:req, _midr:req, _resetfunc:req, \
62		_power_down_ops:vararg
63	.section .cpu_ops, "a"
64	.align 2
65	.type cpu_ops_\_name, %object
66	.word \_midr
67#if defined(IMAGE_AT_EL3)
68	.word \_resetfunc
69#endif
70#ifdef IMAGE_BL32
71	/* Insert list of functions */
72	fill_constants CPU_MAX_PWR_DWN_OPS, \_power_down_ops
73#endif
74
75	/*
76	 * It is possible (although unlikely) that a cpu may have no errata in
77	 * code. In that case the start label will not be defined. The list is
78	 * inteded to be used in a loop, so define it as zero-length for
79	 * predictable behaviour. Since this macro is always called at the end
80	 * of the cpu file (after all errata have been parsed) we can be sure
81	 * that we are at the end of the list. Some cpus call the macro twice,
82	 * so only do this once.
83	 */
84	.pushsection .rodata.errata_entries
85	.ifndef \_name\()_errata_list_start
86		\_name\()_errata_list_start:
87	.endif
88	/* some call this multiple times, so only do this once */
89	.ifndef \_name\()_errata_list_end
90		\_name\()_errata_list_end:
91	.endif
92	.popsection
93
94	/* and now put them in cpu_ops */
95	.word \_name\()_errata_list_start
96	.word \_name\()_errata_list_end
97
98#if REPORT_ERRATA
99	.ifndef \_name\()_cpu_str
100	  /*
101	   * Place errata reported flag, and the spinlock to arbitrate access to
102	   * it in the data section.
103	   */
104	  .pushsection .data
105	  define_asm_spinlock \_name\()_errata_lock
106	  \_name\()_errata_reported:
107	  .word	0
108	  .popsection
109
110	  /* Place CPU string in rodata */
111	  .pushsection .rodata
112	  \_name\()_cpu_str:
113	  .asciz "\_name"
114	  .popsection
115	.endif
116
117	.word \_name\()_cpu_str
118
119#ifdef IMAGE_BL32
120	/* Pointers to errata lock and reported flag */
121	.word \_name\()_errata_lock
122	.word \_name\()_errata_reported
123#endif
124#endif
125	.endm
126
127	/*
128	 * Helper macro that reads the part number of the current CPU and jumps
129	 * to the given label if it matches the CPU MIDR provided.
130	 *
131	 * Clobbers: r0-r1
132	 */
133	.macro  jump_if_cpu_midr _cpu_midr, _label
134	ldcopr	r0, MIDR
135	ubfx	r0, r0, #MIDR_PN_SHIFT, #12
136	ldr	r1, =((\_cpu_midr >> MIDR_PN_SHIFT) & MIDR_PN_MASK)
137	cmp	r0, r1
138	beq	\_label
139	.endm
140
141/*
142 * NOTE an erratum and CVE id could clash. However, both numbers are very large
143 * and the probablity is minuscule. Working around this makes code very
144 * complicated and extremely difficult to read so it is not considered. In the
145 * unlikely event that this does happen, prepending the CVE id with a 0 should
146 * resolve the conflict
147 */
148
149/*
150 * Add an entry for this erratum to the errata framework
151 *
152 * _cpu:
153 *	Name of cpu as given to declare_cpu_ops
154 *
155 * _cve:
156 *	Whether erratum is a CVE. CVE year if yes, 0 otherwise
157 *
158 * _id:
159 *	Erratum or CVE number. Please combine with the previous field with the
160 *	ERRATUM or CVE macros
161 *
162 * _chosen:
163 *	Compile time flag on whether the erratum is included
164 *
165 * _special:
166 *	The special non-standard name of an erratum
167 */
168.macro add_erratum_entry _cpu:req, _cve:req, _id:req, _chosen:req, _special
169	.pushsection .rodata.errata_entries
170		.align	2
171		.ifndef \_cpu\()_errata_list_start
172		\_cpu\()_errata_list_start:
173		.endif
174
175		.ifnb \_special
176			.word	check_errata_\_special
177		.elseif \_cve
178			.word	check_errata_cve_\_cve\()_\_id
179		.else
180			.word	check_errata_\_id
181		.endif
182		/* Will fit CVEs with up to 10 character in the ID field */
183		.word	\_id
184		.hword	\_cve
185		.byte	\_chosen
186		.byte	0x0 /* alignment */
187	.popsection
188.endm
189
190#endif /* CPU_MACROS_S */
191