]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - include/asm-blackfin/bitops.h
imported Ka-Ro specific additions to U-Boot 2009.08 for TX28
[karo-tx-uboot.git] / include / asm-blackfin / bitops.h
1 /*
2  * U-boot - bitops.h Routines for bit operations
3  *
4  * Copyright (c) 2005-2007 Analog Devices Inc.
5  *
6  * See file CREDITS for list of people who contributed to this
7  * project.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation; either version 2 of
12  * the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
22  * MA 02110-1301 USA
23  */
24
25 #ifndef _BLACKFIN_BITOPS_H
26 #define _BLACKFIN_BITOPS_H
27
28 /*
29  * Copyright 1992, Linus Torvalds.
30  */
31
32 #include <linux/config.h>
33 #include <asm/byteorder.h>
34 #include <asm/system.h>
35
36 #ifdef __KERNEL__
37 /*
38  * Function prototypes to keep gcc -Wall happy
39  */
40
41 /*
42  * The __ functions are not atomic
43  */
44
45 /*
46  * ffz = Find First Zero in word. Undefined if no zero exists,
47  * so code should check against ~0UL first..
48  */
49 static __inline__ unsigned long ffz(unsigned long word)
50 {
51         unsigned long result = 0;
52
53         while (word & 1) {
54                 result++;
55                 word >>= 1;
56         }
57         return result;
58 }
59
60 static __inline__ void set_bit(int nr, volatile void *addr)
61 {
62         int *a = (int *)addr;
63         int mask;
64         unsigned long flags;
65
66         a += nr >> 5;
67         mask = 1 << (nr & 0x1f);
68         local_irq_save(flags);
69         *a |= mask;
70         local_irq_restore(flags);
71 }
72
73 static __inline__ void __set_bit(int nr, volatile void *addr)
74 {
75         int *a = (int *)addr;
76         int mask;
77
78         a += nr >> 5;
79         mask = 1 << (nr & 0x1f);
80         *a |= mask;
81 }
82
83 /*
84  * clear_bit() doesn't provide any barrier for the compiler.
85  */
86 #define smp_mb__before_clear_bit()      barrier()
87 #define smp_mb__after_clear_bit()       barrier()
88
89 static __inline__ void clear_bit(int nr, volatile void *addr)
90 {
91         int *a = (int *)addr;
92         int mask;
93         unsigned long flags;
94
95         a += nr >> 5;
96         mask = 1 << (nr & 0x1f);
97         local_irq_save(flags);
98         *a &= ~mask;
99         local_irq_restore(flags);
100 }
101
102 static __inline__ void change_bit(int nr, volatile void *addr)
103 {
104         int mask, flags;
105         unsigned long *ADDR = (unsigned long *)addr;
106
107         ADDR += nr >> 5;
108         mask = 1 << (nr & 31);
109         local_irq_save(flags);
110         *ADDR ^= mask;
111         local_irq_restore(flags);
112 }
113
114 static __inline__ void __change_bit(int nr, volatile void *addr)
115 {
116         int mask;
117         unsigned long *ADDR = (unsigned long *)addr;
118
119         ADDR += nr >> 5;
120         mask = 1 << (nr & 31);
121         *ADDR ^= mask;
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         unsigned long flags;
129
130         a += nr >> 5;
131         mask = 1 << (nr & 0x1f);
132         local_irq_save(flags);
133         retval = (mask & *a) != 0;
134         *a |= mask;
135         local_irq_restore(flags);
136
137         return retval;
138 }
139
140 static __inline__ int __test_and_set_bit(int nr, volatile void *addr)
141 {
142         int mask, retval;
143         volatile unsigned int *a = (volatile unsigned int *)addr;
144
145         a += nr >> 5;
146         mask = 1 << (nr & 0x1f);
147         retval = (mask & *a) != 0;
148         *a |= mask;
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         unsigned long flags;
157
158         a += nr >> 5;
159         mask = 1 << (nr & 0x1f);
160         local_irq_save(flags);
161         retval = (mask & *a) != 0;
162         *a &= ~mask;
163         local_irq_restore(flags);
164
165         return retval;
166 }
167
168 static __inline__ int __test_and_clear_bit(int nr, volatile void *addr)
169 {
170         int mask, retval;
171         volatile unsigned int *a = (volatile unsigned int *)addr;
172
173         a += nr >> 5;
174         mask = 1 << (nr & 0x1f);
175         retval = (mask & *a) != 0;
176         *a &= ~mask;
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         unsigned long flags;
185
186         a += nr >> 5;
187         mask = 1 << (nr & 0x1f);
188         local_irq_save(flags);
189         retval = (mask & *a) != 0;
190         *a ^= mask;
191         local_irq_restore(flags);
192
193         return retval;
194 }
195
196 static __inline__ int __test_and_change_bit(int nr, volatile void *addr)
197 {
198         int mask, retval;
199         volatile unsigned int *a = (volatile unsigned int *)addr;
200
201         a += nr >> 5;
202         mask = 1 << (nr & 0x1f);
203         retval = (mask & *a) != 0;
204         *a ^= mask;
205         return retval;
206 }
207
208 /*
209  * This routine doesn't need to be atomic.
210  */
211 static __inline__ int __constant_test_bit(int nr, const volatile void *addr)
212 {
213         return ((1UL << (nr & 31)) &
214                 (((const volatile unsigned int *)addr)[nr >> 5])) != 0;
215 }
216
217 static __inline__ int __test_bit(int nr, volatile void *addr)
218 {
219         int *a = (int *)addr;
220         int mask;
221
222         a += nr >> 5;
223         mask = 1 << (nr & 0x1f);
224         return ((mask & *a) != 0);
225 }
226
227 #define test_bit(nr,addr) \
228 (__builtin_constant_p(nr) ? \
229  __constant_test_bit((nr),(addr)) : \
230  __test_bit((nr),(addr)))
231
232 #define find_first_zero_bit(addr, size) \
233         find_next_zero_bit((addr), (size), 0)
234
235 static __inline__ int find_next_zero_bit(void *addr, int size, int offset)
236 {
237         unsigned long *p = ((unsigned long *)addr) + (offset >> 5);
238         unsigned long result = offset & ~31UL;
239         unsigned long tmp;
240
241         if (offset >= size)
242                 return size;
243         size -= result;
244         offset &= 31UL;
245         if (offset) {
246                 tmp = *(p++);
247                 tmp |= ~0UL >> (32 - offset);
248                 if (size < 32)
249                         goto found_first;
250                 if (~tmp)
251                         goto found_middle;
252                 size -= 32;
253                 result += 32;
254         }
255         while (size & ~31UL) {
256                 if (~(tmp = *(p++)))
257                         goto found_middle;
258                 result += 32;
259                 size -= 32;
260         }
261         if (!size)
262                 return result;
263         tmp = *p;
264
265       found_first:
266         tmp |= ~0UL >> size;
267       found_middle:
268         return result + ffz(tmp);
269 }
270
271 /*
272  * ffs: find first bit set. This is defined the same way as
273  * the libc and compiler builtin ffs routines, therefore
274  * differs in spirit from the above ffz (man ffs).
275  */
276
277 #define ffs(x)          generic_ffs(x)
278
279 /*
280  * hweightN: returns the hamming weight (i.e. the number
281  * of bits set) of a N-bit word
282  */
283
284 #define hweight32(x)    generic_hweight32(x)
285 #define hweight16(x)    generic_hweight16(x)
286 #define hweight8(x)     generic_hweight8(x)
287
288 static __inline__ int ext2_set_bit(int nr, volatile void *addr)
289 {
290         int mask, retval;
291         unsigned long flags;
292         volatile unsigned char *ADDR = (unsigned char *)addr;
293
294         ADDR += nr >> 3;
295         mask = 1 << (nr & 0x07);
296         local_irq_save(flags);
297         retval = (mask & *ADDR) != 0;
298         *ADDR |= mask;
299         local_irq_restore(flags);
300         return retval;
301 }
302
303 static __inline__ int ext2_clear_bit(int nr, volatile void *addr)
304 {
305         int mask, retval;
306         unsigned long flags;
307         volatile unsigned char *ADDR = (unsigned char *)addr;
308
309         ADDR += nr >> 3;
310         mask = 1 << (nr & 0x07);
311         local_irq_save(flags);
312         retval = (mask & *ADDR) != 0;
313         *ADDR &= ~mask;
314         local_irq_restore(flags);
315         return retval;
316 }
317
318 static __inline__ int ext2_test_bit(int nr, const volatile void *addr)
319 {
320         int mask;
321         const volatile unsigned char *ADDR = (const unsigned char *)addr;
322
323         ADDR += nr >> 3;
324         mask = 1 << (nr & 0x07);
325         return ((mask & *ADDR) != 0);
326 }
327
328 #define ext2_find_first_zero_bit(addr, size) \
329         ext2_find_next_zero_bit((addr), (size), 0)
330
331 static __inline__ unsigned long ext2_find_next_zero_bit(void *addr,
332                                                         unsigned long size,
333                                                         unsigned long offset)
334 {
335         unsigned long *p = ((unsigned long *)addr) + (offset >> 5);
336         unsigned long result = offset & ~31UL;
337         unsigned long tmp;
338
339         if (offset >= size)
340                 return size;
341         size -= result;
342         offset &= 31UL;
343         if (offset) {
344                 tmp = *(p++);
345                 tmp |= ~0UL >> (32 - offset);
346                 if (size < 32)
347                         goto found_first;
348                 if (~tmp)
349                         goto found_middle;
350                 size -= 32;
351                 result += 32;
352         }
353         while (size & ~31UL) {
354                 if (~(tmp = *(p++)))
355                         goto found_middle;
356                 result += 32;
357                 size -= 32;
358         }
359         if (!size)
360                 return result;
361         tmp = *p;
362
363       found_first:
364         tmp |= ~0UL >> size;
365       found_middle:
366         return result + ffz(tmp);
367 }
368
369 /* Bitmap functions for the minix filesystem. */
370 #define minix_test_and_set_bit(nr,addr)         test_and_set_bit(nr,addr)
371 #define minix_set_bit(nr,addr)                  set_bit(nr,addr)
372 #define minix_test_and_clear_bit(nr,addr)       test_and_clear_bit(nr,addr)
373 #define minix_test_bit(nr,addr)                 test_bit(nr,addr)
374 #define minix_find_first_zero_bit(addr,size)    find_first_zero_bit(addr,size)
375
376 #endif
377
378 #endif