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 */ 55 static 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 */ 67 static 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 */ 75 static 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 */ 88 static inline void arch_local_irq_disable(void) 89 { 90 __asm__ __volatile__(" clri \n" : : : "memory"); 91 } 92 93 /* 94 * save IRQ state 95 */ 96 static 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 */ 119 static inline int arch_irqs_disabled_flags(unsigned long flags) 120 { 121 return !(flags & CLRI_STATUS_IE_MASK); 122 } 123 124 static inline int arch_irqs_disabled(void) 125 { 126 return arch_irqs_disabled_flags(arch_local_save_flags()); 127 } 128 129 static inline void arc_softirq_trigger(int irq) 130 { 131 write_aux_reg(AUX_IRQ_HINT, irq); 132 } 133 134 static 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