1
2#ifndef __M32R_LOCAL_H
3#define __M32R_LOCAL_H
4
5
6
7
8
9
10
11
12
13
14#include <linux/percpu.h>
15#include <asm/assembler.h>
16#include <asm/local.h>
17
18
19
20
21
22
23
24
25
26
27
28typedef struct { volatile int counter; } local_t;
29
30#define LOCAL_INIT(i) { (i) }
31
32
33
34
35
36
37
38#define local_read(l) ((l)->counter)
39
40
41
42
43
44
45
46
47#define local_set(l, i) (((l)->counter) = (i))
48
49
50
51
52
53
54
55
56static inline long local_add_return(long i, local_t *l)
57{
58 unsigned long flags;
59 long result;
60
61 local_irq_save(flags);
62 __asm__ __volatile__ (
63 "# local_add_return \n\t"
64 DCACHE_CLEAR("%0", "r4", "%1")
65 "ld %0, @%1; \n\t"
66 "add %0, %2; \n\t"
67 "st %0, @%1; \n\t"
68 : "=&r" (result)
69 : "r" (&l->counter), "r" (i)
70 : "memory"
71#ifdef CONFIG_CHIP_M32700_TS1
72 , "r4"
73#endif
74 );
75 local_irq_restore(flags);
76
77 return result;
78}
79
80
81
82
83
84
85
86
87static inline long local_sub_return(long i, local_t *l)
88{
89 unsigned long flags;
90 long result;
91
92 local_irq_save(flags);
93 __asm__ __volatile__ (
94 "# local_sub_return \n\t"
95 DCACHE_CLEAR("%0", "r4", "%1")
96 "ld %0, @%1; \n\t"
97 "sub %0, %2; \n\t"
98 "st %0, @%1; \n\t"
99 : "=&r" (result)
100 : "r" (&l->counter), "r" (i)
101 : "memory"
102#ifdef CONFIG_CHIP_M32700_TS1
103 , "r4"
104#endif
105 );
106 local_irq_restore(flags);
107
108 return result;
109}
110
111
112
113
114
115
116
117
118#define local_add(i, l) ((void) local_add_return((i), (l)))
119
120
121
122
123
124
125
126
127#define local_sub(i, l) ((void) local_sub_return((i), (l)))
128
129
130
131
132
133
134
135
136
137
138#define local_sub_and_test(i, l) (local_sub_return((i), (l)) == 0)
139
140
141
142
143
144
145
146static inline long local_inc_return(local_t *l)
147{
148 unsigned long flags;
149 long result;
150
151 local_irq_save(flags);
152 __asm__ __volatile__ (
153 "# local_inc_return \n\t"
154 DCACHE_CLEAR("%0", "r4", "%1")
155 "ld %0, @%1; \n\t"
156 "addi %0, #1; \n\t"
157 "st %0, @%1; \n\t"
158 : "=&r" (result)
159 : "r" (&l->counter)
160 : "memory"
161#ifdef CONFIG_CHIP_M32700_TS1
162 , "r4"
163#endif
164 );
165 local_irq_restore(flags);
166
167 return result;
168}
169
170
171
172
173
174
175
176static inline long local_dec_return(local_t *l)
177{
178 unsigned long flags;
179 long result;
180
181 local_irq_save(flags);
182 __asm__ __volatile__ (
183 "# local_dec_return \n\t"
184 DCACHE_CLEAR("%0", "r4", "%1")
185 "ld %0, @%1; \n\t"
186 "addi %0, #-1; \n\t"
187 "st %0, @%1; \n\t"
188 : "=&r" (result)
189 : "r" (&l->counter)
190 : "memory"
191#ifdef CONFIG_CHIP_M32700_TS1
192 , "r4"
193#endif
194 );
195 local_irq_restore(flags);
196
197 return result;
198}
199
200
201
202
203
204
205
206#define local_inc(l) ((void)local_inc_return(l))
207
208
209
210
211
212
213
214#define local_dec(l) ((void)local_dec_return(l))
215
216
217
218
219
220
221
222
223
224#define local_inc_and_test(l) (local_inc_return(l) == 0)
225
226
227
228
229
230
231
232
233
234#define local_dec_and_test(l) (local_dec_return(l) == 0)
235
236
237
238
239
240
241
242
243
244
245#define local_add_negative(i, l) (local_add_return((i), (l)) < 0)
246
247#define local_cmpxchg(l, o, n) (cmpxchg_local(&((l)->counter), (o), (n)))
248#define local_xchg(v, new) (xchg_local(&((l)->counter), new))
249
250
251
252
253
254
255
256
257
258
259static inline int local_add_unless(local_t *l, long a, long u)
260{
261 long c, old;
262 c = local_read(l);
263 for (;;) {
264 if (unlikely(c == (u)))
265 break;
266 old = local_cmpxchg((l), c, c + (a));
267 if (likely(old == c))
268 break;
269 c = old;
270 }
271 return c != (u);
272}
273
274#define local_inc_not_zero(l) local_add_unless((l), 1, 0)
275
276static inline void local_clear_mask(unsigned long mask, local_t *addr)
277{
278 unsigned long flags;
279 unsigned long tmp;
280
281 local_irq_save(flags);
282 __asm__ __volatile__ (
283 "# local_clear_mask \n\t"
284 DCACHE_CLEAR("%0", "r5", "%1")
285 "ld %0, @%1; \n\t"
286 "and %0, %2; \n\t"
287 "st %0, @%1; \n\t"
288 : "=&r" (tmp)
289 : "r" (addr), "r" (~mask)
290 : "memory"
291#ifdef CONFIG_CHIP_M32700_TS1
292 , "r5"
293#endif
294 );
295 local_irq_restore(flags);
296}
297
298static inline void local_set_mask(unsigned long mask, local_t *addr)
299{
300 unsigned long flags;
301 unsigned long tmp;
302
303 local_irq_save(flags);
304 __asm__ __volatile__ (
305 "# local_set_mask \n\t"
306 DCACHE_CLEAR("%0", "r5", "%1")
307 "ld %0, @%1; \n\t"
308 "or %0, %2; \n\t"
309 "st %0, @%1; \n\t"
310 : "=&r" (tmp)
311 : "r" (addr), "r" (mask)
312 : "memory"
313#ifdef CONFIG_CHIP_M32700_TS1
314 , "r5"
315#endif
316 );
317 local_irq_restore(flags);
318}
319
320
321#define smp_mb__before_local_dec() barrier()
322#define smp_mb__after_local_dec() barrier()
323#define smp_mb__before_local_inc() barrier()
324#define smp_mb__after_local_inc() barrier()
325
326
327
328
329
330
331#define __local_inc(l) ((l)->a.counter++)
332#define __local_dec(l) ((l)->a.counter++)
333#define __local_add(i, l) ((l)->a.counter += (i))
334#define __local_sub(i, l) ((l)->a.counter -= (i))
335
336
337
338
339
340
341#endif
342