at master 2.2 kB view raw
1/* SPDX-License-Identifier: GPL-2.0-or-later */ 2/* 3 * Copyright (C) 2025, Collabora Ltd. 4 */ 5 6#ifndef _LINUX_HW_BITFIELD_H 7#define _LINUX_HW_BITFIELD_H 8 9#include <linux/bitfield.h> 10#include <linux/build_bug.h> 11#include <linux/limits.h> 12 13/** 14 * FIELD_PREP_WM16() - prepare a bitfield element with a mask in the upper half 15 * @_mask: shifted mask defining the field's length and position 16 * @_val: value to put in the field 17 * 18 * FIELD_PREP_WM16() masks and shifts up the value, as well as bitwise ORs the 19 * result with the mask shifted up by 16. 20 * 21 * This is useful for a common design of hardware registers where the upper 22 * 16-bit half of a 32-bit register is used as a write-enable mask. In such a 23 * register, a bit in the lower half is only updated if the corresponding bit 24 * in the upper half is high. 25 */ 26#define FIELD_PREP_WM16(_mask, _val) \ 27 ({ \ 28 typeof(_val) __val = _val; \ 29 typeof(_mask) __mask = _mask; \ 30 __BF_FIELD_CHECK(__mask, ((u16)0U), __val, \ 31 "HWORD_UPDATE: "); \ 32 (((typeof(__mask))(__val) << __bf_shf(__mask)) & (__mask)) | \ 33 ((__mask) << 16); \ 34 }) 35 36/** 37 * FIELD_PREP_WM16_CONST() - prepare a constant bitfield element with a mask in 38 * the upper half 39 * @_mask: shifted mask defining the field's length and position 40 * @_val: value to put in the field 41 * 42 * FIELD_PREP_WM16_CONST() masks and shifts up the value, as well as bitwise ORs 43 * the result with the mask shifted up by 16. 44 * 45 * This is useful for a common design of hardware registers where the upper 46 * 16-bit half of a 32-bit register is used as a write-enable mask. In such a 47 * register, a bit in the lower half is only updated if the corresponding bit 48 * in the upper half is high. 49 * 50 * Unlike FIELD_PREP_WM16(), this is a constant expression and can therefore 51 * be used in initializers. Error checking is less comfortable for this 52 * version. 53 */ 54#define FIELD_PREP_WM16_CONST(_mask, _val) \ 55 ( \ 56 FIELD_PREP_CONST(_mask, _val) | \ 57 (BUILD_BUG_ON_ZERO(const_true((u64)(_mask) > U16_MAX)) + \ 58 ((_mask) << 16)) \ 59 ) 60 61 62#endif /* _LINUX_HW_BITFIELD_H */