xref: /openbmc/u-boot/arch/sh/include/asm/bitops.h (revision dd4671cb)
1 #ifndef __ASM_SH_BITOPS_H
2 #define __ASM_SH_BITOPS_H
3 
4 #include <asm-generic/bitops/fls.h>
5 #include <asm-generic/bitops/__fls.h>
6 #include <asm-generic/bitops/fls64.h>
7 #include <asm-generic/bitops/__ffs.h>
8 
9 #ifdef __KERNEL__
10 #include <asm/irqflags.h>
11 /* For __swab32 */
12 #include <asm/byteorder.h>
13 
14 static inline void set_bit(int nr, volatile void * addr)
15 {
16 	int	mask;
17 	volatile unsigned int *a = addr;
18 	unsigned long flags;
19 
20 	a += nr >> 5;
21 	mask = 1 << (nr & 0x1f);
22 	local_irq_save(flags);
23 	*a |= mask;
24 	local_irq_restore(flags);
25 }
26 
27 /*
28  * clear_bit() doesn't provide any barrier for the compiler.
29  */
30 #define smp_mb__before_clear_bit()	barrier()
31 #define smp_mb__after_clear_bit()	barrier()
32 static inline void clear_bit(int nr, volatile void * addr)
33 {
34 	int	mask;
35 	volatile unsigned int *a = addr;
36 	unsigned long flags;
37 
38 	a += nr >> 5;
39 	mask = 1 << (nr & 0x1f);
40 	local_irq_save(flags);
41 	*a &= ~mask;
42 	local_irq_restore(flags);
43 }
44 
45 static inline void change_bit(int nr, volatile void * addr)
46 {
47 	int	mask;
48 	volatile unsigned int *a = addr;
49 	unsigned long flags;
50 
51 	a += nr >> 5;
52 	mask = 1 << (nr & 0x1f);
53 	local_irq_save(flags);
54 	*a ^= mask;
55 	local_irq_restore(flags);
56 }
57 
58 static inline int test_and_set_bit(int nr, volatile void * addr)
59 {
60 	int	mask, retval;
61 	volatile unsigned int *a = addr;
62 	unsigned long flags;
63 
64 	a += nr >> 5;
65 	mask = 1 << (nr & 0x1f);
66 	local_irq_save(flags);
67 	retval = (mask & *a) != 0;
68 	*a |= mask;
69 	local_irq_restore(flags);
70 
71 	return retval;
72 }
73 
74 static inline int test_and_clear_bit(int nr, volatile void * addr)
75 {
76 	int	mask, retval;
77 	volatile unsigned int *a = addr;
78 	unsigned long flags;
79 
80 	a += nr >> 5;
81 	mask = 1 << (nr & 0x1f);
82 	local_irq_save(flags);
83 	retval = (mask & *a) != 0;
84 	*a &= ~mask;
85 	local_irq_restore(flags);
86 
87 	return retval;
88 }
89 
90 static inline int test_and_change_bit(int nr, volatile void * addr)
91 {
92 	int	mask, retval;
93 	volatile unsigned int *a = addr;
94 	unsigned long flags;
95 
96 	a += nr >> 5;
97 	mask = 1 << (nr & 0x1f);
98 	local_irq_save(flags);
99 	retval = (mask & *a) != 0;
100 	*a ^= mask;
101 	local_irq_restore(flags);
102 
103 	return retval;
104 }
105 
106 static inline unsigned long ffz(unsigned long word)
107 {
108 	unsigned long result;
109 
110 	__asm__("1:\n\t"
111 		"shlr	%1\n\t"
112 		"bt/s	1b\n\t"
113 		" add	#1, %0"
114 		: "=r" (result), "=r" (word)
115 		: "0" (~0L), "1" (word)
116 		: "t");
117 	return result;
118 }
119 
120 /**
121  * ffs - find first bit in word.
122  * @word: The word to search
123  *
124  * Undefined if no bit exists, so code should check against 0 first.
125  */
126 static inline int ffs (int x)
127 {
128 	int r = 1;
129 
130 	if (!x)
131 		return 0;
132 	if (!(x & 0xffff)) {
133 		x >>= 16;
134 		r += 16;
135 	}
136 	if (!(x & 0xff)) {
137 		x >>= 8;
138 		r += 8;
139 	}
140 	if (!(x & 0xf)) {
141 		x >>= 4;
142 		r += 4;
143 	}
144 	if (!(x & 3)) {
145 		x >>= 2;
146 		r += 2;
147 	}
148 	if (!(x & 1)) {
149 		x >>= 1;
150 		r += 1;
151 	}
152 	return r;
153 }
154 #define PLATFORM_FFS
155 
156 #endif /* __KERNEL__ */
157 
158 #endif /* __ASM_SH_BITOPS_H */
159