162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com) 462306a36Sopenharmony_ci * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#ifndef __ASM_IRQFLAGS_ARCOMPACT_H 862306a36Sopenharmony_ci#define __ASM_IRQFLAGS_ARCOMPACT_H 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci/* vineetg: March 2010 : local_irq_save( ) optimisation 1162306a36Sopenharmony_ci * -Remove explicit mov of current status32 into reg, that is not needed 1262306a36Sopenharmony_ci * -Use BIC insn instead of INVERTED + AND 1362306a36Sopenharmony_ci * -Conditionally disable interrupts (if they are not enabled, don't disable) 1462306a36Sopenharmony_ci*/ 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include <asm/arcregs.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci/* status32 Reg bits related to Interrupt Handling */ 1962306a36Sopenharmony_ci#define STATUS_E1_BIT 1 /* Int 1 enable */ 2062306a36Sopenharmony_ci#define STATUS_E2_BIT 2 /* Int 2 enable */ 2162306a36Sopenharmony_ci#define STATUS_A1_BIT 3 /* Int 1 active */ 2262306a36Sopenharmony_ci#define STATUS_A2_BIT 4 /* Int 2 active */ 2362306a36Sopenharmony_ci#define STATUS_AE_BIT 5 /* Exception active */ 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#define STATUS_E1_MASK (1<<STATUS_E1_BIT) 2662306a36Sopenharmony_ci#define STATUS_E2_MASK (1<<STATUS_E2_BIT) 2762306a36Sopenharmony_ci#define STATUS_A1_MASK (1<<STATUS_A1_BIT) 2862306a36Sopenharmony_ci#define STATUS_A2_MASK (1<<STATUS_A2_BIT) 2962306a36Sopenharmony_ci#define STATUS_AE_MASK (1<<STATUS_AE_BIT) 3062306a36Sopenharmony_ci#define STATUS_IE_MASK (STATUS_E1_MASK | STATUS_E2_MASK) 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci/* Other Interrupt Handling related Aux regs */ 3362306a36Sopenharmony_ci#define AUX_IRQ_LEV 0x200 /* IRQ Priority: L1 or L2 */ 3462306a36Sopenharmony_ci#define AUX_IRQ_HINT 0x201 /* For generating Soft Interrupts */ 3562306a36Sopenharmony_ci#define AUX_IRQ_LV12 0x43 /* interrupt level register */ 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#define AUX_IENABLE 0x40c 3862306a36Sopenharmony_ci#define AUX_ITRIGGER 0x40d 3962306a36Sopenharmony_ci#define AUX_IPULSE 0x415 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci#define ISA_INIT_STATUS_BITS STATUS_IE_MASK 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci#ifndef __ASSEMBLY__ 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci/****************************************************************** 4662306a36Sopenharmony_ci * IRQ Control Macros 4762306a36Sopenharmony_ci * 4862306a36Sopenharmony_ci * All of them have "memory" clobber (compiler barrier) which is needed to 4962306a36Sopenharmony_ci * ensure that LD/ST requiring irq safetly (R-M-W when LLSC is not available) 5062306a36Sopenharmony_ci * are redone after IRQs are re-enabled (and gcc doesn't reuse stale register) 5162306a36Sopenharmony_ci * 5262306a36Sopenharmony_ci * Noted at the time of Abilis Timer List corruption 5362306a36Sopenharmony_ci * 5462306a36Sopenharmony_ci * Orig Bug + Rejected solution: 5562306a36Sopenharmony_ci * https://lore.kernel.org/lkml/1364553218-31255-1-git-send-email-vgupta@synopsys.com 5662306a36Sopenharmony_ci * 5762306a36Sopenharmony_ci * Reasoning: 5862306a36Sopenharmony_ci * https://lore.kernel.org/lkml/CA+55aFyFWjpSVQM6M266tKrG_ZXJzZ-nYejpmXYQXbrr42mGPQ@mail.gmail.com 5962306a36Sopenharmony_ci * 6062306a36Sopenharmony_ci ******************************************************************/ 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci/* 6362306a36Sopenharmony_ci * Save IRQ state and disable IRQs 6462306a36Sopenharmony_ci */ 6562306a36Sopenharmony_cistatic inline long arch_local_irq_save(void) 6662306a36Sopenharmony_ci{ 6762306a36Sopenharmony_ci unsigned long temp, flags; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci __asm__ __volatile__( 7062306a36Sopenharmony_ci " lr %1, [status32] \n" 7162306a36Sopenharmony_ci " bic %0, %1, %2 \n" 7262306a36Sopenharmony_ci " and.f 0, %1, %2 \n" 7362306a36Sopenharmony_ci " flag.nz %0 \n" 7462306a36Sopenharmony_ci : "=r"(temp), "=r"(flags) 7562306a36Sopenharmony_ci : "n"((STATUS_E1_MASK | STATUS_E2_MASK)) 7662306a36Sopenharmony_ci : "memory", "cc"); 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci return flags; 7962306a36Sopenharmony_ci} 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci/* 8262306a36Sopenharmony_ci * restore saved IRQ state 8362306a36Sopenharmony_ci */ 8462306a36Sopenharmony_cistatic inline void arch_local_irq_restore(unsigned long flags) 8562306a36Sopenharmony_ci{ 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci __asm__ __volatile__( 8862306a36Sopenharmony_ci " flag %0 \n" 8962306a36Sopenharmony_ci : 9062306a36Sopenharmony_ci : "r"(flags) 9162306a36Sopenharmony_ci : "memory"); 9262306a36Sopenharmony_ci} 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci/* 9562306a36Sopenharmony_ci * Unconditionally Enable IRQs 9662306a36Sopenharmony_ci */ 9762306a36Sopenharmony_ci#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS 9862306a36Sopenharmony_ciextern void arch_local_irq_enable(void); 9962306a36Sopenharmony_ci#else 10062306a36Sopenharmony_cistatic inline void arch_local_irq_enable(void) 10162306a36Sopenharmony_ci{ 10262306a36Sopenharmony_ci unsigned long temp; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci __asm__ __volatile__( 10562306a36Sopenharmony_ci " lr %0, [status32] \n" 10662306a36Sopenharmony_ci " or %0, %0, %1 \n" 10762306a36Sopenharmony_ci " flag %0 \n" 10862306a36Sopenharmony_ci : "=&r"(temp) 10962306a36Sopenharmony_ci : "n"((STATUS_E1_MASK | STATUS_E2_MASK)) 11062306a36Sopenharmony_ci : "cc", "memory"); 11162306a36Sopenharmony_ci} 11262306a36Sopenharmony_ci#endif 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci/* 11562306a36Sopenharmony_ci * Unconditionally Disable IRQs 11662306a36Sopenharmony_ci */ 11762306a36Sopenharmony_cistatic inline void arch_local_irq_disable(void) 11862306a36Sopenharmony_ci{ 11962306a36Sopenharmony_ci unsigned long temp; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci __asm__ __volatile__( 12262306a36Sopenharmony_ci " lr %0, [status32] \n" 12362306a36Sopenharmony_ci " and %0, %0, %1 \n" 12462306a36Sopenharmony_ci " flag %0 \n" 12562306a36Sopenharmony_ci : "=&r"(temp) 12662306a36Sopenharmony_ci : "n"(~(STATUS_E1_MASK | STATUS_E2_MASK)) 12762306a36Sopenharmony_ci : "memory"); 12862306a36Sopenharmony_ci} 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci/* 13162306a36Sopenharmony_ci * save IRQ state 13262306a36Sopenharmony_ci */ 13362306a36Sopenharmony_cistatic inline long arch_local_save_flags(void) 13462306a36Sopenharmony_ci{ 13562306a36Sopenharmony_ci unsigned long temp; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci __asm__ __volatile__( 13862306a36Sopenharmony_ci " lr %0, [status32] \n" 13962306a36Sopenharmony_ci : "=&r"(temp) 14062306a36Sopenharmony_ci : 14162306a36Sopenharmony_ci : "memory"); 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci return temp; 14462306a36Sopenharmony_ci} 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci/* 14762306a36Sopenharmony_ci * Query IRQ state 14862306a36Sopenharmony_ci */ 14962306a36Sopenharmony_cistatic inline int arch_irqs_disabled_flags(unsigned long flags) 15062306a36Sopenharmony_ci{ 15162306a36Sopenharmony_ci return !(flags & (STATUS_E1_MASK 15262306a36Sopenharmony_ci#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS 15362306a36Sopenharmony_ci | STATUS_E2_MASK 15462306a36Sopenharmony_ci#endif 15562306a36Sopenharmony_ci )); 15662306a36Sopenharmony_ci} 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_cistatic inline int arch_irqs_disabled(void) 15962306a36Sopenharmony_ci{ 16062306a36Sopenharmony_ci return arch_irqs_disabled_flags(arch_local_save_flags()); 16162306a36Sopenharmony_ci} 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci#else 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci#ifdef CONFIG_TRACE_IRQFLAGS 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci.macro TRACE_ASM_IRQ_DISABLE 16862306a36Sopenharmony_ci bl trace_hardirqs_off 16962306a36Sopenharmony_ci.endm 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci.macro TRACE_ASM_IRQ_ENABLE 17262306a36Sopenharmony_ci bl trace_hardirqs_on 17362306a36Sopenharmony_ci.endm 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci#else 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci.macro TRACE_ASM_IRQ_DISABLE 17862306a36Sopenharmony_ci.endm 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci.macro TRACE_ASM_IRQ_ENABLE 18162306a36Sopenharmony_ci.endm 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci#endif 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci.macro IRQ_DISABLE scratch 18662306a36Sopenharmony_ci lr \scratch, [status32] 18762306a36Sopenharmony_ci bic \scratch, \scratch, (STATUS_E1_MASK | STATUS_E2_MASK) 18862306a36Sopenharmony_ci flag \scratch 18962306a36Sopenharmony_ci TRACE_ASM_IRQ_DISABLE 19062306a36Sopenharmony_ci.endm 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci.macro IRQ_ENABLE scratch 19362306a36Sopenharmony_ci TRACE_ASM_IRQ_ENABLE 19462306a36Sopenharmony_ci lr \scratch, [status32] 19562306a36Sopenharmony_ci or \scratch, \scratch, (STATUS_E1_MASK | STATUS_E2_MASK) 19662306a36Sopenharmony_ci flag \scratch 19762306a36Sopenharmony_ci.endm 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci#endif /* __ASSEMBLY__ */ 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci#endif 202