mirror of https://github.com/thesofproject/sof.git
xtensa: add atomic and spinlock function with exclusive
In mp_asm.S, if XCHAL_HAVE_EXCLUSIVE is defined, it will use exclusive instructions, else it will use s32c1i instructions. It supports S32C1I and exclusive instruction in xthal_compare_and_set() API. Refer to xtos-simc-mutex.c, xtos_mutex_p structure is similar to spinlock_t. For dsp design, we cannot use s32c1i intrcutions in mt8195. In order to not affect other platform, add CONFIG_XTENSA_EXCLUSIVE and __XCC__ compile options. Signed-off-by: YC Hung <yc.hung@mediatek.com> Signed-off-by: Allen-KH Cheng <allen-kh.cheng@mediatek.com>
This commit is contained in:
parent
1e8feb2cf3
commit
83093dadea
|
@ -11,6 +11,10 @@
|
|||
#define __ARCH_ATOMIC_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#if XCHAL_HAVE_EXCLUSIVE && CONFIG_XTENSA_EXCLUSIVE && __XCC__
|
||||
#include <xtensa/tie/xt_core.h>
|
||||
#endif
|
||||
#include <xtensa/config/core-isa.h>
|
||||
|
||||
typedef struct {
|
||||
volatile int32_t value;
|
||||
|
@ -31,6 +35,42 @@ static inline void arch_atomic_init(atomic_t *a, int32_t value)
|
|||
arch_atomic_set(a, value);
|
||||
}
|
||||
|
||||
#if XCHAL_HAVE_EXCLUSIVE && CONFIG_XTENSA_EXCLUSIVE && __XCC__
|
||||
|
||||
/* Use exclusive instructions */
|
||||
static inline int32_t arch_atomic_add(atomic_t *a, int32_t value)
|
||||
{
|
||||
/*reference xtos : xipc_misc.h*/
|
||||
int32_t result = 0;
|
||||
int32_t current;
|
||||
|
||||
while (!result) {
|
||||
current = XT_L32EX((int32_t *)a);
|
||||
result = current + value;
|
||||
XT_S32EX(result, (int32_t *)a);
|
||||
XT_GETEX(result);
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
static inline int32_t arch_atomic_sub(atomic_t *a, int32_t value)
|
||||
{
|
||||
/*reference xtos : xipc_misc.h*/
|
||||
int32_t current;
|
||||
int32_t result = 0;
|
||||
|
||||
while (!result) {
|
||||
current = XT_L32EX((int *)a);
|
||||
result = current - value;
|
||||
XT_S32EX(result, (int *)a);
|
||||
XT_GETEX(result);
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
#elif XCHAL_HAVE_S32C1I
|
||||
|
||||
/* Use S32C1I instructions */
|
||||
static inline int32_t arch_atomic_add(atomic_t *a, int32_t value)
|
||||
{
|
||||
int32_t result, current;
|
||||
|
@ -65,6 +105,42 @@ static inline int32_t arch_atomic_sub(atomic_t *a, int32_t value)
|
|||
return current;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#if CONFIG_CORE_COUNT > 1
|
||||
|
||||
#error No atomic ISA for SMP configuration
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The ISA has no atomic operations so use integer arithmetic on uniprocessor systems.
|
||||
* This helps support GCC and qemu emulation of certain targets.
|
||||
*/
|
||||
|
||||
/* integer arithmetic methods */
|
||||
static inline int32_t arch_atomic_add(atomic_t *a, int32_t value)
|
||||
{
|
||||
int32_t result, current;
|
||||
|
||||
current = arch_atomic_read(a);
|
||||
result = current + value;
|
||||
arch_atomic_set(a, result);
|
||||
return current;
|
||||
}
|
||||
|
||||
static inline int32_t arch_atomic_sub(atomic_t *a, int32_t value)
|
||||
{
|
||||
int32_t result, current;
|
||||
|
||||
current = arch_atomic_read(a);
|
||||
result = current - value;
|
||||
arch_atomic_set(a, result);
|
||||
return current;
|
||||
}
|
||||
|
||||
#endif /* XCHAL_HAVE_EXCLUSIVE && CONFIG_XTENSA_EXCLUSIVE && __XCC__ */
|
||||
|
||||
#endif /* __ARCH_ATOMIC_H__ */
|
||||
|
||||
#else
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#define __ARCH_SPINLOCK_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <xtensa/config/core-isa.h>
|
||||
|
||||
typedef struct {
|
||||
volatile uint32_t lock;
|
||||
|
@ -24,6 +25,44 @@ static inline void arch_spinlock_init(spinlock_t *lock)
|
|||
lock->lock = 0;
|
||||
}
|
||||
|
||||
#if XCHAL_HAVE_EXCLUSIVE && CONFIG_XTENSA_EXCLUSIVE && __XCC__
|
||||
|
||||
static inline void arch_spin_lock(spinlock_t *lock)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" movi %0, 0\n"
|
||||
" l32ex %0, %1\n"
|
||||
"1: movi %0, 1\n"
|
||||
" s32ex %0, %1\n"
|
||||
" getex %0\n"
|
||||
" bnez %0, 1b\n"
|
||||
: "=&a" (result)
|
||||
: "a" (&lock->lock)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline int arch_try_lock(spinlock_t *lock)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" movi %0, 0\n"
|
||||
" l32ex %0, %1\n"
|
||||
" movi %0, 1\n"
|
||||
" s32ex %0, %1\n"
|
||||
" getex %0\n"
|
||||
: "=&a" (result)
|
||||
: "a" (&lock->lock)
|
||||
: "memory");
|
||||
|
||||
/* return 0 for failed lock, 1 otherwise */
|
||||
return result ? 0 : 1;
|
||||
}
|
||||
|
||||
#elif XCHAL_HAVE_S32C1I
|
||||
|
||||
static inline void arch_spin_lock(spinlock_t *lock)
|
||||
{
|
||||
uint32_t result;
|
||||
|
@ -60,6 +99,47 @@ static inline int arch_try_lock(spinlock_t *lock)
|
|||
return result ? 0 : 1;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#if CONFIG_CORE_COUNT > 1
|
||||
|
||||
#error No atomic ISA for SMP configuration
|
||||
|
||||
#endif /* CONFIG_CORE_COUNT > 1 */
|
||||
|
||||
/*
|
||||
* The ISA has no atomic operations so use integer arithmetic on uniprocessor systems.
|
||||
* This helps support GCC and qemu emulation of certain targets.
|
||||
*/
|
||||
static inline void arch_spin_lock(spinlock_t *lock)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
do {
|
||||
if (lock->lock == 0) {
|
||||
lock->lock = 1;
|
||||
result = 1;
|
||||
}
|
||||
} while (!result);
|
||||
}
|
||||
|
||||
static inline int arch_try_lock(spinlock_t *lock)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
if (lock->lock == 0) {
|
||||
lock->lock = 1;
|
||||
result = 1;
|
||||
}
|
||||
|
||||
/* return 0 for failed lock, 1 otherwise */
|
||||
return result ? 0 : 1;
|
||||
}
|
||||
|
||||
#endif /* XCHAL_HAVE_EXCLUSIVE && CONFIG_XTENSA_EXCLUSIVE && __XCC__ */
|
||||
|
||||
#if XCHAL_HAVE_EXCLUSIVE || XCHAL_HAVE_S32C1I
|
||||
|
||||
static inline void arch_spin_unlock(spinlock_t *lock)
|
||||
{
|
||||
uint32_t result;
|
||||
|
@ -72,6 +152,28 @@ static inline void arch_spin_unlock(spinlock_t *lock)
|
|||
: "memory");
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#if CONFIG_CORE_COUNT > 1
|
||||
|
||||
#error No atomic ISA for SMP configuration
|
||||
|
||||
#endif /* CONFIG_CORE_COUNT > 1 */
|
||||
|
||||
/*
|
||||
* The ISA has no atomic operations so use integer arithmetic on uniprocessor systems.
|
||||
* This helps support GCC and qemu emulation of certain targets.
|
||||
*/
|
||||
static inline void arch_spin_unlock(spinlock_t *lock)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
lock->lock = 0;
|
||||
result = 1;
|
||||
}
|
||||
|
||||
#endif /* XCHAL_HAVE_EXCLUSIVE || XCHAL_HAVE_S32C1I */
|
||||
|
||||
#endif /* __ARCH_SPINLOCK_H__ */
|
||||
|
||||
#else
|
||||
|
|
|
@ -458,4 +458,11 @@ config AGENT_PANIC_ON_DELAY
|
|||
If scheduler timing verification fails, SA will
|
||||
call a DSP panic.
|
||||
|
||||
config XTENSA_EXCLUSIVE
|
||||
bool
|
||||
default n
|
||||
help
|
||||
This has to be selected for xtensa exclusive instructions.
|
||||
There is a definition for EXCLUSIVE option in xtensa-config.h
|
||||
|
||||
endmenu
|
||||
|
|
Loading…
Reference in New Issue