115 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * processor thermal device RFIM control4 * 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 12static struct rapl_if_priv rapl_mmio_priv;13 14static 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 22static 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 32static 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 46int 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 92err:93 powercap_unregister_control_type(rapl_mmio_priv.control_type);94 rapl_mmio_priv.control_type = NULL;95 return ret;96}97EXPORT_SYMBOL_GPL(proc_thermal_rapl_add);98 99void 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}111EXPORT_SYMBOL_GPL(proc_thermal_rapl_remove);112 113MODULE_LICENSE("GPL v2");114MODULE_DESCRIPTION("RAPL interface using MMIO");115