• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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#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 32-bit CPUs */
22#define CPU_WORD_SIZE			4
23
24/*
25 * Whether errata status needs reporting. Errata status is printed in debug
26 * builds for both BL1 and BL32 images.
27 */
28#if (defined(IMAGE_BL1) || defined(IMAGE_BL32)) && 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  4
40/* Reset fn is needed during reset */
41#if defined(IMAGE_BL1) || defined(IMAGE_BL32)
42CPU_RESET_FUNC: /* cpu_ops reset_func */
43	.space  4
44#endif
45#ifdef IMAGE_BL32 /* The power down core and cluster is needed only in BL32 */
46CPU_PWR_DWN_OPS: /* cpu_ops power down functions */
47	.space  (4 * CPU_MAX_PWR_DWN_OPS)
48#endif
49
50/*
51 * Fields required to print errata status. Only in BL32 that the printing
52 * require mutual exclusion and printed flag.
53 */
54#if REPORT_ERRATA
55CPU_ERRATA_FUNC: /* CPU errata status printing function */
56	.space  4
57#ifdef IMAGE_BL32
58CPU_ERRATA_LOCK:
59	.space	4
60CPU_ERRATA_PRINTED:
61	.space	4
62#endif
63#endif
64
65CPU_OPS_SIZE = .
66
67	/*
68	 * Write given expressions as words
69	 *
70	 * _count:
71	 *	Write at least _count words. If the given number of expressions
72	 *	is less than _count, repeat the last expression to fill _count
73	 *	words in total
74	 * _rest:
75	 *	Optional list of expressions. _this is for parameter extraction
76	 *	only, and has no significance to the caller
77	 *
78	 * Invoked as:
79	 *	fill_constants 2, foo, bar, blah, ...
80	 */
81	.macro fill_constants _count:req, _this, _rest:vararg
82	  .ifgt \_count
83	    /* Write the current expression */
84	    .ifb \_this
85	      .error "Nothing to fill"
86	    .endif
87	    .word \_this
88
89	    /* Invoke recursively for remaining expressions */
90	    .ifnb \_rest
91	      fill_constants \_count-1, \_rest
92	    .else
93	      fill_constants \_count-1, \_this
94	    .endif
95	  .endif
96	.endm
97
98	/*
99	 * Declare CPU operations
100	 *
101	 * _name:
102	 *	Name of the CPU for which operations are being specified
103	 * _midr:
104	 *	Numeric value expected to read from CPU's MIDR
105	 * _resetfunc:
106	 *	Reset function for the CPU. If there's no CPU reset function,
107	 *	specify CPU_NO_RESET_FUNC
108	 * _power_down_ops:
109	 *	Comma-separated list of functions to perform power-down
110	 *	operatios on the CPU. At least one, and up to
111	 *	CPU_MAX_PWR_DWN_OPS number of functions may be specified.
112	 *	Starting at power level 0, these functions shall handle power
113	 *	down at subsequent power levels. If there aren't exactly
114	 *	CPU_MAX_PWR_DWN_OPS functions, the last specified one will be
115	 *	used to handle power down at subsequent levels
116	 */
117	.macro declare_cpu_ops _name:req, _midr:req, _resetfunc:req, \
118		_power_down_ops:vararg
119	.section cpu_ops, "a"
120	.align 2
121	.type cpu_ops_\_name, %object
122	.word \_midr
123#if defined(IMAGE_BL1) || defined(IMAGE_BL32)
124	.word \_resetfunc
125#endif
126#ifdef IMAGE_BL32
1271:
128	/* Insert list of functions */
129	fill_constants CPU_MAX_PWR_DWN_OPS, \_power_down_ops
1302:
131	/*
132	 * Error if no or more than CPU_MAX_PWR_DWN_OPS were specified in the
133	 * list
134	 */
135	.ifeq 2b - 1b
136	  .error "At least one power down function must be specified"
137	.else
138	  .iflt 2b - 1b - (CPU_MAX_PWR_DWN_OPS * CPU_WORD_SIZE)
139	    .error "More than CPU_MAX_PWR_DWN_OPS functions specified"
140	  .endif
141	.endif
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	 * Weakly-bound, optional errata status printing function for CPUs of
165	 * this class.
166	 */
167	.weak \_name\()_errata_report
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#endif /* __CPU_MACROS_S__ */
219