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