118 lines
2.0 KiB
C
118 lines
2.0 KiB
C
/*
|
|
* 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 <armv7-r/barriers.h>
|
|
|
|
#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 |