bitfield.h 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. /*
  2. * Copyright 2013 Broadcom Corporation.
  3. *
  4. * SPDX-License-Identifier: GPL-2.0+
  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. #include <linux/types.h>
  39. /* Produces a mask of set bits covering a range of a uint value */
  40. static inline uint bitfield_mask(uint shift, uint width)
  41. {
  42. return ((1 << width) - 1) << shift;
  43. }
  44. /* Extract the value of a bitfield found within a given register value */
  45. static inline uint bitfield_extract(uint reg_val, uint shift, uint width)
  46. {
  47. return (reg_val & bitfield_mask(shift, width)) >> shift;
  48. }
  49. /*
  50. * Replace the value of a bitfield found within a given register value
  51. * Returns the newly modified uint value with the replaced field.
  52. */
  53. static inline uint bitfield_replace(uint reg_val, uint shift, uint width,
  54. uint bitfield_val)
  55. {
  56. uint mask = bitfield_mask(shift, width);
  57. return (reg_val & ~mask) | ((bitfield_val << shift) & mask);
  58. }
  59. /* Produces a shift of the bitfield given a mask */
  60. static inline uint bitfield_shift(uint mask)
  61. {
  62. return mask ? ffs(mask) - 1 : 0;
  63. }
  64. /* Extract the value of a bitfield found within a given register value */
  65. static inline uint bitfield_extract_by_mask(uint reg_val, uint mask)
  66. {
  67. uint shift = bitfield_shift(mask);
  68. return (reg_val & mask) >> shift;
  69. }
  70. /*
  71. * Replace the value of a bitfield found within a given register value
  72. * Returns the newly modified uint value with the replaced field.
  73. */
  74. static inline uint bitfield_replace_by_mask(uint reg_val, uint mask,
  75. uint bitfield_val)
  76. {
  77. uint shift = bitfield_shift(mask);
  78. return (reg_val & ~mask) | ((bitfield_val << shift) & mask);
  79. }