diff options
Diffstat (limited to 'drivers/hwmon/coretemp.c')
-rw-r--r-- | drivers/hwmon/coretemp.c | 93 |
1 files changed, 69 insertions, 24 deletions
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index e9b7fbc5a447..2988da150ed6 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c | |||
@@ -241,6 +241,55 @@ static int __devinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device * | |||
241 | return tjmax; | 241 | return tjmax; |
242 | } | 242 | } |
243 | 243 | ||
244 | static int __devinit get_tjmax(struct cpuinfo_x86 *c, u32 id, | ||
245 | struct device *dev) | ||
246 | { | ||
247 | /* The 100C is default for both mobile and non mobile CPUs */ | ||
248 | int err; | ||
249 | u32 eax, edx; | ||
250 | u32 val; | ||
251 | |||
252 | /* A new feature of current Intel(R) processors, the | ||
253 | IA32_TEMPERATURE_TARGET contains the TjMax value */ | ||
254 | err = rdmsr_safe_on_cpu(id, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx); | ||
255 | if (err) { | ||
256 | dev_warn(dev, "Unable to read TjMax from CPU.\n"); | ||
257 | } else { | ||
258 | val = (eax >> 16) & 0xff; | ||
259 | /* | ||
260 | * If the TjMax is not plausible, an assumption | ||
261 | * will be used | ||
262 | */ | ||
263 | if ((val > 80) && (val < 120)) { | ||
264 | dev_info(dev, "TjMax is %d C.\n", val); | ||
265 | return val * 1000; | ||
266 | } | ||
267 | } | ||
268 | |||
269 | /* | ||
270 | * An assumption is made for early CPUs and unreadable MSR. | ||
271 | * NOTE: the given value may not be correct. | ||
272 | */ | ||
273 | |||
274 | switch (c->x86_model) { | ||
275 | case 0xe: | ||
276 | case 0xf: | ||
277 | case 0x16: | ||
278 | case 0x1a: | ||
279 | dev_warn(dev, "TjMax is assumed as 100 C!\n"); | ||
280 | return 100000; | ||
281 | break; | ||
282 | case 0x17: | ||
283 | case 0x1c: /* Atom CPUs */ | ||
284 | return adjust_tjmax(c, id, dev); | ||
285 | break; | ||
286 | default: | ||
287 | dev_warn(dev, "CPU (model=0x%x) is not supported yet," | ||
288 | " using default TjMax of 100C.\n", c->x86_model); | ||
289 | return 100000; | ||
290 | } | ||
291 | } | ||
292 | |||
244 | static int __devinit coretemp_probe(struct platform_device *pdev) | 293 | static int __devinit coretemp_probe(struct platform_device *pdev) |
245 | { | 294 | { |
246 | struct coretemp_data *data; | 295 | struct coretemp_data *data; |
@@ -283,14 +332,18 @@ static int __devinit coretemp_probe(struct platform_device *pdev) | |||
283 | } | 332 | } |
284 | } | 333 | } |
285 | 334 | ||
286 | data->tjmax = adjust_tjmax(c, data->id, &pdev->dev); | 335 | data->tjmax = get_tjmax(c, data->id, &pdev->dev); |
287 | platform_set_drvdata(pdev, data); | 336 | platform_set_drvdata(pdev, data); |
288 | 337 | ||
289 | /* read the still undocumented IA32_TEMPERATURE_TARGET it exists | 338 | /* |
290 | on older CPUs but not in this register, Atoms don't have it either */ | 339 | * read the still undocumented IA32_TEMPERATURE_TARGET. It exists |
340 | * on older CPUs but not in this register, | ||
341 | * Atoms don't have it either. | ||
342 | */ | ||
291 | 343 | ||
292 | if ((c->x86_model > 0xe) && (c->x86_model != 0x1c)) { | 344 | if ((c->x86_model > 0xe) && (c->x86_model != 0x1c)) { |
293 | err = rdmsr_safe_on_cpu(data->id, 0x1a2, &eax, &edx); | 345 | err = rdmsr_safe_on_cpu(data->id, MSR_IA32_TEMPERATURE_TARGET, |
346 | &eax, &edx); | ||
294 | if (err) { | 347 | if (err) { |
295 | dev_warn(&pdev->dev, "Unable to read" | 348 | dev_warn(&pdev->dev, "Unable to read" |
296 | " IA32_TEMPERATURE_TARGET MSR\n"); | 349 | " IA32_TEMPERATURE_TARGET MSR\n"); |
@@ -451,28 +504,20 @@ static int __init coretemp_init(void) | |||
451 | 504 | ||
452 | for_each_online_cpu(i) { | 505 | for_each_online_cpu(i) { |
453 | struct cpuinfo_x86 *c = &cpu_data(i); | 506 | struct cpuinfo_x86 *c = &cpu_data(i); |
507 | /* | ||
508 | * CPUID.06H.EAX[0] indicates whether the CPU has thermal | ||
509 | * sensors. We check this bit only, all the early CPUs | ||
510 | * without thermal sensors will be filtered out. | ||
511 | */ | ||
512 | if (c->cpuid_level >= 6 && (cpuid_eax(0x06) & 0x01)) { | ||
513 | err = coretemp_device_add(i); | ||
514 | if (err) | ||
515 | goto exit_devices_unreg; | ||
454 | 516 | ||
455 | /* check if family 6, models 0xe (Pentium M DC), | 517 | } else { |
456 | 0xf (Core 2 DC 65nm), 0x16 (Core 2 SC 65nm), | 518 | printk(KERN_INFO DRVNAME ": CPU (model=0x%x)" |
457 | 0x17 (Penryn 45nm), 0x1a (Nehalem), 0x1c (Atom), | 519 | " has no thermal sensor.\n", c->x86_model); |
458 | 0x1e (Lynnfield) */ | ||
459 | if ((c->cpuid_level < 0) || (c->x86 != 0x6) || | ||
460 | !((c->x86_model == 0xe) || (c->x86_model == 0xf) || | ||
461 | (c->x86_model == 0x16) || (c->x86_model == 0x17) || | ||
462 | (c->x86_model == 0x1a) || (c->x86_model == 0x1c) || | ||
463 | (c->x86_model == 0x1e))) { | ||
464 | |||
465 | /* supported CPU not found, but report the unknown | ||
466 | family 6 CPU */ | ||
467 | if ((c->x86 == 0x6) && (c->x86_model > 0xf)) | ||
468 | printk(KERN_WARNING DRVNAME ": Unknown CPU " | ||
469 | "model 0x%x\n", c->x86_model); | ||
470 | continue; | ||
471 | } | 520 | } |
472 | |||
473 | err = coretemp_device_add(i); | ||
474 | if (err) | ||
475 | goto exit_devices_unreg; | ||
476 | } | 521 | } |
477 | if (list_empty(&pdev_list)) { | 522 | if (list_empty(&pdev_list)) { |
478 | err = -ENODEV; | 523 | err = -ENODEV; |