| /* |
| * drivers/amlogic/debug/irqflags_debug_arm.h |
| * |
| * Copyright (C) 2015 Amlogic, Inc. All rights reserved. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * 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. |
| * |
| */ |
| |
| #ifndef __ASM_IRQFLAGS_DEBUG_ARM_H |
| #define __ASM_IRQFLAGS_DEBUG_ARM_H |
| |
| #ifdef __KERNEL__ |
| |
| #include <linux/amlogic/debug_lockup.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"); |
| irq_trace_start(flags); |
| return flags; |
| } |
| |
| #define arch_local_irq_enable arch_local_irq_enable |
| static inline void arch_local_irq_enable(void) |
| { |
| irq_trace_stop(0); |
| 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) |
| { |
| #if 0 |
| asm volatile( |
| " cpsid i @ arch_local_irq_disable" |
| : |
| : |
| : "memory", "cc"); |
| #endif |
| arch_local_irq_save(); |
| } |
| |
| #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) |
| { |
| irq_trace_stop(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_IRQFLAGS_DEBUG_ARM_H */ |