#define _LINUX_BITFIELD_H
 
 #include <linux/build_bug.h>
+#include <linux/typecheck.h>
 #include <asm/byteorder.h>
 
 /*
  *       FIELD_PREP(REG_FIELD_D, 0x40);
  *
  * Modify:
- *  reg &= ~REG_FIELD_C;
- *  reg |= FIELD_PREP(REG_FIELD_C, c);
+ *  FIELD_MODIFY(REG_FIELD_C, ®, c);
  */
 
 #define __bf_shf(x) (__builtin_ffsll(x) - 1)
                (typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); \
        })
 
+/**
+ * FIELD_MODIFY() - modify a bitfield element
+ * @_mask: shifted mask defining the field's length and position
+ * @_reg_p: pointer to the memory that should be updated
+ * @_val: value to store in the bitfield
+ *
+ * FIELD_MODIFY() modifies the set of bits in @_reg_p specified by @_mask,
+ * by replacing them with the bitfield value passed in as @_val.
+ */
+#define FIELD_MODIFY(_mask, _reg_p, _val)                                              \
+       ({                                                                              \
+               typecheck_pointer(_reg_p);                                              \
+               __BF_FIELD_CHECK(_mask, *(_reg_p), _val, "FIELD_MODIFY: ");             \
+               *(_reg_p) &= ~(_mask);                                                  \
+               *(_reg_p) |= (((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask));    \
+       })
+
 extern void __compiletime_error("value doesn't fit into mask")
 __field_overflow(void);
 extern void __compiletime_error("bad bitfield mask")