bitfield.h 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. /* SPDX-License-Identifier: GPL-2.0+ */
  2. /*
  3. * Copyright 2013 Broadcom Corporation.
  4. */
  5. /*
  6. * Bitfield operations
  7. *
  8. * These are generic bitfield operations which allow manipulation of variable
  9. * width bitfields within a word. One use of this would be to use data tables
  10. * to determine how to reprogram fields within R/W hardware registers.
  11. *
  12. * Example:
  13. *
  14. * old_reg_val
  15. * +--------+----+---+--+-----+----------+
  16. * | | | | | old | |
  17. * +--------+----+---+--+-----+----------+
  18. *
  19. * new_reg_val
  20. * +--------+----+---+--+-----+----------+
  21. * | | | | | new | |
  22. * +--------+----+---+--+-----+----------+
  23. *
  24. * mask = bitfield_mask(10, 5);
  25. * old = bitfield_extract(old_reg_val, 10, 5);
  26. * new_reg_val = bitfield_replace(old_reg_val, 10, 5, new);
  27. *
  28. * or
  29. *
  30. * mask = bitfield_mask(10, 5);
  31. * old = bitfield_extract_by_mask(old_reg_val, mask);
  32. * new_reg_val = bitfield_replace_by_mask(old_reg_val, mask, new);
  33. *
  34. * The numbers 10 and 5 could for example come from data
  35. * tables which describe all bitfields in all registers.
  36. */
  37. #include <linux/types.h>
  38. /* Produces a mask of set bits covering a range of a uint value */
  39. static inline uint bitfield_mask(uint shift, uint width)
  40. {
  41. return ((1 << width) - 1) << shift;
  42. }
  43. /* Extract the value of a bitfield found within a given register value */
  44. static inline uint bitfield_extract(uint reg_val, uint shift, uint width)
  45. {
  46. return (reg_val & bitfield_mask(shift, width)) >> shift;
  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. return (reg_val & ~mask) | ((bitfield_val << shift) & mask);
  57. }
  58. /* Produces a shift of the bitfield given a mask */
  59. static inline uint bitfield_shift(uint mask)
  60. {
  61. return mask ? ffs(mask) - 1 : 0;
  62. }
  63. /* Extract the value of a bitfield found within a given register value */
  64. static inline uint bitfield_extract_by_mask(uint reg_val, uint mask)
  65. {
  66. uint shift = bitfield_shift(mask);
  67. return (reg_val & mask) >> shift;
  68. }
  69. /*
  70. * Replace the value of a bitfield found within a given register value
  71. * Returns the newly modified uint value with the replaced field.
  72. */
  73. static inline uint bitfield_replace_by_mask(uint reg_val, uint mask,
  74. uint bitfield_val)
  75. {
  76. uint shift = bitfield_shift(mask);
  77. return (reg_val & ~mask) | ((bitfield_val << shift) & mask);
  78. }