xref: /rk3399_ARM-atf/lib/locks/exclusive/aarch32/spinlock.S (revision 5e03b0998201e27732f617d568941d440f908617)
1e33b78a6SSoby Mathew/*
286822f24SManish 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
10*d7e9372fSVarun Wadekar	.globl	spin_trylock
11e33b78a6SSoby Mathew	.globl	spin_unlock
12e33b78a6SSoby Mathew
130147bef5SEtienne Carriere#if ARM_ARCH_AT_LEAST(8, 0)
140147bef5SEtienne Carriere/*
150147bef5SEtienne Carriere * According to the ARMv8-A Architecture Reference Manual, "when the global
160147bef5SEtienne Carriere * monitor for a PE changes from Exclusive Access state to Open Access state,
170147bef5SEtienne Carriere * an event is generated.". This applies to both AArch32 and AArch64 modes of
180147bef5SEtienne Carriere * ARMv8-A. As a result, no explicit SEV with unlock is required.
190147bef5SEtienne Carriere */
200147bef5SEtienne Carriere#define COND_SEV()
210147bef5SEtienne Carriere#else
220147bef5SEtienne Carriere#define COND_SEV()	sev
230147bef5SEtienne Carriere#endif
24e33b78a6SSoby Mathew
2586822f24SManish V Badarkhe/*
2686822f24SManish V Badarkhe * Function: spin_lock
2786822f24SManish V Badarkhe * -------------------
2886822f24SManish V Badarkhe * Acquires a spinlock by continuously attempting to set it.
2986822f24SManish V Badarkhe * Will block (spin) until the lock is successfully acquired.
3086822f24SManish V Badarkhe *
3186822f24SManish V Badarkhe * Arguments:
3286822f24SManish V Badarkhe *   r0 - Pointer to the spinlock variable (uint32_t *lock)
3386822f24SManish V Badarkhe *
3486822f24SManish V Badarkhe * Return:
3586822f24SManish V Badarkhe *   None
3686822f24SManish V Badarkhe *
3786822f24SManish V Badarkhe * Description:
3886822f24SManish V Badarkhe *   Blocks until the lock is acquired using LDREX/STREX with WFE for wait.
3986822f24SManish V Badarkhe */
40e33b78a6SSoby Mathewfunc spin_lock
41e33b78a6SSoby Mathew	mov	r2, #1
42e33b78a6SSoby Mathew1:
43e33b78a6SSoby Mathew	ldrex	r1, [r0]
44e33b78a6SSoby Mathew	cmp	r1, #0
45e33b78a6SSoby Mathew	wfene
46e33b78a6SSoby Mathew	strexeq	r1, r2, [r0]
47e33b78a6SSoby Mathew	cmpeq	r1, #0
48e33b78a6SSoby Mathew	bne	1b
49e33b78a6SSoby Mathew	dmb
50e33b78a6SSoby Mathew	bx	lr
51e33b78a6SSoby Mathewendfunc spin_lock
52e33b78a6SSoby Mathew
5386822f24SManish V Badarkhe/*
5486822f24SManish V Badarkhe * Function: spin_trylock
5586822f24SManish V Badarkhe * ----------------------
5686822f24SManish V Badarkhe * Attempts to acquire the spinlock once without blocking.
5786822f24SManish V Badarkhe *
5886822f24SManish V Badarkhe * Arguments:
5986822f24SManish V Badarkhe *   r0 - Pointer to the spinlock variable (uint32_t *lock)
6086822f24SManish V Badarkhe *
6186822f24SManish V Badarkhe * Return:
6286822f24SManish V Badarkhe *   r0 - 1 if lock was successfully acquired
6386822f24SManish V Badarkhe *        0 if lock was already held
6486822f24SManish V Badarkhe *
6586822f24SManish V Badarkhe * Description:
6686822f24SManish V Badarkhe *   Tries once to acquire the lock using LDREX/STREX.
6786822f24SManish V Badarkhe */
6886822f24SManish V Badarkhefunc spin_trylock
6986822f24SManish V Badarkhe        mov     r2, #1
7086822f24SManish V Badarkhe        ldrex   r1, [r0]
7186822f24SManish V Badarkhe        cmp     r1, #0
7286822f24SManish V Badarkhe        strexeq r1, r2, [r0]
7386822f24SManish V Badarkhe        cmpeq   r1, #0
7486822f24SManish V Badarkhe        dmb
7586822f24SManish V Badarkhe        moveq   r0, #1
7686822f24SManish V Badarkhe        movne   r0, #0
7786822f24SManish V Badarkhe        bx      lr
7886822f24SManish V Badarkheendfunc spin_trylock
79e33b78a6SSoby Mathew
8086822f24SManish V Badarkhe/*
8186822f24SManish V Badarkhe * Function: spin_unlock
8286822f24SManish V Badarkhe * ---------------------
8386822f24SManish V Badarkhe * Releases the spinlock by clearing its value.
8486822f24SManish V Badarkhe *
8586822f24SManish V Badarkhe * Arguments:
8686822f24SManish V Badarkhe *   r0 - Pointer to the spinlock variable (uint32_t *lock)
8786822f24SManish V Badarkhe *
8886822f24SManish V Badarkhe * Return:
8986822f24SManish V Badarkhe *   None
9086822f24SManish V Badarkhe *
9186822f24SManish V Badarkhe * Description:
9286822f24SManish V Badarkhe *   Releases the lock using store-release and sends SEV.
9386822f24SManish V Badarkhe */
94e33b78a6SSoby Mathewfunc spin_unlock
95e33b78a6SSoby Mathew	mov	r1, #0
96e33b78a6SSoby Mathew	stl	r1, [r0]
970147bef5SEtienne Carriere	COND_SEV()
98e33b78a6SSoby Mathew	bx	lr
99e33b78a6SSoby Mathewendfunc spin_unlock
100