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 <lib/cpus/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
140	/* Insert list of functions */
141	fill_constants CPU_MAX_PWR_DWN_OPS, \_power_down_ops
142#endif
143
144#if REPORT_ERRATA
145	.ifndef \_name\()_cpu_str
146	  /*
147	   * Place errata reported flag, and the spinlock to arbitrate access to
148	   * it in the data section.
149	   */
150	  .pushsection .data
151	  define_asm_spinlock \_name\()_errata_lock
152	  \_name\()_errata_reported:
153	  .word	0
154	  .popsection
155
156	  /* Place CPU string in rodata */
157	  .pushsection .rodata
158	  \_name\()_cpu_str:
159	  .asciz "\_name"
160	  .popsection
161	.endif
162
163	/*
164	 * Mandatory errata status printing function for CPUs of
165	 * this class.
166	 */
167	.word \_name\()_errata_report
168
169#ifdef IMAGE_BL32
170	/* Pointers to errata lock and reported flag */
171	.word \_name\()_errata_lock
172	.word \_name\()_errata_reported
173#endif
174#endif
175	.endm
176
177#if REPORT_ERRATA
178	/*
179	 * Print status of a CPU errata
180	 *
181	 * _chosen:
182	 *	Identifier indicating whether or not a CPU errata has been
183	 *	compiled in.
184	 * _cpu:
185	 *	Name of the CPU
186	 * _id:
187	 *	Errata identifier
188	 * _rev_var:
189	 *	Register containing the combined value CPU revision and variant
190	 *	- typically the return value of cpu_get_rev_var
191	 */
192	.macro report_errata _chosen, _cpu, _id, _rev_var=r4
193	/* Stash a string with errata ID */
194	.pushsection .rodata
195	\_cpu\()_errata_\_id\()_str:
196	.asciz	"\_id"
197	.popsection
198
199	/* Check whether errata applies */
200	mov	r0, \_rev_var
201	bl	check_errata_\_id
202
203	.ifeq \_chosen
204	/*
205	 * Errata workaround has not been compiled in. If the errata would have
206	 * applied had it been compiled in, print its status as missing.
207	 */
208	cmp	r0, #0
209	movne	r0, #ERRATA_MISSING
210	.endif
211	ldr	r1, =\_cpu\()_cpu_str
212	ldr	r2, =\_cpu\()_errata_\_id\()_str
213	bl	errata_print_msg
214	.endm
215#endif
216	/*
217	 * Helper macro that reads the part number of the current CPU and jumps
218	 * to the given label if it matches the CPU MIDR provided.
219	 *
220	 * Clobbers: r0-r1
221	 */
222	.macro  jump_if_cpu_midr _cpu_midr, _label
223	ldcopr	r0, MIDR
224	ubfx	r0, r0, #MIDR_PN_SHIFT, #12
225	ldr	r1, =((\_cpu_midr >> MIDR_PN_SHIFT) & MIDR_PN_MASK)
226	cmp	r0, r1
227	beq	\_label
228	.endm
229
230#endif /* CPU_MACROS_S */
231