xref: /rk3399_ARM-atf/lib/cpus/aarch64/cpu_helpers.S (revision aabab09e2c0e3d8f475eac65a9d7cedad9f5dfff)
19b476841SSoby Mathew/*
27791ce21SBoyan Karatotev * Copyright (c) 2014-2025, Arm Limited and Contributors. All rights reserved.
39b476841SSoby Mathew *
482cb2c1aSdp-arm * SPDX-License-Identifier: BSD-3-Clause
59b476841SSoby Mathew */
69b476841SSoby Mathew
79b476841SSoby Mathew#include <arch.h>
89b476841SSoby Mathew#include <asm_macros.S>
99b476841SSoby Mathew#include <assert_macros.S>
10c2ad38ceSVarun Wadekar#include <common/bl_common.h>
1109d40e0eSAntonio Nino Diaz#include <common/debug.h>
1255c70cb7SDavid Cunado#include <cpu_macros.S>
13007433d8SBoyan Karatotev#include <lib/cpus/cpu_ops.h>
146bb96fa6SBoyan Karatotev#include <lib/cpus/errata.h>
1509d40e0eSAntonio Nino Diaz#include <lib/el3_runtime/cpu_data.h>
169b476841SSoby Mathew
173d8256b2SMasahiro Yamada#if defined(IMAGE_BL31) && CRASH_REPORTING
18d3f70af6SSoby Mathew	/*
19d3f70af6SSoby Mathew	 * The cpu specific registers which need to be reported in a crash
20d3f70af6SSoby Mathew	 * are reported via cpu_ops cpu_reg_dump function. After a matching
21d3f70af6SSoby Mathew	 * cpu_ops structure entry is found, the correponding cpu_reg_dump
22d3f70af6SSoby Mathew	 * in the cpu_ops is invoked.
23d3f70af6SSoby Mathew	 */
24d3f70af6SSoby Mathew	.globl	do_cpu_reg_dump
25d3f70af6SSoby Mathewfunc do_cpu_reg_dump
26d3f70af6SSoby Mathew	mov	x16, x30
27d3f70af6SSoby Mathew
28d3f70af6SSoby Mathew	/* Get the matching cpu_ops pointer */
29d3f70af6SSoby Mathew	bl	get_cpu_ops_ptr
30d3f70af6SSoby Mathew	cbz	x0, 1f
31d3f70af6SSoby Mathew
32d3f70af6SSoby Mathew	/* Get the cpu_ops cpu_reg_dump */
33d3f70af6SSoby Mathew	ldr	x2, [x0, #CPU_REG_DUMP]
34d3f70af6SSoby Mathew	cbz	x2, 1f
35d3f70af6SSoby Mathew	blr	x2
36d3f70af6SSoby Mathew1:
37d3f70af6SSoby Mathew	mov	x30, x16
38d3f70af6SSoby Mathew	ret
398b779620SKévin Petitendfunc do_cpu_reg_dump
40d3f70af6SSoby Mathew#endif
41d3f70af6SSoby Mathew
429b476841SSoby Mathew	/*
439b476841SSoby Mathew	 * The below function returns the cpu_ops structure matching the
449b476841SSoby Mathew	 * midr of the core. It reads the MIDR_EL1 and finds the matching
459b476841SSoby Mathew	 * entry in cpu_ops entries. Only the implementation and part number
469b476841SSoby Mathew	 * are used to match the entries.
471994e562SJavier Almansa Sobrino	 *
481994e562SJavier Almansa Sobrino	 * If cpu_ops for the MIDR_EL1 cannot be found and
491994e562SJavier Almansa Sobrino	 * SUPPORT_UNKNOWN_MPID is enabled, it will try to look for a
501994e562SJavier Almansa Sobrino	 * default cpu_ops with an MIDR value of 0.
512e61d687SOlivier Deprez	 * (Implementation number 0x0 should be reserved for software use
521994e562SJavier Almansa Sobrino	 * and therefore no clashes should happen with that default value).
531994e562SJavier Almansa Sobrino	 *
549b476841SSoby Mathew	 * Return :
559b476841SSoby Mathew	 *     x0 - The matching cpu_ops pointer on Success
569b476841SSoby Mathew	 *     x0 - 0 on failure.
579b476841SSoby Mathew	 * Clobbers : x0 - x5
589b476841SSoby Mathew	 */
599b476841SSoby Mathew	.globl	get_cpu_ops_ptr
609b476841SSoby Mathewfunc get_cpu_ops_ptr
619b476841SSoby Mathew	/* Read the MIDR_EL1 */
629b476841SSoby Mathew	mrs	x2, midr_el1
639b476841SSoby Mathew	mov_imm	x3, CPU_IMPL_PN_MASK
649b476841SSoby Mathew
659b476841SSoby Mathew	/* Retain only the implementation and part number using mask */
669b476841SSoby Mathew	and	w2, w2, w3
671994e562SJavier Almansa Sobrino
681994e562SJavier Almansa Sobrino	/* Get the cpu_ops end location */
69a5c4212fSHsin-Hsiung Wang	adr_l	x5, (__CPU_OPS_END__ + CPU_MIDR)
701994e562SJavier Almansa Sobrino
711994e562SJavier Almansa Sobrino	/* Initialize the return parameter */
721994e562SJavier Almansa Sobrino	mov	x0, #0
739b476841SSoby Mathew1:
741994e562SJavier Almansa Sobrino	/* Get the cpu_ops start location */
75a5c4212fSHsin-Hsiung Wang	adr_l	x4, (__CPU_OPS_START__ + CPU_MIDR)
761994e562SJavier Almansa Sobrino
771994e562SJavier Almansa Sobrino2:
789b476841SSoby Mathew	/* Check if we have reached end of list */
799b476841SSoby Mathew	cmp	x4, x5
801994e562SJavier Almansa Sobrino	b.eq	search_def_ptr
819b476841SSoby Mathew
829b476841SSoby Mathew	/* load the midr from the cpu_ops */
839b476841SSoby Mathew	ldr	x1, [x4], #CPU_OPS_SIZE
849b476841SSoby Mathew	and	w1, w1, w3
859b476841SSoby Mathew
869b476841SSoby Mathew	/* Check if midr matches to midr of this core */
879b476841SSoby Mathew	cmp	w1, w2
881994e562SJavier Almansa Sobrino	b.ne	2b
899b476841SSoby Mathew
909b476841SSoby Mathew	/* Subtract the increment and offset to get the cpu-ops pointer */
919b476841SSoby Mathew	sub	x0, x4, #(CPU_OPS_SIZE + CPU_MIDR)
92601e3ed2SVarun Wadekar#if ENABLE_ASSERTIONS
93601e3ed2SVarun Wadekar	cmp	x0, #0
94601e3ed2SVarun Wadekar	ASM_ASSERT(ne)
95601e3ed2SVarun Wadekar#endif
961994e562SJavier Almansa Sobrino#ifdef SUPPORT_UNKNOWN_MPID
971994e562SJavier Almansa Sobrino	cbnz	x2, exit_mpid_found
981994e562SJavier Almansa Sobrino	/* Mark the unsupported MPID flag */
991994e562SJavier Almansa Sobrino	adrp	x1, unsupported_mpid_flag
1001994e562SJavier Almansa Sobrino	add	x1, x1, :lo12:unsupported_mpid_flag
1011994e562SJavier Almansa Sobrino	str	w2, [x1]
1021994e562SJavier Almansa Sobrinoexit_mpid_found:
1031994e562SJavier Almansa Sobrino#endif
1041994e562SJavier Almansa Sobrino	ret
1051994e562SJavier Almansa Sobrino
1061994e562SJavier Almansa Sobrino	/*
1071994e562SJavier Almansa Sobrino	 * Search again for a default pointer (MIDR = 0x0)
1081994e562SJavier Almansa Sobrino	 * or return error if already searched.
1091994e562SJavier Almansa Sobrino	 */
1101994e562SJavier Almansa Sobrinosearch_def_ptr:
1111994e562SJavier Almansa Sobrino#ifdef SUPPORT_UNKNOWN_MPID
1121994e562SJavier Almansa Sobrino	cbz	x2, error_exit
1131994e562SJavier Almansa Sobrino	mov	x2, #0
1141994e562SJavier Almansa Sobrino	b	1b
1159b476841SSoby Mathewerror_exit:
1161994e562SJavier Almansa Sobrino#endif
117*0d020822SBoyan Karatotev#if ENABLE_ASSERTIONS
118*0d020822SBoyan Karatotev	/*
119*0d020822SBoyan Karatotev	 * Assert if invalid cpu_ops obtained. If this is not valid, it may
120*0d020822SBoyan Karatotev	 * suggest that the proper CPU file hasn't been included.
121*0d020822SBoyan Karatotev	 */
122*0d020822SBoyan Karatotev	cmp	x0, #0
123*0d020822SBoyan Karatotev	ASM_ASSERT(ne)
124*0d020822SBoyan Karatotev#endif
1259b476841SSoby Mathew	ret
1268b779620SKévin Petitendfunc get_cpu_ops_ptr
1277395a725SSoby Mathew
12810bcd761SJeenu Viswambharan	.globl	cpu_get_rev_var
12910bcd761SJeenu Viswambharanfunc cpu_get_rev_var
13036eeb59fSBoyan Karatotev	get_rev_var x0, x1
13110bcd761SJeenu Viswambharan	ret
13210bcd761SJeenu Viswambharanendfunc cpu_get_rev_var
133