|
8 | 8 | #define _LINUX_BITFIELD_H
|
9 | 9 |
|
10 | 10 | #include <linux/build_bug.h>
|
| 11 | +#include <linux/typecheck.h> |
11 | 12 | #include <asm/byteorder.h>
|
12 | 13 |
|
13 | 14 | /*
|
|
38 | 39 | * FIELD_PREP(REG_FIELD_D, 0x40);
|
39 | 40 | *
|
40 | 41 | * Modify:
|
41 |
| - * reg &= ~REG_FIELD_C; |
42 |
| - * reg |= FIELD_PREP(REG_FIELD_C, c); |
| 42 | + * FIELD_MODIFY(REG_FIELD_C, ®, c); |
43 | 43 | */
|
44 | 44 |
|
45 | 45 | #define __bf_shf(x) (__builtin_ffsll(x) - 1)
|
|
156 | 156 | (typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); \
|
157 | 157 | })
|
158 | 158 |
|
| 159 | +/** |
| 160 | + * FIELD_MODIFY() - modify a bitfield element |
| 161 | + * @_mask: shifted mask defining the field's length and position |
| 162 | + * @_reg_p: pointer to the memory that should be updated |
| 163 | + * @_val: value to store in the bitfield |
| 164 | + * |
| 165 | + * FIELD_MODIFY() modifies the set of bits in @_reg_p specified by @_mask, |
| 166 | + * by replacing them with the bitfield value passed in as @_val. |
| 167 | + */ |
| 168 | +#define FIELD_MODIFY(_mask, _reg_p, _val) \ |
| 169 | + ({ \ |
| 170 | + typecheck_pointer(_reg_p); \ |
| 171 | + __BF_FIELD_CHECK(_mask, *(_reg_p), _val, "FIELD_MODIFY: "); \ |
| 172 | + *(_reg_p) &= ~(_mask); \ |
| 173 | + *(_reg_p) |= (((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask)); \ |
| 174 | + }) |
| 175 | + |
159 | 176 | extern void __compiletime_error("value doesn't fit into mask")
|
160 | 177 | __field_overflow(void);
|
161 | 178 | extern void __compiletime_error("bad bitfield mask")
|
|
0 commit comments