1473be511SSrinivas Pandruvada // SPDX-License-Identifier: GPL-2.0-only
2473be511SSrinivas Pandruvada /*
3473be511SSrinivas Pandruvada  * processor thermal device RFIM control
4473be511SSrinivas Pandruvada  * Copyright (c) 2020, Intel Corporation.
5473be511SSrinivas Pandruvada  */
6473be511SSrinivas Pandruvada 
7473be511SSrinivas Pandruvada #include <linux/kernel.h>
8473be511SSrinivas Pandruvada #include <linux/module.h>
9473be511SSrinivas Pandruvada #include <linux/pci.h>
10473be511SSrinivas Pandruvada #include "processor_thermal_device.h"
11473be511SSrinivas Pandruvada 
122685c77bSSumeet Pawnikar MODULE_IMPORT_NS(INT340X_THERMAL);
132685c77bSSumeet Pawnikar 
14473be511SSrinivas Pandruvada struct mmio_reg {
15473be511SSrinivas Pandruvada 	int read_only;
16473be511SSrinivas Pandruvada 	u32 offset;
17473be511SSrinivas Pandruvada 	int bits;
18473be511SSrinivas Pandruvada 	u16 mask;
19473be511SSrinivas Pandruvada 	u16 shift;
20473be511SSrinivas Pandruvada };
21473be511SSrinivas Pandruvada 
22473be511SSrinivas Pandruvada /* These will represent sysfs attribute names */
23473be511SSrinivas Pandruvada static const char * const fivr_strings[] = {
24473be511SSrinivas Pandruvada 	"vco_ref_code_lo",
25473be511SSrinivas Pandruvada 	"vco_ref_code_hi",
26473be511SSrinivas Pandruvada 	"spread_spectrum_pct",
27473be511SSrinivas Pandruvada 	"spread_spectrum_clk_enable",
28473be511SSrinivas Pandruvada 	"rfi_vco_ref_code",
29473be511SSrinivas Pandruvada 	"fivr_fffc_rev",
30473be511SSrinivas Pandruvada 	NULL
31473be511SSrinivas Pandruvada };
32473be511SSrinivas Pandruvada 
33473be511SSrinivas Pandruvada static const struct mmio_reg tgl_fivr_mmio_regs[] = {
34f872f736SSumeet Pawnikar 	{ 0, 0x5A18, 3, 0x7, 11}, /* vco_ref_code_lo */
35473be511SSrinivas Pandruvada 	{ 0, 0x5A18, 8, 0xFF, 16}, /* vco_ref_code_hi */
36473be511SSrinivas Pandruvada 	{ 0, 0x5A08, 8, 0xFF, 0}, /* spread_spectrum_pct */
37473be511SSrinivas Pandruvada 	{ 0, 0x5A08, 1, 0x1, 8}, /* spread_spectrum_clk_enable */
38473be511SSrinivas Pandruvada 	{ 1, 0x5A10, 12, 0xFFF, 0}, /* rfi_vco_ref_code */
39473be511SSrinivas Pandruvada 	{ 1, 0x5A14, 2, 0x3, 1}, /* fivr_fffc_rev */
40473be511SSrinivas Pandruvada };
41473be511SSrinivas Pandruvada 
42*5bc6b1dfSSrinivas Pandruvada static const char * const dlvr_strings[] = {
43*5bc6b1dfSSrinivas Pandruvada 	"dlvr_spread_spectrum_pct",
44*5bc6b1dfSSrinivas Pandruvada 	"dlvr_control_mode",
45*5bc6b1dfSSrinivas Pandruvada 	"dlvr_control_lock",
46*5bc6b1dfSSrinivas Pandruvada 	"dlvr_rfim_enable",
47*5bc6b1dfSSrinivas Pandruvada 	"dlvr_freq_select",
48*5bc6b1dfSSrinivas Pandruvada 	"dlvr_hardware_rev",
49*5bc6b1dfSSrinivas Pandruvada 	"dlvr_freq_mhz",
50*5bc6b1dfSSrinivas Pandruvada 	"dlvr_pll_busy",
51*5bc6b1dfSSrinivas Pandruvada 	NULL
52*5bc6b1dfSSrinivas Pandruvada };
53*5bc6b1dfSSrinivas Pandruvada 
54*5bc6b1dfSSrinivas Pandruvada static const struct mmio_reg dlvr_mmio_regs[] = {
55*5bc6b1dfSSrinivas Pandruvada 	{ 0, 0x15A08, 5, 0x1F, 0}, /* dlvr_spread_spectrum_pct */
56*5bc6b1dfSSrinivas Pandruvada 	{ 0, 0x15A08, 1, 0x1, 5}, /* dlvr_control_mode */
57*5bc6b1dfSSrinivas Pandruvada 	{ 0, 0x15A08, 1, 0x1, 6}, /* dlvr_control_lock */
58*5bc6b1dfSSrinivas Pandruvada 	{ 0, 0x15A08, 1, 0x1, 7}, /* dlvr_rfim_enable */
59*5bc6b1dfSSrinivas Pandruvada 	{ 0, 0x15A08, 12, 0xFFF, 8}, /* dlvr_freq_select */
60*5bc6b1dfSSrinivas Pandruvada 	{ 1, 0x15A10, 2, 0x3, 30}, /* dlvr_hardware_rev */
61*5bc6b1dfSSrinivas Pandruvada 	{ 1, 0x15A10, 16, 0xFFFF, 0}, /* dlvr_freq_mhz */
62*5bc6b1dfSSrinivas Pandruvada 	{ 1, 0x15A10, 1, 0x1, 16}, /* dlvr_pll_busy */
63*5bc6b1dfSSrinivas Pandruvada };
64*5bc6b1dfSSrinivas Pandruvada 
65473be511SSrinivas Pandruvada /* These will represent sysfs attribute names */
66473be511SSrinivas Pandruvada static const char * const dvfs_strings[] = {
67473be511SSrinivas Pandruvada 	"rfi_restriction_run_busy",
68473be511SSrinivas Pandruvada 	"rfi_restriction_err_code",
69473be511SSrinivas Pandruvada 	"rfi_restriction_data_rate",
70473be511SSrinivas Pandruvada 	"rfi_restriction_data_rate_base",
71473be511SSrinivas Pandruvada 	"ddr_data_rate_point_0",
72473be511SSrinivas Pandruvada 	"ddr_data_rate_point_1",
73473be511SSrinivas Pandruvada 	"ddr_data_rate_point_2",
74473be511SSrinivas Pandruvada 	"ddr_data_rate_point_3",
75473be511SSrinivas Pandruvada 	"rfi_disable",
76473be511SSrinivas Pandruvada 	NULL
77473be511SSrinivas Pandruvada };
78473be511SSrinivas Pandruvada 
79473be511SSrinivas Pandruvada static const struct mmio_reg adl_dvfs_mmio_regs[] = {
80473be511SSrinivas Pandruvada 	{ 0, 0x5A38, 1, 0x1, 31}, /* rfi_restriction_run_busy */
81473be511SSrinivas Pandruvada 	{ 0, 0x5A38, 7, 0x7F, 24}, /* rfi_restriction_err_code */
82473be511SSrinivas Pandruvada 	{ 0, 0x5A38, 8, 0xFF, 16}, /* rfi_restriction_data_rate */
83473be511SSrinivas Pandruvada 	{ 0, 0x5A38, 16, 0xFFFF, 0}, /* rfi_restriction_data_rate_base */
84473be511SSrinivas Pandruvada 	{ 0, 0x5A30, 10, 0x3FF, 0}, /* ddr_data_rate_point_0 */
85473be511SSrinivas Pandruvada 	{ 0, 0x5A30, 10, 0x3FF, 10}, /* ddr_data_rate_point_1 */
86473be511SSrinivas Pandruvada 	{ 0, 0x5A30, 10, 0x3FF, 20}, /* ddr_data_rate_point_2 */
87473be511SSrinivas Pandruvada 	{ 0, 0x5A30, 10, 0x3FF, 30}, /* ddr_data_rate_point_3 */
88473be511SSrinivas Pandruvada 	{ 0, 0x5A40, 1, 0x1, 0}, /* rfi_disable */
89473be511SSrinivas Pandruvada };
90473be511SSrinivas Pandruvada 
91473be511SSrinivas Pandruvada #define RFIM_SHOW(suffix, table)\
92473be511SSrinivas Pandruvada static ssize_t suffix##_show(struct device *dev,\
93473be511SSrinivas Pandruvada 			      struct device_attribute *attr,\
94473be511SSrinivas Pandruvada 			      char *buf)\
95473be511SSrinivas Pandruvada {\
96473be511SSrinivas Pandruvada 	struct proc_thermal_device *proc_priv;\
97473be511SSrinivas Pandruvada 	struct pci_dev *pdev = to_pci_dev(dev);\
98473be511SSrinivas Pandruvada 	const struct mmio_reg *mmio_regs;\
99473be511SSrinivas Pandruvada 	const char **match_strs;\
100473be511SSrinivas Pandruvada 	u32 reg_val;\
101473be511SSrinivas Pandruvada 	int ret;\
102473be511SSrinivas Pandruvada \
103473be511SSrinivas Pandruvada 	proc_priv = pci_get_drvdata(pdev);\
104*5bc6b1dfSSrinivas Pandruvada 	if (table == 1) {\
105473be511SSrinivas Pandruvada 		match_strs = (const char **)dvfs_strings;\
106473be511SSrinivas Pandruvada 		mmio_regs = adl_dvfs_mmio_regs;\
107*5bc6b1dfSSrinivas Pandruvada 	} else if (table == 2) { \
108*5bc6b1dfSSrinivas Pandruvada 		match_strs = (const char **)dlvr_strings;\
109*5bc6b1dfSSrinivas Pandruvada 		mmio_regs = dlvr_mmio_regs;\
110473be511SSrinivas Pandruvada 	} else {\
111473be511SSrinivas Pandruvada 		match_strs = (const char **)fivr_strings;\
112473be511SSrinivas Pandruvada 		mmio_regs = tgl_fivr_mmio_regs;\
113473be511SSrinivas Pandruvada 	} \
114473be511SSrinivas Pandruvada 	ret = match_string(match_strs, -1, attr->attr.name);\
115473be511SSrinivas Pandruvada 	if (ret < 0)\
116473be511SSrinivas Pandruvada 		return ret;\
117473be511SSrinivas Pandruvada 	reg_val = readl((void __iomem *) (proc_priv->mmio_base + mmio_regs[ret].offset));\
118473be511SSrinivas Pandruvada 	ret = (reg_val >> mmio_regs[ret].shift) & mmio_regs[ret].mask;\
119473be511SSrinivas Pandruvada 	return sprintf(buf, "%u\n", ret);\
120473be511SSrinivas Pandruvada }
121473be511SSrinivas Pandruvada 
122473be511SSrinivas Pandruvada #define RFIM_STORE(suffix, table)\
123473be511SSrinivas Pandruvada static ssize_t suffix##_store(struct device *dev,\
124473be511SSrinivas Pandruvada 			       struct device_attribute *attr,\
125473be511SSrinivas Pandruvada 			       const char *buf, size_t count)\
126473be511SSrinivas Pandruvada {\
127473be511SSrinivas Pandruvada 	struct proc_thermal_device *proc_priv;\
128473be511SSrinivas Pandruvada 	struct pci_dev *pdev = to_pci_dev(dev);\
129473be511SSrinivas Pandruvada 	unsigned int input;\
130473be511SSrinivas Pandruvada 	const char **match_strs;\
131473be511SSrinivas Pandruvada 	const struct mmio_reg *mmio_regs;\
132473be511SSrinivas Pandruvada 	int ret, err;\
133473be511SSrinivas Pandruvada 	u32 reg_val;\
134473be511SSrinivas Pandruvada 	u32 mask;\
135473be511SSrinivas Pandruvada \
136473be511SSrinivas Pandruvada 	proc_priv = pci_get_drvdata(pdev);\
137*5bc6b1dfSSrinivas Pandruvada 	if (table == 1) {\
138473be511SSrinivas Pandruvada 		match_strs = (const char **)dvfs_strings;\
139473be511SSrinivas Pandruvada 		mmio_regs = adl_dvfs_mmio_regs;\
140*5bc6b1dfSSrinivas Pandruvada 	} else if (table == 2) { \
141*5bc6b1dfSSrinivas Pandruvada 		match_strs = (const char **)dlvr_strings;\
142*5bc6b1dfSSrinivas Pandruvada 		mmio_regs = dlvr_mmio_regs;\
143473be511SSrinivas Pandruvada 	} else {\
144473be511SSrinivas Pandruvada 		match_strs = (const char **)fivr_strings;\
145473be511SSrinivas Pandruvada 		mmio_regs = tgl_fivr_mmio_regs;\
146473be511SSrinivas Pandruvada 	} \
147473be511SSrinivas Pandruvada 	\
148473be511SSrinivas Pandruvada 	ret = match_string(match_strs, -1, attr->attr.name);\
149473be511SSrinivas Pandruvada 	if (ret < 0)\
150473be511SSrinivas Pandruvada 		return ret;\
151473be511SSrinivas Pandruvada 	if (mmio_regs[ret].read_only)\
152473be511SSrinivas Pandruvada 		return -EPERM;\
153473be511SSrinivas Pandruvada 	err = kstrtouint(buf, 10, &input);\
154473be511SSrinivas Pandruvada 	if (err)\
155473be511SSrinivas Pandruvada 		return err;\
156473be511SSrinivas Pandruvada 	mask = GENMASK(mmio_regs[ret].shift + mmio_regs[ret].bits - 1, mmio_regs[ret].shift);\
157473be511SSrinivas Pandruvada 	reg_val = readl((void __iomem *) (proc_priv->mmio_base + mmio_regs[ret].offset));\
158473be511SSrinivas Pandruvada 	reg_val &= ~mask;\
159473be511SSrinivas Pandruvada 	reg_val |= (input << mmio_regs[ret].shift);\
160473be511SSrinivas Pandruvada 	writel(reg_val, (void __iomem *) (proc_priv->mmio_base + mmio_regs[ret].offset));\
161473be511SSrinivas Pandruvada 	return count;\
162473be511SSrinivas Pandruvada }
163473be511SSrinivas Pandruvada 
164473be511SSrinivas Pandruvada RFIM_SHOW(vco_ref_code_lo, 0)
165473be511SSrinivas Pandruvada RFIM_SHOW(vco_ref_code_hi, 0)
166473be511SSrinivas Pandruvada RFIM_SHOW(spread_spectrum_pct, 0)
167473be511SSrinivas Pandruvada RFIM_SHOW(spread_spectrum_clk_enable, 0)
168473be511SSrinivas Pandruvada RFIM_SHOW(rfi_vco_ref_code, 0)
169473be511SSrinivas Pandruvada RFIM_SHOW(fivr_fffc_rev, 0)
170473be511SSrinivas Pandruvada 
171473be511SSrinivas Pandruvada RFIM_STORE(vco_ref_code_lo, 0)
172473be511SSrinivas Pandruvada RFIM_STORE(vco_ref_code_hi, 0)
173473be511SSrinivas Pandruvada RFIM_STORE(spread_spectrum_pct, 0)
174473be511SSrinivas Pandruvada RFIM_STORE(spread_spectrum_clk_enable, 0)
175473be511SSrinivas Pandruvada RFIM_STORE(rfi_vco_ref_code, 0)
176473be511SSrinivas Pandruvada RFIM_STORE(fivr_fffc_rev, 0)
177473be511SSrinivas Pandruvada 
178*5bc6b1dfSSrinivas Pandruvada RFIM_SHOW(dlvr_spread_spectrum_pct, 2)
179*5bc6b1dfSSrinivas Pandruvada RFIM_SHOW(dlvr_control_mode, 2)
180*5bc6b1dfSSrinivas Pandruvada RFIM_SHOW(dlvr_control_lock, 2)
181*5bc6b1dfSSrinivas Pandruvada RFIM_SHOW(dlvr_hardware_rev, 2)
182*5bc6b1dfSSrinivas Pandruvada RFIM_SHOW(dlvr_freq_mhz, 2)
183*5bc6b1dfSSrinivas Pandruvada RFIM_SHOW(dlvr_pll_busy, 2)
184*5bc6b1dfSSrinivas Pandruvada RFIM_SHOW(dlvr_freq_select, 2)
185*5bc6b1dfSSrinivas Pandruvada RFIM_SHOW(dlvr_rfim_enable, 2)
186*5bc6b1dfSSrinivas Pandruvada 
187*5bc6b1dfSSrinivas Pandruvada RFIM_STORE(dlvr_spread_spectrum_pct, 2)
188*5bc6b1dfSSrinivas Pandruvada RFIM_STORE(dlvr_rfim_enable, 2)
189*5bc6b1dfSSrinivas Pandruvada RFIM_STORE(dlvr_freq_select, 2)
190*5bc6b1dfSSrinivas Pandruvada RFIM_STORE(dlvr_control_mode, 2)
191*5bc6b1dfSSrinivas Pandruvada RFIM_STORE(dlvr_control_lock, 2)
192*5bc6b1dfSSrinivas Pandruvada 
193*5bc6b1dfSSrinivas Pandruvada static DEVICE_ATTR_RW(dlvr_spread_spectrum_pct);
194*5bc6b1dfSSrinivas Pandruvada static DEVICE_ATTR_RW(dlvr_control_mode);
195*5bc6b1dfSSrinivas Pandruvada static DEVICE_ATTR_RW(dlvr_control_lock);
196*5bc6b1dfSSrinivas Pandruvada static DEVICE_ATTR_RW(dlvr_freq_select);
197*5bc6b1dfSSrinivas Pandruvada static DEVICE_ATTR_RO(dlvr_hardware_rev);
198*5bc6b1dfSSrinivas Pandruvada static DEVICE_ATTR_RO(dlvr_freq_mhz);
199*5bc6b1dfSSrinivas Pandruvada static DEVICE_ATTR_RO(dlvr_pll_busy);
200*5bc6b1dfSSrinivas Pandruvada static DEVICE_ATTR_RW(dlvr_rfim_enable);
201*5bc6b1dfSSrinivas Pandruvada 
202*5bc6b1dfSSrinivas Pandruvada static struct attribute *dlvr_attrs[] = {
203*5bc6b1dfSSrinivas Pandruvada 	&dev_attr_dlvr_spread_spectrum_pct.attr,
204*5bc6b1dfSSrinivas Pandruvada 	&dev_attr_dlvr_control_mode.attr,
205*5bc6b1dfSSrinivas Pandruvada 	&dev_attr_dlvr_control_lock.attr,
206*5bc6b1dfSSrinivas Pandruvada 	&dev_attr_dlvr_freq_select.attr,
207*5bc6b1dfSSrinivas Pandruvada 	&dev_attr_dlvr_hardware_rev.attr,
208*5bc6b1dfSSrinivas Pandruvada 	&dev_attr_dlvr_freq_mhz.attr,
209*5bc6b1dfSSrinivas Pandruvada 	&dev_attr_dlvr_pll_busy.attr,
210*5bc6b1dfSSrinivas Pandruvada 	&dev_attr_dlvr_rfim_enable.attr,
211*5bc6b1dfSSrinivas Pandruvada 	NULL
212*5bc6b1dfSSrinivas Pandruvada };
213*5bc6b1dfSSrinivas Pandruvada 
214*5bc6b1dfSSrinivas Pandruvada static const struct attribute_group dlvr_attribute_group = {
215*5bc6b1dfSSrinivas Pandruvada 	.attrs = dlvr_attrs,
216*5bc6b1dfSSrinivas Pandruvada 	.name = "dlvr"
217*5bc6b1dfSSrinivas Pandruvada };
218*5bc6b1dfSSrinivas Pandruvada 
219473be511SSrinivas Pandruvada static DEVICE_ATTR_RW(vco_ref_code_lo);
220473be511SSrinivas Pandruvada static DEVICE_ATTR_RW(vco_ref_code_hi);
221473be511SSrinivas Pandruvada static DEVICE_ATTR_RW(spread_spectrum_pct);
222473be511SSrinivas Pandruvada static DEVICE_ATTR_RW(spread_spectrum_clk_enable);
223473be511SSrinivas Pandruvada static DEVICE_ATTR_RW(rfi_vco_ref_code);
224473be511SSrinivas Pandruvada static DEVICE_ATTR_RW(fivr_fffc_rev);
225473be511SSrinivas Pandruvada 
226473be511SSrinivas Pandruvada static struct attribute *fivr_attrs[] = {
227473be511SSrinivas Pandruvada 	&dev_attr_vco_ref_code_lo.attr,
228473be511SSrinivas Pandruvada 	&dev_attr_vco_ref_code_hi.attr,
229473be511SSrinivas Pandruvada 	&dev_attr_spread_spectrum_pct.attr,
230473be511SSrinivas Pandruvada 	&dev_attr_spread_spectrum_clk_enable.attr,
231473be511SSrinivas Pandruvada 	&dev_attr_rfi_vco_ref_code.attr,
232473be511SSrinivas Pandruvada 	&dev_attr_fivr_fffc_rev.attr,
233473be511SSrinivas Pandruvada 	NULL
234473be511SSrinivas Pandruvada };
235473be511SSrinivas Pandruvada 
236473be511SSrinivas Pandruvada static const struct attribute_group fivr_attribute_group = {
237473be511SSrinivas Pandruvada 	.attrs = fivr_attrs,
238473be511SSrinivas Pandruvada 	.name = "fivr"
239473be511SSrinivas Pandruvada };
240473be511SSrinivas Pandruvada 
241473be511SSrinivas Pandruvada RFIM_SHOW(rfi_restriction_run_busy, 1)
242473be511SSrinivas Pandruvada RFIM_SHOW(rfi_restriction_err_code, 1)
243473be511SSrinivas Pandruvada RFIM_SHOW(rfi_restriction_data_rate, 1)
244b878d3baSSrinivas Pandruvada RFIM_SHOW(rfi_restriction_data_rate_base, 1)
245473be511SSrinivas Pandruvada RFIM_SHOW(ddr_data_rate_point_0, 1)
246473be511SSrinivas Pandruvada RFIM_SHOW(ddr_data_rate_point_1, 1)
247473be511SSrinivas Pandruvada RFIM_SHOW(ddr_data_rate_point_2, 1)
248473be511SSrinivas Pandruvada RFIM_SHOW(ddr_data_rate_point_3, 1)
249473be511SSrinivas Pandruvada RFIM_SHOW(rfi_disable, 1)
250473be511SSrinivas Pandruvada 
251473be511SSrinivas Pandruvada RFIM_STORE(rfi_restriction_run_busy, 1)
252473be511SSrinivas Pandruvada RFIM_STORE(rfi_restriction_err_code, 1)
253473be511SSrinivas Pandruvada RFIM_STORE(rfi_restriction_data_rate, 1)
254b878d3baSSrinivas Pandruvada RFIM_STORE(rfi_restriction_data_rate_base, 1)
255473be511SSrinivas Pandruvada RFIM_STORE(rfi_disable, 1)
256473be511SSrinivas Pandruvada 
257473be511SSrinivas Pandruvada static DEVICE_ATTR_RW(rfi_restriction_run_busy);
258473be511SSrinivas Pandruvada static DEVICE_ATTR_RW(rfi_restriction_err_code);
259473be511SSrinivas Pandruvada static DEVICE_ATTR_RW(rfi_restriction_data_rate);
260b878d3baSSrinivas Pandruvada static DEVICE_ATTR_RW(rfi_restriction_data_rate_base);
261473be511SSrinivas Pandruvada static DEVICE_ATTR_RO(ddr_data_rate_point_0);
262473be511SSrinivas Pandruvada static DEVICE_ATTR_RO(ddr_data_rate_point_1);
263473be511SSrinivas Pandruvada static DEVICE_ATTR_RO(ddr_data_rate_point_2);
264473be511SSrinivas Pandruvada static DEVICE_ATTR_RO(ddr_data_rate_point_3);
265473be511SSrinivas Pandruvada static DEVICE_ATTR_RW(rfi_disable);
266473be511SSrinivas Pandruvada 
rfi_restriction_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)2675d6fbc96SSrinivas Pandruvada static ssize_t rfi_restriction_store(struct device *dev,
2685d6fbc96SSrinivas Pandruvada 				     struct device_attribute *attr,
2695d6fbc96SSrinivas Pandruvada 				     const char *buf, size_t count)
2705d6fbc96SSrinivas Pandruvada {
2712685c77bSSumeet Pawnikar 	u16 id = 0x0008;
2725d6fbc96SSrinivas Pandruvada 	u32 input;
2735d6fbc96SSrinivas Pandruvada 	int ret;
2745d6fbc96SSrinivas Pandruvada 
2755d6fbc96SSrinivas Pandruvada 	ret = kstrtou32(buf, 10, &input);
2765d6fbc96SSrinivas Pandruvada 	if (ret)
2775d6fbc96SSrinivas Pandruvada 		return ret;
2785d6fbc96SSrinivas Pandruvada 
2792685c77bSSumeet Pawnikar 	ret = processor_thermal_send_mbox_write_cmd(to_pci_dev(dev), id, input);
2805d6fbc96SSrinivas Pandruvada 	if (ret)
2815d6fbc96SSrinivas Pandruvada 		return ret;
2825d6fbc96SSrinivas Pandruvada 
2835d6fbc96SSrinivas Pandruvada 	return count;
2845d6fbc96SSrinivas Pandruvada }
2855d6fbc96SSrinivas Pandruvada 
rfi_restriction_show(struct device * dev,struct device_attribute * attr,char * buf)2865d6fbc96SSrinivas Pandruvada static ssize_t rfi_restriction_show(struct device *dev,
2875d6fbc96SSrinivas Pandruvada 				    struct device_attribute *attr,
2885d6fbc96SSrinivas Pandruvada 				    char *buf)
2895d6fbc96SSrinivas Pandruvada {
2902685c77bSSumeet Pawnikar 	u16 id = 0x0007;
2912685c77bSSumeet Pawnikar 	u64 resp;
2925d6fbc96SSrinivas Pandruvada 	int ret;
2935d6fbc96SSrinivas Pandruvada 
2942685c77bSSumeet Pawnikar 	ret = processor_thermal_send_mbox_read_cmd(to_pci_dev(dev), id, &resp);
2955d6fbc96SSrinivas Pandruvada 	if (ret)
2965d6fbc96SSrinivas Pandruvada 		return ret;
2975d6fbc96SSrinivas Pandruvada 
2982685c77bSSumeet Pawnikar 	return sprintf(buf, "%llu\n", resp);
2995d6fbc96SSrinivas Pandruvada }
3005d6fbc96SSrinivas Pandruvada 
ddr_data_rate_show(struct device * dev,struct device_attribute * attr,char * buf)3015d6fbc96SSrinivas Pandruvada static ssize_t ddr_data_rate_show(struct device *dev,
3025d6fbc96SSrinivas Pandruvada 				  struct device_attribute *attr,
3035d6fbc96SSrinivas Pandruvada 				  char *buf)
3045d6fbc96SSrinivas Pandruvada {
3052685c77bSSumeet Pawnikar 	u16 id = 0x0107;
3062685c77bSSumeet Pawnikar 	u64 resp;
3075d6fbc96SSrinivas Pandruvada 	int ret;
3085d6fbc96SSrinivas Pandruvada 
3092685c77bSSumeet Pawnikar 	ret = processor_thermal_send_mbox_read_cmd(to_pci_dev(dev), id, &resp);
3105d6fbc96SSrinivas Pandruvada 	if (ret)
3115d6fbc96SSrinivas Pandruvada 		return ret;
3125d6fbc96SSrinivas Pandruvada 
3132685c77bSSumeet Pawnikar 	return sprintf(buf, "%llu\n", resp);
3145d6fbc96SSrinivas Pandruvada }
3155d6fbc96SSrinivas Pandruvada 
3165d6fbc96SSrinivas Pandruvada static DEVICE_ATTR_RW(rfi_restriction);
3175d6fbc96SSrinivas Pandruvada static DEVICE_ATTR_RO(ddr_data_rate);
3185d6fbc96SSrinivas Pandruvada 
319473be511SSrinivas Pandruvada static struct attribute *dvfs_attrs[] = {
320473be511SSrinivas Pandruvada 	&dev_attr_rfi_restriction_run_busy.attr,
321473be511SSrinivas Pandruvada 	&dev_attr_rfi_restriction_err_code.attr,
322473be511SSrinivas Pandruvada 	&dev_attr_rfi_restriction_data_rate.attr,
323b878d3baSSrinivas Pandruvada 	&dev_attr_rfi_restriction_data_rate_base.attr,
324473be511SSrinivas Pandruvada 	&dev_attr_ddr_data_rate_point_0.attr,
325473be511SSrinivas Pandruvada 	&dev_attr_ddr_data_rate_point_1.attr,
326473be511SSrinivas Pandruvada 	&dev_attr_ddr_data_rate_point_2.attr,
327473be511SSrinivas Pandruvada 	&dev_attr_ddr_data_rate_point_3.attr,
328473be511SSrinivas Pandruvada 	&dev_attr_rfi_disable.attr,
3295d6fbc96SSrinivas Pandruvada 	&dev_attr_ddr_data_rate.attr,
3305d6fbc96SSrinivas Pandruvada 	&dev_attr_rfi_restriction.attr,
331473be511SSrinivas Pandruvada 	NULL
332473be511SSrinivas Pandruvada };
333473be511SSrinivas Pandruvada 
334473be511SSrinivas Pandruvada static const struct attribute_group dvfs_attribute_group = {
335473be511SSrinivas Pandruvada 	.attrs = dvfs_attrs,
336473be511SSrinivas Pandruvada 	.name = "dvfs"
337473be511SSrinivas Pandruvada };
338473be511SSrinivas Pandruvada 
proc_thermal_rfim_add(struct pci_dev * pdev,struct proc_thermal_device * proc_priv)339473be511SSrinivas Pandruvada int proc_thermal_rfim_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv)
340473be511SSrinivas Pandruvada {
341473be511SSrinivas Pandruvada 	int ret;
342473be511SSrinivas Pandruvada 
343473be511SSrinivas Pandruvada 	if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_FIVR) {
344473be511SSrinivas Pandruvada 		ret = sysfs_create_group(&pdev->dev.kobj, &fivr_attribute_group);
345473be511SSrinivas Pandruvada 		if (ret)
346473be511SSrinivas Pandruvada 			return ret;
347473be511SSrinivas Pandruvada 	}
348473be511SSrinivas Pandruvada 
349*5bc6b1dfSSrinivas Pandruvada 	if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DLVR) {
350*5bc6b1dfSSrinivas Pandruvada 		ret = sysfs_create_group(&pdev->dev.kobj, &dlvr_attribute_group);
351*5bc6b1dfSSrinivas Pandruvada 		if (ret)
352*5bc6b1dfSSrinivas Pandruvada 			return ret;
353*5bc6b1dfSSrinivas Pandruvada 	}
354*5bc6b1dfSSrinivas Pandruvada 
355473be511SSrinivas Pandruvada 	if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DVFS) {
356473be511SSrinivas Pandruvada 		ret = sysfs_create_group(&pdev->dev.kobj, &dvfs_attribute_group);
357473be511SSrinivas Pandruvada 		if (ret && proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_FIVR) {
358473be511SSrinivas Pandruvada 			sysfs_remove_group(&pdev->dev.kobj, &fivr_attribute_group);
359473be511SSrinivas Pandruvada 			return ret;
360473be511SSrinivas Pandruvada 		}
361*5bc6b1dfSSrinivas Pandruvada 		if (ret && proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DLVR) {
362*5bc6b1dfSSrinivas Pandruvada 			sysfs_remove_group(&pdev->dev.kobj, &dlvr_attribute_group);
363*5bc6b1dfSSrinivas Pandruvada 			return ret;
364*5bc6b1dfSSrinivas Pandruvada 		}
365473be511SSrinivas Pandruvada 	}
366473be511SSrinivas Pandruvada 
367473be511SSrinivas Pandruvada 	return 0;
368473be511SSrinivas Pandruvada }
369473be511SSrinivas Pandruvada EXPORT_SYMBOL_GPL(proc_thermal_rfim_add);
370473be511SSrinivas Pandruvada 
proc_thermal_rfim_remove(struct pci_dev * pdev)371473be511SSrinivas Pandruvada void proc_thermal_rfim_remove(struct pci_dev *pdev)
372473be511SSrinivas Pandruvada {
373473be511SSrinivas Pandruvada 	struct proc_thermal_device *proc_priv = pci_get_drvdata(pdev);
374473be511SSrinivas Pandruvada 
375473be511SSrinivas Pandruvada 	if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_FIVR)
376473be511SSrinivas Pandruvada 		sysfs_remove_group(&pdev->dev.kobj, &fivr_attribute_group);
377473be511SSrinivas Pandruvada 
378*5bc6b1dfSSrinivas Pandruvada 	if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DLVR)
379*5bc6b1dfSSrinivas Pandruvada 		sysfs_remove_group(&pdev->dev.kobj, &dlvr_attribute_group);
380*5bc6b1dfSSrinivas Pandruvada 
381473be511SSrinivas Pandruvada 	if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DVFS)
382473be511SSrinivas Pandruvada 		sysfs_remove_group(&pdev->dev.kobj, &dvfs_attribute_group);
383473be511SSrinivas Pandruvada }
384473be511SSrinivas Pandruvada EXPORT_SYMBOL_GPL(proc_thermal_rfim_remove);
385473be511SSrinivas Pandruvada 
386473be511SSrinivas Pandruvada MODULE_LICENSE("GPL v2");
387