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