xref: /rk3399_ARM-atf/lib/locks/exclusive/aarch32/spinlock.S (revision 270d5c5cd9ad6cecc4b581e8a257c6fcfe7d78d6)
1/*
2 * Copyright (c) 2016-2025, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <asm_macros.S>
8
9	.globl	spin_lock
10	.globl	spin_unlock
11
12#if ARM_ARCH_AT_LEAST(8, 0)
13/*
14 * According to the ARMv8-A Architecture Reference Manual, "when the global
15 * monitor for a PE changes from Exclusive Access state to Open Access state,
16 * an event is generated.". This applies to both AArch32 and AArch64 modes of
17 * ARMv8-A. As a result, no explicit SEV with unlock is required.
18 */
19#define COND_SEV()
20#else
21#define COND_SEV()	sev
22#endif
23
24/*
25 * Function: spin_lock
26 * -------------------
27 * Acquires a spinlock by continuously attempting to set it.
28 * Will block (spin) until the lock is successfully acquired.
29 *
30 * Arguments:
31 *   r0 - Pointer to the spinlock variable (uint32_t *lock)
32 *
33 * Return:
34 *   None
35 *
36 * Description:
37 *   Blocks until the lock is acquired using LDREX/STREX with WFE for wait.
38 */
39func spin_lock
40	mov	r2, #1
411:
42	ldrex	r1, [r0]
43	cmp	r1, #0
44	wfene
45	strexeq	r1, r2, [r0]
46	cmpeq	r1, #0
47	bne	1b
48	dmb
49	bx	lr
50endfunc spin_lock
51
52/*
53 * Function: spin_trylock
54 * ----------------------
55 * Attempts to acquire the spinlock once without blocking.
56 *
57 * Arguments:
58 *   r0 - Pointer to the spinlock variable (uint32_t *lock)
59 *
60 * Return:
61 *   r0 - 1 if lock was successfully acquired
62 *        0 if lock was already held
63 *
64 * Description:
65 *   Tries once to acquire the lock using LDREX/STREX.
66 */
67func spin_trylock
68        mov     r2, #1
69        ldrex   r1, [r0]
70        cmp     r1, #0
71        strexeq r1, r2, [r0]
72        cmpeq   r1, #0
73        dmb
74        moveq   r0, #1
75        movne   r0, #0
76        bx      lr
77endfunc spin_trylock
78
79/*
80 * Function: spin_unlock
81 * ---------------------
82 * Releases the spinlock by clearing its value.
83 *
84 * Arguments:
85 *   r0 - Pointer to the spinlock variable (uint32_t *lock)
86 *
87 * Return:
88 *   None
89 *
90 * Description:
91 *   Releases the lock using store-release and sends SEV.
92 */
93func spin_unlock
94	mov	r1, #0
95	stl	r1, [r0]
96	COND_SEV()
97	bx	lr
98endfunc spin_unlock
99