| /* 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 */ |