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