1
2
3#ifndef __ASM_CSKY_ATOMIC_H
4#define __ASM_CSKY_ATOMIC_H
5
6#include <linux/version.h>
7#include <asm/cmpxchg.h>
8#include <asm/barrier.h>
9
10#ifdef CONFIG_CPU_HAS_LDSTEX
11
12#define __atomic_add_unless __atomic_add_unless
13static inline int __atomic_add_unless(atomic_t *v, int a, int u)
14{
15 unsigned long tmp, ret;
16
17 smp_mb();
18
19 asm volatile (
20 "1: ldex.w %0, (%3) \n"
21 " mov %1, %0 \n"
22 " cmpne %0, %4 \n"
23 " bf 2f \n"
24 " add %0, %2 \n"
25 " stex.w %0, (%3) \n"
26 " bez %0, 1b \n"
27 "2: \n"
28 : "=&r" (tmp), "=&r" (ret)
29 : "r" (a), "r"(&v->counter), "r"(u)
30 : "memory");
31
32 if (ret != u)
33 smp_mb();
34
35 return ret;
36}
37
38#define ATOMIC_OP(op, c_op) \
39static inline void atomic_##op(int i, atomic_t *v) \
40{ \
41 unsigned long tmp; \
42 \
43 asm volatile ( \
44 "1: ldex.w %0, (%2) \n" \
45 " " #op " %0, %1 \n" \
46 " stex.w %0, (%2) \n" \
47 " bez %0, 1b \n" \
48 : "=&r" (tmp) \
49 : "r" (i), "r"(&v->counter) \
50 : "memory"); \
51}
52
53#define ATOMIC_OP_RETURN(op, c_op) \
54static inline int atomic_##op##_return(int i, atomic_t *v) \
55{ \
56 unsigned long tmp, ret; \
57 \
58 smp_mb(); \
59 asm volatile ( \
60 "1: ldex.w %0, (%3) \n" \
61 " " #op " %0, %2 \n" \
62 " mov %1, %0 \n" \
63 " stex.w %0, (%3) \n" \
64 " bez %0, 1b \n" \
65 : "=&r" (tmp), "=&r" (ret) \
66 : "r" (i), "r"(&v->counter) \
67 : "memory"); \
68 smp_mb(); \
69 \
70 return ret; \
71}
72
73#define ATOMIC_FETCH_OP(op, c_op) \
74static inline int atomic_fetch_##op(int i, atomic_t *v) \
75{ \
76 unsigned long tmp, ret; \
77 \
78 smp_mb(); \
79 asm volatile ( \
80 "1: ldex.w %0, (%3) \n" \
81 " mov %1, %0 \n" \
82 " " #op " %0, %2 \n" \
83 " stex.w %0, (%3) \n" \
84 " bez %0, 1b \n" \
85 : "=&r" (tmp), "=&r" (ret) \
86 : "r" (i), "r"(&v->counter) \
87 : "memory"); \
88 smp_mb(); \
89 \
90 return ret; \
91}
92
93#else
94
95#include <linux/irqflags.h>
96
97#define __atomic_add_unless __atomic_add_unless
98static inline int __atomic_add_unless(atomic_t *v, int a, int u)
99{
100 unsigned long tmp, ret, flags;
101
102 raw_local_irq_save(flags);
103
104 asm volatile (
105 " ldw %0, (%3) \n"
106 " mov %1, %0 \n"
107 " cmpne %0, %4 \n"
108 " bf 2f \n"
109 " add %0, %2 \n"
110 " stw %0, (%3) \n"
111 "2: \n"
112 : "=&r" (tmp), "=&r" (ret)
113 : "r" (a), "r"(&v->counter), "r"(u)
114 : "memory");
115
116 raw_local_irq_restore(flags);
117
118 return ret;
119}
120
121#define ATOMIC_OP(op, c_op) \
122static inline void atomic_##op(int i, atomic_t *v) \
123{ \
124 unsigned long tmp, flags; \
125 \
126 raw_local_irq_save(flags); \
127 \
128 asm volatile ( \
129 " ldw %0, (%2) \n" \
130 " " #op " %0, %1 \n" \
131 " stw %0, (%2) \n" \
132 : "=&r" (tmp) \
133 : "r" (i), "r"(&v->counter) \
134 : "memory"); \
135 \
136 raw_local_irq_restore(flags); \
137}
138
139#define ATOMIC_OP_RETURN(op, c_op) \
140static inline int atomic_##op##_return(int i, atomic_t *v) \
141{ \
142 unsigned long tmp, ret, flags; \
143 \
144 raw_local_irq_save(flags); \
145 \
146 asm volatile ( \
147 " ldw %0, (%3) \n" \
148 " " #op " %0, %2 \n" \
149 " stw %0, (%3) \n" \
150 " mov %1, %0 \n" \
151 : "=&r" (tmp), "=&r" (ret) \
152 : "r" (i), "r"(&v->counter) \
153 : "memory"); \
154 \
155 raw_local_irq_restore(flags); \
156 \
157 return ret; \
158}
159
160#define ATOMIC_FETCH_OP(op, c_op) \
161static inline int atomic_fetch_##op(int i, atomic_t *v) \
162{ \
163 unsigned long tmp, ret, flags; \
164 \
165 raw_local_irq_save(flags); \
166 \
167 asm volatile ( \
168 " ldw %0, (%3) \n" \
169 " mov %1, %0 \n" \
170 " " #op " %0, %2 \n" \
171 " stw %0, (%3) \n" \
172 : "=&r" (tmp), "=&r" (ret) \
173 : "r" (i), "r"(&v->counter) \
174 : "memory"); \
175 \
176 raw_local_irq_restore(flags); \
177 \
178 return ret; \
179}
180
181#endif
182
183#define atomic_add_return atomic_add_return
184ATOMIC_OP_RETURN(add, +)
185#define atomic_sub_return atomic_sub_return
186ATOMIC_OP_RETURN(sub, -)
187
188#define atomic_fetch_add atomic_fetch_add
189ATOMIC_FETCH_OP(add, +)
190#define atomic_fetch_sub atomic_fetch_sub
191ATOMIC_FETCH_OP(sub, -)
192#define atomic_fetch_and atomic_fetch_and
193ATOMIC_FETCH_OP(and, &)
194#define atomic_fetch_or atomic_fetch_or
195ATOMIC_FETCH_OP(or, |)
196#define atomic_fetch_xor atomic_fetch_xor
197ATOMIC_FETCH_OP(xor, ^)
198
199#define atomic_and atomic_and
200ATOMIC_OP(and, &)
201#define atomic_or atomic_or
202ATOMIC_OP(or, |)
203#define atomic_xor atomic_xor
204ATOMIC_OP(xor, ^)
205
206#undef ATOMIC_FETCH_OP
207#undef ATOMIC_OP_RETURN
208#undef ATOMIC_OP
209
210#include <asm-generic/atomic.h>
211
212#endif
213