| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- /* SPDX-License-Identifier: GPL-2.0 */
- /* Copyright (C) 2022-2024 Linaro Ltd. */
- #ifndef _REG_H_
- #define _REG_H_
- #include <linux/array_size.h>
- #include <linux/bits.h>
- #include <linux/bug.h>
- #include <linux/log2.h>
- #include <linux/types.h>
- /**
- * struct reg - A register descriptor
- * @offset: Register offset relative to base of register memory
- * @stride: Distance between two instances, if parameterized
- * @fcount: Number of entries in the @fmask array
- * @fmask: Array of mask values defining position and width of fields
- * @name: Upper-case name of the register
- */
- struct reg {
- u32 offset;
- u32 stride;
- u32 fcount;
- const u32 *fmask; /* BIT(nr) or GENMASK(h, l) */
- const char *name;
- };
- /* Helper macro for defining "simple" (non-parameterized) registers */
- #define REG(__NAME, __reg_id, __offset) \
- REG_STRIDE(__NAME, __reg_id, __offset, 0)
- /* Helper macro for defining parameterized registers, specifying stride */
- #define REG_STRIDE(__NAME, __reg_id, __offset, __stride) \
- static const struct reg reg_ ## __reg_id = { \
- .name = #__NAME, \
- .offset = __offset, \
- .stride = __stride, \
- }
- #define REG_FIELDS(__NAME, __name, __offset) \
- REG_STRIDE_FIELDS(__NAME, __name, __offset, 0)
- #define REG_STRIDE_FIELDS(__NAME, __name, __offset, __stride) \
- static const struct reg reg_ ## __name = { \
- .name = #__NAME, \
- .offset = __offset, \
- .stride = __stride, \
- .fcount = ARRAY_SIZE(reg_ ## __name ## _fmask), \
- .fmask = reg_ ## __name ## _fmask, \
- }
- /**
- * struct regs - Description of registers supported by hardware
- * @reg_count: Number of registers in the @reg[] array
- * @reg: Array of register descriptors
- */
- struct regs {
- u32 reg_count;
- const struct reg **reg;
- };
- static inline const struct reg *reg(const struct regs *regs, u32 reg_id)
- {
- if (WARN(reg_id >= regs->reg_count,
- "reg out of range (%u > %u)\n", reg_id, regs->reg_count - 1))
- return NULL;
- return regs->reg[reg_id];
- }
- /* Return the field mask for a field in a register, or 0 on error */
- static inline u32 reg_fmask(const struct reg *reg, u32 field_id)
- {
- if (!reg || WARN_ON(field_id >= reg->fcount))
- return 0;
- return reg->fmask[field_id];
- }
- /* Return the mask for a single-bit field in a register, or 0 on error */
- static inline u32 reg_bit(const struct reg *reg, u32 field_id)
- {
- u32 fmask = reg_fmask(reg, field_id);
- if (WARN_ON(!is_power_of_2(fmask)))
- return 0;
- return fmask;
- }
- /* Return the maximum value representable by the given field; always 2^n - 1 */
- static inline u32 reg_field_max(const struct reg *reg, u32 field_id)
- {
- u32 fmask = reg_fmask(reg, field_id);
- return fmask ? fmask >> __ffs(fmask) : 0;
- }
- /* Encode a value into the given field of a register */
- static inline u32 reg_encode(const struct reg *reg, u32 field_id, u32 val)
- {
- u32 fmask = reg_fmask(reg, field_id);
- if (!fmask)
- return 0;
- val <<= __ffs(fmask);
- if (WARN_ON(val & ~fmask))
- return 0;
- return val;
- }
- /* Given a register value, decode (extract) the value in the given field */
- static inline u32 reg_decode(const struct reg *reg, u32 field_id, u32 val)
- {
- u32 fmask = reg_fmask(reg, field_id);
- return fmask ? (val & fmask) >> __ffs(fmask) : 0;
- }
- /* Returns 0 for NULL reg; warning should have already been issued */
- static inline u32 reg_offset(const struct reg *reg)
- {
- return reg ? reg->offset : 0;
- }
- /* Returns 0 for NULL reg; warning should have already been issued */
- static inline u32 reg_n_offset(const struct reg *reg, u32 n)
- {
- return reg ? reg->offset + n * reg->stride : 0;
- }
- #endif /* _REG_H_ */
|