xref: /linux/drivers/platform/x86/intel/plr_tpmi.c (revision 2c1ed907520c50326b8f604907a8478b27881a2e)
1df7f9acdSAndy Shevchenko // SPDX-License-Identifier: GPL-2.0-only
2df7f9acdSAndy Shevchenko /*
3df7f9acdSAndy Shevchenko  * Performance Limit Reasons via TPMI
4df7f9acdSAndy Shevchenko  *
5df7f9acdSAndy Shevchenko  * Copyright (c) 2024, Intel Corporation.
6df7f9acdSAndy Shevchenko  */
7df7f9acdSAndy Shevchenko 
8df7f9acdSAndy Shevchenko #include <linux/array_size.h>
9df7f9acdSAndy Shevchenko #include <linux/auxiliary_bus.h>
10df7f9acdSAndy Shevchenko #include <linux/bitfield.h>
11df7f9acdSAndy Shevchenko #include <linux/bitmap.h>
12df7f9acdSAndy Shevchenko #include <linux/debugfs.h>
13df7f9acdSAndy Shevchenko #include <linux/device.h>
14df7f9acdSAndy Shevchenko #include <linux/err.h>
15df7f9acdSAndy Shevchenko #include <linux/gfp_types.h>
16df7f9acdSAndy Shevchenko #include <linux/intel_tpmi.h>
17df7f9acdSAndy Shevchenko #include <linux/io.h>
18df7f9acdSAndy Shevchenko #include <linux/iopoll.h>
19df7f9acdSAndy Shevchenko #include <linux/kstrtox.h>
20df7f9acdSAndy Shevchenko #include <linux/lockdep.h>
21df7f9acdSAndy Shevchenko #include <linux/module.h>
22df7f9acdSAndy Shevchenko #include <linux/mod_devicetable.h>
23df7f9acdSAndy Shevchenko #include <linux/mutex.h>
24df7f9acdSAndy Shevchenko #include <linux/seq_file.h>
25df7f9acdSAndy Shevchenko #include <linux/sprintf.h>
26df7f9acdSAndy Shevchenko #include <linux/types.h>
27df7f9acdSAndy Shevchenko 
28df7f9acdSAndy Shevchenko #include "tpmi_power_domains.h"
29df7f9acdSAndy Shevchenko 
30df7f9acdSAndy Shevchenko #define PLR_HEADER		0x00
31df7f9acdSAndy Shevchenko #define PLR_MAILBOX_INTERFACE	0x08
32df7f9acdSAndy Shevchenko #define PLR_MAILBOX_DATA	0x10
33df7f9acdSAndy Shevchenko #define PLR_DIE_LEVEL		0x18
34df7f9acdSAndy Shevchenko 
35df7f9acdSAndy Shevchenko #define PLR_MODULE_ID_MASK	GENMASK_ULL(19, 12)
36df7f9acdSAndy Shevchenko #define PLR_RUN_BUSY		BIT_ULL(63)
37df7f9acdSAndy Shevchenko 
38df7f9acdSAndy Shevchenko #define PLR_COMMAND_WRITE	1
39df7f9acdSAndy Shevchenko 
40df7f9acdSAndy Shevchenko #define PLR_INVALID		GENMASK_ULL(63, 0)
41df7f9acdSAndy Shevchenko 
42df7f9acdSAndy Shevchenko #define PLR_TIMEOUT_US		5
43df7f9acdSAndy Shevchenko #define PLR_TIMEOUT_MAX_US	1000
44df7f9acdSAndy Shevchenko 
45df7f9acdSAndy Shevchenko #define PLR_COARSE_REASON_BITS	32
46df7f9acdSAndy Shevchenko 
47df7f9acdSAndy Shevchenko struct tpmi_plr;
48df7f9acdSAndy Shevchenko 
49df7f9acdSAndy Shevchenko struct tpmi_plr_die {
50df7f9acdSAndy Shevchenko 	void __iomem *base;
51df7f9acdSAndy Shevchenko 	struct mutex lock; /* Protect access to PLR mailbox */
52df7f9acdSAndy Shevchenko 	int package_id;
53df7f9acdSAndy Shevchenko 	int die_id;
54df7f9acdSAndy Shevchenko 	struct tpmi_plr *plr;
55df7f9acdSAndy Shevchenko };
56df7f9acdSAndy Shevchenko 
57df7f9acdSAndy Shevchenko struct tpmi_plr {
58df7f9acdSAndy Shevchenko 	struct dentry *dbgfs_dir;
59df7f9acdSAndy Shevchenko 	struct tpmi_plr_die *die_info;
60df7f9acdSAndy Shevchenko 	int num_dies;
61df7f9acdSAndy Shevchenko 	struct auxiliary_device *auxdev;
62df7f9acdSAndy Shevchenko };
63df7f9acdSAndy Shevchenko 
64df7f9acdSAndy Shevchenko static const char * const plr_coarse_reasons[] = {
65df7f9acdSAndy Shevchenko 	"FREQUENCY",
66df7f9acdSAndy Shevchenko 	"CURRENT",
67df7f9acdSAndy Shevchenko 	"POWER",
68df7f9acdSAndy Shevchenko 	"THERMAL",
69df7f9acdSAndy Shevchenko 	"PLATFORM",
70df7f9acdSAndy Shevchenko 	"MCP",
71df7f9acdSAndy Shevchenko 	"RAS",
72df7f9acdSAndy Shevchenko 	"MISC",
73df7f9acdSAndy Shevchenko 	"QOS",
74df7f9acdSAndy Shevchenko 	"DFC",
75df7f9acdSAndy Shevchenko };
76df7f9acdSAndy Shevchenko 
77df7f9acdSAndy Shevchenko static const char * const plr_fine_reasons[] = {
78df7f9acdSAndy Shevchenko 	"FREQUENCY_CDYN0",
79df7f9acdSAndy Shevchenko 	"FREQUENCY_CDYN1",
80df7f9acdSAndy Shevchenko 	"FREQUENCY_CDYN2",
81df7f9acdSAndy Shevchenko 	"FREQUENCY_CDYN3",
82df7f9acdSAndy Shevchenko 	"FREQUENCY_CDYN4",
83df7f9acdSAndy Shevchenko 	"FREQUENCY_CDYN5",
84df7f9acdSAndy Shevchenko 	"FREQUENCY_FCT",
85df7f9acdSAndy Shevchenko 	"FREQUENCY_PCS_TRL",
86df7f9acdSAndy Shevchenko 	"CURRENT_MTPMAX",
87df7f9acdSAndy Shevchenko 	"POWER_FAST_RAPL",
88df7f9acdSAndy Shevchenko 	"POWER_PKG_PL1_MSR_TPMI",
89df7f9acdSAndy Shevchenko 	"POWER_PKG_PL1_MMIO",
90df7f9acdSAndy Shevchenko 	"POWER_PKG_PL1_PCS",
91df7f9acdSAndy Shevchenko 	"POWER_PKG_PL2_MSR_TPMI",
92df7f9acdSAndy Shevchenko 	"POWER_PKG_PL2_MMIO",
93df7f9acdSAndy Shevchenko 	"POWER_PKG_PL2_PCS",
94df7f9acdSAndy Shevchenko 	"POWER_PLATFORM_PL1_MSR_TPMI",
95df7f9acdSAndy Shevchenko 	"POWER_PLATFORM_PL1_MMIO",
96df7f9acdSAndy Shevchenko 	"POWER_PLATFORM_PL1_PCS",
97df7f9acdSAndy Shevchenko 	"POWER_PLATFORM_PL2_MSR_TPMI",
98df7f9acdSAndy Shevchenko 	"POWER_PLATFORM_PL2_MMIO",
99df7f9acdSAndy Shevchenko 	"POWER_PLATFORM_PL2_PCS",
100df7f9acdSAndy Shevchenko 	"UNKNOWN(22)",
101df7f9acdSAndy Shevchenko 	"THERMAL_PER_CORE",
102df7f9acdSAndy Shevchenko 	"DFC_UFS",
103df7f9acdSAndy Shevchenko 	"PLATFORM_PROCHOT",
104df7f9acdSAndy Shevchenko 	"PLATFORM_HOT_VR",
105df7f9acdSAndy Shevchenko 	"UNKNOWN(27)",
106df7f9acdSAndy Shevchenko 	"UNKNOWN(28)",
107df7f9acdSAndy Shevchenko 	"MISC_PCS_PSTATE",
108df7f9acdSAndy Shevchenko };
109df7f9acdSAndy Shevchenko 
plr_read(struct tpmi_plr_die * plr_die,int offset)110df7f9acdSAndy Shevchenko static u64 plr_read(struct tpmi_plr_die *plr_die, int offset)
111df7f9acdSAndy Shevchenko {
112df7f9acdSAndy Shevchenko 	return readq(plr_die->base + offset);
113df7f9acdSAndy Shevchenko }
114df7f9acdSAndy Shevchenko 
plr_write(u64 val,struct tpmi_plr_die * plr_die,int offset)115df7f9acdSAndy Shevchenko static void plr_write(u64 val, struct tpmi_plr_die *plr_die, int offset)
116df7f9acdSAndy Shevchenko {
117df7f9acdSAndy Shevchenko 	writeq(val, plr_die->base + offset);
118df7f9acdSAndy Shevchenko }
119df7f9acdSAndy Shevchenko 
plr_read_cpu_status(struct tpmi_plr_die * plr_die,int cpu,u64 * status)120df7f9acdSAndy Shevchenko static int plr_read_cpu_status(struct tpmi_plr_die *plr_die, int cpu,
121df7f9acdSAndy Shevchenko 			       u64 *status)
122df7f9acdSAndy Shevchenko {
123df7f9acdSAndy Shevchenko 	u64 regval;
124df7f9acdSAndy Shevchenko 	int ret;
125df7f9acdSAndy Shevchenko 
126df7f9acdSAndy Shevchenko 	lockdep_assert_held(&plr_die->lock);
127df7f9acdSAndy Shevchenko 
128df7f9acdSAndy Shevchenko 	regval = FIELD_PREP(PLR_MODULE_ID_MASK, tpmi_get_punit_core_number(cpu));
129df7f9acdSAndy Shevchenko 	regval |= PLR_RUN_BUSY;
130df7f9acdSAndy Shevchenko 
131df7f9acdSAndy Shevchenko 	plr_write(regval, plr_die, PLR_MAILBOX_INTERFACE);
132df7f9acdSAndy Shevchenko 
133df7f9acdSAndy Shevchenko 	ret = readq_poll_timeout(plr_die->base + PLR_MAILBOX_INTERFACE, regval,
134df7f9acdSAndy Shevchenko 				 !(regval & PLR_RUN_BUSY), PLR_TIMEOUT_US,
135df7f9acdSAndy Shevchenko 				 PLR_TIMEOUT_MAX_US);
136df7f9acdSAndy Shevchenko 	if (ret)
137df7f9acdSAndy Shevchenko 		return ret;
138df7f9acdSAndy Shevchenko 
139df7f9acdSAndy Shevchenko 	*status = plr_read(plr_die, PLR_MAILBOX_DATA);
140df7f9acdSAndy Shevchenko 
141df7f9acdSAndy Shevchenko 	return 0;
142df7f9acdSAndy Shevchenko }
143df7f9acdSAndy Shevchenko 
plr_clear_cpu_status(struct tpmi_plr_die * plr_die,int cpu)144df7f9acdSAndy Shevchenko static int plr_clear_cpu_status(struct tpmi_plr_die *plr_die, int cpu)
145df7f9acdSAndy Shevchenko {
146df7f9acdSAndy Shevchenko 	u64 regval;
147df7f9acdSAndy Shevchenko 
148df7f9acdSAndy Shevchenko 	lockdep_assert_held(&plr_die->lock);
149df7f9acdSAndy Shevchenko 
150df7f9acdSAndy Shevchenko 	regval = FIELD_PREP(PLR_MODULE_ID_MASK, tpmi_get_punit_core_number(cpu));
151df7f9acdSAndy Shevchenko 	regval |= PLR_RUN_BUSY | PLR_COMMAND_WRITE;
152df7f9acdSAndy Shevchenko 
153df7f9acdSAndy Shevchenko 	plr_write(0, plr_die, PLR_MAILBOX_DATA);
154df7f9acdSAndy Shevchenko 
155df7f9acdSAndy Shevchenko 	plr_write(regval, plr_die, PLR_MAILBOX_INTERFACE);
156df7f9acdSAndy Shevchenko 
157df7f9acdSAndy Shevchenko 	return readq_poll_timeout(plr_die->base + PLR_MAILBOX_INTERFACE, regval,
158df7f9acdSAndy Shevchenko 				  !(regval & PLR_RUN_BUSY), PLR_TIMEOUT_US,
159df7f9acdSAndy Shevchenko 				  PLR_TIMEOUT_MAX_US);
160df7f9acdSAndy Shevchenko }
161df7f9acdSAndy Shevchenko 
plr_print_bits(struct seq_file * s,u64 val,int bits)162df7f9acdSAndy Shevchenko static void plr_print_bits(struct seq_file *s, u64 val, int bits)
163df7f9acdSAndy Shevchenko {
164df7f9acdSAndy Shevchenko 	const unsigned long mask[] = { BITMAP_FROM_U64(val) };
165df7f9acdSAndy Shevchenko 	int bit, index;
166df7f9acdSAndy Shevchenko 
167df7f9acdSAndy Shevchenko 	for_each_set_bit(bit, mask, bits) {
168df7f9acdSAndy Shevchenko 		const char *str = NULL;
169df7f9acdSAndy Shevchenko 
170df7f9acdSAndy Shevchenko 		if (bit < PLR_COARSE_REASON_BITS) {
171df7f9acdSAndy Shevchenko 			if (bit < ARRAY_SIZE(plr_coarse_reasons))
172df7f9acdSAndy Shevchenko 				str = plr_coarse_reasons[bit];
173df7f9acdSAndy Shevchenko 		} else {
174df7f9acdSAndy Shevchenko 			index = bit - PLR_COARSE_REASON_BITS;
175df7f9acdSAndy Shevchenko 			if (index < ARRAY_SIZE(plr_fine_reasons))
176df7f9acdSAndy Shevchenko 				str = plr_fine_reasons[index];
177df7f9acdSAndy Shevchenko 		}
178df7f9acdSAndy Shevchenko 
179df7f9acdSAndy Shevchenko 		if (str)
180df7f9acdSAndy Shevchenko 			seq_printf(s, " %s", str);
181df7f9acdSAndy Shevchenko 		else
182df7f9acdSAndy Shevchenko 			seq_printf(s, " UNKNOWN(%d)", bit);
183df7f9acdSAndy Shevchenko 	}
184df7f9acdSAndy Shevchenko 
185df7f9acdSAndy Shevchenko 	if (!val)
186df7f9acdSAndy Shevchenko 		seq_puts(s, " none");
187df7f9acdSAndy Shevchenko 
188df7f9acdSAndy Shevchenko 	seq_putc(s, '\n');
189df7f9acdSAndy Shevchenko }
190df7f9acdSAndy Shevchenko 
plr_status_show(struct seq_file * s,void * unused)191df7f9acdSAndy Shevchenko static int plr_status_show(struct seq_file *s, void *unused)
192df7f9acdSAndy Shevchenko {
193df7f9acdSAndy Shevchenko 	struct tpmi_plr_die *plr_die = s->private;
194df7f9acdSAndy Shevchenko 	int ret;
195df7f9acdSAndy Shevchenko 	u64 val;
196df7f9acdSAndy Shevchenko 
197df7f9acdSAndy Shevchenko 	val = plr_read(plr_die, PLR_DIE_LEVEL);
198df7f9acdSAndy Shevchenko 	seq_puts(s, "cpus");
199df7f9acdSAndy Shevchenko 	plr_print_bits(s, val, 32);
200df7f9acdSAndy Shevchenko 
201df7f9acdSAndy Shevchenko 	guard(mutex)(&plr_die->lock);
202df7f9acdSAndy Shevchenko 
203df7f9acdSAndy Shevchenko 	for (int cpu = 0; cpu < nr_cpu_ids; cpu++) {
204df7f9acdSAndy Shevchenko 		if (plr_die->die_id != tpmi_get_power_domain_id(cpu))
205df7f9acdSAndy Shevchenko 			continue;
206df7f9acdSAndy Shevchenko 
207df7f9acdSAndy Shevchenko 		if (plr_die->package_id != topology_physical_package_id(cpu))
208df7f9acdSAndy Shevchenko 			continue;
209df7f9acdSAndy Shevchenko 
210df7f9acdSAndy Shevchenko 		seq_printf(s, "cpu%d", cpu);
211df7f9acdSAndy Shevchenko 		ret = plr_read_cpu_status(plr_die, cpu, &val);
212df7f9acdSAndy Shevchenko 		if (ret) {
213df7f9acdSAndy Shevchenko 			dev_err(&plr_die->plr->auxdev->dev, "Failed to read PLR for cpu %d, ret=%d\n",
214df7f9acdSAndy Shevchenko 				cpu, ret);
215df7f9acdSAndy Shevchenko 			return ret;
216df7f9acdSAndy Shevchenko 		}
217df7f9acdSAndy Shevchenko 
218df7f9acdSAndy Shevchenko 		plr_print_bits(s, val, 64);
219df7f9acdSAndy Shevchenko 	}
220df7f9acdSAndy Shevchenko 
221df7f9acdSAndy Shevchenko 	return 0;
222df7f9acdSAndy Shevchenko }
223df7f9acdSAndy Shevchenko 
plr_status_write(struct file * filp,const char __user * ubuf,size_t count,loff_t * ppos)224df7f9acdSAndy Shevchenko static ssize_t plr_status_write(struct file *filp, const char __user *ubuf,
225df7f9acdSAndy Shevchenko 				size_t count, loff_t *ppos)
226df7f9acdSAndy Shevchenko {
227df7f9acdSAndy Shevchenko 	struct seq_file *s = filp->private_data;
228df7f9acdSAndy Shevchenko 	struct tpmi_plr_die *plr_die = s->private;
229df7f9acdSAndy Shevchenko 	bool val;
230df7f9acdSAndy Shevchenko 	int ret;
231df7f9acdSAndy Shevchenko 
232df7f9acdSAndy Shevchenko 	ret = kstrtobool_from_user(ubuf, count, &val);
233df7f9acdSAndy Shevchenko 	if (ret)
234df7f9acdSAndy Shevchenko 		return ret;
235df7f9acdSAndy Shevchenko 
236df7f9acdSAndy Shevchenko 	if (val != 0)
237df7f9acdSAndy Shevchenko 		return -EINVAL;
238df7f9acdSAndy Shevchenko 
239df7f9acdSAndy Shevchenko 	plr_write(0, plr_die, PLR_DIE_LEVEL);
240df7f9acdSAndy Shevchenko 
241df7f9acdSAndy Shevchenko 	guard(mutex)(&plr_die->lock);
242df7f9acdSAndy Shevchenko 
243df7f9acdSAndy Shevchenko 	for (int cpu = 0; cpu < nr_cpu_ids; cpu++) {
244df7f9acdSAndy Shevchenko 		if (plr_die->die_id != tpmi_get_power_domain_id(cpu))
245df7f9acdSAndy Shevchenko 			continue;
246df7f9acdSAndy Shevchenko 
247df7f9acdSAndy Shevchenko 		if (plr_die->package_id != topology_physical_package_id(cpu))
248df7f9acdSAndy Shevchenko 			continue;
249df7f9acdSAndy Shevchenko 
250df7f9acdSAndy Shevchenko 		plr_clear_cpu_status(plr_die, cpu);
251df7f9acdSAndy Shevchenko 	}
252df7f9acdSAndy Shevchenko 
253df7f9acdSAndy Shevchenko 	return count;
254df7f9acdSAndy Shevchenko }
255df7f9acdSAndy Shevchenko DEFINE_SHOW_STORE_ATTRIBUTE(plr_status);
256df7f9acdSAndy Shevchenko 
intel_plr_probe(struct auxiliary_device * auxdev,const struct auxiliary_device_id * id)257df7f9acdSAndy Shevchenko static int intel_plr_probe(struct auxiliary_device *auxdev, const struct auxiliary_device_id *id)
258df7f9acdSAndy Shevchenko {
259df7f9acdSAndy Shevchenko 	struct intel_tpmi_plat_info *plat_info;
260df7f9acdSAndy Shevchenko 	struct dentry *dentry;
261df7f9acdSAndy Shevchenko 	int i, num_resources;
262df7f9acdSAndy Shevchenko 	struct resource *res;
263df7f9acdSAndy Shevchenko 	struct tpmi_plr *plr;
264df7f9acdSAndy Shevchenko 	void __iomem *base;
265df7f9acdSAndy Shevchenko 	char name[17];
266df7f9acdSAndy Shevchenko 	int err;
267df7f9acdSAndy Shevchenko 
268df7f9acdSAndy Shevchenko 	plat_info = tpmi_get_platform_data(auxdev);
269df7f9acdSAndy Shevchenko 	if (!plat_info)
270df7f9acdSAndy Shevchenko 		return dev_err_probe(&auxdev->dev, -EINVAL, "No platform info\n");
271df7f9acdSAndy Shevchenko 
272df7f9acdSAndy Shevchenko 	dentry = tpmi_get_debugfs_dir(auxdev);
273df7f9acdSAndy Shevchenko 	if (!dentry)
274df7f9acdSAndy Shevchenko 		return dev_err_probe(&auxdev->dev, -ENODEV, "No TPMI debugfs directory.\n");
275df7f9acdSAndy Shevchenko 
276df7f9acdSAndy Shevchenko 	num_resources = tpmi_get_resource_count(auxdev);
277df7f9acdSAndy Shevchenko 	if (!num_resources)
278df7f9acdSAndy Shevchenko 		return -EINVAL;
279df7f9acdSAndy Shevchenko 
280df7f9acdSAndy Shevchenko 	plr = devm_kzalloc(&auxdev->dev, sizeof(*plr), GFP_KERNEL);
281df7f9acdSAndy Shevchenko 	if (!plr)
282df7f9acdSAndy Shevchenko 		return -ENOMEM;
283df7f9acdSAndy Shevchenko 
284df7f9acdSAndy Shevchenko 	plr->die_info = devm_kcalloc(&auxdev->dev, num_resources, sizeof(*plr->die_info),
285df7f9acdSAndy Shevchenko 				     GFP_KERNEL);
286df7f9acdSAndy Shevchenko 	if (!plr->die_info)
287df7f9acdSAndy Shevchenko 		return -ENOMEM;
288df7f9acdSAndy Shevchenko 
289df7f9acdSAndy Shevchenko 	plr->num_dies = num_resources;
290df7f9acdSAndy Shevchenko 	plr->dbgfs_dir = debugfs_create_dir("plr", dentry);
291df7f9acdSAndy Shevchenko 	plr->auxdev = auxdev;
292df7f9acdSAndy Shevchenko 
293df7f9acdSAndy Shevchenko 	for (i = 0; i < num_resources; i++) {
294df7f9acdSAndy Shevchenko 		res = tpmi_get_resource_at_index(auxdev, i);
295df7f9acdSAndy Shevchenko 		if (!res) {
296df7f9acdSAndy Shevchenko 			err = dev_err_probe(&auxdev->dev, -EINVAL, "No resource\n");
297df7f9acdSAndy Shevchenko 			goto err;
298df7f9acdSAndy Shevchenko 		}
299df7f9acdSAndy Shevchenko 
300df7f9acdSAndy Shevchenko 		base = devm_ioremap_resource(&auxdev->dev, res);
301df7f9acdSAndy Shevchenko 		if (IS_ERR(base)) {
302df7f9acdSAndy Shevchenko 			err = PTR_ERR(base);
303df7f9acdSAndy Shevchenko 			goto err;
304df7f9acdSAndy Shevchenko 		}
305df7f9acdSAndy Shevchenko 
306df7f9acdSAndy Shevchenko 		plr->die_info[i].base = base;
307df7f9acdSAndy Shevchenko 		plr->die_info[i].package_id = plat_info->package_id;
308df7f9acdSAndy Shevchenko 		plr->die_info[i].die_id = i;
309df7f9acdSAndy Shevchenko 		plr->die_info[i].plr = plr;
310df7f9acdSAndy Shevchenko 		mutex_init(&plr->die_info[i].lock);
311df7f9acdSAndy Shevchenko 
312df7f9acdSAndy Shevchenko 		if (plr_read(&plr->die_info[i], PLR_HEADER) == PLR_INVALID)
313df7f9acdSAndy Shevchenko 			continue;
314df7f9acdSAndy Shevchenko 
315df7f9acdSAndy Shevchenko 		snprintf(name, sizeof(name), "domain%d", i);
316df7f9acdSAndy Shevchenko 
317df7f9acdSAndy Shevchenko 		dentry = debugfs_create_dir(name, plr->dbgfs_dir);
318df7f9acdSAndy Shevchenko 		debugfs_create_file("status", 0444, dentry, &plr->die_info[i],
319df7f9acdSAndy Shevchenko 				    &plr_status_fops);
320df7f9acdSAndy Shevchenko 	}
321df7f9acdSAndy Shevchenko 
322df7f9acdSAndy Shevchenko 	auxiliary_set_drvdata(auxdev, plr);
323df7f9acdSAndy Shevchenko 
324df7f9acdSAndy Shevchenko 	return 0;
325df7f9acdSAndy Shevchenko 
326df7f9acdSAndy Shevchenko err:
327df7f9acdSAndy Shevchenko 	debugfs_remove_recursive(plr->dbgfs_dir);
328df7f9acdSAndy Shevchenko 	return err;
329df7f9acdSAndy Shevchenko }
330df7f9acdSAndy Shevchenko 
intel_plr_remove(struct auxiliary_device * auxdev)331df7f9acdSAndy Shevchenko static void intel_plr_remove(struct auxiliary_device *auxdev)
332df7f9acdSAndy Shevchenko {
333df7f9acdSAndy Shevchenko 	struct tpmi_plr *plr = auxiliary_get_drvdata(auxdev);
334df7f9acdSAndy Shevchenko 
335df7f9acdSAndy Shevchenko 	debugfs_remove_recursive(plr->dbgfs_dir);
336df7f9acdSAndy Shevchenko }
337df7f9acdSAndy Shevchenko 
338df7f9acdSAndy Shevchenko static const struct auxiliary_device_id intel_plr_id_table[] = {
339df7f9acdSAndy Shevchenko 	{ .name = "intel_vsec.tpmi-plr" },
340df7f9acdSAndy Shevchenko 	{}
341df7f9acdSAndy Shevchenko };
342df7f9acdSAndy Shevchenko MODULE_DEVICE_TABLE(auxiliary, intel_plr_id_table);
343df7f9acdSAndy Shevchenko 
344df7f9acdSAndy Shevchenko static struct auxiliary_driver intel_plr_aux_driver = {
345df7f9acdSAndy Shevchenko 	.id_table       = intel_plr_id_table,
346df7f9acdSAndy Shevchenko 	.remove         = intel_plr_remove,
347df7f9acdSAndy Shevchenko 	.probe          = intel_plr_probe,
348df7f9acdSAndy Shevchenko };
349df7f9acdSAndy Shevchenko module_auxiliary_driver(intel_plr_aux_driver);
350df7f9acdSAndy Shevchenko 
351*cdd30ebbSPeter Zijlstra MODULE_IMPORT_NS("INTEL_TPMI");
352*cdd30ebbSPeter Zijlstra MODULE_IMPORT_NS("INTEL_TPMI_POWER_DOMAIN");
353df7f9acdSAndy Shevchenko MODULE_DESCRIPTION("Intel TPMI PLR Driver");
354df7f9acdSAndy Shevchenko MODULE_LICENSE("GPL");
355