1 /*
2 * Copyright (c) 2020, Wind River Systems, Inc.
3 * Copyright (c) 2017, Oticon A/S
4 * Copyright (c) 2020, Synopsys
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 /* Memory bits manipulation functions in non-arch-specific C code */
10
11 #ifndef ZEPHYR_INCLUDE_ARCH_COMMON_SYS_BITOPS_H_
12 #define ZEPHYR_INCLUDE_ARCH_COMMON_SYS_BITOPS_H_
13
14 #ifndef _ASMLANGUAGE
15
16 #include <zephyr/toolchain.h>
17 #include <zephyr/types.h>
18 #include <zephyr/sys/sys_io.h>
19
20 #ifdef __cplusplus
21 extern "C" {
22 #endif
23
sys_set_bit(mem_addr_t addr,unsigned int bit)24 static ALWAYS_INLINE void sys_set_bit(mem_addr_t addr, unsigned int bit)
25 {
26 uint32_t temp = *(volatile uint32_t *)addr;
27
28 *(volatile uint32_t *)addr = temp | (1 << bit);
29 }
30
sys_clear_bit(mem_addr_t addr,unsigned int bit)31 static ALWAYS_INLINE void sys_clear_bit(mem_addr_t addr, unsigned int bit)
32 {
33 uint32_t temp = *(volatile uint32_t *)addr;
34
35 *(volatile uint32_t *)addr = temp & ~(1 << bit);
36 }
37
sys_test_bit(mem_addr_t addr,unsigned int bit)38 static ALWAYS_INLINE int sys_test_bit(mem_addr_t addr, unsigned int bit)
39 {
40 uint32_t temp = *(volatile uint32_t *)addr;
41
42 return temp & (1 << bit);
43 }
44
sys_set_bits(mem_addr_t addr,unsigned int mask)45 static ALWAYS_INLINE void sys_set_bits(mem_addr_t addr, unsigned int mask)
46 {
47 uint32_t temp = *(volatile uint32_t *)addr;
48
49 *(volatile uint32_t *)addr = temp | mask;
50 }
51
sys_clear_bits(mem_addr_t addr,unsigned int mask)52 static ALWAYS_INLINE void sys_clear_bits(mem_addr_t addr, unsigned int mask)
53 {
54 uint32_t temp = *(volatile uint32_t *)addr;
55
56 *(volatile uint32_t *)addr = temp & ~mask;
57 }
58
59 static ALWAYS_INLINE
sys_bitfield_set_bit(mem_addr_t addr,unsigned int bit)60 void sys_bitfield_set_bit(mem_addr_t addr, unsigned int bit)
61 {
62 /* Doing memory offsets in terms of 32-bit values to prevent
63 * alignment issues
64 */
65 sys_set_bit(addr + ((bit >> 5) << 2), bit & 0x1F);
66 }
67
68 static ALWAYS_INLINE
sys_bitfield_clear_bit(mem_addr_t addr,unsigned int bit)69 void sys_bitfield_clear_bit(mem_addr_t addr, unsigned int bit)
70 {
71 sys_clear_bit(addr + ((bit >> 5) << 2), bit & 0x1F);
72 }
73
74 static ALWAYS_INLINE
sys_bitfield_test_bit(mem_addr_t addr,unsigned int bit)75 int sys_bitfield_test_bit(mem_addr_t addr, unsigned int bit)
76 {
77 return sys_test_bit(addr + ((bit >> 5) << 2), bit & 0x1F);
78 }
79
80 static ALWAYS_INLINE
sys_test_and_set_bit(mem_addr_t addr,unsigned int bit)81 int sys_test_and_set_bit(mem_addr_t addr, unsigned int bit)
82 {
83 int ret;
84
85 ret = sys_test_bit(addr, bit);
86 sys_set_bit(addr, bit);
87
88 return ret;
89 }
90
91 static ALWAYS_INLINE
sys_test_and_clear_bit(mem_addr_t addr,unsigned int bit)92 int sys_test_and_clear_bit(mem_addr_t addr, unsigned int bit)
93 {
94 int ret;
95
96 ret = sys_test_bit(addr, bit);
97 sys_clear_bit(addr, bit);
98
99 return ret;
100 }
101
102 static ALWAYS_INLINE
sys_bitfield_test_and_set_bit(mem_addr_t addr,unsigned int bit)103 int sys_bitfield_test_and_set_bit(mem_addr_t addr, unsigned int bit)
104 {
105 int ret;
106
107 ret = sys_bitfield_test_bit(addr, bit);
108 sys_bitfield_set_bit(addr, bit);
109
110 return ret;
111 }
112
113 static ALWAYS_INLINE
sys_bitfield_test_and_clear_bit(mem_addr_t addr,unsigned int bit)114 int sys_bitfield_test_and_clear_bit(mem_addr_t addr, unsigned int bit)
115 {
116 int ret;
117
118 ret = sys_bitfield_test_bit(addr, bit);
119 sys_bitfield_clear_bit(addr, bit);
120
121 return ret;
122 }
123
124 #ifdef __cplusplus
125 }
126 #endif
127
128 #endif /* _ASMLANGUAGE */
129
130 #endif /* ZEPHYR_INCLUDE_ARCH_COMMON_SYS_BITOPS_H_ */
131