]>
Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
6006c0d8 JH |
2 | #ifndef __ASM_METAG_ATOMIC_LNKGET_H |
3 | #define __ASM_METAG_ATOMIC_LNKGET_H | |
4 | ||
5 | #define ATOMIC_INIT(i) { (i) } | |
6 | ||
62e8a325 | 7 | #define atomic_set(v, i) WRITE_ONCE((v)->counter, (i)) |
6006c0d8 JH |
8 | |
9 | #include <linux/compiler.h> | |
10 | ||
11 | #include <asm/barrier.h> | |
12 | ||
13 | /* | |
14 | * None of these asm statements clobber memory as LNKSET writes around | |
15 | * the cache so the memory it modifies cannot safely be read by any means | |
16 | * other than these accessors. | |
17 | */ | |
18 | ||
19 | static inline int atomic_read(const atomic_t *v) | |
20 | { | |
21 | int temp; | |
22 | ||
23 | asm volatile ( | |
24 | "LNKGETD %0, [%1]\n" | |
25 | : "=da" (temp) | |
26 | : "da" (&v->counter)); | |
27 | ||
28 | return temp; | |
29 | } | |
30 | ||
d6dfe250 PZ |
31 | #define ATOMIC_OP(op) \ |
32 | static inline void atomic_##op(int i, atomic_t *v) \ | |
33 | { \ | |
34 | int temp; \ | |
35 | \ | |
36 | asm volatile ( \ | |
37 | "1: LNKGETD %0, [%1]\n" \ | |
38 | " " #op " %0, %0, %2\n" \ | |
39 | " LNKSETD [%1], %0\n" \ | |
40 | " DEFR %0, TXSTAT\n" \ | |
41 | " ANDT %0, %0, #HI(0x3f000000)\n" \ | |
42 | " CMPT %0, #HI(0x02000000)\n" \ | |
43 | " BNZ 1b\n" \ | |
44 | : "=&d" (temp) \ | |
45 | : "da" (&v->counter), "bd" (i) \ | |
46 | : "cc"); \ | |
47 | } \ | |
48 | ||
49 | #define ATOMIC_OP_RETURN(op) \ | |
50 | static inline int atomic_##op##_return(int i, atomic_t *v) \ | |
51 | { \ | |
52 | int result, temp; \ | |
53 | \ | |
54 | smp_mb(); \ | |
55 | \ | |
56 | asm volatile ( \ | |
57 | "1: LNKGETD %1, [%2]\n" \ | |
58 | " " #op " %1, %1, %3\n" \ | |
59 | " LNKSETD [%2], %1\n" \ | |
60 | " DEFR %0, TXSTAT\n" \ | |
61 | " ANDT %0, %0, #HI(0x3f000000)\n" \ | |
62 | " CMPT %0, #HI(0x02000000)\n" \ | |
63 | " BNZ 1b\n" \ | |
64 | : "=&d" (temp), "=&da" (result) \ | |
096a8b6d | 65 | : "da" (&v->counter), "br" (i) \ |
d6dfe250 PZ |
66 | : "cc"); \ |
67 | \ | |
68 | smp_mb(); \ | |
69 | \ | |
70 | return result; \ | |
6006c0d8 JH |
71 | } |
72 | ||
e898eb27 PZ |
73 | #define ATOMIC_FETCH_OP(op) \ |
74 | static inline int atomic_fetch_##op(int i, atomic_t *v) \ | |
75 | { \ | |
76 | int result, temp; \ | |
77 | \ | |
78 | smp_mb(); \ | |
79 | \ | |
80 | asm volatile ( \ | |
81 | "1: LNKGETD %1, [%2]\n" \ | |
82 | " " #op " %0, %1, %3\n" \ | |
83 | " LNKSETD [%2], %0\n" \ | |
84 | " DEFR %0, TXSTAT\n" \ | |
85 | " ANDT %0, %0, #HI(0x3f000000)\n" \ | |
86 | " CMPT %0, #HI(0x02000000)\n" \ | |
87 | " BNZ 1b\n" \ | |
88 | : "=&d" (temp), "=&d" (result) \ | |
89 | : "da" (&v->counter), "bd" (i) \ | |
90 | : "cc"); \ | |
91 | \ | |
92 | smp_mb(); \ | |
93 | \ | |
94 | return result; \ | |
95 | } | |
96 | ||
97 | #define ATOMIC_OPS(op) ATOMIC_OP(op) ATOMIC_OP_RETURN(op) ATOMIC_FETCH_OP(op) | |
6006c0d8 | 98 | |
d6dfe250 PZ |
99 | ATOMIC_OPS(add) |
100 | ATOMIC_OPS(sub) | |
6006c0d8 | 101 | |
e898eb27 PZ |
102 | #undef ATOMIC_OPS |
103 | #define ATOMIC_OPS(op) ATOMIC_OP(op) ATOMIC_FETCH_OP(op) | |
104 | ||
105 | ATOMIC_OPS(and) | |
106 | ATOMIC_OPS(or) | |
107 | ATOMIC_OPS(xor) | |
5b4a2f0f | 108 | |
d6dfe250 | 109 | #undef ATOMIC_OPS |
e898eb27 | 110 | #undef ATOMIC_FETCH_OP |
d6dfe250 PZ |
111 | #undef ATOMIC_OP_RETURN |
112 | #undef ATOMIC_OP | |
6006c0d8 | 113 | |
6006c0d8 JH |
114 | static inline int atomic_cmpxchg(atomic_t *v, int old, int new) |
115 | { | |
116 | int result, temp; | |
117 | ||
118 | smp_mb(); | |
119 | ||
120 | asm volatile ( | |
121 | "1: LNKGETD %1, [%2]\n" | |
122 | " CMP %1, %3\n" | |
123 | " LNKSETDEQ [%2], %4\n" | |
124 | " BNE 2f\n" | |
125 | " DEFR %0, TXSTAT\n" | |
126 | " ANDT %0, %0, #HI(0x3f000000)\n" | |
127 | " CMPT %0, #HI(0x02000000)\n" | |
128 | " BNZ 1b\n" | |
129 | "2:\n" | |
130 | : "=&d" (temp), "=&d" (result) | |
131 | : "da" (&v->counter), "bd" (old), "da" (new) | |
132 | : "cc"); | |
133 | ||
134 | smp_mb(); | |
135 | ||
136 | return result; | |
137 | } | |
138 | ||
139 | static inline int atomic_xchg(atomic_t *v, int new) | |
140 | { | |
141 | int temp, old; | |
142 | ||
143 | asm volatile ( | |
144 | "1: LNKGETD %1, [%2]\n" | |
145 | " LNKSETD [%2], %3\n" | |
146 | " DEFR %0, TXSTAT\n" | |
147 | " ANDT %0, %0, #HI(0x3f000000)\n" | |
148 | " CMPT %0, #HI(0x02000000)\n" | |
149 | " BNZ 1b\n" | |
150 | : "=&d" (temp), "=&d" (old) | |
151 | : "da" (&v->counter), "da" (new) | |
152 | : "cc"); | |
153 | ||
154 | return old; | |
155 | } | |
156 | ||
157 | static inline int __atomic_add_unless(atomic_t *v, int a, int u) | |
158 | { | |
159 | int result, temp; | |
160 | ||
161 | smp_mb(); | |
162 | ||
163 | asm volatile ( | |
164 | "1: LNKGETD %1, [%2]\n" | |
165 | " CMP %1, %3\n" | |
166 | " ADD %0, %1, %4\n" | |
167 | " LNKSETDNE [%2], %0\n" | |
168 | " BEQ 2f\n" | |
169 | " DEFR %0, TXSTAT\n" | |
170 | " ANDT %0, %0, #HI(0x3f000000)\n" | |
171 | " CMPT %0, #HI(0x02000000)\n" | |
172 | " BNZ 1b\n" | |
173 | "2:\n" | |
174 | : "=&d" (temp), "=&d" (result) | |
175 | : "da" (&v->counter), "bd" (u), "bd" (a) | |
176 | : "cc"); | |
177 | ||
178 | smp_mb(); | |
179 | ||
180 | return result; | |
181 | } | |
182 | ||
183 | static inline int atomic_sub_if_positive(int i, atomic_t *v) | |
184 | { | |
185 | int result, temp; | |
186 | ||
187 | asm volatile ( | |
188 | "1: LNKGETD %1, [%2]\n" | |
189 | " SUBS %1, %1, %3\n" | |
190 | " LNKSETDGE [%2], %1\n" | |
191 | " BLT 2f\n" | |
192 | " DEFR %0, TXSTAT\n" | |
193 | " ANDT %0, %0, #HI(0x3f000000)\n" | |
194 | " CMPT %0, #HI(0x02000000)\n" | |
195 | " BNZ 1b\n" | |
196 | "2:\n" | |
197 | : "=&d" (temp), "=&da" (result) | |
198 | : "da" (&v->counter), "bd" (i) | |
199 | : "cc"); | |
200 | ||
201 | return result; | |
202 | } | |
203 | ||
204 | #endif /* __ASM_METAG_ATOMIC_LNKGET_H */ |