drivers/hwmon/coretemp.c: get TjMax value from MSR

The MSR IA32_TEMPERATURE_TARGET contains the TjMax value in the newer
Intel processors.

Signed-off-by: Huaxu Wan <huaxu.wan@linux.intel.com>
Signed-off-by: Carsten Emde <C.Emde@osadl.org>
Cc: Jean Delvare <khali@linux-fr.org>
Cc: Valdis Kletnieks <valdis.kletnieks@vt.edu>
Cc: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Cc: Yong Wang <yong.y.wang@linux.intel.com>
Cc: Rudolf Marek <r.marek@assembler.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Carsten Emde 2010-05-24 14:33:41 -07:00 коммит произвёл Linus Torvalds
Родитель 5db47b009d
Коммит a321cedb12
2 изменённых файлов: 59 добавлений и 4 удалений

Просмотреть файл

@ -236,6 +236,8 @@
#define MSR_IA32_MISC_ENABLE 0x000001a0 #define MSR_IA32_MISC_ENABLE 0x000001a0
#define MSR_IA32_TEMPERATURE_TARGET 0x000001a2
/* MISC_ENABLE bits: architectural */ /* MISC_ENABLE bits: architectural */
#define MSR_IA32_MISC_ENABLE_FAST_STRING (1ULL << 0) #define MSR_IA32_MISC_ENABLE_FAST_STRING (1ULL << 0)
#define MSR_IA32_MISC_ENABLE_TCC (1ULL << 1) #define MSR_IA32_MISC_ENABLE_TCC (1ULL << 1)

Просмотреть файл

@ -241,6 +241,55 @@ static int __devinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *
return tjmax; return tjmax;
} }
static int __devinit get_tjmax(struct cpuinfo_x86 *c, u32 id,
struct device *dev)
{
/* The 100C is default for both mobile and non mobile CPUs */
int err;
u32 eax, edx;
u32 val;
/* A new feature of current Intel(R) processors, the
IA32_TEMPERATURE_TARGET contains the TjMax value */
err = rdmsr_safe_on_cpu(id, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
if (err) {
dev_warn(dev, "Unable to read TjMax from CPU.\n");
} else {
val = (eax >> 16) & 0xff;
/*
* If the TjMax is not plausible, an assumption
* will be used
*/
if ((val > 80) && (val < 120)) {
dev_info(dev, "TjMax is %d C.\n", val);
return val * 1000;
}
}
/*
* An assumption is made for early CPUs and unreadable MSR.
* NOTE: the given value may not be correct.
*/
switch (c->x86_model) {
case 0xe:
case 0xf:
case 0x16:
case 0x1a:
dev_warn(dev, "TjMax is assumed as 100 C!\n");
return 100000;
break;
case 0x17:
case 0x1c: /* Atom CPUs */
return adjust_tjmax(c, id, dev);
break;
default:
dev_warn(dev, "CPU (model=0x%x) is not supported yet,"
" using default TjMax of 100C.\n", c->x86_model);
return 100000;
}
}
static int __devinit coretemp_probe(struct platform_device *pdev) static int __devinit coretemp_probe(struct platform_device *pdev)
{ {
struct coretemp_data *data; struct coretemp_data *data;
@ -283,14 +332,18 @@ static int __devinit coretemp_probe(struct platform_device *pdev)
} }
} }
data->tjmax = adjust_tjmax(c, data->id, &pdev->dev); data->tjmax = get_tjmax(c, data->id, &pdev->dev);
platform_set_drvdata(pdev, data); platform_set_drvdata(pdev, data);
/* read the still undocumented IA32_TEMPERATURE_TARGET it exists /*
on older CPUs but not in this register, Atoms don't have it either */ * read the still undocumented IA32_TEMPERATURE_TARGET. It exists
* on older CPUs but not in this register,
* Atoms don't have it either.
*/
if ((c->x86_model > 0xe) && (c->x86_model != 0x1c)) { if ((c->x86_model > 0xe) && (c->x86_model != 0x1c)) {
err = rdmsr_safe_on_cpu(data->id, 0x1a2, &eax, &edx); err = rdmsr_safe_on_cpu(data->id, MSR_IA32_TEMPERATURE_TARGET,
&eax, &edx);
if (err) { if (err) {
dev_warn(&pdev->dev, "Unable to read" dev_warn(&pdev->dev, "Unable to read"
" IA32_TEMPERATURE_TARGET MSR\n"); " IA32_TEMPERATURE_TARGET MSR\n");