/* * spinlock.h * * Copyright (c) 2020 Semidrive Semiconductor. * All rights reserved. * * Description: ARM spinlock interface. * * Revision History: * ----------------- */ #ifndef INCLUDE_ARM_SPINLOCK_H #define INCLUDE_ARM_SPINLOCK_H #include #define SPIN_LOCK_INITIAL_VALUE (0) #ifndef ASSEMBLY __BEGIN_CDECLS /* spin lock type */ typedef unsigned long spin_lock_t; #ifdef CONFIG_MULTI_CORE_SMP #else static inline int __arch_spin_lock_testset(spin_lock_t *spinlock, int value) { int result = 0; __ASM volatile ( "1:\n" "\tldrex %0, [%1]\n" "\tcmp %0, %2\n" "\tbeq 2f\n" "\tstrex %0, %2, [%1]\n" "\tcmp %0, %2\n" "\tbeq 1b\n" "\tdmb ish\n" "2:\n" : "=&r" (result) : "r" (spinlock), "r" (value) : "cc", "memory" ); return result; } #endif /* * arch spinlock init. * * @spinlock spinlock address. */ #ifdef CONFIG_MULTI_CORE_SMP void arch_spin_lock_init(spin_lock_t *spinlock); #else static inline void arch_spin_lock_init(spin_lock_t *spinlock) { *spinlock = SPIN_LOCK_INITIAL_VALUE; } #endif /* * arch spin lock. * * @spinlock spinlock address. */ #ifdef CONFIG_MULTI_CORE_SMP void arch_spin_lock(spin_lock_t *spinlock); #else static inline void arch_spin_lock(spin_lock_t *spinlock) { /* spin until lock is acquired */ while (__arch_spin_lock_testset(spinlock, 1)) { DSB; }; } #endif /* * arch spin trylock. * * @spinlock spinlock address. */ #ifdef CONFIG_MULTI_CORE_SMP int arch_spin_trylock(spin_lock_t *spinlock); #else static inline int arch_spin_trylock(spin_lock_t *spinlock) { return __arch_spin_lock_testset(spinlock, 1) == 0; } #endif /* * arch spin unlock. * * @spinlock spinlock address. */ #ifdef CONFIG_MULTI_CORE_SMP void arch_spin_unlock(spin_lock_t *spinlock); #else static inline void arch_spin_unlock(spin_lock_t *spinlock) { DMB; *spinlock = 0; DSB; } #endif __END_CDECLS #endif #endif