/* SPDX-License-Identifier: GPL-2.0 */ /* *Copyright (C) 2022-2023 Linaro Ltd. */ #ifndef _REG_H_ #define _REG_H_ #include #include /** * 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]; } #endif /* _REG_H_ */