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