reg.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /* Copyright (C) 2022-2024 Linaro Ltd. */
  3. #ifndef _REG_H_
  4. #define _REG_H_
  5. #include <linux/array_size.h>
  6. #include <linux/bits.h>
  7. #include <linux/bug.h>
  8. #include <linux/log2.h>
  9. #include <linux/types.h>
  10. /**
  11. * struct reg - A register descriptor
  12. * @offset: Register offset relative to base of register memory
  13. * @stride: Distance between two instances, if parameterized
  14. * @fcount: Number of entries in the @fmask array
  15. * @fmask: Array of mask values defining position and width of fields
  16. * @name: Upper-case name of the register
  17. */
  18. struct reg {
  19. u32 offset;
  20. u32 stride;
  21. u32 fcount;
  22. const u32 *fmask; /* BIT(nr) or GENMASK(h, l) */
  23. const char *name;
  24. };
  25. /* Helper macro for defining "simple" (non-parameterized) registers */
  26. #define REG(__NAME, __reg_id, __offset) \
  27. REG_STRIDE(__NAME, __reg_id, __offset, 0)
  28. /* Helper macro for defining parameterized registers, specifying stride */
  29. #define REG_STRIDE(__NAME, __reg_id, __offset, __stride) \
  30. static const struct reg reg_ ## __reg_id = { \
  31. .name = #__NAME, \
  32. .offset = __offset, \
  33. .stride = __stride, \
  34. }
  35. #define REG_FIELDS(__NAME, __name, __offset) \
  36. REG_STRIDE_FIELDS(__NAME, __name, __offset, 0)
  37. #define REG_STRIDE_FIELDS(__NAME, __name, __offset, __stride) \
  38. static const struct reg reg_ ## __name = { \
  39. .name = #__NAME, \
  40. .offset = __offset, \
  41. .stride = __stride, \
  42. .fcount = ARRAY_SIZE(reg_ ## __name ## _fmask), \
  43. .fmask = reg_ ## __name ## _fmask, \
  44. }
  45. /**
  46. * struct regs - Description of registers supported by hardware
  47. * @reg_count: Number of registers in the @reg[] array
  48. * @reg: Array of register descriptors
  49. */
  50. struct regs {
  51. u32 reg_count;
  52. const struct reg **reg;
  53. };
  54. static inline const struct reg *reg(const struct regs *regs, u32 reg_id)
  55. {
  56. if (WARN(reg_id >= regs->reg_count,
  57. "reg out of range (%u > %u)\n", reg_id, regs->reg_count - 1))
  58. return NULL;
  59. return regs->reg[reg_id];
  60. }
  61. /* Return the field mask for a field in a register, or 0 on error */
  62. static inline u32 reg_fmask(const struct reg *reg, u32 field_id)
  63. {
  64. if (!reg || WARN_ON(field_id >= reg->fcount))
  65. return 0;
  66. return reg->fmask[field_id];
  67. }
  68. /* Return the mask for a single-bit field in a register, or 0 on error */
  69. static inline u32 reg_bit(const struct reg *reg, u32 field_id)
  70. {
  71. u32 fmask = reg_fmask(reg, field_id);
  72. if (WARN_ON(!is_power_of_2(fmask)))
  73. return 0;
  74. return fmask;
  75. }
  76. /* Return the maximum value representable by the given field; always 2^n - 1 */
  77. static inline u32 reg_field_max(const struct reg *reg, u32 field_id)
  78. {
  79. u32 fmask = reg_fmask(reg, field_id);
  80. return fmask ? fmask >> __ffs(fmask) : 0;
  81. }
  82. /* Encode a value into the given field of a register */
  83. static inline u32 reg_encode(const struct reg *reg, u32 field_id, u32 val)
  84. {
  85. u32 fmask = reg_fmask(reg, field_id);
  86. if (!fmask)
  87. return 0;
  88. val <<= __ffs(fmask);
  89. if (WARN_ON(val & ~fmask))
  90. return 0;
  91. return val;
  92. }
  93. /* Given a register value, decode (extract) the value in the given field */
  94. static inline u32 reg_decode(const struct reg *reg, u32 field_id, u32 val)
  95. {
  96. u32 fmask = reg_fmask(reg, field_id);
  97. return fmask ? (val & fmask) >> __ffs(fmask) : 0;
  98. }
  99. /* Returns 0 for NULL reg; warning should have already been issued */
  100. static inline u32 reg_offset(const struct reg *reg)
  101. {
  102. return reg ? reg->offset : 0;
  103. }
  104. /* Returns 0 for NULL reg; warning should have already been issued */
  105. static inline u32 reg_n_offset(const struct reg *reg, u32 n)
  106. {
  107. return reg ? reg->offset + n * reg->stride : 0;
  108. }
  109. #endif /* _REG_H_ */