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