Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
irqflags.h
Go to the documentation of this file.
1 /* MN10300 IRQ flag handling
2  *
3  * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
4  * Written by David Howells ([email protected])
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public Licence
8  * as published by the Free Software Foundation; either version
9  * 2 of the Licence, or (at your option) any later version.
10  */
11 
12 #ifndef _ASM_IRQFLAGS_H
13 #define _ASM_IRQFLAGS_H
14 
15 #include <asm/cpu-regs.h>
16 #ifndef __ASSEMBLY__
17 #include <linux/smp.h>
18 #endif
19 
20 /*
21  * interrupt control
22  * - "disabled": run in IM1/2
23  * - level 0 - kernel debugger
24  * - level 1 - virtual serial DMA (if present)
25  * - level 5 - normal interrupt priority
26  * - level 6 - timer interrupt
27  * - "enabled": run in IM7
28  */
29 #define MN10300_CLI_LEVEL (CONFIG_LINUX_CLI_LEVEL << EPSW_IM_SHIFT)
30 
31 #ifndef __ASSEMBLY__
32 
33 static inline unsigned long arch_local_save_flags(void)
34 {
35  unsigned long flags;
36 
37  asm volatile("mov epsw,%0" : "=d"(flags));
38  return flags;
39 }
40 
41 static inline void arch_local_irq_disable(void)
42 {
43  asm volatile(
44  " and %0,epsw \n"
45  " or %1,epsw \n"
46  " nop \n"
47  " nop \n"
48  " nop \n"
49  :
50  : "i"(~EPSW_IM), "i"(EPSW_IE | MN10300_CLI_LEVEL)
51  : "memory");
52 }
53 
54 static inline unsigned long arch_local_irq_save(void)
55 {
56  unsigned long flags;
57 
58  flags = arch_local_save_flags();
60  return flags;
61 }
62 
63 /*
64  * we make sure arch_irq_enable() doesn't cause priority inversion
65  */
66 extern unsigned long __mn10300_irq_enabled_epsw[];
67 
68 static inline void arch_local_irq_enable(void)
69 {
70  unsigned long tmp;
71  int cpu = raw_smp_processor_id();
72 
73  asm volatile(
74  " mov epsw,%0 \n"
75  " and %1,%0 \n"
76  " or %2,%0 \n"
77  " mov %0,epsw \n"
78  : "=&d"(tmp)
79  : "i"(~EPSW_IM), "r"(__mn10300_irq_enabled_epsw[cpu])
80  : "memory", "cc");
81 }
82 
83 static inline void arch_local_irq_restore(unsigned long flags)
84 {
85  asm volatile(
86  " mov %0,epsw \n"
87  " nop \n"
88  " nop \n"
89  " nop \n"
90  :
91  : "d"(flags)
92  : "memory", "cc");
93 }
94 
95 static inline bool arch_irqs_disabled_flags(unsigned long flags)
96 {
97  return (flags & (EPSW_IE | EPSW_IM)) != (EPSW_IE | EPSW_IM_7);
98 }
99 
100 static inline bool arch_irqs_disabled(void)
101 {
103 }
104 
105 /*
106  * Hook to save power by halting the CPU
107  * - called from the idle loop
108  * - must reenable interrupts (which takes three instruction cycles to complete)
109  */
110 static inline void arch_safe_halt(void)
111 {
112 #ifdef CONFIG_SMP
114 #else
115  asm volatile(
116  " or %0,epsw \n"
117  " nop \n"
118  " nop \n"
119  " bset %2,(%1) \n"
120  :
121  : "i"(EPSW_IE|EPSW_IM), "n"(&CPUM), "i"(CPUM_SLEEP)
122  : "cc");
123 #endif
124 }
125 
126 #define __sleep_cpu() \
127 do { \
128  asm volatile( \
129  " bset %1,(%0)\n" \
130  "1: btst %1,(%0)\n" \
131  " bne 1b\n" \
132  : \
133  : "i"(&CPUM), "i"(CPUM_SLEEP) \
134  : "cc" \
135  ); \
136 } while (0)
137 
138 static inline void arch_local_cli(void)
139 {
140  asm volatile(
141  " and %0,epsw \n"
142  " nop \n"
143  " nop \n"
144  " nop \n"
145  :
146  : "i"(~EPSW_IE)
147  : "memory"
148  );
149 }
150 
151 static inline unsigned long arch_local_cli_save(void)
152 {
153  unsigned long flags = arch_local_save_flags();
154  arch_local_cli();
155  return flags;
156 }
157 
158 static inline void arch_local_sti(void)
159 {
160  asm volatile(
161  " or %0,epsw \n"
162  :
163  : "i"(EPSW_IE)
164  : "memory");
165 }
166 
167 static inline void arch_local_change_intr_mask_level(unsigned long level)
168 {
169  asm volatile(
170  " and %0,epsw \n"
171  " or %1,epsw \n"
172  :
173  : "i"(~EPSW_IM), "i"(EPSW_IE | level)
174  : "cc", "memory");
175 }
176 
177 #else /* !__ASSEMBLY__ */
178 
179 #define LOCAL_SAVE_FLAGS(reg) \
180  mov epsw,reg
181 
182 #define LOCAL_IRQ_DISABLE \
183  and ~EPSW_IM,epsw; \
184  or EPSW_IE|MN10300_CLI_LEVEL,epsw; \
185  nop; \
186  nop; \
187  nop
188 
189 #define LOCAL_IRQ_ENABLE \
190  or EPSW_IE|EPSW_IM_7,epsw
191 
192 #define LOCAL_IRQ_RESTORE(reg) \
193  mov reg,epsw
194 
195 #define LOCAL_CLI_SAVE(reg) \
196  mov epsw,reg; \
197  and ~EPSW_IE,epsw; \
198  nop; \
199  nop; \
200  nop
201 
202 #define LOCAL_CLI \
203  and ~EPSW_IE,epsw; \
204  nop; \
205  nop; \
206  nop
207 
208 #define LOCAL_STI \
209  or EPSW_IE,epsw
210 
211 #define LOCAL_CHANGE_INTR_MASK_LEVEL(level) \
212  and ~EPSW_IM,epsw; \
213  or EPSW_IE|(level),epsw
214 
215 #endif /* __ASSEMBLY__ */
216 #endif /* _ASM_IRQFLAGS_H */