uboot/include/bitfield.h
<<
>>
Prefs
   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 * or
  31 *
  32 * mask = bitfield_mask(10, 5);
  33 * old = bitfield_extract_by_mask(old_reg_val, mask);
  34 * new_reg_val = bitfield_replace_by_mask(old_reg_val, mask, new);
  35 *
  36 * The numbers 10 and 5 could for example come from data
  37 * tables which describe all bitfields in all registers.
  38 */
  39
  40#include <linux/types.h>
  41
  42/* Produces a mask of set bits covering a range of a uint value */
  43static inline uint bitfield_mask(uint shift, uint width)
  44{
  45        return ((1 << width) - 1) << shift;
  46}
  47
  48/* Extract the value of a bitfield found within a given register value */
  49static inline uint bitfield_extract(uint reg_val, uint shift, uint width)
  50{
  51        return (reg_val & bitfield_mask(shift, width)) >> shift;
  52}
  53
  54/*
  55 * Replace the value of a bitfield found within a given register value
  56 * Returns the newly modified uint value with the replaced field.
  57 */
  58static inline uint bitfield_replace(uint reg_val, uint shift, uint width,
  59                                    uint bitfield_val)
  60{
  61        uint mask = bitfield_mask(shift, width);
  62
  63        return (reg_val & ~mask) | ((bitfield_val << shift) & mask);
  64}
  65
  66/* Produces a shift of the bitfield given a mask */
  67static inline uint bitfield_shift(uint mask)
  68{
  69        return mask ? ffs(mask) - 1 : 0;
  70}
  71
  72/* Extract the value of a bitfield found within a given register value */
  73static inline uint bitfield_extract_by_mask(uint reg_val, uint mask)
  74{
  75        uint shift = bitfield_shift(mask);
  76
  77        return (reg_val & mask) >> shift;
  78}
  79
  80/*
  81 * Replace the value of a bitfield found within a given register value
  82 * Returns the newly modified uint value with the replaced field.
  83 */
  84static inline uint bitfield_replace_by_mask(uint reg_val, uint mask,
  85                                            uint bitfield_val)
  86{
  87        uint shift = bitfield_shift(mask);
  88
  89        return (reg_val & ~mask) | ((bitfield_val << shift) & mask);
  90}
  91