1 /* 2 * Copyright 2013 Broadcom Corporation. 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 /* 8 * Bitfield operations 9 * 10 * These are generic bitfield operations which allow manipulation of variable 11 * width bitfields within a word. One use of this would be to use data tables 12 * to determine how to reprogram fields within R/W hardware registers. 13 * 14 * Example: 15 * 16 * old_reg_val 17 * +--------+----+---+--+-----+----------+ 18 * | | | | | old | | 19 * +--------+----+---+--+-----+----------+ 20 * 21 * new_reg_val 22 * +--------+----+---+--+-----+----------+ 23 * | | | | | new | | 24 * +--------+----+---+--+-----+----------+ 25 * 26 * mask = bitfield_mask(10, 5); 27 * old = bitfield_extract(old_reg_val, 10, 5); 28 * new_reg_val = bitfield_replace(old_reg_val, 10, 5, new); 29 * 30 * The numbers 10 and 5 could for example come from data 31 * tables which describe all bitfields in all registers. 32 */ 33 34 #include <linux/types.h> 35 36 /* Produces a mask of set bits covering a range of a uint value */ 37 static inline uint bitfield_mask(uint shift, uint width) 38 { 39 return ((1 << width) - 1) << shift; 40 } 41 42 /* Extract the value of a bitfield found within a given register value */ 43 static inline uint bitfield_extract(uint reg_val, uint shift, uint width) 44 { 45 return (reg_val & bitfield_mask(shift, width)) >> shift; 46 } 47 48 /* 49 * Replace the value of a bitfield found within a given register value 50 * Returns the newly modified uint value with the replaced field. 51 */ 52 static inline uint bitfield_replace(uint reg_val, uint shift, uint width, 53 uint bitfield_val) 54 { 55 uint mask = bitfield_mask(shift, width); 56 57 return (reg_val & ~mask) | ((bitfield_val << shift) & mask); 58 } 59