summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/thermal/intel/Kconfig7
-rw-r--r--drivers/thermal/intel/Makefile1
-rw-r--r--drivers/thermal/intel/int340x_thermal/Kconfig1
-rw-r--r--drivers/thermal/intel/int340x_thermal/int3400_thermal.c10
-rw-r--r--drivers/thermal/intel/int340x_thermal/processor_thermal_device.c119
-rw-r--r--drivers/thermal/intel/intel_menlow.c12
-rw-r--r--drivers/thermal/intel/intel_soc_dts_iosf.c35
-rw-r--r--drivers/thermal/intel/intel_tcc.c139
-rw-r--r--drivers/thermal/intel/intel_tcc_cooling.c37
-rw-r--r--drivers/thermal/intel/x86_pkg_temp_thermal.c60
-rw-r--r--include/linux/intel_tcc.h18
11 files changed, 232 insertions, 207 deletions
diff --git a/drivers/thermal/intel/Kconfig b/drivers/thermal/intel/Kconfig
index f0c845679250..fd41c810629b 100644
--- a/drivers/thermal/intel/Kconfig
+++ b/drivers/thermal/intel/Kconfig
@@ -12,11 +12,16 @@ config X86_THERMAL_VECTOR
def_bool y
depends on X86 && CPU_SUP_INTEL && X86_LOCAL_APIC
+config INTEL_TCC
+ bool
+ depends on X86
+
config X86_PKG_TEMP_THERMAL
tristate "X86 package temperature thermal driver"
depends on X86_THERMAL_VECTOR
select THERMAL_GOV_USER_SPACE
select THERMAL_WRITABLE_TRIPS
+ select INTEL_TCC
default m
help
Enable this to register CPU digital sensor for package temperature as
@@ -28,6 +33,7 @@ config INTEL_SOC_DTS_IOSF_CORE
tristate
depends on X86 && PCI
select IOSF_MBI
+ select INTEL_TCC
help
This is becoming a common feature for Intel SoCs to expose the additional
digital temperature sensors (DTSs) using side band interface (IOSF). This
@@ -83,6 +89,7 @@ config INTEL_PCH_THERMAL
config INTEL_TCC_COOLING
tristate "Intel TCC offset cooling Driver"
depends on X86
+ select INTEL_TCC
help
Enable this to support system cooling by adjusting the effective TCC
activation temperature via the TCC Offset register, which is widely
diff --git a/drivers/thermal/intel/Makefile b/drivers/thermal/intel/Makefile
index 9a8d8054f316..5d8833c82ab6 100644
--- a/drivers/thermal/intel/Makefile
+++ b/drivers/thermal/intel/Makefile
@@ -2,6 +2,7 @@
#
# Makefile for various Intel thermal drivers.
+obj-$(CONFIG_INTEL_TCC) += intel_tcc.o
obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o
obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o
obj-$(CONFIG_INTEL_SOC_DTS_IOSF_CORE) += intel_soc_dts_iosf.o
diff --git a/drivers/thermal/intel/int340x_thermal/Kconfig b/drivers/thermal/intel/int340x_thermal/Kconfig
index 5d046de96a5d..0f511917e0e1 100644
--- a/drivers/thermal/intel/int340x_thermal/Kconfig
+++ b/drivers/thermal/intel/int340x_thermal/Kconfig
@@ -10,6 +10,7 @@ config INT340X_THERMAL
select ACPI_THERMAL_REL
select ACPI_FAN
select INTEL_SOC_DTS_IOSF_CORE
+ select INTEL_TCC
select PROC_THERMAL_MMIO_RAPL if POWERCAP
help
Newer laptops and tablets that use ACPI may have thermal sensors and
diff --git a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c
index db8a6f63657d..c1fc4a78607c 100644
--- a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c
+++ b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c
@@ -130,10 +130,7 @@ static ssize_t available_uuids_show(struct device *dev,
for (i = 0; i < INT3400_THERMAL_MAXIMUM_UUID; i++) {
if (priv->uuid_bitmap & (1 << i))
- length += scnprintf(&buf[length],
- PAGE_SIZE - length,
- "%s\n",
- int3400_thermal_uuids[i]);
+ length += sysfs_emit_at(buf, length, int3400_thermal_uuids[i]);
}
return length;
@@ -151,10 +148,7 @@ static ssize_t current_uuid_show(struct device *dev,
for (i = 0; i <= INT3400_THERMAL_CRITICAL; i++) {
if (priv->os_uuid_mask & BIT(i))
- length += scnprintf(&buf[length],
- PAGE_SIZE - length,
- "%s\n",
- int3400_thermal_uuids[i]);
+ length += sysfs_emit_at(buf, length, int3400_thermal_uuids[i]);
}
if (length)
diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
index 317703027ce9..a1dc18be7609 100644
--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
+++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
@@ -4,6 +4,7 @@
* Copyright (c) 2014, Intel Corporation.
*/
#include <linux/acpi.h>
+#include <linux/intel_tcc.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
@@ -68,54 +69,17 @@ static const struct attribute_group power_limit_attribute_group = {
.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,
struct device_attribute *attr,
char *buf)
{
- int tcc;
-
- tcc = tcc_get_offset();
- if (tcc < 0)
- return tcc;
+ int offset;
- return sprintf(buf, "%d\n", tcc);
-}
-
-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;
+ offset = intel_tcc_get_offset(-1);
+ if (offset < 0)
+ return offset;
- return 0;
+ return sprintf(buf, "%d\n", offset);
}
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))
return -EINVAL;
- err = tcc_offset_update(tcc);
+ err = intel_tcc_set_offset(-1, tcc);
if (err)
return err;
@@ -145,66 +109,25 @@ static ssize_t tcc_offset_degree_celsius_store(struct device *dev,
static DEVICE_ATTR_RW(tcc_offset_degree_celsius);
-static int stored_tjmax; /* since it is fixed, we can have local storage */
-
-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)
+static int proc_thermal_get_zone_temp(struct thermal_zone_device *zone,
+ int *temp)
{
int cpu;
- u32 eax, edx;
- int err;
- unsigned long curr_temp_off = 0;
+ int curr_temp;
*temp = 0;
for_each_online_cpu(cpu) {
- err = rdmsr_safe_on_cpu(cpu, MSR_IA32_THERM_STATUS, &eax,
- &edx);
- if (err)
- goto err_ret;
- else {
- 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;
- }
- }
+ curr_temp = intel_tcc_get_temp(cpu, false);
+ if (curr_temp < 0)
+ return curr_temp;
+ if (!*temp || curr_temp > *temp)
+ *temp = curr_temp;
}
- return 0;
-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;
+ *temp *= 1000;
- return ret;
+ return 0;
}
static int proc_thermal_read_ppcc(struct proc_thermal_device *proc_priv)
@@ -298,8 +221,7 @@ int proc_thermal_add(struct device *dev, struct proc_thermal_device *proc_priv)
status = acpi_evaluate_integer(adev->handle, "_TMP", NULL, &tmp);
if (ACPI_FAILURE(status)) {
/* there is no _TMP method, add local method */
- stored_tjmax = get_tjmax();
- if (stored_tjmax > 0)
+ if (intel_tcc_get_tjmax(-1) > 0)
get_temp = proc_thermal_get_zone_temp;
}
@@ -352,7 +274,7 @@ static int tcc_offset_save = -1;
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)
dev_warn(dev, "failed to save offset (%d)\n", tcc_offset_save);
@@ -369,7 +291,7 @@ int proc_thermal_resume(struct device *dev)
/* Do not update if saving failed */
if (tcc_offset_save >= 0)
- tcc_offset_update(tcc_offset_save);
+ intel_tcc_set_offset(-1, tcc_offset_save);
return 0;
}
@@ -456,6 +378,7 @@ void proc_thermal_mmio_remove(struct pci_dev *pdev, struct proc_thermal_device *
}
EXPORT_SYMBOL_GPL(proc_thermal_mmio_remove);
+MODULE_IMPORT_NS(INTEL_TCC);
MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/thermal/intel/intel_menlow.c b/drivers/thermal/intel/intel_menlow.c
index 3f885b08a490..5a6ad0552311 100644
--- a/drivers/thermal/intel/intel_menlow.c
+++ b/drivers/thermal/intel/intel_menlow.c
@@ -232,9 +232,9 @@ static DEFINE_MUTEX(intel_menlow_attr_lock);
/*
* sensor_get_auxtrip - get the current auxtrip value from sensor
- * @name: Thermalzone name
- * @auxtype : AUX0/AUX1
- * @buf: syfs buffer
+ * @handle: Object handle
+ * @index : GET_AUX1/GET_AUX0
+ * @value : The address will be fill by the value
*/
static int sensor_get_auxtrip(acpi_handle handle, int index,
unsigned long long *value)
@@ -254,9 +254,9 @@ static int sensor_get_auxtrip(acpi_handle handle, int index,
/*
* sensor_set_auxtrip - set the new auxtrip value to sensor
- * @name: Thermalzone name
- * @auxtype : AUX0/AUX1
- * @buf: syfs buffer
+ * @handle: Object handle
+ * @index : GET_AUX1/GET_AUX0
+ * @value : The value will be set
*/
static int sensor_set_auxtrip(acpi_handle handle, int index, int value)
{
diff --git a/drivers/thermal/intel/intel_soc_dts_iosf.c b/drivers/thermal/intel/intel_soc_dts_iosf.c
index 342b0bb5a56d..8c26f7b2316b 100644
--- a/drivers/thermal/intel/intel_soc_dts_iosf.c
+++ b/drivers/thermal/intel/intel_soc_dts_iosf.c
@@ -7,6 +7,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/bitops.h>
+#include <linux/intel_tcc.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
@@ -45,32 +46,6 @@
/* DTS0 and DTS 1 */
#define SOC_MAX_DTS_SENSORS 2
-static int get_tj_max(u32 *tj_max)
-{
- u32 eax, edx;
- u32 val;
- int err;
-
- err = rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
- if (err)
- goto err_ret;
- else {
- val = (eax >> 16) & 0xff;
- if (val)
- *tj_max = val * 1000;
- else {
- err = -EINVAL;
- goto err_ret;
- }
- }
-
- return 0;
-err_ret:
- *tj_max = 0;
-
- return err;
-}
-
static int sys_get_trip_temp(struct thermal_zone_device *tzd, int trip,
int *temp)
{
@@ -405,7 +380,7 @@ struct intel_soc_dts_sensors *intel_soc_dts_iosf_init(
{
struct intel_soc_dts_sensors *sensors;
bool notification;
- u32 tj_max;
+ int tj_max;
int ret;
int i;
@@ -415,8 +390,9 @@ struct intel_soc_dts_sensors *intel_soc_dts_iosf_init(
if (!trip_count || read_only_trip_count > trip_count)
return ERR_PTR(-EINVAL);
- if (get_tj_max(&tj_max))
- return ERR_PTR(-EINVAL);
+ tj_max = intel_tcc_get_tjmax(-1);
+ if (tj_max < 0)
+ return ERR_PTR(tj_max);
sensors = kzalloc(sizeof(*sensors), GFP_KERNEL);
if (!sensors)
@@ -475,4 +451,5 @@ void intel_soc_dts_iosf_exit(struct intel_soc_dts_sensors *sensors)
}
EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_exit);
+MODULE_IMPORT_NS(INTEL_TCC);
MODULE_LICENSE("GPL v2");
diff --git a/drivers/thermal/intel/intel_tcc.c b/drivers/thermal/intel/intel_tcc.c
new file mode 100644
index 000000000000..2e5c741c41ca
--- /dev/null
+++ b/drivers/thermal/intel/intel_tcc.c
@@ -0,0 +1,139 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * intel_tcc.c - Library for Intel TCC (thermal control circuitry) MSR access
+ * Copyright (c) 2022, Intel Corporation.
+ */
+
+#include <linux/errno.h>
+#include <linux/intel_tcc.h>
+#include <asm/msr.h>
+
+/**
+ * intel_tcc_get_tjmax() - returns the default TCC activation Temperature
+ * @cpu: cpu that the MSR should be run on, nagative value means any cpu.
+ *
+ * Get the TjMax value, which is the default thermal throttling or TCC
+ * activation temperature in degrees C.
+ *
+ * Return: Tjmax value in degrees C on success, negative error code otherwise.
+ */
+int intel_tcc_get_tjmax(int cpu)
+{
+ u32 low, high;
+ int val, err;
+
+ if (cpu < 0)
+ err = rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET, &low, &high);
+ else
+ err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &low, &high);
+ if (err)
+ return err;
+
+ val = (low >> 16) & 0xff;
+
+ return val ? val : -ENODATA;
+}
+EXPORT_SYMBOL_NS_GPL(intel_tcc_get_tjmax, INTEL_TCC);
+
+/**
+ * intel_tcc_get_offset() - returns the TCC Offset value to Tjmax
+ * @cpu: cpu that the MSR should be run on, nagative value means any cpu.
+ *
+ * Get the TCC offset value to Tjmax. The effective thermal throttling or TCC
+ * activation temperature equals "Tjmax" - "TCC Offset", in degrees C.
+ *
+ * Return: Tcc offset value in degrees C on success, negative error code otherwise.
+ */
+int intel_tcc_get_offset(int cpu)
+{
+ u32 low, high;
+ int err;
+
+ if (cpu < 0)
+ err = rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET, &low, &high);
+ else
+ err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &low, &high);
+ if (err)
+ return err;
+
+ return (low >> 24) & 0x3f;
+}
+EXPORT_SYMBOL_NS_GPL(intel_tcc_get_offset, INTEL_TCC);
+
+/**
+ * intel_tcc_set_offset() - set the TCC offset value to Tjmax
+ * @cpu: cpu that the MSR should be run on, nagative value means any cpu.
+ * @offset: TCC offset value in degree C
+ *
+ * Set the TCC Offset value to Tjmax. The effective thermal throttling or TCC
+ * activation temperature equals "Tjmax" - "TCC Offset", in degree C.
+ *
+ * Return: On success returns 0, negative error code otherwise.
+ */
+
+int intel_tcc_set_offset(int cpu, int offset)
+{
+ u32 low, high;
+ int err;
+
+ if (offset < 0 || offset > 0x3f)
+ return -EINVAL;
+
+ if (cpu < 0)
+ err = rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET, &low, &high);
+ else
+ err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &low, &high);
+ if (err)
+ return err;
+
+ /* MSR Locked */
+ if (low & BIT(31))
+ return -EPERM;
+
+ low &= ~(0x3f << 24);
+ low |= offset << 24;
+
+ if (cpu < 0)
+ return wrmsr_safe(MSR_IA32_TEMPERATURE_TARGET, low, high);
+ else
+ return wrmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, low, high);
+}
+EXPORT_SYMBOL_NS_GPL(intel_tcc_set_offset, INTEL_TCC);
+
+/**
+ * intel_tcc_get_temp() - returns the current temperature
+ * @cpu: cpu that the MSR should be run on, nagative value means any cpu.
+ * @pkg: true: Package Thermal Sensor. false: Core Thermal Sensor.
+ *
+ * Get the current temperature returned by the CPU core/package level
+ * thermal sensor, in degrees C.
+ *
+ * Return: Temperature in degrees C on success, negative error code otherwise.
+ */
+int intel_tcc_get_temp(int cpu, bool pkg)
+{
+ u32 low, high;
+ u32 msr = pkg ? MSR_IA32_PACKAGE_THERM_STATUS : MSR_IA32_THERM_STATUS;
+ int tjmax, temp, err;
+
+ tjmax = intel_tcc_get_tjmax(cpu);
+ if (tjmax < 0)
+ return tjmax;
+
+ if (cpu < 0)
+ err = rdmsr_safe(msr, &low, &high);
+ else
+ err = rdmsr_safe_on_cpu(cpu, msr, &low, &high);
+ if (err)
+ return err;
+
+ /* Temperature is beyond the valid thermal sensor range */
+ if (!(low & BIT(31)))
+ return -ENODATA;
+
+ temp = tjmax - ((low >> 16) & 0x7f);
+
+ /* Do not allow negative CPU temperature */
+ return temp >= 0 ? temp : -ENODATA;
+}
+EXPORT_SYMBOL_NS_GPL(intel_tcc_get_temp, INTEL_TCC);
diff --git a/drivers/thermal/intel/intel_tcc_cooling.c b/drivers/thermal/intel/intel_tcc_cooling.c
index a89e7e1890e4..e95f799454fe 100644
--- a/drivers/thermal/intel/intel_tcc_cooling.c
+++ b/drivers/thermal/intel/intel_tcc_cooling.c
@@ -7,12 +7,11 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/device.h>
+#include <linux/intel_tcc.h>
#include <linux/module.h>
#include <linux/thermal.h>
#include <asm/cpu_device_id.h>
-#define TCC_SHIFT 24
-#define TCC_MASK (0x3fULL<<24)
#define TCC_PROGRAMMABLE BIT(30)
#define TCC_LOCKED BIT(31)
@@ -21,47 +20,26 @@ static struct thermal_cooling_device *tcc_cdev;
static int tcc_get_max_state(struct thermal_cooling_device *cdev, unsigned long
*state)
{
- *state = TCC_MASK >> TCC_SHIFT;
- return 0;
-}
-
-static int tcc_offset_update(int tcc)
-{
- u64 val;
- int err;
-
- err = rdmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, &val);
- if (err)
- return err;
-
- val &= ~TCC_MASK;
- val |= tcc << TCC_SHIFT;
-
- err = wrmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, val);
- if (err)
- return err;
-
+ *state = 0x3f;
return 0;
}
static int tcc_get_cur_state(struct thermal_cooling_device *cdev, unsigned long
*state)
{
- u64 val;
- int err;
+ int offset = intel_tcc_get_offset(-1);
- err = rdmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, &val);
- if (err)
- return err;
+ if (offset < 0)
+ return offset;
- *state = (val & TCC_MASK) >> TCC_SHIFT;
+ *state = offset;
return 0;
}
static int tcc_set_cur_state(struct thermal_cooling_device *cdev, unsigned long
state)
{
- return tcc_offset_update(state);
+ return intel_tcc_set_offset(-1, (int)state);
}
static const struct thermal_cooling_device_ops tcc_cooling_ops = {
@@ -140,6 +118,7 @@ static void __exit tcc_cooling_exit(void)
module_exit(tcc_cooling_exit)
+MODULE_IMPORT_NS(INTEL_TCC);
MODULE_DESCRIPTION("TCC offset cooling device Driver");
MODULE_AUTHOR("Zhang Rui <rui.zhang@intel.com>");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/thermal/intel/x86_pkg_temp_thermal.c b/drivers/thermal/intel/x86_pkg_temp_thermal.c
index 494f25250c2d..1c2de84742df 100644
--- a/drivers/thermal/intel/x86_pkg_temp_thermal.c
+++ b/drivers/thermal/intel/x86_pkg_temp_thermal.c
@@ -7,6 +7,7 @@
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/intel_tcc.h>
#include <linux/err.h>
#include <linux/param.h>
#include <linux/device.h>
@@ -48,7 +49,6 @@ MODULE_PARM_DESC(notify_delay_ms,
struct zone_device {
int cpu;
bool work_scheduled;
- u32 tj_max;
u32 msr_pkg_therm_low;
u32 msr_pkg_therm_high;
struct delayed_work work;
@@ -105,38 +105,18 @@ static struct zone_device *pkg_temp_thermal_get_dev(unsigned int cpu)
return NULL;
}
-/*
-* tj-max is interesting because threshold is set relative to this
-* temperature.
-*/
-static int get_tj_max(int cpu, u32 *tj_max)
-{
- u32 eax, edx, val;
- int err;
-
- err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
- if (err)
- return err;
-
- val = (eax >> 16) & 0xff;
- *tj_max = val * 1000;
-
- return val ? 0 : -EINVAL;
-}
-
static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp)
{
struct zone_device *zonedev = tzd->devdata;
- u32 eax, edx;
+ int val;
- rdmsr_on_cpu(zonedev->cpu, MSR_IA32_PACKAGE_THERM_STATUS,
- &eax, &edx);
- if (eax & 0x80000000) {
- *temp = zonedev->tj_max - ((eax >> 16) & 0x7f) * 1000;
- pr_debug("sys_get_curr_temp %d\n", *temp);
- return 0;
- }
- return -EINVAL;
+ val = intel_tcc_get_temp(zonedev->cpu, true);
+ if (val < 0)
+ return val;
+
+ *temp = val * 1000;
+ pr_debug("sys_get_curr_temp %d\n", *temp);
+ return 0;
}
static int
@@ -144,9 +124,14 @@ sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp)
{
struct zone_device *zonedev = tzd->devdata;
u32 l, h, mask, shift, intr;
- int ret;
+ int tj_max, ret;
- if (trip >= MAX_NUMBER_OF_TRIPS || temp >= zonedev->tj_max)
+ tj_max = intel_tcc_get_tjmax(zonedev->cpu);
+ if (tj_max < 0)
+ return tj_max;
+ tj_max *= 1000;
+
+ if (trip >= MAX_NUMBER_OF_TRIPS || temp >= tj_max)
return -EINVAL;
ret = rdmsr_on_cpu(zonedev->cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT,
@@ -171,7 +156,7 @@ sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp)
if (!temp) {
l &= ~intr;
} else {
- l |= (zonedev->tj_max - temp)/1000 << shift;
+ l |= (tj_max - temp)/1000 << shift;
l |= intr;
}
@@ -326,9 +311,10 @@ static struct thermal_trip *pkg_temp_thermal_trips_init(int cpu, int tj_max, int
static int pkg_temp_thermal_device_add(unsigned int cpu)
{
int id = topology_logical_die_id(cpu);
- u32 tj_max, eax, ebx, ecx, edx;
+ u32 eax, ebx, ecx, edx;
struct zone_device *zonedev;
int thres_count, err;
+ int tj_max;
if (id >= max_id)
return -ENOMEM;
@@ -340,9 +326,9 @@ static int pkg_temp_thermal_device_add(unsigned int cpu)
thres_count = clamp_val(thres_count, 0, MAX_NUMBER_OF_TRIPS);
- err = get_tj_max(cpu, &tj_max);
- if (err)
- return err;
+ tj_max = intel_tcc_get_tjmax(cpu);
+ if (tj_max < 0)
+ return tj_max;
zonedev = kzalloc(sizeof(*zonedev), GFP_KERNEL);
if (!zonedev)
@@ -356,7 +342,6 @@ static int pkg_temp_thermal_device_add(unsigned int cpu)
INIT_DELAYED_WORK(&zonedev->work, pkg_temp_thermal_threshold_work_fn);
zonedev->cpu = cpu;
- zonedev->tj_max = tj_max;
zonedev->tzone = thermal_zone_device_register_with_trips("x86_pkg_temp",
zonedev->trips, thres_count,
(thres_count == MAX_NUMBER_OF_TRIPS) ? 0x03 : 0x01,
@@ -545,6 +530,7 @@ static void __exit pkg_temp_thermal_exit(void)
}
module_exit(pkg_temp_thermal_exit)
+MODULE_IMPORT_NS(INTEL_TCC);
MODULE_DESCRIPTION("X86 PKG TEMP Thermal Driver");
MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
MODULE_LICENSE("GPL v2");
diff --git a/include/linux/intel_tcc.h b/include/linux/intel_tcc.h
new file mode 100644
index 000000000000..f422612c28d6
--- /dev/null
+++ b/include/linux/intel_tcc.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * header for Intel TCC (thermal control circuitry) library
+ *
+ * Copyright (C) 2022 Intel Corporation.
+ */
+
+#ifndef __INTEL_TCC_H__
+#define __INTEL_TCC_H__
+
+#include <linux/types.h>
+
+int intel_tcc_get_tjmax(int cpu);
+int intel_tcc_get_offset(int cpu);
+int intel_tcc_set_offset(int cpu, int offset);
+int intel_tcc_get_temp(int cpu, bool pkg);
+
+#endif /* __INTEL_TCC_H__ */