--- arch/x86/include/asm/msr-index.h | 3 ++ drivers/hwmon/coretemp.c | 54 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 53 insertions(+), 4 deletions(-) Index: head/arch/x86/include/asm/msr-index.h =================================================================== --- head.orig/arch/x86/include/asm/msr-index.h +++ head/arch/x86/include/asm/msr-index.h @@ -277,6 +277,9 @@ #define MSR_IA32_MCG_EIP 0x00000189 #define MSR_IA32_MCG_RESERVED 0x0000018a +/* Specific to i series processors */ +#define MSR_IA32_TEMPERATURE_TARGET 0x000001a2 + /* Pentium IV performance counter MSRs */ #define MSR_P4_BPU_PERFCTR0 0x00000300 #define MSR_P4_BPU_PERFCTR1 0x00000301 Index: head/drivers/hwmon/coretemp.c =================================================================== --- head.orig/drivers/hwmon/coretemp.c +++ head/drivers/hwmon/coretemp.c @@ -153,7 +153,8 @@ static struct coretemp_data *coretemp_up return data; } -static int __devinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev) +static int __devinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, + struct device *dev) { /* The 100C is default for both mobile and non mobile CPUs */ @@ -241,6 +242,51 @@ static int __devinit adjust_tjmax(struct return tjmax; } +static int __devinit get_tjmax(struct cpuinfo_x86 *c, u32 id, + struct device *dev) +{ + int err; + u32 eax, edx; + u32 val; + + 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 (val > 80 && val < 120) { + dev_info(dev, "TjMax is %dC.\n", val); + return val * 1000; + } else { + dev_warn(dev, "TjMax of %dC not plausible," + " using 100C instead." , val); + return 100000; + } + } + + /* + * An assumption is made for early CPUs and unreadable MSR. + * NOTE: the given value may not be correct. + */ + switch (c->x86_model) { + case 0x0e: + case 0x0f: + case 0x16: + case 0x1a: + dev_warn(dev, "TjMax is assumed as 100C!\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) { struct coretemp_data *data; @@ -283,14 +329,14 @@ static int __devinit coretemp_probe(stru } } - data->tjmax = adjust_tjmax(c, data->id, &pdev->dev); + data->tjmax = get_tjmax(c, data->id, &pdev->dev); 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 */ - 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) { dev_warn(&pdev->dev, "Unable to read" " IA32_TEMPERATURE_TARGET MSR\n");