flash/nor/rp2040: preparatory refactoring
[fw/openocd] / src / helper / bits.h
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2
3 /*
4  * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
5  * Author(s): Antonio Borneo <borneo.antonio@gmail.com> for STMicroelectronics
6  */
7
8 /*
9  * The content of this file is mainly copied/inspired from Linux kernel
10  * code in include/linux/types.h include/linux/bitmap.h include/linux/bitops.h
11  */
12
13 #ifndef OPENOCD_HELPER_BITS_H
14 #define OPENOCD_HELPER_BITS_H
15
16 #include <helper/replacements.h>
17 #include <helper/types.h>
18
19 #define BIT(nr)                     (1UL << (nr))
20 #define BIT_ULL(nr)                 (1ULL << (nr))
21 #define BITS_PER_BYTE               8
22 #define BITS_PER_LONG               (BITS_PER_BYTE * sizeof(long))
23 #define BITS_PER_LONG_LONG          (BITS_PER_BYTE * sizeof(long long))
24 #define GENMASK(h, l)               (((~0UL) - (1UL << (l)) + 1) & (~0UL >> (BITS_PER_LONG - 1 - (h))))
25 #define GENMASK_ULL(h, l)           (((~0ULL) - (1ULL << (l)) + 1) & (~0ULL >> (BITS_PER_LONG_LONG - 1 - (h))))
26 #define BITS_TO_LONGS(nr)           DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
27 #define BIT_MASK(nr)                (1UL << ((nr) % BITS_PER_LONG))
28 #define BIT_WORD(nr)                ((nr) / BITS_PER_LONG)
29 #define DECLARE_BITMAP(name, bits)  unsigned long name[BITS_TO_LONGS(bits)]
30
31 /**
32  * bitmap_zero - Clears all the bits in memory
33  * @param dst the address of the bitmap
34  * @param nbits the number of bits to clear
35  */
36 static inline void bitmap_zero(unsigned long *dst, unsigned int nbits)
37 {
38         unsigned int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
39         memset(dst, 0, len);
40 }
41
42 /**
43  * clear_bit - Clear a bit in memory
44  * @param nr the bit to set
45  * @param addr the address to start counting from
46  */
47 static inline void clear_bit(unsigned int nr, volatile unsigned long *addr)
48 {
49         unsigned long mask = BIT_MASK(nr);
50         unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
51
52         *p &= ~mask;
53 }
54
55 /**
56  * set_bit - Set a bit in memory
57  * @param nr the bit to set
58  * @param addr the address to start counting from
59  */
60 static inline void set_bit(unsigned int nr, volatile unsigned long *addr)
61 {
62         unsigned long mask = BIT_MASK(nr);
63         unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
64
65         *p |= mask;
66 }
67
68 /**
69  * test_bit - Determine whether a bit is set
70  * @param nr bit number to test
71  * @param addr Address to start counting from
72  */
73 static inline int test_bit(unsigned int nr, const volatile unsigned long *addr)
74 {
75         return 1UL & (addr[BIT_WORD(nr)] >> (nr % BITS_PER_LONG));
76 }
77
78 #endif /* OPENOCD_HELPER_BITS_H */