]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/blackfin/include/asm/bitops.h
Merge branch 'master' of git://www.denx.de/git/u-boot-usb
[karo-tx-uboot.git] / arch / blackfin / include / asm / bitops.h
1 /*
2  * U-boot - bitops.h Routines for bit operations
3  *
4  * Copyright (c) 2005-2007 Analog Devices Inc.
5  *
6  * SPDX-License-Identifier:     GPL-2.0+
7  */
8
9 #ifndef _BLACKFIN_BITOPS_H
10 #define _BLACKFIN_BITOPS_H
11
12 /*
13  * Copyright 1992, Linus Torvalds.
14  */
15
16 #include <asm/byteorder.h>
17 #include <asm/system.h>
18
19 #ifdef __KERNEL__
20 /*
21  * Function prototypes to keep gcc -Wall happy
22  */
23
24 /*
25  * The __ functions are not atomic
26  */
27
28 /*
29  * ffz = Find First Zero in word. Undefined if no zero exists,
30  * so code should check against ~0UL first..
31  */
32 static __inline__ unsigned long ffz(unsigned long word)
33 {
34         unsigned long result = 0;
35
36         while (word & 1) {
37                 result++;
38                 word >>= 1;
39         }
40         return result;
41 }
42
43 static __inline__ void set_bit(int nr, volatile void *addr)
44 {
45         int *a = (int *)addr;
46         int mask;
47         unsigned long flags;
48
49         a += nr >> 5;
50         mask = 1 << (nr & 0x1f);
51         local_irq_save(flags);
52         *a |= mask;
53         local_irq_restore(flags);
54 }
55
56 static __inline__ void __set_bit(int nr, volatile void *addr)
57 {
58         int *a = (int *)addr;
59         int mask;
60
61         a += nr >> 5;
62         mask = 1 << (nr & 0x1f);
63         *a |= mask;
64 }
65 #define PLATFORM__SET_BIT
66
67 /*
68  * clear_bit() doesn't provide any barrier for the compiler.
69  */
70 #define smp_mb__before_clear_bit()      barrier()
71 #define smp_mb__after_clear_bit()       barrier()
72
73 static __inline__ void clear_bit(int nr, volatile void *addr)
74 {
75         int *a = (int *)addr;
76         int mask;
77         unsigned long flags;
78
79         a += nr >> 5;
80         mask = 1 << (nr & 0x1f);
81         local_irq_save(flags);
82         *a &= ~mask;
83         local_irq_restore(flags);
84 }
85
86 static __inline__ void change_bit(int nr, volatile void *addr)
87 {
88         int mask, flags;
89         unsigned long *ADDR = (unsigned long *)addr;
90
91         ADDR += nr >> 5;
92         mask = 1 << (nr & 31);
93         local_irq_save(flags);
94         *ADDR ^= mask;
95         local_irq_restore(flags);
96 }
97
98 static __inline__ void __change_bit(int nr, volatile void *addr)
99 {
100         int mask;
101         unsigned long *ADDR = (unsigned long *)addr;
102
103         ADDR += nr >> 5;
104         mask = 1 << (nr & 31);
105         *ADDR ^= mask;
106 }
107
108 static __inline__ int test_and_set_bit(int nr, volatile void *addr)
109 {
110         int mask, retval;
111         volatile unsigned int *a = (volatile unsigned int *)addr;
112         unsigned long flags;
113
114         a += nr >> 5;
115         mask = 1 << (nr & 0x1f);
116         local_irq_save(flags);
117         retval = (mask & *a) != 0;
118         *a |= mask;
119         local_irq_restore(flags);
120
121         return retval;
122 }
123
124 static __inline__ int __test_and_set_bit(int nr, volatile void *addr)
125 {
126         int mask, retval;
127         volatile unsigned int *a = (volatile unsigned int *)addr;
128
129         a += nr >> 5;
130         mask = 1 << (nr & 0x1f);
131         retval = (mask & *a) != 0;
132         *a |= mask;
133         return retval;
134 }
135
136 static __inline__ int test_and_clear_bit(int nr, volatile void *addr)
137 {
138         int mask, retval;
139         volatile unsigned int *a = (volatile unsigned int *)addr;
140         unsigned long flags;
141
142         a += nr >> 5;
143         mask = 1 << (nr & 0x1f);
144         local_irq_save(flags);
145         retval = (mask & *a) != 0;
146         *a &= ~mask;
147         local_irq_restore(flags);
148
149         return retval;
150 }
151
152 static __inline__ int __test_and_clear_bit(int nr, volatile void *addr)
153 {
154         int mask, retval;
155         volatile unsigned int *a = (volatile unsigned int *)addr;
156
157         a += nr >> 5;
158         mask = 1 << (nr & 0x1f);
159         retval = (mask & *a) != 0;
160         *a &= ~mask;
161         return retval;
162 }
163
164 static __inline__ int test_and_change_bit(int nr, volatile void *addr)
165 {
166         int mask, retval;
167         volatile unsigned int *a = (volatile unsigned int *)addr;
168         unsigned long flags;
169
170         a += nr >> 5;
171         mask = 1 << (nr & 0x1f);
172         local_irq_save(flags);
173         retval = (mask & *a) != 0;
174         *a ^= mask;
175         local_irq_restore(flags);
176
177         return retval;
178 }
179
180 static __inline__ int __test_and_change_bit(int nr, volatile void *addr)
181 {
182         int mask, retval;
183         volatile unsigned int *a = (volatile unsigned int *)addr;
184
185         a += nr >> 5;
186         mask = 1 << (nr & 0x1f);
187         retval = (mask & *a) != 0;
188         *a ^= mask;
189         return retval;
190 }
191
192 /*
193  * This routine doesn't need to be atomic.
194  */
195 static __inline__ int __constant_test_bit(int nr, const volatile void *addr)
196 {
197         return ((1UL << (nr & 31)) &
198                 (((const volatile unsigned int *)addr)[nr >> 5])) != 0;
199 }
200
201 static __inline__ int __test_bit(int nr, volatile void *addr)
202 {
203         int *a = (int *)addr;
204         int mask;
205
206         a += nr >> 5;
207         mask = 1 << (nr & 0x1f);
208         return ((mask & *a) != 0);
209 }
210
211 #define test_bit(nr,addr) \
212 (__builtin_constant_p(nr) ? \
213  __constant_test_bit((nr),(addr)) : \
214  __test_bit((nr),(addr)))
215
216 #define find_first_zero_bit(addr, size) \
217         find_next_zero_bit((addr), (size), 0)
218
219 static __inline__ int find_next_zero_bit(void *addr, int size, int offset)
220 {
221         unsigned long *p = ((unsigned long *)addr) + (offset >> 5);
222         unsigned long result = offset & ~31UL;
223         unsigned long tmp;
224
225         if (offset >= size)
226                 return size;
227         size -= result;
228         offset &= 31UL;
229         if (offset) {
230                 tmp = *(p++);
231                 tmp |= ~0UL >> (32 - offset);
232                 if (size < 32)
233                         goto found_first;
234                 if (~tmp)
235                         goto found_middle;
236                 size -= 32;
237                 result += 32;
238         }
239         while (size & ~31UL) {
240                 if (~(tmp = *(p++)))
241                         goto found_middle;
242                 result += 32;
243                 size -= 32;
244         }
245         if (!size)
246                 return result;
247         tmp = *p;
248
249       found_first:
250         tmp |= ~0UL >> size;
251       found_middle:
252         return result + ffz(tmp);
253 }
254
255 /*
256  * hweightN: returns the hamming weight (i.e. the number
257  * of bits set) of a N-bit word
258  */
259
260 #define hweight32(x)    generic_hweight32(x)
261 #define hweight16(x)    generic_hweight16(x)
262 #define hweight8(x)     generic_hweight8(x)
263
264 static __inline__ int ext2_set_bit(int nr, volatile void *addr)
265 {
266         int mask, retval;
267         unsigned long flags;
268         volatile unsigned char *ADDR = (unsigned char *)addr;
269
270         ADDR += nr >> 3;
271         mask = 1 << (nr & 0x07);
272         local_irq_save(flags);
273         retval = (mask & *ADDR) != 0;
274         *ADDR |= mask;
275         local_irq_restore(flags);
276         return retval;
277 }
278
279 static __inline__ int ext2_clear_bit(int nr, volatile void *addr)
280 {
281         int mask, retval;
282         unsigned long flags;
283         volatile unsigned char *ADDR = (unsigned char *)addr;
284
285         ADDR += nr >> 3;
286         mask = 1 << (nr & 0x07);
287         local_irq_save(flags);
288         retval = (mask & *ADDR) != 0;
289         *ADDR &= ~mask;
290         local_irq_restore(flags);
291         return retval;
292 }
293
294 static __inline__ int ext2_test_bit(int nr, const volatile void *addr)
295 {
296         int mask;
297         const volatile unsigned char *ADDR = (const unsigned char *)addr;
298
299         ADDR += nr >> 3;
300         mask = 1 << (nr & 0x07);
301         return ((mask & *ADDR) != 0);
302 }
303
304 #define ext2_find_first_zero_bit(addr, size) \
305         ext2_find_next_zero_bit((addr), (size), 0)
306
307 static __inline__ unsigned long ext2_find_next_zero_bit(void *addr,
308                                                         unsigned long size,
309                                                         unsigned long offset)
310 {
311         unsigned long *p = ((unsigned long *)addr) + (offset >> 5);
312         unsigned long result = offset & ~31UL;
313         unsigned long tmp;
314
315         if (offset >= size)
316                 return size;
317         size -= result;
318         offset &= 31UL;
319         if (offset) {
320                 tmp = *(p++);
321                 tmp |= ~0UL >> (32 - offset);
322                 if (size < 32)
323                         goto found_first;
324                 if (~tmp)
325                         goto found_middle;
326                 size -= 32;
327                 result += 32;
328         }
329         while (size & ~31UL) {
330                 if (~(tmp = *(p++)))
331                         goto found_middle;
332                 result += 32;
333                 size -= 32;
334         }
335         if (!size)
336                 return result;
337         tmp = *p;
338
339       found_first:
340         tmp |= ~0UL >> size;
341       found_middle:
342         return result + ffz(tmp);
343 }
344
345 /* Bitmap functions for the minix filesystem. */
346 #define minix_test_and_set_bit(nr,addr)         test_and_set_bit(nr,addr)
347 #define minix_set_bit(nr,addr)                  set_bit(nr,addr)
348 #define minix_test_and_clear_bit(nr,addr)       test_and_clear_bit(nr,addr)
349 #define minix_test_bit(nr,addr)                 test_bit(nr,addr)
350 #define minix_find_first_zero_bit(addr,size)    find_first_zero_bit(addr,size)
351
352 #endif
353
354 #endif