diff options
author | Vineet Gupta <vgupta@synopsys.com> | 2013-01-18 15:12:16 +0530 |
---|---|---|
committer | Vineet Gupta <vgupta@synopsys.com> | 2013-02-11 20:00:30 +0530 |
commit | ac4c244d4e5d914f9a5642cdcc03b18780e55dbc (patch) | |
tree | fbc0a3da0a135dac46883eba654c862119060c3e /arch/arc/include/asm/irqflags.h | |
parent | cfdbc2e16e65c1ec1c23057640607cee98d1a1bd (diff) |
ARC: irqflags - Interrupt enabling/disabling at in-core intc
ARC700 has an in-core intc which provides 2 priorities (a.k.a.) "levels"
of interrupts (per IRQ) hencforth referred to as L1/L2 interrupts.
CPU flags register STATUS32 has Interrupt Enable bits per level (E1/E2)
to globally enable (or disable) all IRQs at a level. Hence the
implementation of arch_local_irq_{save,restore,enable,disable}( )
The STATUS32 reg can be r/w only using the AUX Interface of ARC, hence
the use of LR/SR instructions. Further, E1/E2 bits in there can only be
updated using the FLAG insn.
The intc supports 32 interrupts - and per IRQ enabling is controlled by
a bit in the AUX_IENABLE register, hence the implmentation of
arch_{,un}mask_irq( ) routines.
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/arc/include/asm/irqflags.h')
-rw-r--r-- | arch/arc/include/asm/irqflags.h | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/arch/arc/include/asm/irqflags.h b/arch/arc/include/asm/irqflags.h new file mode 100644 index 000000000000..5cc1080d7c26 --- /dev/null +++ b/arch/arc/include/asm/irqflags.h @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) + * + * 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. + */ + +#ifndef __ASM_ARC_IRQFLAGS_H +#define __ASM_ARC_IRQFLAGS_H + +/* vineetg: March 2010 : local_irq_save( ) optimisation + * -Remove explicit mov of current status32 into reg, that is not needed + * -Use BIC insn instead of INVERTED + AND + * -Conditionally disable interrupts (if they are not enabled, don't disable) +*/ + +#ifdef __KERNEL__ + +#include <asm/arcregs.h> + +#ifndef __ASSEMBLY__ + +/****************************************************************** + * IRQ Control Macros + ******************************************************************/ + +/* + * Save IRQ state and disable IRQs + */ +static inline long arch_local_irq_save(void) +{ + unsigned long temp, flags; + + __asm__ __volatile__( + " lr %1, [status32] \n" + " bic %0, %1, %2 \n" + " and.f 0, %1, %2 \n" + " flag.nz %0 \n" + : "=r"(temp), "=r"(flags) + : "n"((STATUS_E1_MASK | STATUS_E2_MASK)) + : "cc"); + + return flags; +} + +/* + * restore saved IRQ state + */ +static inline void arch_local_irq_restore(unsigned long flags) +{ + + __asm__ __volatile__( + " flag %0 \n" + : + : "r"(flags)); +} + +/* + * Unconditionally Enable IRQs + */ +extern void arch_local_irq_enable(void); + +/* + * Unconditionally Disable IRQs + */ +static inline void arch_local_irq_disable(void) +{ + unsigned long temp; + + __asm__ __volatile__( + " lr %0, [status32] \n" + " and %0, %0, %1 \n" + " flag %0 \n" + : "=&r"(temp) + : "n"(~(STATUS_E1_MASK | STATUS_E2_MASK))); +} + +/* + * save IRQ state + */ +static inline long arch_local_save_flags(void) +{ + unsigned long temp; + + __asm__ __volatile__( + " lr %0, [status32] \n" + : "=&r"(temp)); + + return temp; +} + +/* + * Query IRQ state + */ +static inline int arch_irqs_disabled_flags(unsigned long flags) +{ + return !(flags & (STATUS_E1_MASK)); +} + +static inline int arch_irqs_disabled(void) +{ + return arch_irqs_disabled_flags(arch_local_save_flags()); +} + +static inline void arch_mask_irq(unsigned int irq) +{ + unsigned int ienb; + + ienb = read_aux_reg(AUX_IENABLE); + ienb &= ~(1 << irq); + write_aux_reg(AUX_IENABLE, ienb); +} + +static inline void arch_unmask_irq(unsigned int irq) +{ + unsigned int ienb; + + ienb = read_aux_reg(AUX_IENABLE); + ienb |= (1 << irq); + write_aux_reg(AUX_IENABLE, ienb); +} + +#else + +.macro IRQ_DISABLE scratch + lr \scratch, [status32] + bic \scratch, \scratch, (STATUS_E1_MASK | STATUS_E2_MASK) + flag \scratch +.endm + +.macro IRQ_DISABLE_SAVE scratch, save + lr \scratch, [status32] + mov \save, \scratch /* Make a copy */ + bic \scratch, \scratch, (STATUS_E1_MASK | STATUS_E2_MASK) + flag \scratch +.endm + +.macro IRQ_ENABLE scratch + lr \scratch, [status32] + or \scratch, \scratch, (STATUS_E1_MASK | STATUS_E2_MASK) + flag \scratch +.endm + +#endif /* __ASSEMBLY__ */ + +#endif /* KERNEL */ + +#endif |