GNU Linux-libre 6.8.7-gnu
[releases.git] / drivers / net / ipa / reg.h
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  */
20 struct 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  */
57 struct regs {
58         u32 reg_count;
59         const struct reg **reg;
60 };
61
62 static 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 */
72 static 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  */
81 static 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 */
92 static 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 */
100 static 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 */
115 static 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 */
123 static 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 */
129 static 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_ */