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 31unsigned long __fls(unsigned long word); 32unsigned long __ffs(unsigned long word); 33int fls(unsigned int x); 34int 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 */ 61extern void set_bit(int nr, volatile void * addr); 62 63extern void clear_bit(int nr, volatile void * addr); 64 65extern void change_bit(int nr, volatile void * addr); 66 67static 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 75static 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 85static 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 97static 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 107static 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 119extern int test_and_change_bit(int nr, volatile void * addr); 120 121static 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 */ 134static inline int test_bit(int nr, const void * addr) 135{ 136 return ((unsigned char *) addr)[nr >> 3] & (1U << (nr & 7)); 137} 138 139static inline int __ilog2(unsigned int x) 140{ 141 return fls(x) - 1; 142} 143 144#define ffz(x) __ffs(~(x)) 145 146static 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 177found_first: 178 tmp |= ~0UL << size; 179found_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