18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright 1995, Russell King. 48c2ecf20Sopenharmony_ci * Various bits and pieces copyrights include: 58c2ecf20Sopenharmony_ci * Linus Torvalds (test_bit). 68c2ecf20Sopenharmony_ci * Big endian support: Copyright 2001, Nicolas Pitre 78c2ecf20Sopenharmony_ci * reworked by rmk. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * bit 0 is the LSB of an "unsigned long" quantity. 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * Please note that the code in this file should never be included 128c2ecf20Sopenharmony_ci * from user space. Many of these are not implemented in assembler 138c2ecf20Sopenharmony_ci * since they would be too costly. Also, they require privileged 148c2ecf20Sopenharmony_ci * instructions (which are not available from user mode) to ensure 158c2ecf20Sopenharmony_ci * that they are atomic. 168c2ecf20Sopenharmony_ci */ 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#ifndef __ASM_ARM_BITOPS_H 198c2ecf20Sopenharmony_ci#define __ASM_ARM_BITOPS_H 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#ifdef __KERNEL__ 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#ifndef _LINUX_BITOPS_H 248c2ecf20Sopenharmony_ci#error only <linux/bitops.h> can be included directly 258c2ecf20Sopenharmony_ci#endif 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci#include <linux/compiler.h> 288c2ecf20Sopenharmony_ci#include <linux/irqflags.h> 298c2ecf20Sopenharmony_ci#include <asm/barrier.h> 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci/* 328c2ecf20Sopenharmony_ci * These functions are the basis of our bit ops. 338c2ecf20Sopenharmony_ci * 348c2ecf20Sopenharmony_ci * First, the atomic bitops. These use native endian. 358c2ecf20Sopenharmony_ci */ 368c2ecf20Sopenharmony_cistatic inline void ____atomic_set_bit(unsigned int bit, volatile unsigned long *p) 378c2ecf20Sopenharmony_ci{ 388c2ecf20Sopenharmony_ci unsigned long flags; 398c2ecf20Sopenharmony_ci unsigned long mask = BIT_MASK(bit); 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci p += BIT_WORD(bit); 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci raw_local_irq_save(flags); 448c2ecf20Sopenharmony_ci *p |= mask; 458c2ecf20Sopenharmony_ci raw_local_irq_restore(flags); 468c2ecf20Sopenharmony_ci} 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_cistatic inline void ____atomic_clear_bit(unsigned int bit, volatile unsigned long *p) 498c2ecf20Sopenharmony_ci{ 508c2ecf20Sopenharmony_ci unsigned long flags; 518c2ecf20Sopenharmony_ci unsigned long mask = BIT_MASK(bit); 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci p += BIT_WORD(bit); 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci raw_local_irq_save(flags); 568c2ecf20Sopenharmony_ci *p &= ~mask; 578c2ecf20Sopenharmony_ci raw_local_irq_restore(flags); 588c2ecf20Sopenharmony_ci} 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_cistatic inline void ____atomic_change_bit(unsigned int bit, volatile unsigned long *p) 618c2ecf20Sopenharmony_ci{ 628c2ecf20Sopenharmony_ci unsigned long flags; 638c2ecf20Sopenharmony_ci unsigned long mask = BIT_MASK(bit); 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci p += BIT_WORD(bit); 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci raw_local_irq_save(flags); 688c2ecf20Sopenharmony_ci *p ^= mask; 698c2ecf20Sopenharmony_ci raw_local_irq_restore(flags); 708c2ecf20Sopenharmony_ci} 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_cistatic inline int 738c2ecf20Sopenharmony_ci____atomic_test_and_set_bit(unsigned int bit, volatile unsigned long *p) 748c2ecf20Sopenharmony_ci{ 758c2ecf20Sopenharmony_ci unsigned long flags; 768c2ecf20Sopenharmony_ci unsigned int res; 778c2ecf20Sopenharmony_ci unsigned long mask = BIT_MASK(bit); 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci p += BIT_WORD(bit); 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci raw_local_irq_save(flags); 828c2ecf20Sopenharmony_ci res = *p; 838c2ecf20Sopenharmony_ci *p = res | mask; 848c2ecf20Sopenharmony_ci raw_local_irq_restore(flags); 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci return (res & mask) != 0; 878c2ecf20Sopenharmony_ci} 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_cistatic inline int 908c2ecf20Sopenharmony_ci____atomic_test_and_clear_bit(unsigned int bit, volatile unsigned long *p) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci unsigned long flags; 938c2ecf20Sopenharmony_ci unsigned int res; 948c2ecf20Sopenharmony_ci unsigned long mask = BIT_MASK(bit); 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci p += BIT_WORD(bit); 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci raw_local_irq_save(flags); 998c2ecf20Sopenharmony_ci res = *p; 1008c2ecf20Sopenharmony_ci *p = res & ~mask; 1018c2ecf20Sopenharmony_ci raw_local_irq_restore(flags); 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci return (res & mask) != 0; 1048c2ecf20Sopenharmony_ci} 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_cistatic inline int 1078c2ecf20Sopenharmony_ci____atomic_test_and_change_bit(unsigned int bit, volatile unsigned long *p) 1088c2ecf20Sopenharmony_ci{ 1098c2ecf20Sopenharmony_ci unsigned long flags; 1108c2ecf20Sopenharmony_ci unsigned int res; 1118c2ecf20Sopenharmony_ci unsigned long mask = BIT_MASK(bit); 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci p += BIT_WORD(bit); 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci raw_local_irq_save(flags); 1168c2ecf20Sopenharmony_ci res = *p; 1178c2ecf20Sopenharmony_ci *p = res ^ mask; 1188c2ecf20Sopenharmony_ci raw_local_irq_restore(flags); 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci return (res & mask) != 0; 1218c2ecf20Sopenharmony_ci} 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci#include <asm-generic/bitops/non-atomic.h> 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci/* 1268c2ecf20Sopenharmony_ci * A note about Endian-ness. 1278c2ecf20Sopenharmony_ci * ------------------------- 1288c2ecf20Sopenharmony_ci * 1298c2ecf20Sopenharmony_ci * When the ARM is put into big endian mode via CR15, the processor 1308c2ecf20Sopenharmony_ci * merely swaps the order of bytes within words, thus: 1318c2ecf20Sopenharmony_ci * 1328c2ecf20Sopenharmony_ci * ------------ physical data bus bits ----------- 1338c2ecf20Sopenharmony_ci * D31 ... D24 D23 ... D16 D15 ... D8 D7 ... D0 1348c2ecf20Sopenharmony_ci * little byte 3 byte 2 byte 1 byte 0 1358c2ecf20Sopenharmony_ci * big byte 0 byte 1 byte 2 byte 3 1368c2ecf20Sopenharmony_ci * 1378c2ecf20Sopenharmony_ci * This means that reading a 32-bit word at address 0 returns the same 1388c2ecf20Sopenharmony_ci * value irrespective of the endian mode bit. 1398c2ecf20Sopenharmony_ci * 1408c2ecf20Sopenharmony_ci * Peripheral devices should be connected with the data bus reversed in 1418c2ecf20Sopenharmony_ci * "Big Endian" mode. ARM Application Note 61 is applicable, and is 1428c2ecf20Sopenharmony_ci * available from http://www.arm.com/. 1438c2ecf20Sopenharmony_ci * 1448c2ecf20Sopenharmony_ci * The following assumes that the data bus connectivity for big endian 1458c2ecf20Sopenharmony_ci * mode has been followed. 1468c2ecf20Sopenharmony_ci * 1478c2ecf20Sopenharmony_ci * Note that bit 0 is defined to be 32-bit word bit 0, not byte 0 bit 0. 1488c2ecf20Sopenharmony_ci */ 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci/* 1518c2ecf20Sopenharmony_ci * Native endian assembly bitops. nr = 0 -> word 0 bit 0. 1528c2ecf20Sopenharmony_ci */ 1538c2ecf20Sopenharmony_ciextern void _set_bit(int nr, volatile unsigned long * p); 1548c2ecf20Sopenharmony_ciextern void _clear_bit(int nr, volatile unsigned long * p); 1558c2ecf20Sopenharmony_ciextern void _change_bit(int nr, volatile unsigned long * p); 1568c2ecf20Sopenharmony_ciextern int _test_and_set_bit(int nr, volatile unsigned long * p); 1578c2ecf20Sopenharmony_ciextern int _test_and_clear_bit(int nr, volatile unsigned long * p); 1588c2ecf20Sopenharmony_ciextern int _test_and_change_bit(int nr, volatile unsigned long * p); 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci/* 1618c2ecf20Sopenharmony_ci * Little endian assembly bitops. nr = 0 -> byte 0 bit 0. 1628c2ecf20Sopenharmony_ci */ 1638c2ecf20Sopenharmony_ciextern int _find_first_zero_bit_le(const unsigned long *p, unsigned size); 1648c2ecf20Sopenharmony_ciextern int _find_next_zero_bit_le(const unsigned long *p, int size, int offset); 1658c2ecf20Sopenharmony_ciextern int _find_first_bit_le(const unsigned long *p, unsigned size); 1668c2ecf20Sopenharmony_ciextern int _find_next_bit_le(const unsigned long *p, int size, int offset); 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci/* 1698c2ecf20Sopenharmony_ci * Big endian assembly bitops. nr = 0 -> byte 3 bit 0. 1708c2ecf20Sopenharmony_ci */ 1718c2ecf20Sopenharmony_ciextern int _find_first_zero_bit_be(const unsigned long *p, unsigned size); 1728c2ecf20Sopenharmony_ciextern int _find_next_zero_bit_be(const unsigned long *p, int size, int offset); 1738c2ecf20Sopenharmony_ciextern int _find_first_bit_be(const unsigned long *p, unsigned size); 1748c2ecf20Sopenharmony_ciextern int _find_next_bit_be(const unsigned long *p, int size, int offset); 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci#ifndef CONFIG_SMP 1778c2ecf20Sopenharmony_ci/* 1788c2ecf20Sopenharmony_ci * The __* form of bitops are non-atomic and may be reordered. 1798c2ecf20Sopenharmony_ci */ 1808c2ecf20Sopenharmony_ci#define ATOMIC_BITOP(name,nr,p) \ 1818c2ecf20Sopenharmony_ci (__builtin_constant_p(nr) ? ____atomic_##name(nr, p) : _##name(nr,p)) 1828c2ecf20Sopenharmony_ci#else 1838c2ecf20Sopenharmony_ci#define ATOMIC_BITOP(name,nr,p) _##name(nr,p) 1848c2ecf20Sopenharmony_ci#endif 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci/* 1878c2ecf20Sopenharmony_ci * Native endian atomic definitions. 1888c2ecf20Sopenharmony_ci */ 1898c2ecf20Sopenharmony_ci#define set_bit(nr,p) ATOMIC_BITOP(set_bit,nr,p) 1908c2ecf20Sopenharmony_ci#define clear_bit(nr,p) ATOMIC_BITOP(clear_bit,nr,p) 1918c2ecf20Sopenharmony_ci#define change_bit(nr,p) ATOMIC_BITOP(change_bit,nr,p) 1928c2ecf20Sopenharmony_ci#define test_and_set_bit(nr,p) ATOMIC_BITOP(test_and_set_bit,nr,p) 1938c2ecf20Sopenharmony_ci#define test_and_clear_bit(nr,p) ATOMIC_BITOP(test_and_clear_bit,nr,p) 1948c2ecf20Sopenharmony_ci#define test_and_change_bit(nr,p) ATOMIC_BITOP(test_and_change_bit,nr,p) 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci#ifndef __ARMEB__ 1978c2ecf20Sopenharmony_ci/* 1988c2ecf20Sopenharmony_ci * These are the little endian, atomic definitions. 1998c2ecf20Sopenharmony_ci */ 2008c2ecf20Sopenharmony_ci#define find_first_zero_bit(p,sz) _find_first_zero_bit_le(p,sz) 2018c2ecf20Sopenharmony_ci#define find_next_zero_bit(p,sz,off) _find_next_zero_bit_le(p,sz,off) 2028c2ecf20Sopenharmony_ci#define find_first_bit(p,sz) _find_first_bit_le(p,sz) 2038c2ecf20Sopenharmony_ci#define find_next_bit(p,sz,off) _find_next_bit_le(p,sz,off) 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci#else 2068c2ecf20Sopenharmony_ci/* 2078c2ecf20Sopenharmony_ci * These are the big endian, atomic definitions. 2088c2ecf20Sopenharmony_ci */ 2098c2ecf20Sopenharmony_ci#define find_first_zero_bit(p,sz) _find_first_zero_bit_be(p,sz) 2108c2ecf20Sopenharmony_ci#define find_next_zero_bit(p,sz,off) _find_next_zero_bit_be(p,sz,off) 2118c2ecf20Sopenharmony_ci#define find_first_bit(p,sz) _find_first_bit_be(p,sz) 2128c2ecf20Sopenharmony_ci#define find_next_bit(p,sz,off) _find_next_bit_be(p,sz,off) 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci#endif 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci#if __LINUX_ARM_ARCH__ < 5 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci#include <asm-generic/bitops/__fls.h> 2198c2ecf20Sopenharmony_ci#include <asm-generic/bitops/__ffs.h> 2208c2ecf20Sopenharmony_ci#include <asm-generic/bitops/fls.h> 2218c2ecf20Sopenharmony_ci#include <asm-generic/bitops/ffs.h> 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci#else 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci/* 2268c2ecf20Sopenharmony_ci * On ARMv5 and above, the gcc built-ins may rely on the clz instruction 2278c2ecf20Sopenharmony_ci * and produce optimal inlined code in all cases. On ARMv7 it is even 2288c2ecf20Sopenharmony_ci * better by also using the rbit instruction. 2298c2ecf20Sopenharmony_ci */ 2308c2ecf20Sopenharmony_ci#include <asm-generic/bitops/builtin-__fls.h> 2318c2ecf20Sopenharmony_ci#include <asm-generic/bitops/builtin-__ffs.h> 2328c2ecf20Sopenharmony_ci#include <asm-generic/bitops/builtin-fls.h> 2338c2ecf20Sopenharmony_ci#include <asm-generic/bitops/builtin-ffs.h> 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci#endif 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci#include <asm-generic/bitops/ffz.h> 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci#include <asm-generic/bitops/fls64.h> 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci#include <asm-generic/bitops/sched.h> 2428c2ecf20Sopenharmony_ci#include <asm-generic/bitops/hweight.h> 2438c2ecf20Sopenharmony_ci#include <asm-generic/bitops/lock.h> 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci#ifdef __ARMEB__ 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_cistatic inline int find_first_zero_bit_le(const void *p, unsigned size) 2488c2ecf20Sopenharmony_ci{ 2498c2ecf20Sopenharmony_ci return _find_first_zero_bit_le(p, size); 2508c2ecf20Sopenharmony_ci} 2518c2ecf20Sopenharmony_ci#define find_first_zero_bit_le find_first_zero_bit_le 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_cistatic inline int find_next_zero_bit_le(const void *p, int size, int offset) 2548c2ecf20Sopenharmony_ci{ 2558c2ecf20Sopenharmony_ci return _find_next_zero_bit_le(p, size, offset); 2568c2ecf20Sopenharmony_ci} 2578c2ecf20Sopenharmony_ci#define find_next_zero_bit_le find_next_zero_bit_le 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_cistatic inline int find_next_bit_le(const void *p, int size, int offset) 2608c2ecf20Sopenharmony_ci{ 2618c2ecf20Sopenharmony_ci return _find_next_bit_le(p, size, offset); 2628c2ecf20Sopenharmony_ci} 2638c2ecf20Sopenharmony_ci#define find_next_bit_le find_next_bit_le 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci#endif 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci#include <asm-generic/bitops/find.h> 2688c2ecf20Sopenharmony_ci#include <asm-generic/bitops/le.h> 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci/* 2718c2ecf20Sopenharmony_ci * Ext2 is defined to use little-endian byte ordering. 2728c2ecf20Sopenharmony_ci */ 2738c2ecf20Sopenharmony_ci#include <asm-generic/bitops/ext2-atomic-setbit.h> 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci#endif /* __KERNEL__ */ 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci#endif /* _ARM_BITOPS_H */ 278