66
77#include <linux/errno.h>
88#include <linux/intel_tcc.h>
9+ #include <asm/cpu_device_id.h>
10+ #include <asm/intel-family.h>
911#include <asm/msr.h>
1012
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+
11173/**
12174 * intel_tcc_get_tjmax() - returns the default TCC activation Temperature
13175 * @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)
56218 if (err )
57219 return err ;
58220
59- return (low >> 24 ) & 0x3f ;
221+ return (low >> 24 ) & intel_tcc_temp_masks . tcc_offset ;
60222}
61223EXPORT_SYMBOL_NS_GPL (intel_tcc_get_offset , INTEL_TCC );
62224
@@ -76,7 +238,10 @@ int intel_tcc_set_offset(int cpu, int offset)
76238 u32 low , high ;
77239 int err ;
78240
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 )
80245 return - EINVAL ;
81246
82247 if (cpu < 0 )
@@ -90,7 +255,7 @@ int intel_tcc_set_offset(int cpu, int offset)
90255 if (low & BIT (31 ))
91256 return - EPERM ;
92257
93- low &= ~(0x3f << 24 );
258+ low &= ~(intel_tcc_temp_masks . tcc_offset << 24 );
94259 low |= offset << 24 ;
95260
96261 if (cpu < 0 )
@@ -113,8 +278,8 @@ EXPORT_SYMBOL_NS_GPL(intel_tcc_set_offset, INTEL_TCC);
113278 */
114279int intel_tcc_get_temp (int cpu , int * temp , bool pkg )
115280{
116- u32 low , high ;
117281 u32 msr = pkg ? MSR_IA32_PACKAGE_THERM_STATUS : MSR_IA32_THERM_STATUS ;
282+ u32 low , high , mask ;
118283 int tjmax , err ;
119284
120285 tjmax = intel_tcc_get_tjmax (cpu );
@@ -132,7 +297,9 @@ int intel_tcc_get_temp(int cpu, int *temp, bool pkg)
132297 if (!(low & BIT (31 )))
133298 return - ENODATA ;
134299
135- * temp = tjmax - ((low >> 16 ) & 0x7f );
300+ mask = get_temp_mask (pkg );
301+
302+ * temp = tjmax - ((low >> 16 ) & mask );
136303
137304 return 0 ;
138305}
0 commit comments