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 */ 20 int 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 } 36 EXPORT_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 */ 47 int 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 } 61 EXPORT_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 74 int 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 } 101 EXPORT_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 * @pkg: true: Package Thermal Sensor. false: Core Thermal Sensor. 107 * 108 * Get the current temperature returned by the CPU core/package level 109 * thermal sensor, in degrees C. 110 * 111 * Return: Temperature in degrees C on success, negative error code otherwise. 112 */ 113 int intel_tcc_get_temp(int cpu, bool pkg) 114 { 115 u32 low, high; 116 u32 msr = pkg ? MSR_IA32_PACKAGE_THERM_STATUS : MSR_IA32_THERM_STATUS; 117 int tjmax, temp, err; 118 119 tjmax = intel_tcc_get_tjmax(cpu); 120 if (tjmax < 0) 121 return tjmax; 122 123 if (cpu < 0) 124 err = rdmsr_safe(msr, &low, &high); 125 else 126 err = rdmsr_safe_on_cpu(cpu, msr, &low, &high); 127 if (err) 128 return err; 129 130 /* Temperature is beyond the valid thermal sensor range */ 131 if (!(low & BIT(31))) 132 return -ENODATA; 133 134 temp = tjmax - ((low >> 16) & 0x7f); 135 136 /* Do not allow negative CPU temperature */ 137 return temp >= 0 ? temp : -ENODATA; 138 } 139 EXPORT_SYMBOL_NS_GPL(intel_tcc_get_temp, INTEL_TCC); 140