]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - arch/avr32/include/asm/bitops.h
Merge branch 'ras-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[mirror_ubuntu-artful-kernel.git] / arch / avr32 / include / asm / bitops.h
1 /*
2 * Copyright (C) 2004-2006 Atmel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8 #ifndef __ASM_AVR32_BITOPS_H
9 #define __ASM_AVR32_BITOPS_H
10
11 #ifndef _LINUX_BITOPS_H
12 #error only <linux/bitops.h> can be included directly
13 #endif
14
15 #include <asm/byteorder.h>
16 #include <asm/barrier.h>
17
18 /*
19 * set_bit - Atomically set a bit in memory
20 * @nr: the bit to set
21 * @addr: the address to start counting from
22 *
23 * This function is atomic and may not be reordered. See __set_bit()
24 * if you do not require the atomic guarantees.
25 *
26 * Note that @nr may be almost arbitrarily large; this function is not
27 * restricted to acting on a single-word quantity.
28 */
29 static inline void set_bit(int nr, volatile void * addr)
30 {
31 unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG;
32 unsigned long tmp;
33
34 if (__builtin_constant_p(nr)) {
35 asm volatile(
36 "1: ssrf 5\n"
37 " ld.w %0, %2\n"
38 " sbr %0, %3\n"
39 " stcond %1, %0\n"
40 " brne 1b"
41 : "=&r"(tmp), "=o"(*p)
42 : "m"(*p), "i"(nr)
43 : "cc");
44 } else {
45 unsigned long mask = 1UL << (nr % BITS_PER_LONG);
46 asm volatile(
47 "1: ssrf 5\n"
48 " ld.w %0, %2\n"
49 " or %0, %3\n"
50 " stcond %1, %0\n"
51 " brne 1b"
52 : "=&r"(tmp), "=o"(*p)
53 : "m"(*p), "r"(mask)
54 : "cc");
55 }
56 }
57
58 /*
59 * clear_bit - Clears a bit in memory
60 * @nr: Bit to clear
61 * @addr: Address to start counting from
62 *
63 * clear_bit() is atomic and may not be reordered. However, it does
64 * not contain a memory barrier, so if it is used for locking purposes,
65 * you should call smp_mb__before_atomic() and/or smp_mb__after_atomic()
66 * in order to ensure changes are visible on other processors.
67 */
68 static inline void clear_bit(int nr, volatile void * addr)
69 {
70 unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG;
71 unsigned long tmp;
72
73 if (__builtin_constant_p(nr)) {
74 asm volatile(
75 "1: ssrf 5\n"
76 " ld.w %0, %2\n"
77 " cbr %0, %3\n"
78 " stcond %1, %0\n"
79 " brne 1b"
80 : "=&r"(tmp), "=o"(*p)
81 : "m"(*p), "i"(nr)
82 : "cc");
83 } else {
84 unsigned long mask = 1UL << (nr % BITS_PER_LONG);
85 asm volatile(
86 "1: ssrf 5\n"
87 " ld.w %0, %2\n"
88 " andn %0, %3\n"
89 " stcond %1, %0\n"
90 " brne 1b"
91 : "=&r"(tmp), "=o"(*p)
92 : "m"(*p), "r"(mask)
93 : "cc");
94 }
95 }
96
97 /*
98 * change_bit - Toggle a bit in memory
99 * @nr: Bit to change
100 * @addr: Address to start counting from
101 *
102 * change_bit() is atomic and may not be reordered.
103 * Note that @nr may be almost arbitrarily large; this function is not
104 * restricted to acting on a single-word quantity.
105 */
106 static inline void change_bit(int nr, volatile void * addr)
107 {
108 unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG;
109 unsigned long mask = 1UL << (nr % BITS_PER_LONG);
110 unsigned long tmp;
111
112 asm volatile(
113 "1: ssrf 5\n"
114 " ld.w %0, %2\n"
115 " eor %0, %3\n"
116 " stcond %1, %0\n"
117 " brne 1b"
118 : "=&r"(tmp), "=o"(*p)
119 : "m"(*p), "r"(mask)
120 : "cc");
121 }
122
123 /*
124 * test_and_set_bit - Set a bit and return its old value
125 * @nr: Bit to set
126 * @addr: Address to count from
127 *
128 * This operation is atomic and cannot be reordered.
129 * It also implies a memory barrier.
130 */
131 static inline int test_and_set_bit(int nr, volatile void * addr)
132 {
133 unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG;
134 unsigned long mask = 1UL << (nr % BITS_PER_LONG);
135 unsigned long tmp, old;
136
137 if (__builtin_constant_p(nr)) {
138 asm volatile(
139 "1: ssrf 5\n"
140 " ld.w %0, %3\n"
141 " mov %2, %0\n"
142 " sbr %0, %4\n"
143 " stcond %1, %0\n"
144 " brne 1b"
145 : "=&r"(tmp), "=o"(*p), "=&r"(old)
146 : "m"(*p), "i"(nr)
147 : "memory", "cc");
148 } else {
149 asm volatile(
150 "1: ssrf 5\n"
151 " ld.w %2, %3\n"
152 " or %0, %2, %4\n"
153 " stcond %1, %0\n"
154 " brne 1b"
155 : "=&r"(tmp), "=o"(*p), "=&r"(old)
156 : "m"(*p), "r"(mask)
157 : "memory", "cc");
158 }
159
160 return (old & mask) != 0;
161 }
162
163 /*
164 * test_and_clear_bit - Clear a bit and return its old value
165 * @nr: Bit to clear
166 * @addr: Address to count from
167 *
168 * This operation is atomic and cannot be reordered.
169 * It also implies a memory barrier.
170 */
171 static inline int test_and_clear_bit(int nr, volatile void * addr)
172 {
173 unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG;
174 unsigned long mask = 1UL << (nr % BITS_PER_LONG);
175 unsigned long tmp, old;
176
177 if (__builtin_constant_p(nr)) {
178 asm volatile(
179 "1: ssrf 5\n"
180 " ld.w %0, %3\n"
181 " mov %2, %0\n"
182 " cbr %0, %4\n"
183 " stcond %1, %0\n"
184 " brne 1b"
185 : "=&r"(tmp), "=o"(*p), "=&r"(old)
186 : "m"(*p), "i"(nr)
187 : "memory", "cc");
188 } else {
189 asm volatile(
190 "1: ssrf 5\n"
191 " ld.w %0, %3\n"
192 " mov %2, %0\n"
193 " andn %0, %4\n"
194 " stcond %1, %0\n"
195 " brne 1b"
196 : "=&r"(tmp), "=o"(*p), "=&r"(old)
197 : "m"(*p), "r"(mask)
198 : "memory", "cc");
199 }
200
201 return (old & mask) != 0;
202 }
203
204 /*
205 * test_and_change_bit - Change a bit and return its old value
206 * @nr: Bit to change
207 * @addr: Address to count from
208 *
209 * This operation is atomic and cannot be reordered.
210 * It also implies a memory barrier.
211 */
212 static inline int test_and_change_bit(int nr, volatile void * addr)
213 {
214 unsigned long *p = ((unsigned long *)addr) + nr / BITS_PER_LONG;
215 unsigned long mask = 1UL << (nr % BITS_PER_LONG);
216 unsigned long tmp, old;
217
218 asm volatile(
219 "1: ssrf 5\n"
220 " ld.w %2, %3\n"
221 " eor %0, %2, %4\n"
222 " stcond %1, %0\n"
223 " brne 1b"
224 : "=&r"(tmp), "=o"(*p), "=&r"(old)
225 : "m"(*p), "r"(mask)
226 : "memory", "cc");
227
228 return (old & mask) != 0;
229 }
230
231 #include <asm-generic/bitops/non-atomic.h>
232
233 /* Find First bit Set */
234 static inline unsigned long __ffs(unsigned long word)
235 {
236 unsigned long result;
237
238 asm("brev %1\n\t"
239 "clz %0,%1"
240 : "=r"(result), "=&r"(word)
241 : "1"(word));
242 return result;
243 }
244
245 /* Find First Zero */
246 static inline unsigned long ffz(unsigned long word)
247 {
248 return __ffs(~word);
249 }
250
251 /* Find Last bit Set */
252 static inline int fls(unsigned long word)
253 {
254 unsigned long result;
255
256 asm("clz %0,%1" : "=r"(result) : "r"(word));
257 return 32 - result;
258 }
259
260 static inline int __fls(unsigned long word)
261 {
262 return fls(word) - 1;
263 }
264
265 unsigned long find_first_zero_bit(const unsigned long *addr,
266 unsigned long size);
267 #define find_first_zero_bit find_first_zero_bit
268
269 unsigned long find_next_zero_bit(const unsigned long *addr,
270 unsigned long size,
271 unsigned long offset);
272 #define find_next_zero_bit find_next_zero_bit
273
274 unsigned long find_first_bit(const unsigned long *addr,
275 unsigned long size);
276 #define find_first_bit find_first_bit
277
278 unsigned long find_next_bit(const unsigned long *addr,
279 unsigned long size,
280 unsigned long offset);
281 #define find_next_bit find_next_bit
282
283 /*
284 * ffs: find first bit set. This is defined the same way as
285 * the libc and compiler builtin ffs routines, therefore
286 * differs in spirit from the above ffz (man ffs).
287 *
288 * The difference is that bit numbering starts at 1, and if no bit is set,
289 * the function returns 0.
290 */
291 static inline int ffs(unsigned long word)
292 {
293 if(word == 0)
294 return 0;
295 return __ffs(word) + 1;
296 }
297
298 #include <asm-generic/bitops/fls64.h>
299 #include <asm-generic/bitops/sched.h>
300 #include <asm-generic/bitops/hweight.h>
301 #include <asm-generic/bitops/lock.h>
302
303 extern unsigned long find_next_zero_bit_le(const void *addr,
304 unsigned long size, unsigned long offset);
305 #define find_next_zero_bit_le find_next_zero_bit_le
306
307 extern unsigned long find_next_bit_le(const void *addr,
308 unsigned long size, unsigned long offset);
309 #define find_next_bit_le find_next_bit_le
310
311 #include <asm-generic/bitops/le.h>
312 #include <asm-generic/bitops/ext2-atomic.h>
313
314 #endif /* __ASM_AVR32_BITOPS_H */