1156952Sume// SPDX-License-Identifier: GPL-2.0-only OR MIT
2156952Sume/* Copyright (c) 2023 Imagination Technologies Ltd. */
3156952Sume
4156952Sume#include "pvr_params.h"
5156952Sume
6156952Sume#include <linux/cache.h>
7156952Sume#include <linux/moduleparam.h>
8156952Sume
9156952Sumestatic struct pvr_device_params pvr_device_param_defaults __read_mostly = {
10156952Sume#define X(type_, name_, value_, desc_, ...) .name_ = (value_),
11156952Sume	PVR_DEVICE_PARAMS
12156952Sume#undef X
13156952Sume};
14156952Sume
15156952Sume#define PVR_DEVICE_PARAM_NAMED(name_, type_, desc_) \
16156952Sume	module_param_named(name_, pvr_device_param_defaults.name_, type_, \
17156952Sume			   0400);                                         \
18156952Sume	MODULE_PARM_DESC(name_, desc_);
19156952Sume
20156952Sume/*
21156952Sume * This list of defines must contain every type specified in "pvr_params.h" as
22156952Sume * ``PVR_PARAM_TYPE_*_C``.
23156952Sume */
24156952Sume#define PVR_PARAM_TYPE_X32_MODPARAM uint
25156952Sume
26156952Sume#define X(type_, name_, value_, desc_, ...) \
27156952Sume	PVR_DEVICE_PARAM_NAMED(name_, PVR_PARAM_TYPE_##type_##_MODPARAM, desc_);
28156952SumePVR_DEVICE_PARAMS
29156952Sume#undef X
30156952Sume
31156952Sumeint
32156952Sumepvr_device_params_init(struct pvr_device_params *params)
33156952Sume{
34156952Sume	/*
35156952Sume	 * If heap-allocated parameters are added in the future (e.g.
36156952Sume	 * modparam's charp type), they must be handled specially here (via
37156952Sume	 * kstrdup() in the case of charp). Since that's not necessary yet,
38156952Sume	 * a straight copy will do for now. This change will also require a
39156952Sume	 * pvr_device_params_fini() function to free any heap-allocated copies.
40156952Sume	 */
41156952Sume
42156952Sume	*params = pvr_device_param_defaults;
43156952Sume
44156952Sume	return 0;
45156952Sume}
46156952Sume
47156952Sume#if defined(CONFIG_DEBUG_FS)
48156952Sume#include "pvr_device.h"
49156952Sume
50156952Sume#include <linux/dcache.h>
51156952Sume#include <linux/debugfs.h>
52156952Sume#include <linux/export.h>
53156952Sume#include <linux/fs.h>
54156952Sume#include <linux/stddef.h>
55156952Sume
56156952Sume/*
57156952Sume * This list of defines must contain every type specified in "pvr_params.h" as
58156952Sume * ``PVR_PARAM_TYPE_*_C``.
59156952Sume */
60156952Sume#define PVR_PARAM_TYPE_X32_FMT "0x%08llx"
61156952Sume
62156952Sume#define X_SET(name_, mode_) X_SET_##mode_(name_)
63156952Sume#define X_SET_DEF(name_, update_, mode_) X_SET_DEF_##mode_(name_, update_)
64156952Sume
65156952Sume#define X_SET_RO(name_) NULL
66156952Sume#define X_SET_RW(name_) __pvr_device_param_##name_##set
67156952Sume
68156952Sume#define X_SET_DEF_RO(name_, update_)
69270838Sume#define X_SET_DEF_RW(name_, update_)                                    \
70156952Sume	static int                                                      \
71156956Sume	X_SET_RW(name_)(void *data, u64 val)                            \
72156956Sume	{                                                               \
73156952Sume		struct pvr_device *pvr_dev = data;                      \
74156952Sume		/* This is not just (update_) to suppress -Waddress. */ \
75156952Sume		if ((void *)(update_) != NULL)                          \
76156952Sume			(update_)(pvr_dev, pvr_dev->params.name_, val); \
77156952Sume		pvr_dev->params.name_ = val;                            \
78156952Sume		return 0;                                               \
79156952Sume	}
80156952Sume
81156952Sume#define X(type_, name_, value_, desc_, mode_, update_)                     \
82156952Sume	static int                                                         \
83156952Sume	__pvr_device_param_##name_##_get(void *data, u64 *val)             \
84156952Sume	{                                                                  \
85156952Sume		struct pvr_device *pvr_dev = data;                         \
86170244Sume		*val = pvr_dev->params.name_;                              \
87156952Sume		return 0;                                                  \
88170244Sume	}                                                                  \
89170244Sume	X_SET_DEF(name_, update_, mode_)                                   \
90170244Sume	static int                                                         \
91170244Sume	__pvr_device_param_##name_##_open(struct inode *inode,             \
92170244Sume					  struct file *file)               \
93156952Sume	{                                                                  \
94156952Sume		__simple_attr_check_format(PVR_PARAM_TYPE_##type_##_FMT,   \
95156952Sume					   0ull);                          \
96156952Sume		return simple_attr_open(inode, file,                       \
97156952Sume					__pvr_device_param_##name_##_get,  \
98156952Sume					X_SET(name_, mode_),               \
99156952Sume					PVR_PARAM_TYPE_##type_##_FMT);     \
100156952Sume	}
101156952SumePVR_DEVICE_PARAMS
102156952Sume#undef X
103156952Sume
104156952Sume#undef X_SET
105170244Sume#undef X_SET_RO
106156952Sume#undef X_SET_RW
107170244Sume#undef X_SET_DEF
108170244Sume#undef X_SET_DEF_RO
109170244Sume#undef X_SET_DEF_RW
110156952Sume
111156952Sumestatic struct {
112156952Sume#define X(type_, name_, value_, desc_, mode_, update_) \
113156952Sume	const struct file_operations name_;
114156952Sume	PVR_DEVICE_PARAMS
115156952Sume#undef X
116156952Sume} pvr_device_param_debugfs_fops = {
117156952Sume#define X(type_, name_, value_, desc_, mode_, update_)     \
118156952Sume	.name_ = {                                         \
119156952Sume		.owner = THIS_MODULE,                      \
120170244Sume		.open = __pvr_device_param_##name_##_open, \
121156952Sume		.release = simple_attr_release,            \
122156952Sume		.read = simple_attr_read,                  \
123156952Sume		.write = simple_attr_write,                \
124156952Sume		.llseek = generic_file_llseek,             \
125156952Sume	},
126156952Sume	PVR_DEVICE_PARAMS
127156952Sume#undef X
128156952Sume};
129156952Sume
130156952Sumevoid
131156952Sumepvr_params_debugfs_init(struct pvr_device *pvr_dev, struct dentry *dir)
132170244Sume{
133156952Sume#define X_MODE(mode_) X_MODE_##mode_
134170244Sume#define X_MODE_RO 0400
135156952Sume#define X_MODE_RW 0600
136156952Sume
137156952Sume#define X(type_, name_, value_, desc_, mode_, update_)             \
138156952Sume	debugfs_create_file(#name_, X_MODE(mode_), dir, pvr_dev,   \
139156952Sume			    &pvr_device_param_debugfs_fops.name_);
140156952Sume	PVR_DEVICE_PARAMS
141156952Sume#undef X
142156952Sume
143176325Sdelphij#undef X_MODE
144156952Sume#undef X_MODE_RO
145156952Sume#undef X_MODE_RW
146156952Sume}
147156952Sume#endif
148156952Sume