/*
* Copyright (C) 2012 ARM Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#ifndef __ASM_IRQFLAGS_H
#define __ASM_IRQFLAGS_H
#ifdef __KERNEL__
#include
#ifndef CONFIG_USE_ICC_SYSREGS_FOR_IRQFLAGS
#include
/*
* CPU interrupt mask handling.
*/
static inline unsigned long arch_local_irq_save(void)
{
unsigned long flags;
unsigned long pmr = 0xef;
asm volatile(
"mrs %0, daif // arch_local_irq_save\n"
"msr daifset, #2\n"
"msr_s " __stringify(ICC_PMR_EL1) ",%1\n"
"dsb sy"
: "=r" (flags)
: "r" (pmr)
: "memory");
return flags;
}
static inline void arch_local_irq_enable(void)
{
unsigned long pmr = 0xf0;
asm volatile(
"msr daifclr, #2 // arch_local_irq_enable\n"
"msr_s " __stringify(ICC_PMR_EL1) ",%0\n"
"dsb sy"
:
: "r" (pmr)
: "memory");
}
static inline void arch_local_irq_disable(void)
{
unsigned long pmr = 0xef;
asm volatile(
"msr daifset, #2 // arch_local_irq_disable\n"
"msr_s " __stringify(ICC_PMR_EL1) ",%0\n"
"dsb sy"
:
: "r" (pmr)
: "memory");
}
/*
* Save the current interrupt enable state.
*/
static inline unsigned long arch_local_save_flags(void)
{
unsigned long flags;
asm volatile(
"mrs %0, daif // arch_local_save_flags"
: "=r" (flags)
:
: "memory");
return flags;
}
/*
* restore saved IRQ state
*/
static inline void arch_local_irq_restore(unsigned long flags)
{
unsigned long pmr = 0xf0;
asm volatile(
"msr daif, %0 // arch_local_irq_restore\n"
"msr_s " __stringify(ICC_PMR_EL1) ",%1\n"
"dsb sy"
:
: "r" (flags), "r" (pmr)
: "memory");
}
static inline int arch_irqs_disabled_flags(unsigned long flags)
{
return flags & PSR_I_BIT;
}
#else /* CONFIG_IRQFLAGS_GIC_MASKING */
#include
/*
* CPU interrupt mask handling.
*/
static inline unsigned long arch_local_irq_save(void)
{
unsigned long flags, masked = ICC_PMR_EL1_MASKED;
asm volatile(
"// arch_local_irq_save\n"
"mrs_s %0, " __stringify(ICC_PMR_EL1) "\n"
"msr_s " __stringify(ICC_PMR_EL1) ",%1\n"
//"dsb sy\n"
: "=&r" (flags)
: "r" (masked)
: "memory");
return flags;
}
static inline void arch_local_irq_enable(void)
{
unsigned long unmasked = ICC_PMR_EL1_UNMASKED;
asm volatile(
"// arch_local_irq_enable\n"
"msr_s " __stringify(ICC_PMR_EL1) ",%0\n"
"dsb sy\n"
:
: "r" (unmasked)
: "memory");
}
static inline void arch_local_irq_disable(void)
{
unsigned long masked = ICC_PMR_EL1_MASKED;
asm volatile(
"// arch_local_irq_disable\n"
"msr_s " __stringify(ICC_PMR_EL1) ",%0\n"
//"dsb sy\n"
:
: "r" (masked)
: "memory");
}
/*
* Save the current interrupt enable state.
*/
static inline unsigned long arch_local_save_flags(void)
{
unsigned long flags;
asm volatile(
"// arch_local_save_flags\n"
"mrs_s %0, " __stringify(ICC_PMR_EL1) "\n"
: "=r" (flags)
:
: "memory");
return flags;
}
/*
* restore saved IRQ state
*/
static inline void arch_local_irq_restore(unsigned long flags)
{
asm volatile(
"// arch_local_irq_restore\n"
"msr_s " __stringify(ICC_PMR_EL1) ",%0\n"
"dsb sy\n"
:
: "r" (flags)
: "memory");
}
static inline int arch_irqs_disabled_flags(unsigned long flags)
{
return !(flags & ICC_PMR_EL1_G_BIT);
}
#endif /* CONFIG_IRQFLAGS_GIC_MASKING */
#define local_fiq_enable() asm("msr daifclr, #1" : : : "memory")
#define local_fiq_disable() asm("msr daifset, #1" : : : "memory")
#define local_async_enable() asm("msr daifclr, #4" : : : "memory")
#define local_async_disable() asm("msr daifset, #4" : : : "memory")
/*
* save and restore debug state
*/
#define local_dbg_save(flags) \
do { \
typecheck(unsigned long, flags); \
asm volatile( \
"mrs %0, daif // local_dbg_save\n" \
"msr daifset, #8" \
: "=r" (flags) : : "memory"); \
} while (0)
#define local_dbg_restore(flags) \
do { \
typecheck(unsigned long, flags); \
asm volatile( \
"msr daif, %0 // local_dbg_restore\n" \
: : "r" (flags) : "memory"); \
} while (0)
#define local_dbg_enable() asm("msr daifclr, #8" : : : "memory")
#define local_dbg_disable() asm("msr daifset, #8" : : : "memory")
#endif
#endif