sys: util: provide bitfield construction/extraction utility macros
Those are especially useful with hardware device registers.
They behave the same way as their Linux equivalent, with a much
simpler implementation for now.
Example:
#define REG_FIELD_A GENMASK(6, 0)
#define REG_FIELD_B BIT(7)
#define REG_FIELD_C GENMASK(15, 8)
#define REG_FIELD_D GENMASK(31, 16)
Get:
a = FIELD_GET(REG_FIELD_A, reg);
b = FIELD_GET(REG_FIELD_B, reg);
Set:
reg = FIELD_PREP(REG_FIELD_A, 1) |
FIELD_PREP(REG_FIELD_B, 0) |
FIELD_PREP(REG_FIELD_C, c) |
FIELD_PREP(REG_FIELD_D, 0x40);
Modify:
reg &= ~REG_FIELD_C;
reg |= FIELD_PREP(REG_FIELD_C, c);
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
This commit is contained in:
parent
aeee57bfe1
commit
bd73cd5512
@ -58,6 +58,22 @@ extern "C" {
|
||||
#define GENMASK(h, l) \
|
||||
(((~0UL) - (1UL << (l)) + 1) & (~0UL >> (BITS_PER_LONG - 1 - (h))))
|
||||
|
||||
/** @brief Extract the Least Significant Bit from @p value. */
|
||||
#define LSB_GET(value) ((value) & -(value))
|
||||
|
||||
/**
|
||||
* @brief Extract a bitfield element from @p value corresponding to
|
||||
* the field mask @p mask.
|
||||
*/
|
||||
#define FIELD_GET(mask, value) (((value) & (mask)) / LSB_GET(mask))
|
||||
|
||||
/**
|
||||
* @brief Prepare a bitfield element using @p value with @p mask representing
|
||||
* its field position and width. The result should be combined
|
||||
* with other fields using a logical OR.
|
||||
*/
|
||||
#define FIELD_PREP(mask, value) (((value) * LSB_GET(mask)) & (mask))
|
||||
|
||||
/** @brief 0 if @p cond is true-ish; causes a compile error otherwise. */
|
||||
#define ZERO_OR_COMPILE_ERROR(cond) ((int) sizeof(char[1 - 2 * !(cond)]) - 1)
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user