Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 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. * @temp: pointer to the memory for saving cpu temperature. * @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: 0 on success, negative error code otherwise. */ int intel_tcc_get_temp(int cpu, int *temp, bool pkg) { u32 low, high; u32 msr = pkg ? MSR_IA32_PACKAGE_THERM_STATUS : MSR_IA32_THERM_STATUS; int tjmax, 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); return 0; } EXPORT_SYMBOL_NS_GPL(intel_tcc_get_temp, INTEL_TCC); |