diff options
| author | Jonas Karlman <[email protected]> | 2026-08-03 18:43:12 +0000 |
|---|---|---|
| committer | Quentin Schulz <[email protected]> | 2026-08-11 17:35:22 +0200 |
| commit | 0c68b88ce574ddaa2f94f3e5d747c25db693dc18 (patch) | |
| tree | eff26d6da5486609a7e750ee595ba39f671adb62 /include | |
| parent | 36c377b9859ffb53eb1e39ea31e8d96d1e0fe1e5 (diff) | |
include: linux: Import hw_bitfield.h from Linux v6.18
Hardware of various vendors, but very notably Rockchip, often uses
32-bit registers where the upper 16-bit half of the register is a
write-enable mask for the lower half.
Add hw_bitfield.h with two macros: FIELD_PREP_WM16, and
FIELD_PREP_WM16_CONST. The latter is a version that can be used in
initializers, like FIELD_PREP_CONST.
Import hw_bitfield.h from Linux commit 21368fcbb124 ("bitmap: introduce
hardware-specific bitfield operations"), first introduced in v6.18-rc1.
This contains two changes compared to the Linux version:
- include of linux/limit.h was dropped
- use of const_true() in FIELD_PREP_WM16_CONST() was dropped
Signed-off-by: Jonas Karlman <[email protected]>
Acked-by: Quentin Schulz <[email protected]>
Reviewed-by: Tom Rini <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Quentin Schulz <[email protected]>
Diffstat (limited to 'include')
| -rw-r--r-- | include/linux/hw_bitfield.h | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/include/linux/hw_bitfield.h b/include/linux/hw_bitfield.h new file mode 100644 index 00000000000..6e74d902ed3 --- /dev/null +++ b/include/linux/hw_bitfield.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2025, Collabora Ltd. + */ + +#ifndef _LINUX_HW_BITFIELD_H +#define _LINUX_HW_BITFIELD_H + +#include <linux/bitfield.h> +#include <linux/build_bug.h> + +/** + * FIELD_PREP_WM16() - prepare a bitfield element with a mask in the upper half + * @_mask: shifted mask defining the field's length and position + * @_val: value to put in the field + * + * FIELD_PREP_WM16() masks and shifts up the value, as well as bitwise ORs the + * result with the mask shifted up by 16. + * + * This is useful for a common design of hardware registers where the upper + * 16-bit half of a 32-bit register is used as a write-enable mask. In such a + * register, a bit in the lower half is only updated if the corresponding bit + * in the upper half is high. + */ +#define FIELD_PREP_WM16(_mask, _val) \ + ({ \ + typeof(_val) __val = _val; \ + typeof(_mask) __mask = _mask; \ + __BF_FIELD_CHECK(__mask, ((u16)0U), __val, \ + "HWORD_UPDATE: "); \ + (((typeof(__mask))(__val) << __bf_shf(__mask)) & (__mask)) | \ + ((__mask) << 16); \ + }) + +/** + * FIELD_PREP_WM16_CONST() - prepare a constant bitfield element with a mask in + * the upper half + * @_mask: shifted mask defining the field's length and position + * @_val: value to put in the field + * + * FIELD_PREP_WM16_CONST() masks and shifts up the value, as well as bitwise ORs + * the result with the mask shifted up by 16. + * + * This is useful for a common design of hardware registers where the upper + * 16-bit half of a 32-bit register is used as a write-enable mask. In such a + * register, a bit in the lower half is only updated if the corresponding bit + * in the upper half is high. + * + * Unlike FIELD_PREP_WM16(), this is a constant expression and can therefore + * be used in initializers. Error checking is less comfortable for this + * version. + */ +#define FIELD_PREP_WM16_CONST(_mask, _val) \ + ( \ + FIELD_PREP_CONST(_mask, _val) | \ + (BUILD_BUG_ON_ZERO((u64)(_mask) > U16_MAX) + \ + ((_mask) << 16)) \ + ) + + +#endif /* _LINUX_HW_BITFIELD_H */ |
