Home | History | Annotate | Download | only in aarch32
      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
     38 CPU_MIDR: /* cpu_ops midr */
     39 	.space  4
     40 /* Reset fn is needed during reset */
     41 #if defined(IMAGE_BL1) || defined(IMAGE_BL32)
     42 CPU_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 */
     46 CPU_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
     55 CPU_ERRATA_FUNC: /* CPU errata status printing function */
     56 	.space  4
     57 #ifdef IMAGE_BL32
     58 CPU_ERRATA_LOCK:
     59 	.space	4
     60 CPU_ERRATA_PRINTED:
     61 	.space	4
     62 #endif
     63 #endif
     64 
     65 CPU_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
    127 1:
    128 	/* Insert list of functions */
    129 	fill_constants CPU_MAX_PWR_DWN_OPS, \_power_down_ops
    130 2:
    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