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