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