170 lines
4.0 KiB
C
170 lines
4.0 KiB
C
/* SPDX-License-Identifier: GPL-2.0
|
|
* (C) Copyright 2013
|
|
*/
|
|
#ifndef _SPINLOCK_H_
|
|
#define _SPINLOCK_H_
|
|
#include <asm/system.h>
|
|
|
|
typedef struct {
|
|
volatile u32 lock;
|
|
} spin_lock_t;
|
|
|
|
#define UNLOCK 0
|
|
#define LOCK 1
|
|
|
|
/* Current Program Status Register(CPSR) */
|
|
#define CPSR_N_FLAG (0x01 << 31)
|
|
#define CPSR_Z_FLAG (0x01 << 30)
|
|
#define CPSR_C_FLAG (0x01 << 29)
|
|
#define CPSR_V_FLAG (0x01 << 28)
|
|
#define CPSR_Q_FLAG (0x01 << 27)
|
|
#define CPSR_IT_1_0 (0x03 << 25)
|
|
#define CPSR_JAZELLE (0x01 << 24)
|
|
/* [23:20] RAZ/SBZP */
|
|
#define CPSR_GE (0x01 << 16)
|
|
#define CPSR_IT_7_2 (0x3F << 10)
|
|
#define CPSR_E_STATE (0x01 << 9) /* Endianness execution state. 0:Little, 1:Big */
|
|
#define CPSR_A_DISABLE (0x01 << 8) /* Asynchronous abort disable bit */
|
|
#define CPSR_I_DISABLE (0x01 << 7) /* Interrupt disable bit */
|
|
#define CPSR_F_DISABLE (0x01 << 6) /* Fast interrupt disable bit */
|
|
#define CPSR_T_STATE (0x01 << 5) /* Thumb execution state bit */
|
|
#define CPSR_MODE (0x1F << 0) /* The current mode of the processor */
|
|
|
|
#define CPSR_MODE_USER 0x10
|
|
#define CPSR_MODE_FIQ 0x11
|
|
#define CPSR_MODE_IRQ 0x12
|
|
#define CPSR_MODE_SVC 0x13
|
|
#define CPSR_MODE_ABT 0x17
|
|
#define CPSR_MODE_UND 0x1B
|
|
#define CPSR_MODE_SYS 0x1F
|
|
|
|
#define INIT_SPIN_LOCK {.lock = UNLOCK}
|
|
|
|
/*
|
|
* RTK FIXME: there is a the same name definition in io.h.
|
|
* So in orderto prevent compiler error, we comment this function temporarily.
|
|
*/
|
|
static inline unsigned long local_irq_flags(void)
|
|
{
|
|
unsigned long flags;
|
|
|
|
asm volatile ("mrs %0, daif // arch_local_irq_save\n"
|
|
: "=r" (flags)
|
|
:
|
|
: "memory", "cc"
|
|
);
|
|
return flags;
|
|
}
|
|
|
|
static inline int is_irq_on(void)
|
|
{
|
|
if (local_irq_flags() & CPSR_I_DISABLE)
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
static inline unsigned long arch_local_irq_save(void)
|
|
{
|
|
unsigned long flags;
|
|
|
|
asm volatile("mrs %0, daif /// save arch local irq\n"
|
|
"msr daifset, #2"
|
|
: "=r" (flags)
|
|
:
|
|
: "memory");
|
|
return flags;
|
|
}
|
|
|
|
static inline void arch_local_irq_enable(void)
|
|
{
|
|
asm volatile("msr daifclr, #2 // enable arch local irq\n"
|
|
:
|
|
:
|
|
: "memory");
|
|
}
|
|
|
|
static inline void arch_local_irq_disable(void)
|
|
{
|
|
asm volatile("msr daifset, #2 // disable arch local irq\n"
|
|
:
|
|
:
|
|
: "memory");
|
|
}
|
|
|
|
/*
|
|
* restore saved IRQ state
|
|
*/
|
|
static inline void arch_local_irq_restore(unsigned long flags)
|
|
{
|
|
asm volatile("msr daif, %0 // restore arch local irq\n"
|
|
:
|
|
: "r" (flags)
|
|
: "memory");
|
|
}
|
|
|
|
static inline unsigned long save_cpsr(void)
|
|
{
|
|
return arch_local_irq_save();
|
|
}
|
|
|
|
static inline void restore_cpsr(unsigned long flags)
|
|
{
|
|
arch_local_irq_restore(flags);
|
|
}
|
|
|
|
static inline void irq_enable(void)
|
|
{
|
|
arch_local_irq_enable();
|
|
}
|
|
|
|
static inline void irq_disable(void)
|
|
{
|
|
arch_local_irq_disable();
|
|
}
|
|
|
|
#ifdef CONFIG_ARMV8_MULTIENTRY
|
|
/* Below functions should be defined in arch */
|
|
void arch_spin_lock(void *lock);
|
|
int arch_try_lock(void *lock);
|
|
void arch_spin_unlock(void *lock);
|
|
|
|
static inline void spin_lock_init(spin_lock_t *lock)
|
|
{
|
|
lock->lock = UNLOCK;
|
|
}
|
|
|
|
static inline void spin_lock(spin_lock_t *lock)
|
|
{
|
|
arch_spin_lock((void *)&lock->lock);
|
|
}
|
|
|
|
static inline int spin_trylock(spin_lock_t *lock)
|
|
{
|
|
return arch_try_lock((void *)&lock->lock);
|
|
}
|
|
|
|
static inline void spin_unlock(spin_lock_t *lock)
|
|
{
|
|
arch_spin_unlock((void *)&lock->lock);
|
|
}
|
|
|
|
#define spin_lock_irq(lock) { irq_disable(); spin_lock(lock); }
|
|
#define spin_unlock_irq(lock) { spin_unlock(lock); irq_enable(); }
|
|
|
|
#define spin_lock_save(lock, flags) { flags = save_cpsr(); spin_lock(lock); }
|
|
#define spin_unlock_restore(lock, flags) { spin_unlock(lock); restore_cpsr(flags); }
|
|
|
|
#else
|
|
#define spin_lock_init(lock) {(void)lock; }
|
|
#define spin_lock(lock) {(void)lock; }
|
|
#define spin_trylock(lock) (1)
|
|
#define spin_unlock(lock) {(void)lock; }
|
|
|
|
#define spin_lock_irq(lock) do {irq_disable(); (void)lock; } while (0)
|
|
#define spin_unlock_irq(lock) do {(void)lock; irq_enable(); } while (0)
|
|
#define spin_lock_save(lock, flags) do {flags = save_cpsr(); (void)lock; } while (0)
|
|
#define spin_unlock_restore(lock, flags) do {(void)lock; restore_cpsr(flags); } while (0)
|
|
#endif
|
|
#endif //_SPINLOCK_H_
|
|
|