diff options
author | Rudolf Marek <r.marek@assembler.cz> | 2008-02-17 16:59:39 -0500 |
---|---|---|
committer | Mark M. Hoffman <mhoffman@lightlink.com> | 2008-02-17 21:57:28 -0500 |
commit | 118a88718886a6cb7fb2cf7fb77ef2eea30c73a1 (patch) | |
tree | 0d72f79ac05067ebe988417122f21e46c89d3d2d /drivers/hwmon/coretemp.c | |
parent | cd19ba1391f93bc3741d298667c074d2d3fcc9fd (diff) |
hwmon: (coretemp) Add TjMax detection for mobile CPUs
Following patch will finally solve the detection of Intel Mobile CPUs which
share same CPUID with Desktop/Server CPUs. We need this information to test
some bit so we know if TjMax is 100C or 85C. Intel claims this works for mobiles
only, respect that and set for desktops the TjMax to 100C. Intel provided some
table on their wiki based on my chat with them at:
http://softwarecommunity.intel.com/isn/Community/en-US/forums/30247249/ShowThread.aspx#30247249
Signed-off-by: Rudolf Marek <r.marek@assembler.cz>
Signed-off-by: Mark M. Hoffman <mhoffman@lightlink.com>
Diffstat (limited to 'drivers/hwmon/coretemp.c')
-rw-r--r-- | drivers/hwmon/coretemp.c | 83 |
1 files changed, 51 insertions, 32 deletions
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index cbd047eac5b4..1f34ad84c557 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c | |||
@@ -152,6 +152,56 @@ static struct coretemp_data *coretemp_update_device(struct device *dev) | |||
152 | return data; | 152 | return data; |
153 | } | 153 | } |
154 | 154 | ||
155 | static int __devinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev) | ||
156 | { | ||
157 | /* The 100C is default for both mobile and non mobile CPUs */ | ||
158 | |||
159 | int tjmax = 100000; | ||
160 | int ismobile = 1; | ||
161 | int err; | ||
162 | u32 eax, edx; | ||
163 | |||
164 | /* Early chips have no MSR for TjMax */ | ||
165 | |||
166 | if ((c->x86_model == 0xf) && (c->x86_mask < 4)) { | ||
167 | ismobile = 0; | ||
168 | } | ||
169 | |||
170 | if ((c->x86_model > 0xe) && (ismobile)) { | ||
171 | |||
172 | /* Now we can detect the mobile CPU using Intel provided table | ||
173 | http://softwarecommunity.intel.com/Wiki/Mobility/720.htm | ||
174 | For Core2 cores, check MSR 0x17, bit 28 1 = Mobile CPU | ||
175 | */ | ||
176 | |||
177 | err = rdmsr_safe_on_cpu(id, 0x17, &eax, &edx); | ||
178 | if (err) { | ||
179 | dev_warn(dev, | ||
180 | "Unable to access MSR 0x17, assuming desktop" | ||
181 | " CPU\n"); | ||
182 | ismobile = 0; | ||
183 | } else if (!(eax & 0x10000000)) { | ||
184 | ismobile = 0; | ||
185 | } | ||
186 | } | ||
187 | |||
188 | if (ismobile) { | ||
189 | |||
190 | err = rdmsr_safe_on_cpu(id, 0xee, &eax, &edx); | ||
191 | if (err) { | ||
192 | dev_warn(dev, | ||
193 | "Unable to access MSR 0xEE, for Tjmax, left" | ||
194 | " at default"); | ||
195 | } else if (eax & 0x40000000) { | ||
196 | tjmax = 85000; | ||
197 | } | ||
198 | } else { | ||
199 | dev_warn(dev, "Using relative temperature scale!\n"); | ||
200 | } | ||
201 | |||
202 | return tjmax; | ||
203 | } | ||
204 | |||
155 | static int __devinit coretemp_probe(struct platform_device *pdev) | 205 | static int __devinit coretemp_probe(struct platform_device *pdev) |
156 | { | 206 | { |
157 | struct coretemp_data *data; | 207 | struct coretemp_data *data; |
@@ -168,8 +218,6 @@ static int __devinit coretemp_probe(struct platform_device *pdev) | |||
168 | data->id = pdev->id; | 218 | data->id = pdev->id; |
169 | data->name = "coretemp"; | 219 | data->name = "coretemp"; |
170 | mutex_init(&data->update_lock); | 220 | mutex_init(&data->update_lock); |
171 | /* Tjmax default is 100 degrees C */ | ||
172 | data->tjmax = 100000; | ||
173 | 221 | ||
174 | /* test if we can access the THERM_STATUS MSR */ | 222 | /* test if we can access the THERM_STATUS MSR */ |
175 | err = rdmsr_safe_on_cpu(data->id, MSR_IA32_THERM_STATUS, &eax, &edx); | 223 | err = rdmsr_safe_on_cpu(data->id, MSR_IA32_THERM_STATUS, &eax, &edx); |
@@ -196,36 +244,7 @@ static int __devinit coretemp_probe(struct platform_device *pdev) | |||
196 | } | 244 | } |
197 | } | 245 | } |
198 | 246 | ||
199 | /* Some processors have Tjmax 85 following magic should detect it | 247 | data->tjmax = adjust_tjmax(c, data->id, &pdev->dev); |
200 | Intel won't disclose the information without signed NDA, but | ||
201 | individuals cannot sign it. Catch(ed) 22. | ||
202 | */ | ||
203 | |||
204 | if (((c->x86_model == 0xf) && (c->x86_mask > 3)) || | ||
205 | (c->x86_model == 0xe)) { | ||
206 | err = rdmsr_safe_on_cpu(data->id, 0xee, &eax, &edx); | ||
207 | if (err) { | ||
208 | dev_warn(&pdev->dev, | ||
209 | "Unable to access MSR 0xEE, Tjmax left at %d " | ||
210 | "degrees C\n", data->tjmax/1000); | ||
211 | } else if (eax & 0x40000000) { | ||
212 | data->tjmax = 85000; | ||
213 | } | ||
214 | } | ||
215 | |||
216 | /* Intel says that above should not work for desktop Core2 processors, | ||
217 | but it seems to work. There is no other way how get the absolute | ||
218 | readings. Warn the user about this. First check if are desktop, | ||
219 | bit 50 of MSR_IA32_PLATFORM_ID should be 0. | ||
220 | */ | ||
221 | |||
222 | rdmsr_safe_on_cpu(data->id, MSR_IA32_PLATFORM_ID, &eax, &edx); | ||
223 | |||
224 | if ((c->x86_model == 0xf) && (!(edx & 0x00040000))) { | ||
225 | dev_warn(&pdev->dev, "Using undocumented features, absolute " | ||
226 | "temperature might be wrong!\n"); | ||
227 | } | ||
228 | |||
229 | platform_set_drvdata(pdev, data); | 248 | platform_set_drvdata(pdev, data); |
230 | 249 | ||
231 | /* read the still undocumented IA32_TEMPERATURE_TARGET it exists | 250 | /* read the still undocumented IA32_TEMPERATURE_TARGET it exists |