Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm
[pandora-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/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  */
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  */
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  */
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  */
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  */
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  */
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 */
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 */
252 static inline unsigned long ffz(unsigned long word)
253 {
254         return __ffs(~word);
255 }
256
257 /* Find Last bit Set */
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
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  */
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 */