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