1 /*
2  * Copyright 1995, Russell King.
3  * Various bits and pieces copyrights include:
4  *  Linus Torvalds (test_bit).
5  * Big endian support: Copyright 2001, Nicolas Pitre
6  *  reworked by rmk.
7  */
8 
9 #ifndef _ARM_BITOPS_H
10 #define _ARM_BITOPS_H
11 
12 #include <asm/asm_defns.h>
13 
14 /*
15  * Non-atomic bit manipulation.
16  *
17  * Implemented using atomics to be interrupt safe. Could alternatively
18  * implement with local interrupt masking.
19  */
20 #define __set_bit(n,p)            set_bit(n,p)
21 #define __clear_bit(n,p)          clear_bit(n,p)
22 
23 #define BITS_PER_WORD           32
24 #define BIT(nr)                 (1UL << (nr))
25 #define BIT_MASK(nr)            (1UL << ((nr) % BITS_PER_WORD))
26 #define BIT_WORD(nr)            ((nr) / BITS_PER_WORD)
27 #define BIT_ULL(nr)             (1ULL << (nr))
28 #define BITS_PER_BYTE           8
29 
30 #define ADDR (*(volatile int *) addr)
31 #define CONST_ADDR (*(const volatile int *) addr)
32 
33 #if defined(CONFIG_ARM_32)
34 # include <asm/arm32/bitops.h>
35 #elif defined(CONFIG_ARM_64)
36 # include <asm/arm64/bitops.h>
37 #else
38 # error "unknown ARM variant"
39 #endif
40 
41 /**
42  * __test_and_set_bit - Set a bit and return its old value
43  * @nr: Bit to set
44  * @addr: Address to count from
45  *
46  * This operation is non-atomic and can be reordered.
47  * If two examples of this operation race, one can appear to succeed
48  * but actually fail.  You must protect multiple accesses with a lock.
49  */
__test_and_set_bit(int nr,volatile void * addr)50 static inline int __test_and_set_bit(int nr, volatile void *addr)
51 {
52         unsigned int mask = BIT_MASK(nr);
53         volatile unsigned int *p =
54                 ((volatile unsigned int *)addr) + BIT_WORD(nr);
55         unsigned int old = *p;
56 
57         *p = old | mask;
58         return (old & mask) != 0;
59 }
60 
61 /**
62  * __test_and_clear_bit - Clear a bit and return its old value
63  * @nr: Bit to clear
64  * @addr: Address to count from
65  *
66  * This operation is non-atomic and can be reordered.
67  * If two examples of this operation race, one can appear to succeed
68  * but actually fail.  You must protect multiple accesses with a lock.
69  */
__test_and_clear_bit(int nr,volatile void * addr)70 static inline int __test_and_clear_bit(int nr, volatile void *addr)
71 {
72         unsigned int mask = BIT_MASK(nr);
73         volatile unsigned int *p =
74                 ((volatile unsigned int *)addr) + BIT_WORD(nr);
75         unsigned int old = *p;
76 
77         *p = old & ~mask;
78         return (old & mask) != 0;
79 }
80 
81 /* WARNING: non atomic and it can be reordered! */
__test_and_change_bit(int nr,volatile void * addr)82 static inline int __test_and_change_bit(int nr,
83                                             volatile void *addr)
84 {
85         unsigned int mask = BIT_MASK(nr);
86         volatile unsigned int *p =
87                 ((volatile unsigned int *)addr) + BIT_WORD(nr);
88         unsigned int old = *p;
89 
90         *p = old ^ mask;
91         return (old & mask) != 0;
92 }
93 
94 /**
95  * test_bit - Determine whether a bit is set
96  * @nr: bit number to test
97  * @addr: Address to start counting from
98  */
test_bit(int nr,const volatile void * addr)99 static inline int test_bit(int nr, const volatile void *addr)
100 {
101         const volatile unsigned int *p = (const volatile unsigned int *)addr;
102         return 1UL & (p[BIT_WORD(nr)] >> (nr & (BITS_PER_WORD-1)));
103 }
104 
105 /*
106  * On ARMv5 and above those functions can be implemented around
107  * the clz instruction for much better code efficiency.
108  */
109 
fls(unsigned int x)110 static inline int fls(unsigned int x)
111 {
112         int ret;
113 
114         if (__builtin_constant_p(x))
115                return generic_fls(x);
116 
117         asm("clz\t%"__OP32"0, %"__OP32"1" : "=r" (ret) : "r" (x));
118         return 32 - ret;
119 }
120 
121 
122 #define ffs(x) ({ unsigned int __t = (x); fls(__t & -__t); })
123 #define ffsl(x) ({ unsigned long __t = (x); flsl(__t & -__t); })
124 
125 /**
126  * find_first_set_bit - find the first set bit in @word
127  * @word: the word to search
128  *
129  * Returns the bit-number of the first set bit (first bit being 0).
130  * The input must *not* be zero.
131  */
find_first_set_bit(unsigned long word)132 static inline unsigned int find_first_set_bit(unsigned long word)
133 {
134         return ffsl(word) - 1;
135 }
136 
137 /**
138  * hweightN - returns the hamming weight of a N-bit word
139  * @x: the word to weigh
140  *
141  * The Hamming Weight of a number is the total number of bits set in it.
142  */
143 #define hweight64(x) generic_hweight64(x)
144 #define hweight32(x) generic_hweight32(x)
145 #define hweight16(x) generic_hweight16(x)
146 #define hweight8(x) generic_hweight8(x)
147 
148 #endif /* _ARM_BITOPS_H */
149 /*
150  * Local variables:
151  * mode: C
152  * c-file-style: "BSD"
153  * c-basic-offset: 4
154  * indent-tabs-mode: nil
155  * End:
156  */
157