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