Commit d91a4714 authored by Zhang Rui's avatar Zhang Rui Committed by Rafael J. Wysocki

thermal/int340x/processor_thermal: Use Intel TCC library

Cleanup the code by using Intel TCC library for TCC (Thermal Control
Circuitry) MSR access.
Signed-off-by: default avatarZhang Rui <rui.zhang@intel.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent a3c1f066
...@@ -10,6 +10,7 @@ config INT340X_THERMAL ...@@ -10,6 +10,7 @@ config INT340X_THERMAL
select ACPI_THERMAL_REL select ACPI_THERMAL_REL
select ACPI_FAN select ACPI_FAN
select INTEL_SOC_DTS_IOSF_CORE select INTEL_SOC_DTS_IOSF_CORE
select INTEL_TCC
select PROC_THERMAL_MMIO_RAPL if POWERCAP select PROC_THERMAL_MMIO_RAPL if POWERCAP
help help
Newer laptops and tablets that use ACPI may have thermal sensors and Newer laptops and tablets that use ACPI may have thermal sensors and
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* Copyright (c) 2014, Intel Corporation. * Copyright (c) 2014, Intel Corporation.
*/ */
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/intel_tcc.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pci.h> #include <linux/pci.h>
...@@ -68,54 +69,17 @@ static const struct attribute_group power_limit_attribute_group = { ...@@ -68,54 +69,17 @@ static const struct attribute_group power_limit_attribute_group = {
.name = "power_limits" .name = "power_limits"
}; };
static int tcc_get_offset(void)
{
u64 val;
int err;
err = rdmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, &val);
if (err)
return err;
return (val >> 24) & 0x3f;
}
static ssize_t tcc_offset_degree_celsius_show(struct device *dev, static ssize_t tcc_offset_degree_celsius_show(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
int tcc; int offset;
tcc = tcc_get_offset();
if (tcc < 0)
return tcc;
return sprintf(buf, "%d\n", tcc); offset = intel_tcc_get_offset(-1);
} if (offset < 0)
return offset;
static int tcc_offset_update(unsigned int tcc)
{
u64 val;
int err;
if (tcc > 63)
return -EINVAL;
err = rdmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, &val);
if (err)
return err;
if (val & BIT(31))
return -EPERM;
val &= ~GENMASK_ULL(29, 24);
val |= (tcc & 0x3f) << 24;
err = wrmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, val);
if (err)
return err;
return 0; return sprintf(buf, "%d\n", offset);
} }
static ssize_t tcc_offset_degree_celsius_store(struct device *dev, static ssize_t tcc_offset_degree_celsius_store(struct device *dev,
...@@ -136,7 +100,7 @@ static ssize_t tcc_offset_degree_celsius_store(struct device *dev, ...@@ -136,7 +100,7 @@ static ssize_t tcc_offset_degree_celsius_store(struct device *dev,
if (kstrtouint(buf, 0, &tcc)) if (kstrtouint(buf, 0, &tcc))
return -EINVAL; return -EINVAL;
err = tcc_offset_update(tcc); err = intel_tcc_set_offset(-1, tcc);
if (err) if (err)
return err; return err;
...@@ -145,66 +109,25 @@ static ssize_t tcc_offset_degree_celsius_store(struct device *dev, ...@@ -145,66 +109,25 @@ static ssize_t tcc_offset_degree_celsius_store(struct device *dev,
static DEVICE_ATTR_RW(tcc_offset_degree_celsius); static DEVICE_ATTR_RW(tcc_offset_degree_celsius);
static int stored_tjmax; /* since it is fixed, we can have local storage */ static int proc_thermal_get_zone_temp(struct thermal_zone_device *zone,
int *temp)
static int get_tjmax(void)
{
u32 eax, edx;
u32 val;
int err;
err = rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
if (err)
return err;
val = (eax >> 16) & 0xff;
if (val)
return val;
return -EINVAL;
}
static int read_temp_msr(int *temp)
{ {
int cpu; int cpu;
u32 eax, edx; int curr_temp;
int err;
unsigned long curr_temp_off = 0;
*temp = 0; *temp = 0;
for_each_online_cpu(cpu) { for_each_online_cpu(cpu) {
err = rdmsr_safe_on_cpu(cpu, MSR_IA32_THERM_STATUS, &eax, curr_temp = intel_tcc_get_temp(cpu, false);
&edx); if (curr_temp < 0)
if (err) return curr_temp;
goto err_ret; if (!*temp || curr_temp > *temp)
else { *temp = curr_temp;
if (eax & 0x80000000) {
curr_temp_off = (eax >> 16) & 0x7f;
if (!*temp || curr_temp_off < *temp)
*temp = curr_temp_off;
} else {
err = -EINVAL;
goto err_ret;
}
}
} }
return 0; *temp *= 1000;
err_ret:
return err;
}
static int proc_thermal_get_zone_temp(struct thermal_zone_device *zone,
int *temp)
{
int ret;
ret = read_temp_msr(temp);
if (!ret)
*temp = (stored_tjmax - *temp) * 1000;
return ret; return 0;
} }
static struct thermal_zone_device_ops proc_thermal_local_ops = { static struct thermal_zone_device_ops proc_thermal_local_ops = {
...@@ -302,8 +225,7 @@ int proc_thermal_add(struct device *dev, struct proc_thermal_device *proc_priv) ...@@ -302,8 +225,7 @@ int proc_thermal_add(struct device *dev, struct proc_thermal_device *proc_priv)
status = acpi_evaluate_integer(adev->handle, "_TMP", NULL, &tmp); status = acpi_evaluate_integer(adev->handle, "_TMP", NULL, &tmp);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
/* there is no _TMP method, add local method */ /* there is no _TMP method, add local method */
stored_tjmax = get_tjmax(); if (intel_tcc_get_tjmax(-1) > 0)
if (stored_tjmax > 0)
ops = &proc_thermal_local_ops; ops = &proc_thermal_local_ops;
} }
...@@ -356,7 +278,7 @@ static int tcc_offset_save = -1; ...@@ -356,7 +278,7 @@ static int tcc_offset_save = -1;
int proc_thermal_suspend(struct device *dev) int proc_thermal_suspend(struct device *dev)
{ {
tcc_offset_save = tcc_get_offset(); tcc_offset_save = intel_tcc_get_offset(-1);
if (tcc_offset_save < 0) if (tcc_offset_save < 0)
dev_warn(dev, "failed to save offset (%d)\n", tcc_offset_save); dev_warn(dev, "failed to save offset (%d)\n", tcc_offset_save);
...@@ -373,7 +295,7 @@ int proc_thermal_resume(struct device *dev) ...@@ -373,7 +295,7 @@ int proc_thermal_resume(struct device *dev)
/* Do not update if saving failed */ /* Do not update if saving failed */
if (tcc_offset_save >= 0) if (tcc_offset_save >= 0)
tcc_offset_update(tcc_offset_save); intel_tcc_set_offset(-1, tcc_offset_save);
return 0; return 0;
} }
...@@ -460,6 +382,7 @@ void proc_thermal_mmio_remove(struct pci_dev *pdev, struct proc_thermal_device * ...@@ -460,6 +382,7 @@ void proc_thermal_mmio_remove(struct pci_dev *pdev, struct proc_thermal_device *
} }
EXPORT_SYMBOL_GPL(proc_thermal_mmio_remove); EXPORT_SYMBOL_GPL(proc_thermal_mmio_remove);
MODULE_IMPORT_NS(INTEL_TCC);
MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver"); MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment