2 * This confidential and proprietary software may be used only as
3 * authorised by a licensing agreement from ARM Limited
4 * (C) COPYRIGHT 2008-2010, 2013 ARM Limited
6 * The entire notice above must be reproduced on all authorised
7 * copies and copies may only be made to the extent permitted
8 * by a licensing agreement from ARM Limited.
12 * @file mali_osk_bitops.h
13 * Implementation of the OS abstraction layer for the kernel device driver
16 #ifndef __MALI_OSK_BITOPS_H__
17 #define __MALI_OSK_BITOPS_H__
23 MALI_STATIC_INLINE
void _mali_internal_clear_bit( u32 bit
, u32
*addr
)
25 MALI_DEBUG_ASSERT( bit
< 32 );
26 MALI_DEBUG_ASSERT( NULL
!= addr
);
28 (*addr
) &= ~(1 << bit
);
31 MALI_STATIC_INLINE
void _mali_internal_set_bit( u32 bit
, u32
*addr
)
33 MALI_DEBUG_ASSERT( bit
< 32 );
34 MALI_DEBUG_ASSERT( NULL
!= addr
);
36 (*addr
) |= (1 << bit
);
39 MALI_STATIC_INLINE u32
_mali_internal_test_bit( u32 bit
, u32 value
)
41 MALI_DEBUG_ASSERT( bit
< 32 );
42 return value
& (1 << bit
);
45 MALI_STATIC_INLINE
int _mali_internal_find_first_zero_bit( u32 value
)
52 /* Begin with xxx...x0yyy...y, where ys are 1, number of ys is in range 0..31 */
53 inverted
= ~value
; /* zzz...z1000...0 */
54 /* Using count_trailing_zeros on inverted value -
55 * See ARM System Developers Guide for details of count_trailing_zeros */
57 /* Isolate the zero: it is preceeded by a run of 1s, so add 1 to it */
58 negated
= (u32
)-inverted
; /* -a == ~a + 1 (mod 2^n) for n-bit numbers */
59 /* negated = xxx...x1000...0 */
61 isolated
= negated
& inverted
; /* xxx...x1000...0 & zzz...z1000...0, zs are ~xs */
62 /* And so the first zero bit is in the same position as the 1 == number of 1s that preceeded it
63 * Note that the output is zero if value was all 1s */
65 leading_zeros
= _mali_osk_clz( isolated
);
67 return 31 - leading_zeros
;
71 /** @defgroup _mali_osk_bitops OSK Non-atomic Bit-operations
75 * These bit-operations do not work atomically, and so locks must be used if
76 * atomicity is required.
78 * Reference implementations for Little Endian are provided, and so it should
79 * not normally be necessary to re-implement these. Efficient bit-twiddling
80 * techniques are used where possible, implemented in portable C.
82 * Note that these reference implementations rely on _mali_osk_clz() being
86 /** @brief Clear a bit in a sequence of 32-bit words
87 * @param nr bit number to clear, starting from the (Little-endian) least
89 * @param addr starting point for counting.
91 MALI_STATIC_INLINE
void _mali_osk_clear_nonatomic_bit( u32 nr
, u32
*addr
)
93 addr
+= nr
>> 5; /* find the correct word */
94 nr
= nr
& ((1 << 5)-1); /* The bit number within the word */
96 _mali_internal_clear_bit( nr
, addr
);
99 /** @brief Set a bit in a sequence of 32-bit words
100 * @param nr bit number to set, starting from the (Little-endian) least
102 * @param addr starting point for counting.
104 MALI_STATIC_INLINE
void _mali_osk_set_nonatomic_bit( u32 nr
, u32
*addr
)
106 addr
+= nr
>> 5; /* find the correct word */
107 nr
= nr
& ((1 << 5)-1); /* The bit number within the word */
109 _mali_internal_set_bit( nr
, addr
);
112 /** @brief Test a bit in a sequence of 32-bit words
113 * @param nr bit number to test, starting from the (Little-endian) least
115 * @param addr starting point for counting.
116 * @return zero if bit was clear, non-zero if set. Do not rely on the return
117 * value being related to the actual word under test.
119 MALI_STATIC_INLINE u32
_mali_osk_test_bit( u32 nr
, u32
*addr
)
121 addr
+= nr
>> 5; /* find the correct word */
122 nr
= nr
& ((1 << 5)-1); /* The bit number within the word */
124 return _mali_internal_test_bit( nr
, *addr
);
127 /* Return maxbit if not found */
128 /** @brief Find the first zero bit in a sequence of 32-bit words
129 * @param addr starting point for search.
130 * @param maxbit the maximum number of bits to search
131 * @return the number of the first zero bit found, or maxbit if none were found
132 * in the specified range.
134 MALI_STATIC_INLINE u32
_mali_osk_find_first_zero_bit( const u32
*addr
, u32 maxbit
)
138 for ( total
= 0; total
< maxbit
; total
+= 32, ++addr
) {
140 result
= _mali_internal_find_first_zero_bit( *addr
);
142 /* non-negative signifies the bit was found */
144 total
+= (u32
)result
;
149 /* Now check if we reached maxbit or above */
150 if ( total
>= maxbit
) {
154 return total
; /* either the found bit nr, or maxbit if not found */
156 /** @} */ /* end group _mali_osk_bitops */
162 #endif /* __MALI_OSK_BITOPS_H__ */