summaryrefslogtreecommitdiff
path: root/drivers/net/ipa/reg.h
blob: f0be664676d369955ca91b497048a469d4b2d548 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/* SPDX-License-Identifier: GPL-2.0 */

/* *Copyright (C) 2022-2023 Linaro Ltd. */

#ifndef _REG_H_
#define _REG_H_

#include <linux/types.h>
#include <linux/bits.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];
}

#endif /* _REG_H_ */