Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a321cedb authored by Carsten Emde's avatar Carsten Emde Committed by Linus Torvalds
Browse files

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: default avatarHuaxu Wan <huaxu.wan@linux.intel.com>
Signed-off-by: default avatarCarsten 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: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 5db47b00
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -236,6 +236,8 @@

#define MSR_IA32_MISC_ENABLE		0x000001a0

#define MSR_IA32_TEMPERATURE_TARGET	0x000001a2

/* MISC_ENABLE bits: architectural */
#define MSR_IA32_MISC_ENABLE_FAST_STRING	(1ULL << 0)
#define MSR_IA32_MISC_ENABLE_TCC		(1ULL << 1)
+57 −4
Original line number Diff line number Diff line
@@ -241,6 +241,55 @@ static int __devinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *
	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)
{
	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);

	/* 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)) {
		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");