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},
17 .regs[RAPL_DOMAIN_DRAM] = { 0x58e0, 0x58e8, 0x58ec, 0, 0},
18 .limits[RAPL_DOMAIN_PACKAGE] = 2,
19 .limits[RAPL_DOMAIN_DRAM] = 2,
20 };
21
rapl_mmio_cpu_online(unsigned int cpu)22 static int rapl_mmio_cpu_online(unsigned int cpu)
23 {
24 struct rapl_package *rp;
25
26 /* mmio rapl supports package 0 only for now */
27 if (topology_physical_package_id(cpu))
28 return 0;
29
30 rp = rapl_find_package_domain(cpu, &rapl_mmio_priv);
31 if (!rp) {
32 rp = rapl_add_package(cpu, &rapl_mmio_priv);
33 if (IS_ERR(rp))
34 return PTR_ERR(rp);
35 }
36 cpumask_set_cpu(cpu, &rp->cpumask);
37 return 0;
38 }
39
rapl_mmio_cpu_down_prep(unsigned int cpu)40 static int rapl_mmio_cpu_down_prep(unsigned int cpu)
41 {
42 struct rapl_package *rp;
43 int lead_cpu;
44
45 rp = rapl_find_package_domain(cpu, &rapl_mmio_priv);
46 if (!rp)
47 return 0;
48
49 cpumask_clear_cpu(cpu, &rp->cpumask);
50 lead_cpu = cpumask_first(&rp->cpumask);
51 if (lead_cpu >= nr_cpu_ids)
52 rapl_remove_package(rp);
53 else if (rp->lead_cpu == cpu)
54 rp->lead_cpu = lead_cpu;
55 return 0;
56 }
57
rapl_mmio_read_raw(int cpu,struct reg_action * ra)58 static int rapl_mmio_read_raw(int cpu, struct reg_action *ra)
59 {
60 if (!ra->reg)
61 return -EINVAL;
62
63 ra->value = readq((void __iomem *)ra->reg);
64 ra->value &= ra->mask;
65 return 0;
66 }
67
rapl_mmio_write_raw(int cpu,struct reg_action * ra)68 static int rapl_mmio_write_raw(int cpu, struct reg_action *ra)
69 {
70 u64 val;
71
72 if (!ra->reg)
73 return -EINVAL;
74
75 val = readq((void __iomem *)ra->reg);
76 val &= ~ra->mask;
77 val |= ra->value;
78 writeq(val, (void __iomem *)ra->reg);
79 return 0;
80 }
81
proc_thermal_rapl_add(struct pci_dev * pdev,struct proc_thermal_device * proc_priv)82 int proc_thermal_rapl_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv)
83 {
84 const struct rapl_mmio_regs *rapl_regs = &rapl_mmio_default;
85 enum rapl_domain_reg_id reg;
86 enum rapl_domain_type domain;
87 int ret;
88
89 if (!rapl_regs)
90 return 0;
91
92 for (domain = RAPL_DOMAIN_PACKAGE; domain < RAPL_DOMAIN_MAX; domain++) {
93 for (reg = RAPL_DOMAIN_REG_LIMIT; reg < RAPL_DOMAIN_REG_MAX; reg++)
94 if (rapl_regs->regs[domain][reg])
95 rapl_mmio_priv.regs[domain][reg] =
96 (u64)proc_priv->mmio_base +
97 rapl_regs->regs[domain][reg];
98 rapl_mmio_priv.limits[domain] = rapl_regs->limits[domain];
99 }
100 rapl_mmio_priv.reg_unit = (u64)proc_priv->mmio_base + rapl_regs->reg_unit;
101
102 rapl_mmio_priv.read_raw = rapl_mmio_read_raw;
103 rapl_mmio_priv.write_raw = rapl_mmio_write_raw;
104
105 rapl_mmio_priv.control_type = powercap_register_control_type(NULL, "intel-rapl-mmio", NULL);
106 if (IS_ERR(rapl_mmio_priv.control_type)) {
107 pr_debug("failed to register powercap control_type.\n");
108 return PTR_ERR(rapl_mmio_priv.control_type);
109 }
110
111 ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "powercap/rapl:online",
112 rapl_mmio_cpu_online, rapl_mmio_cpu_down_prep);
113 if (ret < 0) {
114 powercap_unregister_control_type(rapl_mmio_priv.control_type);
115 rapl_mmio_priv.control_type = NULL;
116 return ret;
117 }
118 rapl_mmio_priv.pcap_rapl_online = ret;
119
120 return 0;
121 }
122 EXPORT_SYMBOL_GPL(proc_thermal_rapl_add);
123
proc_thermal_rapl_remove(void)124 void proc_thermal_rapl_remove(void)
125 {
126 if (IS_ERR_OR_NULL(rapl_mmio_priv.control_type))
127 return;
128
129 cpuhp_remove_state(rapl_mmio_priv.pcap_rapl_online);
130 powercap_unregister_control_type(rapl_mmio_priv.control_type);
131 }
132 EXPORT_SYMBOL_GPL(proc_thermal_rapl_remove);
133
134 MODULE_LICENSE("GPL v2");
135