1#ifndef _ASM_M32R_SYSTEM_H
2#define _ASM_M32R_SYSTEM_H
3
4
5
6
7
8
9
10
11
12
13#include <linux/compiler.h>
14#include <asm/assembler.h>
15
16#ifdef __KERNEL__
17
18
19
20
21
22
23
24
25#if defined(CONFIG_FRAME_POINTER) || \
26 !defined(CONFIG_SCHED_OMIT_FRAME_POINTER)
27#define M32R_PUSH_FP " push fp\n"
28#define M32R_POP_FP " pop fp\n"
29#else
30#define M32R_PUSH_FP ""
31#define M32R_POP_FP ""
32#endif
33
34#define switch_to(prev, next, last) do { \
35 __asm__ __volatile__ ( \
36 " seth lr, #high(1f) \n" \
37 " or3 lr, lr, #low(1f) \n" \
38 " st lr, @%4 ; store old LR \n" \
39 " ld lr, @%5 ; load new LR \n" \
40 M32R_PUSH_FP \
41 " st sp, @%2 ; store old SP \n" \
42 " ld sp, @%3 ; load new SP \n" \
43 " push %1 ; store `prev' on new stack \n" \
44 " jmp lr \n" \
45 " .fillinsn \n" \
46 "1: \n" \
47 " pop %0 ; restore `__last' from new stack \n" \
48 M32R_POP_FP \
49 : "=r" (last) \
50 : "0" (prev), \
51 "r" (&(prev->thread.sp)), "r" (&(next->thread.sp)), \
52 "r" (&(prev->thread.lr)), "r" (&(next->thread.lr)) \
53 : "memory", "lr" \
54 ); \
55} while(0)
56
57
58#if !defined(CONFIG_CHIP_M32102) && !defined(CONFIG_CHIP_M32104)
59#define local_irq_enable() \
60 __asm__ __volatile__ ("setpsw #0x40 -> nop": : :"memory")
61#define local_irq_disable() \
62 __asm__ __volatile__ ("clrpsw #0x40 -> nop": : :"memory")
63#else
64static inline void local_irq_enable(void)
65{
66 unsigned long tmpreg;
67 __asm__ __volatile__(
68 "mvfc %0, psw; \n\t"
69 "or3 %0, %0, #0x0040; \n\t"
70 "mvtc %0, psw; \n\t"
71 : "=&r" (tmpreg) : : "cbit", "memory");
72}
73
74static inline void local_irq_disable(void)
75{
76 unsigned long tmpreg0, tmpreg1;
77 __asm__ __volatile__(
78 "ld24 %0, #0 ; Use 32-bit insn. \n\t"
79 "mvfc %1, psw ; No interrupt can be accepted here. \n\t"
80 "mvtc %0, psw \n\t"
81 "and3 %0, %1, #0xffbf \n\t"
82 "mvtc %0, psw \n\t"
83 : "=&r" (tmpreg0), "=&r" (tmpreg1) : : "cbit", "memory");
84}
85#endif
86
87#define local_save_flags(x) \
88 __asm__ __volatile__("mvfc %0,psw" : "=r"(x) : )
89
90#define local_irq_restore(x) \
91 __asm__ __volatile__("mvtc %0,psw" : \
92 : "r" (x) : "cbit", "memory")
93
94#if !(defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_M32104))
95#define local_irq_save(x) \
96 __asm__ __volatile__( \
97 "mvfc %0, psw; \n\t" \
98 "clrpsw #0x40 -> nop; \n\t" \
99 : "=r" (x) : : "memory")
100#else
101#define local_irq_save(x) \
102 ({ \
103 unsigned long tmpreg; \
104 __asm__ __volatile__( \
105 "ld24 %1, #0 \n\t" \
106 "mvfc %0, psw \n\t" \
107 "mvtc %1, psw \n\t" \
108 "and3 %1, %0, #0xffbf \n\t" \
109 "mvtc %1, psw \n\t" \
110 : "=r" (x), "=&r" (tmpreg) \
111 : : "cbit", "memory"); \
112 })
113#endif
114
115#define irqs_disabled() \
116 ({ \
117 unsigned long flags; \
118 local_save_flags(flags); \
119 !(flags & 0x40); \
120 })
121
122#define nop() __asm__ __volatile__ ("nop" : : )
123
124#define xchg(ptr, x) \
125 ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
126#define xchg_local(ptr, x) \
127 ((__typeof__(*(ptr)))__xchg_local((unsigned long)(x), (ptr), \
128 sizeof(*(ptr))))
129
130extern void __xchg_called_with_bad_pointer(void);
131
132#ifdef CONFIG_CHIP_M32700_TS1
133#define DCACHE_CLEAR(reg0, reg1, addr) \
134 "seth "reg1", #high(dcache_dummy); \n\t" \
135 "or3 "reg1", "reg1", #low(dcache_dummy); \n\t" \
136 "lock "reg0", @"reg1"; \n\t" \
137 "add3 "reg0", "addr", #0x1000; \n\t" \
138 "ld "reg0", @"reg0"; \n\t" \
139 "add3 "reg0", "addr", #0x2000; \n\t" \
140 "ld "reg0", @"reg0"; \n\t" \
141 "unlock "reg0", @"reg1"; \n\t"
142
143
144
145#else
146#define DCACHE_CLEAR(reg0, reg1, addr)
147#endif
148
149static __always_inline unsigned long
150__xchg(unsigned long x, volatile void *ptr, int size)
151{
152 unsigned long flags;
153 unsigned long tmp = 0;
154
155 local_irq_save(flags);
156
157 switch (size) {
158#ifndef CONFIG_SMP
159 case 1:
160 __asm__ __volatile__ (
161 "ldb %0, @%2 \n\t"
162 "stb %1, @%2 \n\t"
163 : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
164 break;
165 case 2:
166 __asm__ __volatile__ (
167 "ldh %0, @%2 \n\t"
168 "sth %1, @%2 \n\t"
169 : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
170 break;
171 case 4:
172 __asm__ __volatile__ (
173 "ld %0, @%2 \n\t"
174 "st %1, @%2 \n\t"
175 : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
176 break;
177#else
178 case 4:
179 __asm__ __volatile__ (
180 DCACHE_CLEAR("%0", "r4", "%2")
181 "lock %0, @%2; \n\t"
182 "unlock %1, @%2; \n\t"
183 : "=&r" (tmp) : "r" (x), "r" (ptr)
184 : "memory"
185#ifdef CONFIG_CHIP_M32700_TS1
186 , "r4"
187#endif
188 );
189 break;
190#endif
191 default:
192 __xchg_called_with_bad_pointer();
193 }
194
195 local_irq_restore(flags);
196
197 return (tmp);
198}
199
200static __always_inline unsigned long
201__xchg_local(unsigned long x, volatile void *ptr, int size)
202{
203 unsigned long flags;
204 unsigned long tmp = 0;
205
206 local_irq_save(flags);
207
208 switch (size) {
209 case 1:
210 __asm__ __volatile__ (
211 "ldb %0, @%2 \n\t"
212 "stb %1, @%2 \n\t"
213 : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
214 break;
215 case 2:
216 __asm__ __volatile__ (
217 "ldh %0, @%2 \n\t"
218 "sth %1, @%2 \n\t"
219 : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
220 break;
221 case 4:
222 __asm__ __volatile__ (
223 "ld %0, @%2 \n\t"
224 "st %1, @%2 \n\t"
225 : "=&r" (tmp) : "r" (x), "r" (ptr) : "memory");
226 break;
227 default:
228 __xchg_called_with_bad_pointer();
229 }
230
231 local_irq_restore(flags);
232
233 return (tmp);
234}
235
236#define __HAVE_ARCH_CMPXCHG 1
237
238static inline unsigned long
239__cmpxchg_u32(volatile unsigned int *p, unsigned int old, unsigned int new)
240{
241 unsigned long flags;
242 unsigned int retval;
243
244 local_irq_save(flags);
245 __asm__ __volatile__ (
246 DCACHE_CLEAR("%0", "r4", "%1")
247 M32R_LOCK" %0, @%1; \n"
248 " bne %0, %2, 1f; \n"
249 M32R_UNLOCK" %3, @%1; \n"
250 " bra 2f; \n"
251 " .fillinsn \n"
252 "1:"
253 M32R_UNLOCK" %0, @%1; \n"
254 " .fillinsn \n"
255 "2:"
256 : "=&r" (retval)
257 : "r" (p), "r" (old), "r" (new)
258 : "cbit", "memory"
259#ifdef CONFIG_CHIP_M32700_TS1
260 , "r4"
261#endif
262 );
263 local_irq_restore(flags);
264
265 return retval;
266}
267
268static inline unsigned long
269__cmpxchg_local_u32(volatile unsigned int *p, unsigned int old,
270 unsigned int new)
271{
272 unsigned long flags;
273 unsigned int retval;
274
275 local_irq_save(flags);
276 __asm__ __volatile__ (
277 DCACHE_CLEAR("%0", "r4", "%1")
278 "ld %0, @%1; \n"
279 " bne %0, %2, 1f; \n"
280 "st %3, @%1; \n"
281 " bra 2f; \n"
282 " .fillinsn \n"
283 "1:"
284 "st %0, @%1; \n"
285 " .fillinsn \n"
286 "2:"
287 : "=&r" (retval)
288 : "r" (p), "r" (old), "r" (new)
289 : "cbit", "memory"
290#ifdef CONFIG_CHIP_M32700_TS1
291 , "r4"
292#endif
293 );
294 local_irq_restore(flags);
295
296 return retval;
297}
298
299
300
301extern void __cmpxchg_called_with_bad_pointer(void);
302
303static inline unsigned long
304__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
305{
306 switch (size) {
307 case 4:
308 return __cmpxchg_u32(ptr, old, new);
309#if 0
310 case 8:
311 return __cmpxchg_u64(ptr, old, new);
312#endif
313 }
314 __cmpxchg_called_with_bad_pointer();
315 return old;
316}
317
318#define cmpxchg(ptr, o, n) \
319 ((__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)(o), \
320 (unsigned long)(n), sizeof(*(ptr))))
321
322#include <asm-generic/cmpxchg-local.h>
323
324static inline unsigned long __cmpxchg_local(volatile void *ptr,
325 unsigned long old,
326 unsigned long new, int size)
327{
328 switch (size) {
329 case 4:
330 return __cmpxchg_local_u32(ptr, old, new);
331 default:
332 return __cmpxchg_local_generic(ptr, old, new, size);
333 }
334
335 return old;
336}
337
338
339
340
341
342#define cmpxchg_local(ptr, o, n) \
343 ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \
344 (unsigned long)(n), sizeof(*(ptr))))
345#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
346
347#endif
348
349
350
351
352
353
354
355
356#define mb() barrier()
357#define rmb() mb()
358#define wmb() mb()
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413#define read_barrier_depends() do { } while (0)
414
415#ifdef CONFIG_SMP
416#define smp_mb() mb()
417#define smp_rmb() rmb()
418#define smp_wmb() wmb()
419#define smp_read_barrier_depends() read_barrier_depends()
420#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
421#else
422#define smp_mb() barrier()
423#define smp_rmb() barrier()
424#define smp_wmb() barrier()
425#define smp_read_barrier_depends() do { } while (0)
426#define set_mb(var, value) do { var = value; barrier(); } while (0)
427#endif
428
429#define arch_align_stack(x) (x)
430
431#endif
432