1 /*
2  * Copyright 1995, Russell King.
3  * Various bits and pieces copyrights include:
4  *  Linus Torvalds (test_bit).
5  *
6  * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
7  *
8  * Please note that the code in this file should never be included
9  * from user space.  Many of these are not implemented in assembler
10  * since they would be too costly.  Also, they require priviledged
11  * instructions (which are not available from user mode) to ensure
12  * that they are atomic.
13  */
14 
15 #ifndef __ASM_ARM_BITOPS_H
16 #define __ASM_ARM_BITOPS_H
17 
18 #if __LINUX_ARM_ARCH__ < 5
19 
20 #include <asm-generic/bitops/__ffs.h>
21 #include <asm-generic/bitops/__fls.h>
22 #include <asm-generic/bitops/fls.h>
23 
24 #else
25 
26 #define PLATFORM_FFS
27 #define PLATFORM_FLS
28 
29 #if !IS_ENABLED(CONFIG_HAS_THUMB2) && CONFIG_IS_ENABLED(SYS_THUMB_BUILD)
30 
31 unsigned long __fls(unsigned long word);
32 unsigned long __ffs(unsigned long word);
33 int fls(unsigned int x);
34 int ffs(int x);
35 
36 #else
37 
38 #include <asm-generic/bitops/builtin-__fls.h>
39 #include <asm-generic/bitops/builtin-__ffs.h>
40 #include <asm-generic/bitops/builtin-fls.h>
41 #include <asm-generic/bitops/builtin-ffs.h>
42 
43 #endif
44 #endif
45 
46 #include <asm-generic/bitops/fls64.h>
47 
48 #ifdef __KERNEL__
49 
50 #ifndef __ASSEMBLY__
51 #include <linux/bitops.h>
52 #endif
53 #include <asm/proc-armv/system.h>
54 
55 #define smp_mb__before_clear_bit()	do { } while (0)
56 #define smp_mb__after_clear_bit()	do { } while (0)
57 
58 /*
59  * Function prototypes to keep gcc -Wall happy.
60  */
61 extern void set_bit(int nr, volatile void * addr);
62 
63 extern void clear_bit(int nr, volatile void * addr);
64 
65 extern void change_bit(int nr, volatile void * addr);
66 
__change_bit(int nr,volatile void * addr)67 static inline void __change_bit(int nr, volatile void *addr)
68 {
69 	unsigned long mask = BIT_MASK(nr);
70 	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
71 
72 	*p ^= mask;
73 }
74 
__test_and_set_bit(int nr,volatile void * addr)75 static inline int __test_and_set_bit(int nr, volatile void *addr)
76 {
77 	unsigned long mask = BIT_MASK(nr);
78 	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
79 	unsigned long old = *p;
80 
81 	*p = old | mask;
82 	return (old & mask) != 0;
83 }
84 
test_and_set_bit(int nr,volatile void * addr)85 static inline int test_and_set_bit(int nr, volatile void * addr)
86 {
87 	unsigned long flags = 0;
88 	int out;
89 
90 	local_irq_save(flags);
91 	out = __test_and_set_bit(nr, addr);
92 	local_irq_restore(flags);
93 
94 	return out;
95 }
96 
__test_and_clear_bit(int nr,volatile void * addr)97 static inline int __test_and_clear_bit(int nr, volatile void *addr)
98 {
99 	unsigned long mask = BIT_MASK(nr);
100 	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
101 	unsigned long old = *p;
102 
103 	*p = old & ~mask;
104 	return (old & mask) != 0;
105 }
106 
test_and_clear_bit(int nr,volatile void * addr)107 static inline int test_and_clear_bit(int nr, volatile void * addr)
108 {
109 	unsigned long flags = 0;
110 	int out;
111 
112 	local_irq_save(flags);
113 	out = __test_and_clear_bit(nr, addr);
114 	local_irq_restore(flags);
115 
116 	return out;
117 }
118 
119 extern int test_and_change_bit(int nr, volatile void * addr);
120 
__test_and_change_bit(int nr,volatile void * addr)121 static inline int __test_and_change_bit(int nr, volatile void *addr)
122 {
123 	unsigned long mask = BIT_MASK(nr);
124 	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
125 	unsigned long old = *p;
126 
127 	*p = old ^ mask;
128 	return (old & mask) != 0;
129 }
130 
131 /*
132  * This routine doesn't need to be atomic.
133  */
test_bit(int nr,const void * addr)134 static inline int test_bit(int nr, const void * addr)
135 {
136     return ((unsigned char *) addr)[nr >> 3] & (1U << (nr & 7));
137 }
138 
__ilog2(unsigned int x)139 static inline int __ilog2(unsigned int x)
140 {
141 	return fls(x) - 1;
142 }
143 
144 #define ffz(x)  __ffs(~(x))
145 
find_next_zero_bit(void * addr,int size,int offset)146 static inline int find_next_zero_bit(void *addr, int size, int offset)
147 {
148 	unsigned long *p = ((unsigned long *)addr) + (offset / BITS_PER_LONG);
149 	unsigned long result = offset & ~(BITS_PER_LONG - 1);
150 	unsigned long tmp;
151 
152 	if (offset >= size)
153 		return size;
154 	size -= result;
155 	offset &= (BITS_PER_LONG - 1);
156 	if (offset) {
157 		tmp = *(p++);
158 		tmp |= ~0UL >> (BITS_PER_LONG - offset);
159 		if (size < BITS_PER_LONG)
160 			goto found_first;
161 		if (~tmp)
162 			goto found_middle;
163 		size -= BITS_PER_LONG;
164 		result += BITS_PER_LONG;
165 	}
166 	while (size & ~(BITS_PER_LONG - 1)) {
167 		tmp = *(p++);
168 		if (~tmp)
169 			goto found_middle;
170 		result += BITS_PER_LONG;
171 		size -= BITS_PER_LONG;
172 	}
173 	if (!size)
174 		return result;
175 	tmp = *p;
176 
177 found_first:
178 	tmp |= ~0UL << size;
179 found_middle:
180 	return result + ffz(tmp);
181 }
182 
183 /*
184  * hweightN: returns the hamming weight (i.e. the number
185  * of bits set) of a N-bit word
186  */
187 
188 #define hweight32(x) generic_hweight32(x)
189 #define hweight16(x) generic_hweight16(x)
190 #define hweight8(x) generic_hweight8(x)
191 
192 #define find_first_zero_bit(addr, size) \
193 	find_next_zero_bit((addr), (size), 0)
194 
195 #define ext2_set_bit			test_and_set_bit
196 #define ext2_clear_bit			test_and_clear_bit
197 #define ext2_test_bit			test_bit
198 #define ext2_find_first_zero_bit	find_first_zero_bit
199 #define ext2_find_next_zero_bit		find_next_zero_bit
200 
201 /* Bitmap functions for the minix filesystem. */
202 #define minix_test_and_set_bit(nr,addr)	test_and_set_bit(nr,addr)
203 #define minix_set_bit(nr,addr)		set_bit(nr,addr)
204 #define minix_test_and_clear_bit(nr,addr)	test_and_clear_bit(nr,addr)
205 #define minix_test_bit(nr,addr)		test_bit(nr,addr)
206 #define minix_find_first_zero_bit(addr,size)	find_first_zero_bit(addr,size)
207 
208 #endif /* __KERNEL__ */
209 
210 #endif /* _ARM_BITOPS_H */
211