uboot/include/bitfield.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0+ */
   2/*
   3 * Copyright 2013 Broadcom Corporation.
   4 */
   5
   6/*
   7 * Bitfield operations
   8 *
   9 * These are generic bitfield operations which allow manipulation of variable
  10 * width bitfields within a word. One use of this would be to use data tables
  11 * to determine how to reprogram fields within R/W hardware registers.
  12 *
  13 * Example:
  14 *
  15 *            old_reg_val
  16 * +--------+----+---+--+-----+----------+
  17 * |        |    |   |  | old |          |
  18 * +--------+----+---+--+-----+----------+
  19 *
  20 *            new_reg_val
  21 * +--------+----+---+--+-----+----------+
  22 * |        |    |   |  | new |          |
  23 * +--------+----+---+--+-----+----------+
  24 *
  25 * mask = bitfield_mask(10, 5);
  26 * old = bitfield_extract(old_reg_val, 10, 5);
  27 * new_reg_val = bitfield_replace(old_reg_val, 10, 5, new);
  28 *
  29 * or
  30 *
  31 * mask = bitfield_mask(10, 5);
  32 * old = bitfield_extract_by_mask(old_reg_val, mask);
  33 * new_reg_val = bitfield_replace_by_mask(old_reg_val, mask, new);
  34 *
  35 * The numbers 10 and 5 could for example come from data
  36 * tables which describe all bitfields in all registers.
  37 */
  38
  39#include <linux/bitops.h>
  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