1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * processor thermal device RFIM control
4  * Copyright (c) 2020, Intel Corporation.
5  */
6 
7 #include <linux/kernel.h>
8 #include <linux/module.h>
9 #include <linux/pci.h>
10 #include "processor_thermal_device.h"
11 
12 MODULE_IMPORT_NS(INT340X_THERMAL);
13 
14 struct mmio_reg {
15 	int read_only;
16 	u32 offset;
17 	int bits;
18 	u16 mask;
19 	u16 shift;
20 };
21 
22 /* These will represent sysfs attribute names */
23 static const char * const fivr_strings[] = {
24 	"vco_ref_code_lo",
25 	"vco_ref_code_hi",
26 	"spread_spectrum_pct",
27 	"spread_spectrum_clk_enable",
28 	"rfi_vco_ref_code",
29 	"fivr_fffc_rev",
30 	NULL
31 };
32 
33 static const struct mmio_reg tgl_fivr_mmio_regs[] = {
34 	{ 0, 0x5A18, 3, 0x7, 11}, /* vco_ref_code_lo */
35 	{ 0, 0x5A18, 8, 0xFF, 16}, /* vco_ref_code_hi */
36 	{ 0, 0x5A08, 8, 0xFF, 0}, /* spread_spectrum_pct */
37 	{ 0, 0x5A08, 1, 0x1, 8}, /* spread_spectrum_clk_enable */
38 	{ 1, 0x5A10, 12, 0xFFF, 0}, /* rfi_vco_ref_code */
39 	{ 1, 0x5A14, 2, 0x3, 1}, /* fivr_fffc_rev */
40 };
41 
42 static const char * const dlvr_strings[] = {
43 	"dlvr_spread_spectrum_pct",
44 	"dlvr_control_mode",
45 	"dlvr_control_lock",
46 	"dlvr_rfim_enable",
47 	"dlvr_freq_select",
48 	"dlvr_hardware_rev",
49 	"dlvr_freq_mhz",
50 	"dlvr_pll_busy",
51 	NULL
52 };
53 
54 static const struct mmio_reg dlvr_mmio_regs[] = {
55 	{ 0, 0x15A08, 5, 0x1F, 0}, /* dlvr_spread_spectrum_pct */
56 	{ 0, 0x15A08, 1, 0x1, 5}, /* dlvr_control_mode */
57 	{ 0, 0x15A08, 1, 0x1, 6}, /* dlvr_control_lock */
58 	{ 0, 0x15A08, 1, 0x1, 7}, /* dlvr_rfim_enable */
59 	{ 0, 0x15A08, 12, 0xFFF, 8}, /* dlvr_freq_select */
60 	{ 1, 0x15A10, 2, 0x3, 30}, /* dlvr_hardware_rev */
61 	{ 1, 0x15A10, 16, 0xFFFF, 0}, /* dlvr_freq_mhz */
62 	{ 1, 0x15A10, 1, 0x1, 16}, /* dlvr_pll_busy */
63 };
64 
65 /* These will represent sysfs attribute names */
66 static const char * const dvfs_strings[] = {
67 	"rfi_restriction_run_busy",
68 	"rfi_restriction_err_code",
69 	"rfi_restriction_data_rate",
70 	"rfi_restriction_data_rate_base",
71 	"ddr_data_rate_point_0",
72 	"ddr_data_rate_point_1",
73 	"ddr_data_rate_point_2",
74 	"ddr_data_rate_point_3",
75 	"rfi_disable",
76 	NULL
77 };
78 
79 static const struct mmio_reg adl_dvfs_mmio_regs[] = {
80 	{ 0, 0x5A38, 1, 0x1, 31}, /* rfi_restriction_run_busy */
81 	{ 0, 0x5A38, 7, 0x7F, 24}, /* rfi_restriction_err_code */
82 	{ 0, 0x5A38, 8, 0xFF, 16}, /* rfi_restriction_data_rate */
83 	{ 0, 0x5A38, 16, 0xFFFF, 0}, /* rfi_restriction_data_rate_base */
84 	{ 0, 0x5A30, 10, 0x3FF, 0}, /* ddr_data_rate_point_0 */
85 	{ 0, 0x5A30, 10, 0x3FF, 10}, /* ddr_data_rate_point_1 */
86 	{ 0, 0x5A30, 10, 0x3FF, 20}, /* ddr_data_rate_point_2 */
87 	{ 0, 0x5A30, 10, 0x3FF, 30}, /* ddr_data_rate_point_3 */
88 	{ 0, 0x5A40, 1, 0x1, 0}, /* rfi_disable */
89 };
90 
91 #define RFIM_SHOW(suffix, table)\
92 static ssize_t suffix##_show(struct device *dev,\
93 			      struct device_attribute *attr,\
94 			      char *buf)\
95 {\
96 	struct proc_thermal_device *proc_priv;\
97 	struct pci_dev *pdev = to_pci_dev(dev);\
98 	const struct mmio_reg *mmio_regs;\
99 	const char **match_strs;\
100 	u32 reg_val;\
101 	int ret;\
102 \
103 	proc_priv = pci_get_drvdata(pdev);\
104 	if (table == 1) {\
105 		match_strs = (const char **)dvfs_strings;\
106 		mmio_regs = adl_dvfs_mmio_regs;\
107 	} else if (table == 2) { \
108 		match_strs = (const char **)dlvr_strings;\
109 		mmio_regs = dlvr_mmio_regs;\
110 	} else {\
111 		match_strs = (const char **)fivr_strings;\
112 		mmio_regs = tgl_fivr_mmio_regs;\
113 	} \
114 	ret = match_string(match_strs, -1, attr->attr.name);\
115 	if (ret < 0)\
116 		return ret;\
117 	reg_val = readl((void __iomem *) (proc_priv->mmio_base + mmio_regs[ret].offset));\
118 	ret = (reg_val >> mmio_regs[ret].shift) & mmio_regs[ret].mask;\
119 	return sprintf(buf, "%u\n", ret);\
120 }
121 
122 #define RFIM_STORE(suffix, table)\
123 static ssize_t suffix##_store(struct device *dev,\
124 			       struct device_attribute *attr,\
125 			       const char *buf, size_t count)\
126 {\
127 	struct proc_thermal_device *proc_priv;\
128 	struct pci_dev *pdev = to_pci_dev(dev);\
129 	unsigned int input;\
130 	const char **match_strs;\
131 	const struct mmio_reg *mmio_regs;\
132 	int ret, err;\
133 	u32 reg_val;\
134 	u32 mask;\
135 \
136 	proc_priv = pci_get_drvdata(pdev);\
137 	if (table == 1) {\
138 		match_strs = (const char **)dvfs_strings;\
139 		mmio_regs = adl_dvfs_mmio_regs;\
140 	} else if (table == 2) { \
141 		match_strs = (const char **)dlvr_strings;\
142 		mmio_regs = dlvr_mmio_regs;\
143 	} else {\
144 		match_strs = (const char **)fivr_strings;\
145 		mmio_regs = tgl_fivr_mmio_regs;\
146 	} \
147 	\
148 	ret = match_string(match_strs, -1, attr->attr.name);\
149 	if (ret < 0)\
150 		return ret;\
151 	if (mmio_regs[ret].read_only)\
152 		return -EPERM;\
153 	err = kstrtouint(buf, 10, &input);\
154 	if (err)\
155 		return err;\
156 	mask = GENMASK(mmio_regs[ret].shift + mmio_regs[ret].bits - 1, mmio_regs[ret].shift);\
157 	reg_val = readl((void __iomem *) (proc_priv->mmio_base + mmio_regs[ret].offset));\
158 	reg_val &= ~mask;\
159 	reg_val |= (input << mmio_regs[ret].shift);\
160 	writel(reg_val, (void __iomem *) (proc_priv->mmio_base + mmio_regs[ret].offset));\
161 	return count;\
162 }
163 
164 RFIM_SHOW(vco_ref_code_lo, 0)
165 RFIM_SHOW(vco_ref_code_hi, 0)
166 RFIM_SHOW(spread_spectrum_pct, 0)
167 RFIM_SHOW(spread_spectrum_clk_enable, 0)
168 RFIM_SHOW(rfi_vco_ref_code, 0)
169 RFIM_SHOW(fivr_fffc_rev, 0)
170 
171 RFIM_STORE(vco_ref_code_lo, 0)
172 RFIM_STORE(vco_ref_code_hi, 0)
173 RFIM_STORE(spread_spectrum_pct, 0)
174 RFIM_STORE(spread_spectrum_clk_enable, 0)
175 RFIM_STORE(rfi_vco_ref_code, 0)
176 RFIM_STORE(fivr_fffc_rev, 0)
177 
178 RFIM_SHOW(dlvr_spread_spectrum_pct, 2)
179 RFIM_SHOW(dlvr_control_mode, 2)
180 RFIM_SHOW(dlvr_control_lock, 2)
181 RFIM_SHOW(dlvr_hardware_rev, 2)
182 RFIM_SHOW(dlvr_freq_mhz, 2)
183 RFIM_SHOW(dlvr_pll_busy, 2)
184 RFIM_SHOW(dlvr_freq_select, 2)
185 RFIM_SHOW(dlvr_rfim_enable, 2)
186 
187 RFIM_STORE(dlvr_spread_spectrum_pct, 2)
188 RFIM_STORE(dlvr_rfim_enable, 2)
189 RFIM_STORE(dlvr_freq_select, 2)
190 RFIM_STORE(dlvr_control_mode, 2)
191 RFIM_STORE(dlvr_control_lock, 2)
192 
193 static DEVICE_ATTR_RW(dlvr_spread_spectrum_pct);
194 static DEVICE_ATTR_RW(dlvr_control_mode);
195 static DEVICE_ATTR_RW(dlvr_control_lock);
196 static DEVICE_ATTR_RW(dlvr_freq_select);
197 static DEVICE_ATTR_RO(dlvr_hardware_rev);
198 static DEVICE_ATTR_RO(dlvr_freq_mhz);
199 static DEVICE_ATTR_RO(dlvr_pll_busy);
200 static DEVICE_ATTR_RW(dlvr_rfim_enable);
201 
202 static struct attribute *dlvr_attrs[] = {
203 	&dev_attr_dlvr_spread_spectrum_pct.attr,
204 	&dev_attr_dlvr_control_mode.attr,
205 	&dev_attr_dlvr_control_lock.attr,
206 	&dev_attr_dlvr_freq_select.attr,
207 	&dev_attr_dlvr_hardware_rev.attr,
208 	&dev_attr_dlvr_freq_mhz.attr,
209 	&dev_attr_dlvr_pll_busy.attr,
210 	&dev_attr_dlvr_rfim_enable.attr,
211 	NULL
212 };
213 
214 static const struct attribute_group dlvr_attribute_group = {
215 	.attrs = dlvr_attrs,
216 	.name = "dlvr"
217 };
218 
219 static DEVICE_ATTR_RW(vco_ref_code_lo);
220 static DEVICE_ATTR_RW(vco_ref_code_hi);
221 static DEVICE_ATTR_RW(spread_spectrum_pct);
222 static DEVICE_ATTR_RW(spread_spectrum_clk_enable);
223 static DEVICE_ATTR_RW(rfi_vco_ref_code);
224 static DEVICE_ATTR_RW(fivr_fffc_rev);
225 
226 static struct attribute *fivr_attrs[] = {
227 	&dev_attr_vco_ref_code_lo.attr,
228 	&dev_attr_vco_ref_code_hi.attr,
229 	&dev_attr_spread_spectrum_pct.attr,
230 	&dev_attr_spread_spectrum_clk_enable.attr,
231 	&dev_attr_rfi_vco_ref_code.attr,
232 	&dev_attr_fivr_fffc_rev.attr,
233 	NULL
234 };
235 
236 static const struct attribute_group fivr_attribute_group = {
237 	.attrs = fivr_attrs,
238 	.name = "fivr"
239 };
240 
241 RFIM_SHOW(rfi_restriction_run_busy, 1)
242 RFIM_SHOW(rfi_restriction_err_code, 1)
243 RFIM_SHOW(rfi_restriction_data_rate, 1)
244 RFIM_SHOW(rfi_restriction_data_rate_base, 1)
245 RFIM_SHOW(ddr_data_rate_point_0, 1)
246 RFIM_SHOW(ddr_data_rate_point_1, 1)
247 RFIM_SHOW(ddr_data_rate_point_2, 1)
248 RFIM_SHOW(ddr_data_rate_point_3, 1)
249 RFIM_SHOW(rfi_disable, 1)
250 
251 RFIM_STORE(rfi_restriction_run_busy, 1)
252 RFIM_STORE(rfi_restriction_err_code, 1)
253 RFIM_STORE(rfi_restriction_data_rate, 1)
254 RFIM_STORE(rfi_restriction_data_rate_base, 1)
255 RFIM_STORE(rfi_disable, 1)
256 
257 static DEVICE_ATTR_RW(rfi_restriction_run_busy);
258 static DEVICE_ATTR_RW(rfi_restriction_err_code);
259 static DEVICE_ATTR_RW(rfi_restriction_data_rate);
260 static DEVICE_ATTR_RW(rfi_restriction_data_rate_base);
261 static DEVICE_ATTR_RO(ddr_data_rate_point_0);
262 static DEVICE_ATTR_RO(ddr_data_rate_point_1);
263 static DEVICE_ATTR_RO(ddr_data_rate_point_2);
264 static DEVICE_ATTR_RO(ddr_data_rate_point_3);
265 static DEVICE_ATTR_RW(rfi_disable);
266 
267 static ssize_t rfi_restriction_store(struct device *dev,
268 				     struct device_attribute *attr,
269 				     const char *buf, size_t count)
270 {
271 	u16 id = 0x0008;
272 	u32 input;
273 	int ret;
274 
275 	ret = kstrtou32(buf, 10, &input);
276 	if (ret)
277 		return ret;
278 
279 	ret = processor_thermal_send_mbox_write_cmd(to_pci_dev(dev), id, input);
280 	if (ret)
281 		return ret;
282 
283 	return count;
284 }
285 
286 static ssize_t rfi_restriction_show(struct device *dev,
287 				    struct device_attribute *attr,
288 				    char *buf)
289 {
290 	u16 id = 0x0007;
291 	u64 resp;
292 	int ret;
293 
294 	ret = processor_thermal_send_mbox_read_cmd(to_pci_dev(dev), id, &resp);
295 	if (ret)
296 		return ret;
297 
298 	return sprintf(buf, "%llu\n", resp);
299 }
300 
301 static ssize_t ddr_data_rate_show(struct device *dev,
302 				  struct device_attribute *attr,
303 				  char *buf)
304 {
305 	u16 id = 0x0107;
306 	u64 resp;
307 	int ret;
308 
309 	ret = processor_thermal_send_mbox_read_cmd(to_pci_dev(dev), id, &resp);
310 	if (ret)
311 		return ret;
312 
313 	return sprintf(buf, "%llu\n", resp);
314 }
315 
316 static DEVICE_ATTR_RW(rfi_restriction);
317 static DEVICE_ATTR_RO(ddr_data_rate);
318 
319 static struct attribute *dvfs_attrs[] = {
320 	&dev_attr_rfi_restriction_run_busy.attr,
321 	&dev_attr_rfi_restriction_err_code.attr,
322 	&dev_attr_rfi_restriction_data_rate.attr,
323 	&dev_attr_rfi_restriction_data_rate_base.attr,
324 	&dev_attr_ddr_data_rate_point_0.attr,
325 	&dev_attr_ddr_data_rate_point_1.attr,
326 	&dev_attr_ddr_data_rate_point_2.attr,
327 	&dev_attr_ddr_data_rate_point_3.attr,
328 	&dev_attr_rfi_disable.attr,
329 	&dev_attr_ddr_data_rate.attr,
330 	&dev_attr_rfi_restriction.attr,
331 	NULL
332 };
333 
334 static const struct attribute_group dvfs_attribute_group = {
335 	.attrs = dvfs_attrs,
336 	.name = "dvfs"
337 };
338 
339 int proc_thermal_rfim_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv)
340 {
341 	int ret;
342 
343 	if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_FIVR) {
344 		ret = sysfs_create_group(&pdev->dev.kobj, &fivr_attribute_group);
345 		if (ret)
346 			return ret;
347 	}
348 
349 	if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DLVR) {
350 		ret = sysfs_create_group(&pdev->dev.kobj, &dlvr_attribute_group);
351 		if (ret)
352 			return ret;
353 	}
354 
355 	if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DVFS) {
356 		ret = sysfs_create_group(&pdev->dev.kobj, &dvfs_attribute_group);
357 		if (ret && proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_FIVR) {
358 			sysfs_remove_group(&pdev->dev.kobj, &fivr_attribute_group);
359 			return ret;
360 		}
361 		if (ret && proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DLVR) {
362 			sysfs_remove_group(&pdev->dev.kobj, &dlvr_attribute_group);
363 			return ret;
364 		}
365 	}
366 
367 	return 0;
368 }
369 EXPORT_SYMBOL_GPL(proc_thermal_rfim_add);
370 
371 void proc_thermal_rfim_remove(struct pci_dev *pdev)
372 {
373 	struct proc_thermal_device *proc_priv = pci_get_drvdata(pdev);
374 
375 	if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_FIVR)
376 		sysfs_remove_group(&pdev->dev.kobj, &fivr_attribute_group);
377 
378 	if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DLVR)
379 		sysfs_remove_group(&pdev->dev.kobj, &dlvr_attribute_group);
380 
381 	if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DVFS)
382 		sysfs_remove_group(&pdev->dev.kobj, &dvfs_attribute_group);
383 }
384 EXPORT_SYMBOL_GPL(proc_thermal_rfim_remove);
385 
386 MODULE_LICENSE("GPL v2");
387