1#ifndef _ASM_M32R_SPINLOCK_H
2#define _ASM_M32R_SPINLOCK_H
3
4
5
6
7
8
9
10
11
12#include <linux/config.h>
13#include <linux/compiler.h>
14#include <asm/atomic.h>
15#include <asm/page.h>
16
17extern int printk(const char * fmt, ...)
18 __attribute__ ((format (printf, 1, 2)));
19
20#define RW_LOCK_BIAS 0x01000000
21#define RW_LOCK_BIAS_STR "0x01000000"
22
23
24
25
26
27typedef struct {
28 volatile int slock;
29#ifdef CONFIG_DEBUG_SPINLOCK
30 unsigned magic;
31#endif
32#ifdef CONFIG_PREEMPT
33 unsigned int break_lock;
34#endif
35} spinlock_t;
36
37#define SPINLOCK_MAGIC 0xdead4ead
38
39#ifdef CONFIG_DEBUG_SPINLOCK
40#define SPINLOCK_MAGIC_INIT , SPINLOCK_MAGIC
41#else
42#define SPINLOCK_MAGIC_INIT
43#endif
44
45#define SPIN_LOCK_UNLOCKED (spinlock_t) { 1 SPINLOCK_MAGIC_INIT }
46
47#define spin_lock_init(x) do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
48
49
50
51
52
53
54
55
56#define spin_is_locked(x) (*(volatile int *)(&(x)->slock) <= 0)
57#define spin_unlock_wait(x) do { barrier(); } while(spin_is_locked(x))
58#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
59
60
61
62
63
64
65
66
67static inline int _raw_spin_trylock(spinlock_t *lock)
68{
69 int oldval;
70 unsigned long tmp1, tmp2;
71
72
73
74
75
76
77
78
79
80 __asm__ __volatile__ (
81 "# spin_trylock \n\t"
82 "ldi %1, #0; \n\t"
83 "mvfc %2, psw; \n\t"
84 "clrpsw #0x40 -> nop; \n\t"
85 DCACHE_CLEAR("%0", "r6", "%3")
86 "lock %0, @%3; \n\t"
87 "unlock %1, @%3; \n\t"
88 "mvtc %2, psw; \n\t"
89 : "=&r" (oldval), "=&r" (tmp1), "=&r" (tmp2)
90 : "r" (&lock->slock)
91 : "memory"
92#ifdef CONFIG_CHIP_M32700_TS1
93 , "r6"
94#endif
95 );
96
97 return (oldval > 0);
98}
99
100static inline void _raw_spin_lock(spinlock_t *lock)
101{
102 unsigned long tmp0, tmp1;
103
104#ifdef CONFIG_DEBUG_SPINLOCK
105 __label__ here;
106here:
107 if (lock->magic != SPINLOCK_MAGIC) {
108 printk("pc: %p\n", &&here);
109 BUG();
110 }
111#endif
112
113
114
115
116
117
118
119
120
121
122 __asm__ __volatile__ (
123 "# spin_lock \n\t"
124 ".fillinsn \n"
125 "1: \n\t"
126 "mvfc %1, psw; \n\t"
127 "clrpsw #0x40 -> nop; \n\t"
128 DCACHE_CLEAR("%0", "r6", "%2")
129 "lock %0, @%2; \n\t"
130 "addi %0, #-1; \n\t"
131 "unlock %0, @%2; \n\t"
132 "mvtc %1, psw; \n\t"
133 "bltz %0, 2f; \n\t"
134 LOCK_SECTION_START(".balign 4 \n\t")
135 ".fillinsn \n"
136 "2: \n\t"
137 "ld %0, @%2; \n\t"
138 "bgtz %0, 1b; \n\t"
139 "bra 2b; \n\t"
140 LOCK_SECTION_END
141 : "=&r" (tmp0), "=&r" (tmp1)
142 : "r" (&lock->slock)
143 : "memory"
144#ifdef CONFIG_CHIP_M32700_TS1
145 , "r6"
146#endif
147 );
148}
149
150static inline void _raw_spin_unlock(spinlock_t *lock)
151{
152#ifdef CONFIG_DEBUG_SPINLOCK
153 BUG_ON(lock->magic != SPINLOCK_MAGIC);
154 BUG_ON(!spin_is_locked(lock));
155#endif
156 mb();
157 lock->slock = 1;
158}
159
160
161
162
163
164
165
166
167
168
169
170typedef struct {
171 volatile int lock;
172#ifdef CONFIG_DEBUG_SPINLOCK
173 unsigned magic;
174#endif
175#ifdef CONFIG_PREEMPT
176 unsigned int break_lock;
177#endif
178} rwlock_t;
179
180#define RWLOCK_MAGIC 0xdeaf1eed
181
182#ifdef CONFIG_DEBUG_SPINLOCK
183#define RWLOCK_MAGIC_INIT , RWLOCK_MAGIC
184#else
185#define RWLOCK_MAGIC_INIT
186#endif
187
188#define RW_LOCK_UNLOCKED (rwlock_t) { RW_LOCK_BIAS RWLOCK_MAGIC_INIT }
189
190#define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0)
191
192
193
194
195
196#define read_can_lock(x) ((int)(x)->lock > 0)
197
198
199
200
201
202#define write_can_lock(x) ((x)->lock == RW_LOCK_BIAS)
203
204
205
206
207
208
209
210
211
212
213
214
215static inline void _raw_read_lock(rwlock_t *rw)
216{
217 unsigned long tmp0, tmp1;
218
219#ifdef CONFIG_DEBUG_SPINLOCK
220 BUG_ON(rw->magic != RWLOCK_MAGIC);
221#endif
222
223
224
225
226
227
228
229
230
231
232
233 __asm__ __volatile__ (
234 "# read_lock \n\t"
235 ".fillinsn \n"
236 "1: \n\t"
237 "mvfc %1, psw; \n\t"
238 "clrpsw #0x40 -> nop; \n\t"
239 DCACHE_CLEAR("%0", "r6", "%2")
240 "lock %0, @%2; \n\t"
241 "addi %0, #-1; \n\t"
242 "unlock %0, @%2; \n\t"
243 "mvtc %1, psw; \n\t"
244 "bltz %0, 2f; \n\t"
245 LOCK_SECTION_START(".balign 4 \n\t")
246 ".fillinsn \n"
247 "2: \n\t"
248 "clrpsw #0x40 -> nop; \n\t"
249 DCACHE_CLEAR("%0", "r6", "%2")
250 "lock %0, @%2; \n\t"
251 "addi %0, #1; \n\t"
252 "unlock %0, @%2; \n\t"
253 "mvtc %1, psw; \n\t"
254 ".fillinsn \n"
255 "3: \n\t"
256 "ld %0, @%2; \n\t"
257 "bgtz %0, 1b; \n\t"
258 "bra 3b; \n\t"
259 LOCK_SECTION_END
260 : "=&r" (tmp0), "=&r" (tmp1)
261 : "r" (&rw->lock)
262 : "memory"
263#ifdef CONFIG_CHIP_M32700_TS1
264 , "r6"
265#endif
266 );
267}
268
269static inline void _raw_write_lock(rwlock_t *rw)
270{
271 unsigned long tmp0, tmp1, tmp2;
272
273#ifdef CONFIG_DEBUG_SPINLOCK
274 BUG_ON(rw->magic != RWLOCK_MAGIC);
275#endif
276
277
278
279
280
281
282
283
284
285
286
287 __asm__ __volatile__ (
288 "# write_lock \n\t"
289 "seth %1, #high(" RW_LOCK_BIAS_STR "); \n\t"
290 "or3 %1, %1, #low(" RW_LOCK_BIAS_STR "); \n\t"
291 ".fillinsn \n"
292 "1: \n\t"
293 "mvfc %2, psw; \n\t"
294 "clrpsw #0x40 -> nop; \n\t"
295 DCACHE_CLEAR("%0", "r7", "%3")
296 "lock %0, @%3; \n\t"
297 "sub %0, %1; \n\t"
298 "unlock %0, @%3; \n\t"
299 "mvtc %2, psw; \n\t"
300 "bnez %0, 2f; \n\t"
301 LOCK_SECTION_START(".balign 4 \n\t")
302 ".fillinsn \n"
303 "2: \n\t"
304 "clrpsw #0x40 -> nop; \n\t"
305 DCACHE_CLEAR("%0", "r7", "%3")
306 "lock %0, @%3; \n\t"
307 "add %0, %1; \n\t"
308 "unlock %0, @%3; \n\t"
309 "mvtc %2, psw; \n\t"
310 ".fillinsn \n"
311 "3: \n\t"
312 "ld %0, @%3; \n\t"
313 "beq %0, %1, 1b; \n\t"
314 "bra 3b; \n\t"
315 LOCK_SECTION_END
316 : "=&r" (tmp0), "=&r" (tmp1), "=&r" (tmp2)
317 : "r" (&rw->lock)
318 : "memory"
319#ifdef CONFIG_CHIP_M32700_TS1
320 , "r7"
321#endif
322 );
323}
324
325static inline void _raw_read_unlock(rwlock_t *rw)
326{
327 unsigned long tmp0, tmp1;
328
329 __asm__ __volatile__ (
330 "# read_unlock \n\t"
331 "mvfc %1, psw; \n\t"
332 "clrpsw #0x40 -> nop; \n\t"
333 DCACHE_CLEAR("%0", "r6", "%2")
334 "lock %0, @%2; \n\t"
335 "addi %0, #1; \n\t"
336 "unlock %0, @%2; \n\t"
337 "mvtc %1, psw; \n\t"
338 : "=&r" (tmp0), "=&r" (tmp1)
339 : "r" (&rw->lock)
340 : "memory"
341#ifdef CONFIG_CHIP_M32700_TS1
342 , "r6"
343#endif
344 );
345}
346
347static inline void _raw_write_unlock(rwlock_t *rw)
348{
349 unsigned long tmp0, tmp1, tmp2;
350
351 __asm__ __volatile__ (
352 "# write_unlock \n\t"
353 "seth %1, #high(" RW_LOCK_BIAS_STR "); \n\t"
354 "or3 %1, %1, #low(" RW_LOCK_BIAS_STR "); \n\t"
355 "mvfc %2, psw; \n\t"
356 "clrpsw #0x40 -> nop; \n\t"
357 DCACHE_CLEAR("%0", "r7", "%3")
358 "lock %0, @%3; \n\t"
359 "add %0, %1; \n\t"
360 "unlock %0, @%3; \n\t"
361 "mvtc %2, psw; \n\t"
362 : "=&r" (tmp0), "=&r" (tmp1), "=&r" (tmp2)
363 : "r" (&rw->lock)
364 : "memory"
365#ifdef CONFIG_CHIP_M32700_TS1
366 , "r7"
367#endif
368 );
369}
370
371#define _raw_read_trylock(lock) generic_raw_read_trylock(lock)
372
373static inline int _raw_write_trylock(rwlock_t *lock)
374{
375 atomic_t *count = (atomic_t *)lock;
376 if (atomic_sub_and_test(RW_LOCK_BIAS, count))
377 return 1;
378 atomic_add(RW_LOCK_BIAS, count);
379 return 0;
380}
381
382#endif
383