1/* 2 * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com) 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 */ 8 9#ifndef __ASM_IRQFLAGS_ARCV2_H 10#define __ASM_IRQFLAGS_ARCV2_H 11 12#include <asm/arcregs.h> 13 14/* status32 Bits */ 15#define STATUS_AD_BIT 19 /* Disable Align chk: core supports non-aligned */ 16#define STATUS_IE_BIT 31 17 18#define STATUS_AD_MASK (1<<STATUS_AD_BIT) 19#define STATUS_IE_MASK (1<<STATUS_IE_BIT) 20 21/* status32 Bits as encoded/expected by CLRI/SETI */ 22#define CLRI_STATUS_IE_BIT 4 23 24#define CLRI_STATUS_E_MASK 0xF 25#define CLRI_STATUS_IE_MASK (1 << CLRI_STATUS_IE_BIT) 26 27#define AUX_USER_SP 0x00D 28#define AUX_IRQ_CTRL 0x00E 29#define AUX_IRQ_ACT 0x043 /* Active Intr across all levels */ 30#define AUX_IRQ_LVL_PEND 0x200 /* Pending Intr across all levels */ 31#define AUX_IRQ_HINT 0x201 /* For generating Soft Interrupts */ 32#define AUX_IRQ_PRIORITY 0x206 33#define ICAUSE 0x40a 34#define AUX_IRQ_SELECT 0x40b 35#define AUX_IRQ_ENABLE 0x40c 36 37/* Was Intr taken in User Mode */ 38#define AUX_IRQ_ACT_BIT_U 31 39 40/* 41 * Hardware supports 16 priorities (0 highest, 15 lowest) 42 * Linux by default runs at 1, priority 0 reserved for NMI style interrupts 43 */ 44#define ARCV2_IRQ_DEF_PRIO 1 45 46/* seed value for status register */ 47#define ISA_INIT_STATUS_BITS (STATUS_IE_MASK | STATUS_AD_MASK | \ 48 (ARCV2_IRQ_DEF_PRIO << 1)) 49 50#ifndef __ASSEMBLY__ 51 52/* 53 * Save IRQ state and disable IRQs 54 */ 55static inline long arch_local_irq_save(void) 56{ 57 unsigned long flags; 58 59 __asm__ __volatile__(" clri %0 \n" : "=r" (flags) : : "memory"); 60 61 return flags; 62} 63 64/* 65 * restore saved IRQ state 66 */ 67static inline void arch_local_irq_restore(unsigned long flags) 68{ 69 __asm__ __volatile__(" seti %0 \n" : : "r" (flags) : "memory"); 70} 71 72/* 73 * Unconditionally Enable IRQs 74 */ 75static inline void arch_local_irq_enable(void) 76{ 77 unsigned int irqact = read_aux_reg(AUX_IRQ_ACT); 78 79 if (irqact & 0xffff) 80 write_aux_reg(AUX_IRQ_ACT, irqact & ~0xffff); 81 82 __asm__ __volatile__(" seti \n" : : : "memory"); 83} 84 85/* 86 * Unconditionally Disable IRQs 87 */ 88static inline void arch_local_irq_disable(void) 89{ 90 __asm__ __volatile__(" clri \n" : : : "memory"); 91} 92 93/* 94 * save IRQ state 95 */ 96static inline long arch_local_save_flags(void) 97{ 98 unsigned long temp; 99 100 __asm__ __volatile__( 101 " lr %0, [status32] \n" 102 : "=&r"(temp) 103 : 104 : "memory"); 105 106 /* To be compatible with irq_save()/irq_restore() 107 * encode the irq bits as expected by CLRI/SETI 108 * (this was needed to make CONFIG_TRACE_IRQFLAGS work) 109 */ 110 temp = (1 << 5) | 111 ((!!(temp & STATUS_IE_MASK)) << CLRI_STATUS_IE_BIT) | 112 ((temp >> 1) & CLRI_STATUS_E_MASK); 113 return temp; 114} 115 116/* 117 * Query IRQ state 118 */ 119static inline int arch_irqs_disabled_flags(unsigned long flags) 120{ 121 return !(flags & CLRI_STATUS_IE_MASK); 122} 123 124static inline int arch_irqs_disabled(void) 125{ 126 return arch_irqs_disabled_flags(arch_local_save_flags()); 127} 128 129static inline void arc_softirq_trigger(int irq) 130{ 131 write_aux_reg(AUX_IRQ_HINT, irq); 132} 133 134static inline void arc_softirq_clear(int irq) 135{ 136 write_aux_reg(AUX_IRQ_HINT, 0); 137} 138 139#else 140 141#ifdef CONFIG_TRACE_IRQFLAGS 142 143.macro TRACE_ASM_IRQ_DISABLE 144 bl trace_hardirqs_off 145.endm 146 147.macro TRACE_ASM_IRQ_ENABLE 148 bl trace_hardirqs_on 149.endm 150 151#else 152 153.macro TRACE_ASM_IRQ_DISABLE 154.endm 155 156.macro TRACE_ASM_IRQ_ENABLE 157.endm 158 159#endif 160.macro IRQ_DISABLE scratch 161 clri 162 TRACE_ASM_IRQ_DISABLE 163.endm 164 165.macro IRQ_ENABLE scratch 166 TRACE_ASM_IRQ_ENABLE 167 seti 168.endm 169 170#endif /* __ASSEMBLY__ */ 171 172#endif 173