Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * intel_tcc.c - Library for Intel TCC (thermal control circuitry) MSR access
  4 * Copyright (c) 2022, Intel Corporation.
  5 */
  6
  7#include <linux/errno.h>
  8#include <linux/intel_tcc.h>
  9#include <asm/msr.h>
 10
 11/**
 12 * intel_tcc_get_tjmax() - returns the default TCC activation Temperature
 13 * @cpu: cpu that the MSR should be run on, nagative value means any cpu.
 14 *
 15 * Get the TjMax value, which is the default thermal throttling or TCC
 16 * activation temperature in degrees C.
 17 *
 18 * Return: Tjmax value in degrees C on success, negative error code otherwise.
 19 */
 20int intel_tcc_get_tjmax(int cpu)
 21{
 22	u32 low, high;
 23	int val, err;
 24
 25	if (cpu < 0)
 26		err = rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET, &low, &high);
 27	else
 28		err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &low, &high);
 29	if (err)
 30		return err;
 31
 32	val = (low >> 16) & 0xff;
 33
 34	return val ? val : -ENODATA;
 35}
 36EXPORT_SYMBOL_NS_GPL(intel_tcc_get_tjmax, INTEL_TCC);
 37
 38/**
 39 * intel_tcc_get_offset() - returns the TCC Offset value to Tjmax
 40 * @cpu: cpu that the MSR should be run on, nagative value means any cpu.
 41 *
 42 * Get the TCC offset value to Tjmax. The effective thermal throttling or TCC
 43 * activation temperature equals "Tjmax" - "TCC Offset", in degrees C.
 44 *
 45 * Return: Tcc offset value in degrees C on success, negative error code otherwise.
 46 */
 47int intel_tcc_get_offset(int cpu)
 48{
 49	u32 low, high;
 50	int err;
 51
 52	if (cpu < 0)
 53		err = rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET, &low, &high);
 54	else
 55		err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &low, &high);
 56	if (err)
 57		return err;
 58
 59	return (low >> 24) & 0x3f;
 60}
 61EXPORT_SYMBOL_NS_GPL(intel_tcc_get_offset, INTEL_TCC);
 62
 63/**
 64 * intel_tcc_set_offset() - set the TCC offset value to Tjmax
 65 * @cpu: cpu that the MSR should be run on, nagative value means any cpu.
 66 * @offset: TCC offset value in degree C
 67 *
 68 * Set the TCC Offset value to Tjmax. The effective thermal throttling or TCC
 69 * activation temperature equals "Tjmax" - "TCC Offset", in degree C.
 70 *
 71 * Return: On success returns 0, negative error code otherwise.
 72 */
 73
 74int intel_tcc_set_offset(int cpu, int offset)
 75{
 76	u32 low, high;
 77	int err;
 78
 79	if (offset < 0 || offset > 0x3f)
 80		return -EINVAL;
 81
 82	if (cpu < 0)
 83		err = rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET, &low, &high);
 84	else
 85		err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &low, &high);
 86	if (err)
 87		return err;
 88
 89	/* MSR Locked */
 90	if (low & BIT(31))
 91		return -EPERM;
 92
 93	low &= ~(0x3f << 24);
 94	low |= offset << 24;
 95
 96	if (cpu < 0)
 97		return wrmsr_safe(MSR_IA32_TEMPERATURE_TARGET, low, high);
 98	else
 99		return wrmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, low, high);
100}
101EXPORT_SYMBOL_NS_GPL(intel_tcc_set_offset, INTEL_TCC);
102
103/**
104 * intel_tcc_get_temp() - returns the current temperature
105 * @cpu: cpu that the MSR should be run on, nagative value means any cpu.
106 * @temp: pointer to the memory for saving cpu temperature.
107 * @pkg: true: Package Thermal Sensor. false: Core Thermal Sensor.
108 *
109 * Get the current temperature returned by the CPU core/package level
110 * thermal sensor, in degrees C.
111 *
112 * Return: 0 on success, negative error code otherwise.
113 */
114int intel_tcc_get_temp(int cpu, int *temp, bool pkg)
115{
116	u32 low, high;
117	u32 msr = pkg ? MSR_IA32_PACKAGE_THERM_STATUS : MSR_IA32_THERM_STATUS;
118	int tjmax, err;
119
120	tjmax = intel_tcc_get_tjmax(cpu);
121	if (tjmax < 0)
122		return tjmax;
123
124	if (cpu < 0)
125		err = rdmsr_safe(msr, &low, &high);
126	else
127		err = rdmsr_safe_on_cpu(cpu, msr, &low, &high);
128	if (err)
129		return err;
130
131	/* Temperature is beyond the valid thermal sensor range */
132	if (!(low & BIT(31)))
133		return -ENODATA;
134
135	*temp = tjmax - ((low >> 16) & 0x7f);
136
137	return 0;
138}
139EXPORT_SYMBOL_NS_GPL(intel_tcc_get_temp, INTEL_TCC);