| /* SPDX-License-Identifier: GPL-2.0 */ | |
| #ifndef __ASM_ARM_IRQFLAGS_H | |
| #define __ASM_ARM_IRQFLAGS_H | |
| #ifdef __KERNEL__ | |
| #include <asm/ptrace.h> | |
| /* | |
| * CPU interrupt mask handling. | |
| */ | |
| #ifdef CONFIG_CPU_V7M | |
| #define IRQMASK_REG_NAME_R "primask" | |
| #define IRQMASK_REG_NAME_W "primask" | |
| #define IRQMASK_I_BIT 1 | |
| #else | |
| #define IRQMASK_REG_NAME_R "cpsr" | |
| #define IRQMASK_REG_NAME_W "cpsr_c" | |
| #define IRQMASK_I_BIT PSR_I_BIT | |
| #endif | |
| #if __LINUX_ARM_ARCH__ >= 6 | |
| #define arch_local_irq_save arch_local_irq_save | |
| static inline unsigned long arch_local_irq_save(void) | |
| { | |
| unsigned long flags; | |
| asm volatile( | |
| " mrs %0, " IRQMASK_REG_NAME_R " @ arch_local_irq_save\n" | |
| " cpsid i" | |
| : "=r" (flags) : : "memory", "cc"); | |
| return flags; | |
| } | |
| #define arch_local_irq_enable arch_local_irq_enable | |
| static inline void arch_local_irq_enable(void) | |
| { | |
| asm volatile( | |
| " cpsie i @ arch_local_irq_enable" | |
| : | |
| : | |
| : "memory", "cc"); | |
| } | |
| #define arch_local_irq_disable arch_local_irq_disable | |
| static inline void arch_local_irq_disable(void) | |
| { | |
| asm volatile( | |
| " cpsid i @ arch_local_irq_disable" | |
| : | |
| : | |
| : "memory", "cc"); | |
| } | |
| #define local_fiq_enable() __asm__("cpsie f @ __stf" : : : "memory", "cc") | |
| #define local_fiq_disable() __asm__("cpsid f @ __clf" : : : "memory", "cc") | |
| #ifndef CONFIG_CPU_V7M | |
| #define local_abt_enable() __asm__("cpsie a @ __sta" : : : "memory", "cc") | |
| #define local_abt_disable() __asm__("cpsid a @ __cla" : : : "memory", "cc") | |
| #else | |
| #define local_abt_enable() do { } while (0) | |
| #define local_abt_disable() do { } while (0) | |
| #endif | |
| #else | |
| /* | |
| * Save the current interrupt enable state & disable IRQs | |
| */ | |
| #define arch_local_irq_save arch_local_irq_save | |
| static inline unsigned long arch_local_irq_save(void) | |
| { | |
| unsigned long flags, temp; | |
| asm volatile( | |
| " mrs %0, cpsr @ arch_local_irq_save\n" | |
| " orr %1, %0, #128\n" | |
| " msr cpsr_c, %1" | |
| : "=r" (flags), "=r" (temp) | |
| : | |
| : "memory", "cc"); | |
| return flags; | |
| } | |
| /* | |
| * Enable IRQs | |
| */ | |
| #define arch_local_irq_enable arch_local_irq_enable | |
| static inline void arch_local_irq_enable(void) | |
| { | |
| unsigned long temp; | |
| asm volatile( | |
| " mrs %0, cpsr @ arch_local_irq_enable\n" | |
| " bic %0, %0, #128\n" | |
| " msr cpsr_c, %0" | |
| : "=r" (temp) | |
| : | |
| : "memory", "cc"); | |
| } | |
| /* | |
| * Disable IRQs | |
| */ | |
| #define arch_local_irq_disable arch_local_irq_disable | |
| static inline void arch_local_irq_disable(void) | |
| { | |
| unsigned long temp; | |
| asm volatile( | |
| " mrs %0, cpsr @ arch_local_irq_disable\n" | |
| " orr %0, %0, #128\n" | |
| " msr cpsr_c, %0" | |
| : "=r" (temp) | |
| : | |
| : "memory", "cc"); | |
| } | |
| /* | |
| * Enable FIQs | |
| */ | |
| #define local_fiq_enable() \ | |
| ({ \ | |
| unsigned long temp; \ | |
| __asm__ __volatile__( \ | |
| "mrs %0, cpsr @ stf\n" \ | |
| " bic %0, %0, #64\n" \ | |
| " msr cpsr_c, %0" \ | |
| : "=r" (temp) \ | |
| : \ | |
| : "memory", "cc"); \ | |
| }) | |
| /* | |
| * Disable FIQs | |
| */ | |
| #define local_fiq_disable() \ | |
| ({ \ | |
| unsigned long temp; \ | |
| __asm__ __volatile__( \ | |
| "mrs %0, cpsr @ clf\n" \ | |
| " orr %0, %0, #64\n" \ | |
| " msr cpsr_c, %0" \ | |
| : "=r" (temp) \ | |
| : \ | |
| : "memory", "cc"); \ | |
| }) | |
| #define local_abt_enable() do { } while (0) | |
| #define local_abt_disable() do { } while (0) | |
| #endif | |
| /* | |
| * Save the current interrupt enable state. | |
| */ | |
| #define arch_local_save_flags arch_local_save_flags | |
| static inline unsigned long arch_local_save_flags(void) | |
| { | |
| unsigned long flags; | |
| asm volatile( | |
| " mrs %0, " IRQMASK_REG_NAME_R " @ local_save_flags" | |
| : "=r" (flags) : : "memory", "cc"); | |
| return flags; | |
| } | |
| /* | |
| * restore saved IRQ & FIQ state | |
| */ | |
| #define arch_local_irq_restore arch_local_irq_restore | |
| static inline void arch_local_irq_restore(unsigned long flags) | |
| { | |
| asm volatile( | |
| " msr " IRQMASK_REG_NAME_W ", %0 @ local_irq_restore" | |
| : | |
| : "r" (flags) | |
| : "memory", "cc"); | |
| } | |
| #define arch_irqs_disabled_flags arch_irqs_disabled_flags | |
| static inline int arch_irqs_disabled_flags(unsigned long flags) | |
| { | |
| return flags & IRQMASK_I_BIT; | |
| } | |
| #include <asm-generic/irqflags.h> | |
| #endif /* ifdef __KERNEL__ */ | |
| #endif /* ifndef __ASM_ARM_IRQFLAGS_H */ |