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 static struct rapl_if_priv rapl_mmio_priv;
13 
14 static const struct rapl_mmio_regs rapl_mmio_default = {
15 	.reg_unit = 0x5938,
16 	.regs[RAPL_DOMAIN_PACKAGE] = { 0x59a0, 0x593c, 0x58f0, 0, 0x5930, 0x59b0},
17 	.regs[RAPL_DOMAIN_DRAM] = { 0x58e0, 0x58e8, 0x58ec, 0, 0},
18 	.limits[RAPL_DOMAIN_PACKAGE] = BIT(POWER_LIMIT2) | BIT(POWER_LIMIT4),
19 	.limits[RAPL_DOMAIN_DRAM] = BIT(POWER_LIMIT2),
20 };
21 
22 static int rapl_mmio_read_raw(int cpu, struct reg_action *ra)
23 {
24 	if (!ra->reg.mmio)
25 		return -EINVAL;
26 
27 	ra->value = readq(ra->reg.mmio);
28 	ra->value &= ra->mask;
29 	return 0;
30 }
31 
32 static int rapl_mmio_write_raw(int cpu, struct reg_action *ra)
33 {
34 	u64 val;
35 
36 	if (!ra->reg.mmio)
37 		return -EINVAL;
38 
39 	val = readq(ra->reg.mmio);
40 	val &= ~ra->mask;
41 	val |= ra->value;
42 	writeq(val, ra->reg.mmio);
43 	return 0;
44 }
45 
46 int proc_thermal_rapl_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv)
47 {
48 	const struct rapl_mmio_regs *rapl_regs = &rapl_mmio_default;
49 	struct rapl_package *rp;
50 	enum rapl_domain_reg_id reg;
51 	enum rapl_domain_type domain;
52 	int ret;
53 
54 	if (!rapl_regs)
55 		return 0;
56 
57 	for (domain = RAPL_DOMAIN_PACKAGE; domain < RAPL_DOMAIN_MAX; domain++) {
58 		for (reg = RAPL_DOMAIN_REG_LIMIT; reg < RAPL_DOMAIN_REG_MAX; reg++)
59 			if (rapl_regs->regs[domain][reg])
60 				rapl_mmio_priv.regs[domain][reg].mmio =
61 						proc_priv->mmio_base +
62 						rapl_regs->regs[domain][reg];
63 		rapl_mmio_priv.limits[domain] = rapl_regs->limits[domain];
64 	}
65 	rapl_mmio_priv.type = RAPL_IF_MMIO;
66 	rapl_mmio_priv.reg_unit.mmio = proc_priv->mmio_base + rapl_regs->reg_unit;
67 
68 	rapl_mmio_priv.read_raw = rapl_mmio_read_raw;
69 	rapl_mmio_priv.write_raw = rapl_mmio_write_raw;
70 
71 	rapl_mmio_priv.control_type = powercap_register_control_type(NULL, "intel-rapl-mmio", NULL);
72 	if (IS_ERR(rapl_mmio_priv.control_type)) {
73 		pr_debug("failed to register powercap control_type.\n");
74 		return PTR_ERR(rapl_mmio_priv.control_type);
75 	}
76 
77 	/* Register a RAPL package device for package 0 which is always online */
78 	rp = rapl_find_package_domain(0, &rapl_mmio_priv, false);
79 	if (rp) {
80 		ret = -EEXIST;
81 		goto err;
82 	}
83 
84 	rp = rapl_add_package(0, &rapl_mmio_priv, false);
85 	if (IS_ERR(rp)) {
86 		ret = PTR_ERR(rp);
87 		goto err;
88 	}
89 
90 	return 0;
91 
92 err:
93 	powercap_unregister_control_type(rapl_mmio_priv.control_type);
94 	rapl_mmio_priv.control_type = NULL;
95 	return ret;
96 }
97 EXPORT_SYMBOL_GPL(proc_thermal_rapl_add);
98 
99 void proc_thermal_rapl_remove(void)
100 {
101 	struct rapl_package *rp;
102 
103 	if (IS_ERR_OR_NULL(rapl_mmio_priv.control_type))
104 		return;
105 
106 	rp = rapl_find_package_domain(0, &rapl_mmio_priv, false);
107 	if (rp)
108 		rapl_remove_package(rp);
109 	powercap_unregister_control_type(rapl_mmio_priv.control_type);
110 }
111 EXPORT_SYMBOL_GPL(proc_thermal_rapl_remove);
112 
113 MODULE_LICENSE("GPL v2");
114