xref: /rk3399_ARM-atf/include/lib/cpus/aarch32/cpu_macros.S (revision dd9fae1ce0e7b985c9fe8f8f8ae358b8c166c6a9)
1/*
2 * Copyright (c) 2016-2023, 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/cpu_ops.h>
11#include <lib/cpus/errata.h>
12
13	/*
14	 * Write given expressions as words
15	 *
16	 * _count:
17	 *	Write at least _count words. If the given number of expressions
18	 *	is less than _count, repeat the last expression to fill _count
19	 *	words in total
20	 * _rest:
21	 *	Optional list of expressions. _this is for parameter extraction
22	 *	only, and has no significance to the caller
23	 *
24	 * Invoked as:
25	 *	fill_constants 2, foo, bar, blah, ...
26	 */
27	.macro fill_constants _count:req, _this, _rest:vararg
28	  .ifgt \_count
29	    /* Write the current expression */
30	    .ifb \_this
31	      .error "Nothing to fill"
32	    .endif
33	    .word \_this
34
35	    /* Invoke recursively for remaining expressions */
36	    .ifnb \_rest
37	      fill_constants \_count-1, \_rest
38	    .else
39	      fill_constants \_count-1, \_this
40	    .endif
41	  .endif
42	.endm
43
44	/*
45	 * Declare CPU operations
46	 *
47	 * _name:
48	 *	Name of the CPU for which operations are being specified
49	 * _midr:
50	 *	Numeric value expected to read from CPU's MIDR
51	 * _resetfunc:
52	 *	Reset function for the CPU. If there's no CPU reset function,
53	 *	specify CPU_NO_RESET_FUNC
54	 * _power_down_ops:
55	 *	Comma-separated list of functions to perform power-down
56	 *	operatios on the CPU. At least one, and up to
57	 *	CPU_MAX_PWR_DWN_OPS number of functions may be specified.
58	 *	Starting at power level 0, these functions shall handle power
59	 *	down at subsequent power levels. If there aren't exactly
60	 *	CPU_MAX_PWR_DWN_OPS functions, the last specified one will be
61	 *	used to handle power down at subsequent levels
62	 */
63	.macro declare_cpu_ops _name:req, _midr:req, _resetfunc:req, \
64		_power_down_ops:vararg
65	.section .cpu_ops, "a"
66	.align 2
67	.type cpu_ops_\_name, %object
68	.word \_midr
69#if defined(IMAGE_AT_EL3)
70	.word \_resetfunc
71#endif
72#ifdef IMAGE_BL32
73	/* Insert list of functions */
74	fill_constants CPU_MAX_PWR_DWN_OPS, \_power_down_ops
75#endif
76
77#if REPORT_ERRATA
78	.ifndef \_name\()_cpu_str
79	  /*
80	   * Place errata reported flag, and the spinlock to arbitrate access to
81	   * it in the data section.
82	   */
83	  .pushsection .data
84	  define_asm_spinlock \_name\()_errata_lock
85	  \_name\()_errata_reported:
86	  .word	0
87	  .popsection
88
89	  /* Place CPU string in rodata */
90	  .pushsection .rodata
91	  \_name\()_cpu_str:
92	  .asciz "\_name"
93	  .popsection
94	.endif
95
96	/*
97	 * Mandatory errata status printing function for CPUs of
98	 * this class.
99	 */
100	.word \_name\()_errata_report
101
102#ifdef IMAGE_BL32
103	/* Pointers to errata lock and reported flag */
104	.word \_name\()_errata_lock
105	.word \_name\()_errata_reported
106#endif
107#endif
108	.endm
109
110#if REPORT_ERRATA
111	/*
112	 * Print status of a CPU errata
113	 *
114	 * _chosen:
115	 *	Identifier indicating whether or not a CPU errata has been
116	 *	compiled in.
117	 * _cpu:
118	 *	Name of the CPU
119	 * _id:
120	 *	Errata identifier
121	 * _rev_var:
122	 *	Register containing the combined value CPU revision and variant
123	 *	- typically the return value of cpu_get_rev_var
124	 */
125	.macro report_errata _chosen, _cpu, _id, _rev_var=r4
126	/* Stash a string with errata ID */
127	.pushsection .rodata
128	\_cpu\()_errata_\_id\()_str:
129	.asciz	"\_id"
130	.popsection
131
132	/* Check whether errata applies */
133	mov	r0, \_rev_var
134	bl	check_errata_\_id
135
136	.ifeq \_chosen
137	/*
138	 * Errata workaround has not been compiled in. If the errata would have
139	 * applied had it been compiled in, print its status as missing.
140	 */
141	cmp	r0, #0
142	movne	r0, #ERRATA_MISSING
143	.endif
144	ldr	r1, =\_cpu\()_cpu_str
145	ldr	r2, =\_cpu\()_errata_\_id\()_str
146	bl	errata_print_msg
147	.endm
148#endif
149	/*
150	 * Helper macro that reads the part number of the current CPU and jumps
151	 * to the given label if it matches the CPU MIDR provided.
152	 *
153	 * Clobbers: r0-r1
154	 */
155	.macro  jump_if_cpu_midr _cpu_midr, _label
156	ldcopr	r0, MIDR
157	ubfx	r0, r0, #MIDR_PN_SHIFT, #12
158	ldr	r1, =((\_cpu_midr >> MIDR_PN_SHIFT) & MIDR_PN_MASK)
159	cmp	r0, r1
160	beq	\_label
161	.endm
162
163#endif /* CPU_MACROS_S */
164