diff options
Diffstat (limited to 'drivers/thermal/intel/intel_tcc.c')
| -rw-r--r-- | drivers/thermal/intel/intel_tcc.c | 139 | 
1 files changed, 139 insertions, 0 deletions
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);  |