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