xref: /openbmc/linux/drivers/net/ipa/reg.h (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
181772e44SAlex Elder /* SPDX-License-Identifier: GPL-2.0 */
281772e44SAlex Elder 
381772e44SAlex Elder /* *Copyright (C) 2022-2023 Linaro Ltd. */
481772e44SAlex Elder 
581772e44SAlex Elder #ifndef _REG_H_
681772e44SAlex Elder #define _REG_H_
781772e44SAlex Elder 
881772e44SAlex Elder #include <linux/types.h>
9*dd172d0cSAlex Elder #include <linux/log2.h>
10*dd172d0cSAlex Elder #include <linux/bug.h>
1181772e44SAlex Elder 
1281772e44SAlex Elder /**
1381772e44SAlex Elder  * struct reg - A register descriptor
1481772e44SAlex Elder  * @offset:	Register offset relative to base of register memory
1581772e44SAlex Elder  * @stride:	Distance between two instances, if parameterized
1681772e44SAlex Elder  * @fcount:	Number of entries in the @fmask array
1781772e44SAlex Elder  * @fmask:	Array of mask values defining position and width of fields
1881772e44SAlex Elder  * @name:	Upper-case name of the register
1981772e44SAlex Elder  */
2081772e44SAlex Elder struct reg {
2181772e44SAlex Elder 	u32 offset;
2281772e44SAlex Elder 	u32 stride;
2381772e44SAlex Elder 	u32 fcount;
2481772e44SAlex Elder 	const u32 *fmask;			/* BIT(nr) or GENMASK(h, l) */
2581772e44SAlex Elder 	const char *name;
2681772e44SAlex Elder };
2781772e44SAlex Elder 
2881772e44SAlex Elder /* Helper macro for defining "simple" (non-parameterized) registers */
2981772e44SAlex Elder #define REG(__NAME, __reg_id, __offset)					\
3081772e44SAlex Elder 	REG_STRIDE(__NAME, __reg_id, __offset, 0)
3181772e44SAlex Elder 
3281772e44SAlex Elder /* Helper macro for defining parameterized registers, specifying stride */
3381772e44SAlex Elder #define REG_STRIDE(__NAME, __reg_id, __offset, __stride)		\
3481772e44SAlex Elder 	static const struct reg reg_ ## __reg_id = {			\
3581772e44SAlex Elder 		.name	= #__NAME,					\
3681772e44SAlex Elder 		.offset	= __offset,					\
3781772e44SAlex Elder 		.stride	= __stride,					\
3881772e44SAlex Elder 	}
3981772e44SAlex Elder 
4081772e44SAlex Elder #define REG_FIELDS(__NAME, __name, __offset)				\
4181772e44SAlex Elder 	REG_STRIDE_FIELDS(__NAME, __name, __offset, 0)
4281772e44SAlex Elder 
4381772e44SAlex Elder #define REG_STRIDE_FIELDS(__NAME, __name, __offset, __stride)		\
4481772e44SAlex Elder 	static const struct reg reg_ ## __name = {			\
4581772e44SAlex Elder 		.name   = #__NAME,					\
4681772e44SAlex Elder 		.offset = __offset,					\
4781772e44SAlex Elder 		.stride = __stride,					\
4881772e44SAlex Elder 		.fcount = ARRAY_SIZE(reg_ ## __name ## _fmask),		\
4981772e44SAlex Elder 		.fmask  = reg_ ## __name ## _fmask,			\
5081772e44SAlex Elder 	}
5181772e44SAlex Elder 
5281772e44SAlex Elder /**
5381772e44SAlex Elder  * struct regs - Description of registers supported by hardware
5481772e44SAlex Elder  * @reg_count:	Number of registers in the @reg[] array
5581772e44SAlex Elder  * @reg:	Array of register descriptors
5681772e44SAlex Elder  */
5781772e44SAlex Elder struct regs {
5881772e44SAlex Elder 	u32 reg_count;
5981772e44SAlex Elder 	const struct reg **reg;
6081772e44SAlex Elder };
6181772e44SAlex Elder 
reg(const struct regs * regs,u32 reg_id)6281772e44SAlex Elder static inline const struct reg *reg(const struct regs *regs, u32 reg_id)
6381772e44SAlex Elder {
6481772e44SAlex Elder 	if (WARN(reg_id >= regs->reg_count,
6581772e44SAlex Elder 		 "reg out of range (%u > %u)\n", reg_id, regs->reg_count - 1))
6681772e44SAlex Elder 		return NULL;
6781772e44SAlex Elder 
6881772e44SAlex Elder 	return regs->reg[reg_id];
6981772e44SAlex Elder }
7081772e44SAlex Elder 
71f1470fd7SAlex Elder /* Return the field mask for a field in a register, or 0 on error */
reg_fmask(const struct reg * reg,u32 field_id)72f1470fd7SAlex Elder static inline u32 reg_fmask(const struct reg *reg, u32 field_id)
73f1470fd7SAlex Elder {
74f1470fd7SAlex Elder 	if (!reg || WARN_ON(field_id >= reg->fcount))
75f1470fd7SAlex Elder 		return 0;
76f1470fd7SAlex Elder 
77f1470fd7SAlex Elder 	return reg->fmask[field_id];
78f1470fd7SAlex Elder }
79f1470fd7SAlex Elder 
80f1470fd7SAlex Elder /* Return the mask for a single-bit field in a register, or 0 on error  */
reg_bit(const struct reg * reg,u32 field_id)81f1470fd7SAlex Elder static inline u32 reg_bit(const struct reg *reg, u32 field_id)
82f1470fd7SAlex Elder {
83f1470fd7SAlex Elder 	u32 fmask = reg_fmask(reg, field_id);
84f1470fd7SAlex Elder 
85f1470fd7SAlex Elder 	if (WARN_ON(!is_power_of_2(fmask)))
86f1470fd7SAlex Elder 		return 0;
87f1470fd7SAlex Elder 
88f1470fd7SAlex Elder 	return fmask;
89f1470fd7SAlex Elder }
90f1470fd7SAlex Elder 
91f1470fd7SAlex Elder /* Return the maximum value representable by the given field; always 2^n - 1 */
reg_field_max(const struct reg * reg,u32 field_id)92f1470fd7SAlex Elder static inline u32 reg_field_max(const struct reg *reg, u32 field_id)
93f1470fd7SAlex Elder {
94f1470fd7SAlex Elder 	u32 fmask = reg_fmask(reg, field_id);
95f1470fd7SAlex Elder 
96f1470fd7SAlex Elder 	return fmask ? fmask >> __ffs(fmask) : 0;
97f1470fd7SAlex Elder }
98f1470fd7SAlex Elder 
99f1470fd7SAlex Elder /* Encode a value into the given field of a register */
reg_encode(const struct reg * reg,u32 field_id,u32 val)100f1470fd7SAlex Elder static inline u32 reg_encode(const struct reg *reg, u32 field_id, u32 val)
101f1470fd7SAlex Elder {
102f1470fd7SAlex Elder 	u32 fmask = reg_fmask(reg, field_id);
103f1470fd7SAlex Elder 
104f1470fd7SAlex Elder 	if (!fmask)
105f1470fd7SAlex Elder 		return 0;
106f1470fd7SAlex Elder 
107f1470fd7SAlex Elder 	val <<= __ffs(fmask);
108f1470fd7SAlex Elder 	if (WARN_ON(val & ~fmask))
109f1470fd7SAlex Elder 		return 0;
110f1470fd7SAlex Elder 
111f1470fd7SAlex Elder 	return val;
112f1470fd7SAlex Elder }
113f1470fd7SAlex Elder 
114f1470fd7SAlex Elder /* Given a register value, decode (extract) the value in the given field */
reg_decode(const struct reg * reg,u32 field_id,u32 val)115f1470fd7SAlex Elder static inline u32 reg_decode(const struct reg *reg, u32 field_id, u32 val)
116f1470fd7SAlex Elder {
117f1470fd7SAlex Elder 	u32 fmask = reg_fmask(reg, field_id);
118f1470fd7SAlex Elder 
119f1470fd7SAlex Elder 	return fmask ? (val & fmask) >> __ffs(fmask) : 0;
120f1470fd7SAlex Elder }
121f1470fd7SAlex Elder 
122fc4cecf7SAlex Elder /* Returns 0 for NULL reg; warning should have already been issued */
reg_offset(const struct reg * reg)123fc4cecf7SAlex Elder static inline u32 reg_offset(const struct reg *reg)
124fc4cecf7SAlex Elder {
125fc4cecf7SAlex Elder 	return reg ? reg->offset : 0;
126fc4cecf7SAlex Elder }
127fc4cecf7SAlex Elder 
128fc4cecf7SAlex Elder /* Returns 0 for NULL reg; warning should have already been issued */
reg_n_offset(const struct reg * reg,u32 n)129fc4cecf7SAlex Elder static inline u32 reg_n_offset(const struct reg *reg, u32 n)
130fc4cecf7SAlex Elder {
131fc4cecf7SAlex Elder 	return reg ? reg->offset + n * reg->stride : 0;
132fc4cecf7SAlex Elder }
133fc4cecf7SAlex Elder 
13481772e44SAlex Elder #endif /* _REG_H_ */
135