136 lines · 3.5 KB · C
RawDownload
/* 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_ */