]>
Commit | Line | Data |
---|---|---|
b920de1b DH |
1 | /* MN10300 System definitions |
2 | * | |
3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | |
4 | * Written by David Howells (dhowells@redhat.com) | |
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 | #ifndef _ASM_SYSTEM_H | |
12 | #define _ASM_SYSTEM_H | |
13 | ||
14 | #include <asm/cpu-regs.h> | |
15 | ||
16 | #ifdef __KERNEL__ | |
17 | #ifndef __ASSEMBLY__ | |
18 | ||
19 | #include <linux/kernel.h> | |
20 | ||
21 | struct task_struct; | |
22 | struct thread_struct; | |
23 | ||
24 | extern asmlinkage | |
25 | struct task_struct *__switch_to(struct thread_struct *prev, | |
26 | struct thread_struct *next, | |
27 | struct task_struct *prev_task); | |
28 | ||
29 | /* context switching is now performed out-of-line in switch_to.S */ | |
30 | #define switch_to(prev, next, last) \ | |
31 | do { \ | |
32 | current->thread.wchan = (u_long) __builtin_return_address(0); \ | |
33 | (last) = __switch_to(&(prev)->thread, &(next)->thread, (prev)); \ | |
34 | mb(); \ | |
35 | current->thread.wchan = 0; \ | |
36 | } while (0) | |
37 | ||
38 | #define arch_align_stack(x) (x) | |
39 | ||
40 | #define nop() asm volatile ("nop") | |
41 | ||
42 | #endif /* !__ASSEMBLY__ */ | |
43 | ||
44 | /* | |
45 | * Force strict CPU ordering. | |
46 | * And yes, this is required on UP too when we're talking | |
47 | * to devices. | |
48 | * | |
49 | * For now, "wmb()" doesn't actually do anything, as all | |
50 | * Intel CPU's follow what Intel calls a *Processor Order*, | |
51 | * in which all writes are seen in the program order even | |
52 | * outside the CPU. | |
53 | * | |
54 | * I expect future Intel CPU's to have a weaker ordering, | |
55 | * but I'd also expect them to finally get their act together | |
56 | * and add some real memory barriers if so. | |
57 | * | |
58 | * Some non intel clones support out of order store. wmb() ceases to be a | |
59 | * nop for these. | |
60 | */ | |
61 | ||
62 | #define mb() asm volatile ("": : :"memory") | |
63 | #define rmb() mb() | |
64 | #define wmb() asm volatile ("": : :"memory") | |
65 | ||
66 | #ifdef CONFIG_SMP | |
67 | #define smp_mb() mb() | |
68 | #define smp_rmb() rmb() | |
69 | #define smp_wmb() wmb() | |
70 | #else | |
71 | #define smp_mb() barrier() | |
72 | #define smp_rmb() barrier() | |
73 | #define smp_wmb() barrier() | |
74 | #endif | |
75 | ||
76 | #define set_mb(var, value) do { var = value; mb(); } while (0) | |
77 | #define set_wmb(var, value) do { var = value; wmb(); } while (0) | |
78 | ||
79 | #define read_barrier_depends() do {} while (0) | |
80 | #define smp_read_barrier_depends() do {} while (0) | |
81 | ||
82 | /*****************************************************************************/ | |
83 | /* | |
84 | * interrupt control | |
85 | * - "disabled": run in IM1/2 | |
86 | * - level 0 - GDB stub | |
87 | * - level 1 - virtual serial DMA (if present) | |
88 | * - level 5 - normal interrupt priority | |
89 | * - level 6 - timer interrupt | |
90 | * - "enabled": run in IM7 | |
91 | */ | |
92 | #ifdef CONFIG_MN10300_TTYSM | |
93 | #define MN10300_CLI_LEVEL EPSW_IM_2 | |
94 | #else | |
95 | #define MN10300_CLI_LEVEL EPSW_IM_1 | |
96 | #endif | |
97 | ||
98 | #define local_save_flags(x) \ | |
99 | do { \ | |
100 | typecheck(unsigned long, x); \ | |
101 | asm volatile( \ | |
102 | " mov epsw,%0 \n" \ | |
103 | : "=d"(x) \ | |
104 | ); \ | |
105 | } while (0) | |
106 | ||
107 | #define local_irq_disable() \ | |
108 | do { \ | |
109 | asm volatile( \ | |
110 | " and %0,epsw \n" \ | |
111 | " or %1,epsw \n" \ | |
112 | " nop \n" \ | |
113 | " nop \n" \ | |
114 | " nop \n" \ | |
115 | : \ | |
116 | : "i"(~EPSW_IM), "i"(EPSW_IE | MN10300_CLI_LEVEL) \ | |
117 | ); \ | |
118 | } while (0) | |
119 | ||
120 | #define local_irq_save(x) \ | |
121 | do { \ | |
122 | local_save_flags(x); \ | |
123 | local_irq_disable(); \ | |
124 | } while (0) | |
125 | ||
126 | /* | |
127 | * we make sure local_irq_enable() doesn't cause priority inversion | |
128 | */ | |
129 | #ifndef __ASSEMBLY__ | |
130 | ||
131 | extern unsigned long __mn10300_irq_enabled_epsw; | |
132 | ||
133 | #endif | |
134 | ||
135 | #define local_irq_enable() \ | |
136 | do { \ | |
137 | unsigned long tmp; \ | |
138 | \ | |
139 | asm volatile( \ | |
140 | " mov epsw,%0 \n" \ | |
141 | " and %1,%0 \n" \ | |
142 | " or %2,%0 \n" \ | |
143 | " mov %0,epsw \n" \ | |
144 | : "=&d"(tmp) \ | |
145 | : "i"(~EPSW_IM), "r"(__mn10300_irq_enabled_epsw) \ | |
146 | ); \ | |
147 | } while (0) | |
148 | ||
149 | #define local_irq_restore(x) \ | |
150 | do { \ | |
151 | typecheck(unsigned long, x); \ | |
152 | asm volatile( \ | |
153 | " mov %0,epsw \n" \ | |
154 | " nop \n" \ | |
155 | " nop \n" \ | |
156 | " nop \n" \ | |
157 | : \ | |
158 | : "d"(x) \ | |
159 | : "memory", "cc" \ | |
160 | ); \ | |
161 | } while (0) | |
162 | ||
163 | #define irqs_disabled() \ | |
164 | ({ \ | |
165 | unsigned long flags; \ | |
166 | local_save_flags(flags); \ | |
167 | (flags & EPSW_IM) <= MN10300_CLI_LEVEL; \ | |
168 | }) | |
169 | ||
170 | /* hook to save power by halting the CPU | |
171 | * - called from the idle loop | |
172 | * - must reenable interrupts (which takes three instruction cycles to complete) | |
173 | */ | |
174 | #define safe_halt() \ | |
175 | do { \ | |
176 | asm volatile(" or %0,epsw \n" \ | |
177 | " nop \n" \ | |
178 | " nop \n" \ | |
179 | " bset %2,(%1) \n" \ | |
180 | : \ | |
181 | : "i"(EPSW_IE|EPSW_IM), "n"(&CPUM), "i"(CPUM_SLEEP)\ | |
182 | : "cc" \ | |
183 | ); \ | |
184 | } while (0) | |
185 | ||
186 | #define STI or EPSW_IE|EPSW_IM,epsw | |
187 | #define CLI and ~EPSW_IM,epsw; or EPSW_IE|MN10300_CLI_LEVEL,epsw; nop; nop; nop | |
188 | ||
189 | /*****************************************************************************/ | |
190 | /* | |
191 | * MN10300 doesn't actually have an exchange instruction | |
192 | */ | |
193 | #ifndef __ASSEMBLY__ | |
194 | ||
195 | struct __xchg_dummy { unsigned long a[100]; }; | |
196 | #define __xg(x) ((struct __xchg_dummy *)(x)) | |
197 | ||
198 | static inline | |
199 | unsigned long __xchg(volatile unsigned long *m, unsigned long val) | |
200 | { | |
201 | unsigned long retval; | |
202 | unsigned long flags; | |
203 | ||
204 | local_irq_save(flags); | |
205 | retval = *m; | |
206 | *m = val; | |
207 | local_irq_restore(flags); | |
208 | return retval; | |
209 | } | |
210 | ||
211 | #define xchg(ptr, v) \ | |
212 | ((__typeof__(*(ptr))) __xchg((unsigned long *)(ptr), \ | |
213 | (unsigned long)(v))) | |
214 | ||
215 | static inline unsigned long __cmpxchg(volatile unsigned long *m, | |
216 | unsigned long old, unsigned long new) | |
217 | { | |
218 | unsigned long retval; | |
219 | unsigned long flags; | |
220 | ||
221 | local_irq_save(flags); | |
222 | retval = *m; | |
223 | if (retval == old) | |
224 | *m = new; | |
225 | local_irq_restore(flags); | |
226 | return retval; | |
227 | } | |
228 | ||
229 | #define cmpxchg(ptr, o, n) \ | |
230 | ((__typeof__(*(ptr))) __cmpxchg((unsigned long *)(ptr), \ | |
231 | (unsigned long)(o), \ | |
232 | (unsigned long)(n))) | |
233 | ||
234 | #endif /* !__ASSEMBLY__ */ | |
235 | ||
236 | #endif /* __KERNEL__ */ | |
237 | #endif /* _ASM_SYSTEM_H */ |