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