6
6
7
7
#include <linux/errno.h>
8
8
#include <linux/intel_tcc.h>
9
+ #include <asm/cpu_device_id.h>
10
+ #include <asm/intel-family.h>
9
11
#include <asm/msr.h>
10
12
13
+ /**
14
+ * struct temp_masks - Bitmasks for temperature readings
15
+ * @tcc_offset: TCC offset in MSR_TEMPERATURE_TARGET
16
+ * @digital_readout: Digital readout in MSR_IA32_THERM_STATUS
17
+ * @pkg_digital_readout: Digital readout in MSR_IA32_PACKAGE_THERM_STATUS
18
+ *
19
+ * Bitmasks to extract the fields of the MSR_TEMPERATURE and IA32_[PACKAGE]_
20
+ * THERM_STATUS registers for different processor models.
21
+ *
22
+ * The bitmask of TjMax is not included in this structure. It is always 0xff.
23
+ */
24
+ struct temp_masks {
25
+ u32 tcc_offset ;
26
+ u32 digital_readout ;
27
+ u32 pkg_digital_readout ;
28
+ };
29
+
30
+ #define TCC_MODEL_TEMP_MASKS (model , _tcc_offset , _digital_readout , \
31
+ _pkg_digital_readout ) \
32
+ static const struct temp_masks temp_##model __initconst = { \
33
+ .tcc_offset = _tcc_offset, \
34
+ .digital_readout = _digital_readout, \
35
+ .pkg_digital_readout = _pkg_digital_readout \
36
+ }
37
+
38
+ TCC_MODEL_TEMP_MASKS (nehalem , 0 , 0x7f , 0x7f );
39
+ TCC_MODEL_TEMP_MASKS (haswell_x , 0xf , 0x7f , 0x7f );
40
+ TCC_MODEL_TEMP_MASKS (broadwell , 0x3f , 0x7f , 0x7f );
41
+ TCC_MODEL_TEMP_MASKS (goldmont , 0x7f , 0x7f , 0x7f );
42
+ TCC_MODEL_TEMP_MASKS (tigerlake , 0x3f , 0xff , 0xff );
43
+ TCC_MODEL_TEMP_MASKS (sapphirerapids , 0x3f , 0x7f , 0xff );
44
+
45
+ /* Use these masks for processors not included in @tcc_cpu_ids. */
46
+ static struct temp_masks intel_tcc_temp_masks __ro_after_init = {
47
+ .tcc_offset = 0x7f ,
48
+ .digital_readout = 0xff ,
49
+ .pkg_digital_readout = 0xff ,
50
+ };
51
+
52
+ static const struct x86_cpu_id intel_tcc_cpu_ids [] __initconst = {
53
+ X86_MATCH_VFM (INTEL_CORE_YONAH , & temp_nehalem ),
54
+ X86_MATCH_VFM (INTEL_CORE2_MEROM , & temp_nehalem ),
55
+ X86_MATCH_VFM (INTEL_CORE2_MEROM_L , & temp_nehalem ),
56
+ X86_MATCH_VFM (INTEL_CORE2_PENRYN , & temp_nehalem ),
57
+ X86_MATCH_VFM (INTEL_CORE2_DUNNINGTON , & temp_nehalem ),
58
+ X86_MATCH_VFM (INTEL_NEHALEM , & temp_nehalem ),
59
+ X86_MATCH_VFM (INTEL_NEHALEM_G , & temp_nehalem ),
60
+ X86_MATCH_VFM (INTEL_NEHALEM_EP , & temp_nehalem ),
61
+ X86_MATCH_VFM (INTEL_NEHALEM_EX , & temp_nehalem ),
62
+ X86_MATCH_VFM (INTEL_WESTMERE , & temp_nehalem ),
63
+ X86_MATCH_VFM (INTEL_WESTMERE_EP , & temp_nehalem ),
64
+ X86_MATCH_VFM (INTEL_WESTMERE_EX , & temp_nehalem ),
65
+ X86_MATCH_VFM (INTEL_SANDYBRIDGE , & temp_nehalem ),
66
+ X86_MATCH_VFM (INTEL_SANDYBRIDGE_X , & temp_nehalem ),
67
+ X86_MATCH_VFM (INTEL_IVYBRIDGE , & temp_nehalem ),
68
+ X86_MATCH_VFM (INTEL_IVYBRIDGE_X , & temp_haswell_x ),
69
+ X86_MATCH_VFM (INTEL_HASWELL , & temp_nehalem ),
70
+ X86_MATCH_VFM (INTEL_HASWELL_X , & temp_haswell_x ),
71
+ X86_MATCH_VFM (INTEL_HASWELL_L , & temp_nehalem ),
72
+ X86_MATCH_VFM (INTEL_HASWELL_G , & temp_nehalem ),
73
+ X86_MATCH_VFM (INTEL_BROADWELL , & temp_broadwell ),
74
+ X86_MATCH_VFM (INTEL_BROADWELL_G , & temp_broadwell ),
75
+ X86_MATCH_VFM (INTEL_BROADWELL_X , & temp_haswell_x ),
76
+ X86_MATCH_VFM (INTEL_BROADWELL_D , & temp_haswell_x ),
77
+ X86_MATCH_VFM (INTEL_SKYLAKE_L , & temp_broadwell ),
78
+ X86_MATCH_VFM (INTEL_SKYLAKE , & temp_broadwell ),
79
+ X86_MATCH_VFM (INTEL_SKYLAKE_X , & temp_haswell_x ),
80
+ X86_MATCH_VFM (INTEL_KABYLAKE_L , & temp_broadwell ),
81
+ X86_MATCH_VFM (INTEL_KABYLAKE , & temp_broadwell ),
82
+ X86_MATCH_VFM (INTEL_COMETLAKE , & temp_broadwell ),
83
+ X86_MATCH_VFM (INTEL_COMETLAKE_L , & temp_broadwell ),
84
+ X86_MATCH_VFM (INTEL_CANNONLAKE_L , & temp_broadwell ),
85
+ X86_MATCH_VFM (INTEL_ICELAKE_X , & temp_broadwell ),
86
+ X86_MATCH_VFM (INTEL_ICELAKE_D , & temp_broadwell ),
87
+ X86_MATCH_VFM (INTEL_ICELAKE , & temp_broadwell ),
88
+ X86_MATCH_VFM (INTEL_ICELAKE_L , & temp_broadwell ),
89
+ X86_MATCH_VFM (INTEL_ICELAKE_NNPI , & temp_broadwell ),
90
+ X86_MATCH_VFM (INTEL_ROCKETLAKE , & temp_broadwell ),
91
+ X86_MATCH_VFM (INTEL_TIGERLAKE_L , & temp_tigerlake ),
92
+ X86_MATCH_VFM (INTEL_TIGERLAKE , & temp_tigerlake ),
93
+ X86_MATCH_VFM (INTEL_SAPPHIRERAPIDS_X , & temp_sapphirerapids ),
94
+ X86_MATCH_VFM (INTEL_EMERALDRAPIDS_X , & temp_sapphirerapids ),
95
+ X86_MATCH_VFM (INTEL_LAKEFIELD , & temp_broadwell ),
96
+ X86_MATCH_VFM (INTEL_ALDERLAKE , & temp_tigerlake ),
97
+ X86_MATCH_VFM (INTEL_ALDERLAKE_L , & temp_tigerlake ),
98
+ X86_MATCH_VFM (INTEL_RAPTORLAKE , & temp_tigerlake ),
99
+ X86_MATCH_VFM (INTEL_RAPTORLAKE_P , & temp_tigerlake ),
100
+ X86_MATCH_VFM (INTEL_RAPTORLAKE_S , & temp_tigerlake ),
101
+ X86_MATCH_VFM (INTEL_ATOM_BONNELL , & temp_nehalem ),
102
+ X86_MATCH_VFM (INTEL_ATOM_BONNELL_MID , & temp_nehalem ),
103
+ X86_MATCH_VFM (INTEL_ATOM_SALTWELL , & temp_nehalem ),
104
+ X86_MATCH_VFM (INTEL_ATOM_SALTWELL_MID , & temp_nehalem ),
105
+ X86_MATCH_VFM (INTEL_ATOM_SILVERMONT , & temp_broadwell ),
106
+ X86_MATCH_VFM (INTEL_ATOM_SILVERMONT_D , & temp_broadwell ),
107
+ X86_MATCH_VFM (INTEL_ATOM_SILVERMONT_MID , & temp_broadwell ),
108
+ X86_MATCH_VFM (INTEL_ATOM_AIRMONT , & temp_broadwell ),
109
+ X86_MATCH_VFM (INTEL_ATOM_AIRMONT_MID , & temp_broadwell ),
110
+ X86_MATCH_VFM (INTEL_ATOM_AIRMONT_NP , & temp_broadwell ),
111
+ X86_MATCH_VFM (INTEL_ATOM_GOLDMONT , & temp_goldmont ),
112
+ X86_MATCH_VFM (INTEL_ATOM_GOLDMONT_D , & temp_goldmont ),
113
+ X86_MATCH_VFM (INTEL_ATOM_GOLDMONT_PLUS , & temp_goldmont ),
114
+ X86_MATCH_VFM (INTEL_ATOM_TREMONT_D , & temp_broadwell ),
115
+ X86_MATCH_VFM (INTEL_ATOM_TREMONT , & temp_broadwell ),
116
+ X86_MATCH_VFM (INTEL_ATOM_TREMONT_L , & temp_broadwell ),
117
+ X86_MATCH_VFM (INTEL_ATOM_GRACEMONT , & temp_tigerlake ),
118
+ X86_MATCH_VFM (INTEL_XEON_PHI_KNL , & temp_broadwell ),
119
+ X86_MATCH_VFM (INTEL_XEON_PHI_KNM , & temp_broadwell ),
120
+ {}
121
+ };
122
+
123
+ static int __init intel_tcc_init (void )
124
+ {
125
+ const struct x86_cpu_id * id ;
126
+
127
+ id = x86_match_cpu (intel_tcc_cpu_ids );
128
+ if (id )
129
+ memcpy (& intel_tcc_temp_masks , (const void * )id -> driver_data ,
130
+ sizeof (intel_tcc_temp_masks ));
131
+
132
+ return 0 ;
133
+ }
134
+ /*
135
+ * Use subsys_initcall to ensure temperature bitmasks are initialized before
136
+ * the drivers that use this library.
137
+ */
138
+ subsys_initcall (intel_tcc_init );
139
+
140
+ /**
141
+ * intel_tcc_get_offset_mask() - Returns the bitmask to read TCC offset
142
+ *
143
+ * Get the model-specific bitmask to extract TCC_OFFSET from the MSR
144
+ * TEMPERATURE_TARGET register. If the mask is 0, it means the processor does
145
+ * not support TCC offset.
146
+ *
147
+ * Return: The model-specific bitmask for TCC offset.
148
+ */
149
+ u32 intel_tcc_get_offset_mask (void )
150
+ {
151
+ return intel_tcc_temp_masks .tcc_offset ;
152
+ }
153
+ EXPORT_SYMBOL_NS (intel_tcc_get_offset_mask , INTEL_TCC );
154
+
155
+ /**
156
+ * get_temp_mask() - Returns the model-specific bitmask for temperature
157
+ *
158
+ * @pkg: true: Package Thermal Sensor. false: Core Thermal Sensor.
159
+ *
160
+ * Get the model-specific bitmask to extract the temperature reading from the
161
+ * MSR_IA32_[PACKAGE]_THERM_STATUS register.
162
+ *
163
+ * Callers must check if the thermal status registers are supported.
164
+ *
165
+ * Return: The model-specific bitmask for temperature reading
166
+ */
167
+ static u32 get_temp_mask (bool pkg )
168
+ {
169
+ return pkg ? intel_tcc_temp_masks .pkg_digital_readout :
170
+ intel_tcc_temp_masks .digital_readout ;
171
+ }
172
+
11
173
/**
12
174
* intel_tcc_get_tjmax() - returns the default TCC activation Temperature
13
175
* @cpu: cpu that the MSR should be run on, nagative value means any cpu.
@@ -56,7 +218,7 @@ int intel_tcc_get_offset(int cpu)
56
218
if (err )
57
219
return err ;
58
220
59
- return (low >> 24 ) & 0x3f ;
221
+ return (low >> 24 ) & intel_tcc_temp_masks . tcc_offset ;
60
222
}
61
223
EXPORT_SYMBOL_NS_GPL (intel_tcc_get_offset , INTEL_TCC );
62
224
@@ -76,7 +238,10 @@ int intel_tcc_set_offset(int cpu, int offset)
76
238
u32 low , high ;
77
239
int err ;
78
240
79
- if (offset < 0 || offset > 0x3f )
241
+ if (!intel_tcc_temp_masks .tcc_offset )
242
+ return - ENODEV ;
243
+
244
+ if (offset < 0 || offset > intel_tcc_temp_masks .tcc_offset )
80
245
return - EINVAL ;
81
246
82
247
if (cpu < 0 )
@@ -90,7 +255,7 @@ int intel_tcc_set_offset(int cpu, int offset)
90
255
if (low & BIT (31 ))
91
256
return - EPERM ;
92
257
93
- low &= ~(0x3f << 24 );
258
+ low &= ~(intel_tcc_temp_masks . tcc_offset << 24 );
94
259
low |= offset << 24 ;
95
260
96
261
if (cpu < 0 )
@@ -113,8 +278,8 @@ EXPORT_SYMBOL_NS_GPL(intel_tcc_set_offset, INTEL_TCC);
113
278
*/
114
279
int intel_tcc_get_temp (int cpu , int * temp , bool pkg )
115
280
{
116
- u32 low , high ;
117
281
u32 msr = pkg ? MSR_IA32_PACKAGE_THERM_STATUS : MSR_IA32_THERM_STATUS ;
282
+ u32 low , high , mask ;
118
283
int tjmax , err ;
119
284
120
285
tjmax = intel_tcc_get_tjmax (cpu );
@@ -132,7 +297,9 @@ int intel_tcc_get_temp(int cpu, int *temp, bool pkg)
132
297
if (!(low & BIT (31 )))
133
298
return - ENODATA ;
134
299
135
- * temp = tjmax - ((low >> 16 ) & 0x7f );
300
+ mask = get_temp_mask (pkg );
301
+
302
+ * temp = tjmax - ((low >> 16 ) & mask );
136
303
137
304
return 0 ;
138
305
}
0 commit comments