Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 24 Feb 2012 00:02:46 +0000 (UTC)
From:      Jung-uk Kim <jkim@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r232090 - in head: share/man/man4 sys/dev/amdtemp
Message-ID:  <201202240002.q1O02k8w032291@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jkim
Date: Fri Feb 24 00:02:46 2012
New Revision: 232090
URL: http://svn.freebsd.org/changeset/base/232090

Log:
  - Add support for Family 12h, 14h and 15h processors.
  - Remove all attempts to guess physical temperature using DiodeOffset.
  There are too many reports that it varies wildly depending on motherboard.
  Instead, if it is known to scale well and its offset is known from other
  temperature sensors on board, the user may set "dev.amdtemp.0.sensor_offset"
  tunable to compensate the difference.  Document the caveats in amdtemp(4).
  - Add a quirk for Socket AM2 Revision G processors.  These processors are
  known to have a different offset according to Linux k8temp driver.
  - Warn about Family 10h Erratum 319.  These processors have broken sensors.
  - Report temperature in more logical orders under dev.amdtemp node.  For
  example, "dev.amdtemp.0.sensor0.core0" is now "dev.amdtemp.0.core0.sensor0".
  - Replace K8, K10 and K11 with official processor names in amdtemp(4).

Modified:
  head/share/man/man4/amdtemp.4
  head/sys/dev/amdtemp/amdtemp.c

Modified: head/share/man/man4/amdtemp.4
==============================================================================
--- head/share/man/man4/amdtemp.4	Thu Feb 23 23:37:29 2012	(r232089)
+++ head/share/man/man4/amdtemp.4	Fri Feb 24 00:02:46 2012	(r232090)
@@ -25,12 +25,14 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd April 8, 2008
+.Dd February 23, 2012
 .Dt AMDTEMP 4
 .Os
 .Sh NAME
 .Nm amdtemp
-.Nd device driver for AMD K8, K10 and K11 on-die digital thermal sensor
+.Nd device driver for
+.Tn AMD
+processor on-die digital thermal sensor
 .Sh SYNOPSIS
 To compile this driver into the kernel,
 place the following line in your
@@ -49,22 +51,38 @@ amdtemp_load="YES"
 The
 .Nm
 driver provides support for the on-die digital thermal sensor present
-in AMD K8, K10 and K11 processors.
+in
+.Tn AMD
+Family 0Fh, 10h, 11h, 12h, 14h, and 15h processors.
 .Pp
-For the K8 family, the
+For Family 0Fh processors, the
 .Nm
-driver reports each core's temperature through a sysctl node in the
-corresponding CPU devices's sysctl tree, named
-.Va dev.amdtemp.%d.sensor{0,1}.core{0,1} .
+driver reports each core's temperature through sysctl nodes, named
+.Va dev.amdtemp.%d.core{0,1}.sensor{0,1} .
 The driver also creates
 .Va dev.cpu.%d.temperature
-displaying the maximum temperature of the two sensors 
-located in each CPU core.
+in the corresponding CPU device's sysctl tree, displaying the maximum
+temperature of the two sensors located in each CPU core.
 .Pp
-For the K10 and K11 families, the driver creates
+For Family 10h, 11h, 12h, 14h, and 15h processors, the driver reports each
+package's temperature through a sysctl node, named
+.Va dev.amdtemp.%d.core0.sensor0 .
+The driver also creates
 .Va dev.cpu.%d.temperature
-with the temperature of each core.
+in the corresponding CPU device's sysctl tree, displaying the temperature
+of the shared sensor located in each CPU package.
+.Sh SYSCTL VARIABLES
+The following variable is available as both
+.Xr sysctl 8
+variable and
+.Xr loader 8
+tunable:
+.Bl -tag -width indent
+.It Va dev.amdtemp.%d.sensor_offset
+.El
+Add the given offset to the temperature of the sensor.  Default is 0.
 .Sh SEE ALSO
+.Xr loader 8 ,
 .Xr sysctl 8
 .Sh HISTORY
 The
@@ -74,6 +92,19 @@ driver first appeared in
 .Sh AUTHORS
 .An Rui Paulo Aq rpaulo@FreeBSD.org
 .An Norikatsu Shigemura Aq nork@FreeBSD.org
-.Sh BUGS
-AMD K9 is not supported because temperature reporting has been replaced
-by Maltese.
+.An Jung-uk Kim Aq jkim@FreeBSD.org
+.Sh CAVEATS
+For Family 10h and later processors,
+.Do
+(the reported temperature) is a non-physical temperature measured on
+an arbitrary scale and it does not represent an actual physical
+temperature like die or case temperature.  Instead, it specifies
+the processor temperature relative to the point at which the system
+must supply the maximum cooling for the processor's specified maximum
+case temperature and maximum thermal power dissipation
+.Dc
+according to
+.Rs
+.%T BIOS and Kernel Developer's Guide (BKDG) for AMD Processors
+.%U http://developer.amd.com/documentation/guides/Pages/default.aspx
+.Re

Modified: head/sys/dev/amdtemp/amdtemp.c
==============================================================================
--- head/sys/dev/amdtemp/amdtemp.c	Thu Feb 23 23:37:29 2012	(r232089)
+++ head/sys/dev/amdtemp/amdtemp.c	Fri Feb 24 00:02:46 2012	(r232090)
@@ -1,7 +1,7 @@
 /*-
  * Copyright (c) 2008, 2009 Rui Paulo <rpaulo@FreeBSD.org>
  * Copyright (c) 2009 Norikatsu Shigemura <nork@FreeBSD.org>
- * Copyright (c) 2009 Jung-uk Kim <jkim@FreeBSD.org>
+ * Copyright (c) 2009-2012 Jung-uk Kim <jkim@FreeBSD.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -27,7 +27,7 @@
  */
 
 /*
- * Driver for the AMD CPU on-die thermal sensors for Family 0Fh/10h/11h procs.
+ * Driver for the AMD CPU on-die thermal sensors.
  * Initially based on the k8temp Linux driver.
  */
 
@@ -47,12 +47,13 @@ __FBSDID("$FreeBSD$");
 #include <machine/specialreg.h>
 
 #include <dev/pci/pcivar.h>
+#include <x86/pci_cfgreg.h>
 
 typedef enum {
-	SENSOR0_CORE0,
-	SENSOR0_CORE1,
-	SENSOR1_CORE0,
-	SENSOR1_CORE1,
+	CORE0_SENSOR0,
+	CORE0_SENSOR1,
+	CORE1_SENSOR0,
+	CORE1_SENSOR1,
 	CORE0,
 	CORE1
 } amdsensor_t;
@@ -62,11 +63,10 @@ struct amdtemp_softc {
 	int		sc_ncores;
 	int		sc_ntemps;
 	int		sc_flags;
-#define	AMDTEMP_FLAG_DO_QUIRK	0x01	/* DiodeOffset may be incorrect. */
-#define	AMDTEMP_FLAG_DO_ZERO	0x02	/* DiodeOffset starts from 0C. */
-#define	AMDTEMP_FLAG_DO_SIGN	0x04	/* DiodeOffsetSignBit is present. */
-#define	AMDTEMP_FLAG_CS_SWAP	0x08	/* ThermSenseCoreSel is inverted. */
-#define	AMDTEMP_FLAG_CT_10BIT	0x10	/* CurTmp is 10-bit wide. */
+#define	AMDTEMP_FLAG_CS_SWAP	0x01	/* ThermSenseCoreSel is inverted. */
+#define	AMDTEMP_FLAG_CT_10BIT	0x02	/* CurTmp is 10-bit wide. */
+#define	AMDTEMP_FLAG_ALT_OFFSET	0x04	/* CurTmp starts at -28C. */
+	int32_t		sc_offset;
 	int32_t		(*sc_gettemp)(device_t, amdsensor_t);
 	struct sysctl_oid *sc_sysctl_cpu[MAXCPU];
 	struct intr_config_hook sc_ich;
@@ -76,6 +76,8 @@ struct amdtemp_softc {
 #define	DEVICEID_AMD_MISC0F	0x1103
 #define	DEVICEID_AMD_MISC10	0x1203
 #define	DEVICEID_AMD_MISC11	0x1303
+#define	DEVICEID_AMD_MISC14	0x1703
+#define	DEVICEID_AMD_MISC15	0x1603
 
 static struct amdtemp_product {
 	uint16_t	amdtemp_vendorid;
@@ -84,20 +86,28 @@ static struct amdtemp_product {
 	{ VENDORID_AMD,	DEVICEID_AMD_MISC0F },
 	{ VENDORID_AMD,	DEVICEID_AMD_MISC10 },
 	{ VENDORID_AMD,	DEVICEID_AMD_MISC11 },
+	{ VENDORID_AMD,	DEVICEID_AMD_MISC14 },
+	{ VENDORID_AMD,	DEVICEID_AMD_MISC15 },
 	{ 0, 0 }
 };
 
 /*
- * Reported Temperature Control Register (Family 10h/11h only)
+ * Reported Temperature Control Register
  */
 #define	AMDTEMP_REPTMP_CTRL	0xa4
 
 /*
- * Thermaltrip Status Register
+ * Thermaltrip Status Register (Family 0Fh only)
  */
 #define	AMDTEMP_THERMTP_STAT	0xe4
-#define	AMDTEMP_TTSR_SELCORE	0x04	/* Family 0Fh only */
-#define	AMDTEMP_TTSR_SELSENSOR	0x40	/* Family 0Fh only */
+#define	AMDTEMP_TTSR_SELCORE	0x04
+#define	AMDTEMP_TTSR_SELSENSOR	0x40
+
+/*
+ * DRAM Configuration High Register
+ */
+#define	AMDTEMP_DRAM_CONF_HIGH	0x94	/* Function 2 */
+#define	AMDTEMP_DRAM_MODE_DDR3	0x0100
 
 /*
  * CPU Family/Model Register
@@ -189,6 +199,9 @@ amdtemp_probe(device_t dev)
 		break;
 	case 0x10:
 	case 0x11:
+	case 0x12:
+	case 0x14:
+	case 0x15:
 		break;
 	default:
 		return (ENXIO);
@@ -201,26 +214,23 @@ amdtemp_probe(device_t dev)
 static int
 amdtemp_attach(device_t dev)
 {
+	char tn[32];
+	u_int regs[4];
 	struct amdtemp_softc *sc = device_get_softc(dev);
 	struct sysctl_ctx_list *sysctlctx;
 	struct sysctl_oid *sysctlnode;
-	uint32_t regs[4];
 	uint32_t cpuid, family, model;
+	u_int bid;
+	int erratum319, unit;
 
-	/*
-	 * Errata #154: Incorect Diode Offset
-	 */
-	if (cpu_id == 0x20f32) {
-		do_cpuid(0x80000001, regs);
-		if ((regs[1] & 0xfff) == 0x2c)
-			sc->sc_flags |= AMDTEMP_FLAG_DO_QUIRK;
-	}
+	erratum319 = 0;
 
 	/*
 	 * CPUID Register is available from Revision F.
 	 */
-	family = CPUID_TO_FAMILY(cpu_id);
-	model = CPUID_TO_MODEL(cpu_id);
+	cpuid = cpu_id;
+	family = CPUID_TO_FAMILY(cpuid);
+	model = CPUID_TO_MODEL(cpuid);
 	if (family != 0x0f || model >= 0x40) {
 		cpuid = pci_read_config(dev, AMDTEMP_CPUID, 4);
 		family = CPUID_TO_FAMILY(cpuid);
@@ -232,11 +242,6 @@ amdtemp_attach(device_t dev)
 		/*
 		 * Thermaltrip Status Register
 		 *
-		 * - DiodeOffsetSignBit
-		 *
-		 * Revision D & E:	bit 24
-		 * Other:		N/A
-		 *
 		 * - ThermSenseCoreSel
 		 *
 		 * Revision F & G:	0 - Core1, 1 - Core0
@@ -254,15 +259,37 @@ amdtemp_attach(device_t dev)
 		 * ThermSenseCoreSel work in undocumented cases as well.
 		 * In fact, the Linux driver suggests it may not work but
 		 * we just assume it does until we find otherwise.
+		 *
+		 * XXX According to Linux, CurTmp starts at -28C on
+		 * Socket AM2 Revision G processors, which is not
+		 * documented anywhere.
 		 */
-		if (model < 0x40) {
-			sc->sc_flags |= AMDTEMP_FLAG_DO_ZERO;
-			if (model >= 0x10)
-				sc->sc_flags |= AMDTEMP_FLAG_DO_SIGN;
-		} else {
+		if (model >= 0x40)
 			sc->sc_flags |= AMDTEMP_FLAG_CS_SWAP;
-			if (model >= 0x60 && model != 0xc1)
-				sc->sc_flags |= AMDTEMP_FLAG_CT_10BIT;
+		if (model >= 0x60 && model != 0xc1) {
+			do_cpuid(0x80000001, regs);
+			bid = (regs[1] >> 9) & 0x1f;
+			switch (model) {
+			case 0x68: /* Socket S1g1 */
+			case 0x6c:
+			case 0x7c:
+				break;
+			case 0x6b: /* Socket AM2 and ASB1 (2 cores) */
+				if (bid != 0x0b && bid != 0x0c)
+					sc->sc_flags |=
+					    AMDTEMP_FLAG_ALT_OFFSET;
+				break;
+			case 0x6f: /* Socket AM2 and ASB1 (1 core) */
+			case 0x7f:
+				if (bid != 0x07 && bid != 0x09 &&
+				    bid != 0x0c)
+					sc->sc_flags |=
+					    AMDTEMP_FLAG_ALT_OFFSET;
+				break;
+			default:
+				sc->sc_flags |= AMDTEMP_FLAG_ALT_OFFSET;
+			}
+			sc->sc_flags |= AMDTEMP_FLAG_CT_10BIT;
 		}
 
 		/*
@@ -273,7 +300,31 @@ amdtemp_attach(device_t dev)
 		sc->sc_gettemp = amdtemp_gettemp0f;
 		break;
 	case 0x10:
+		/*
+		 * Erratum 319 Inaccurate Temperature Measurement
+		 *
+		 * http://support.amd.com/us/Processor_TechDocs/41322.pdf
+		 */
+		do_cpuid(0x80000001, regs);
+		switch ((regs[1] >> 28) & 0xf) {
+		case 0:	/* Socket F */
+			erratum319 = 1;
+			break;
+		case 1:	/* Socket AM2+ or AM3 */
+			if ((pci_cfgregread(pci_get_bus(dev),
+			    pci_get_slot(dev), 2, AMDTEMP_DRAM_CONF_HIGH, 2) &
+			    AMDTEMP_DRAM_MODE_DDR3) != 0 || model > 0x04 ||
+			    (model == 0x04 && (cpuid & CPUID_STEPPING) >= 3))
+				break;
+			/* XXX 00100F42h (RB-C2) exists in both formats. */
+			erratum319 = 1;
+			break;
+		}
+		/* FALLTHROUGH */
 	case 0x11:
+	case 0x12:
+	case 0x14:
+	case 0x15:
 		/*
 		 * There is only one sensor per package.
 		 */
@@ -289,6 +340,9 @@ amdtemp_attach(device_t dev)
 	if (sc->sc_ncores > MAXCPU)
 		return (ENXIO);
 
+	if (erratum319)
+		device_printf(dev,
+		    "Erratum 319: temperature measurement may be inaccurate\n");
 	if (bootverbose)
 		device_printf(dev, "Found %d cores and %d sensors.\n",
 		    sc->sc_ncores,
@@ -297,41 +351,49 @@ amdtemp_attach(device_t dev)
 	/*
 	 * dev.amdtemp.N tree.
 	 */
+	unit = device_get_unit(dev);
+	snprintf(tn, sizeof(tn), "dev.amdtemp.%d.sensor_offset", unit);
+	TUNABLE_INT_FETCH(tn, &sc->sc_offset);
+
 	sysctlctx = device_get_sysctl_ctx(dev);
+	SYSCTL_ADD_INT(sysctlctx,
+	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
+	    "sensor_offset", CTLFLAG_RW, &sc->sc_offset, 0,
+	    "Temperature sensor offset");
 	sysctlnode = SYSCTL_ADD_NODE(sysctlctx,
 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
-	    "sensor0", CTLFLAG_RD, 0, "Sensor 0");
+	    "core0", CTLFLAG_RD, 0, "Core 0");
 
 	SYSCTL_ADD_PROC(sysctlctx,
 	    SYSCTL_CHILDREN(sysctlnode),
-	    OID_AUTO, "core0", CTLTYPE_INT | CTLFLAG_RD,
-	    dev, SENSOR0_CORE0, amdtemp_sysctl, "IK",
-	    "Sensor 0 / Core 0 temperature");
+	    OID_AUTO, "sensor0", CTLTYPE_INT | CTLFLAG_RD,
+	    dev, CORE0_SENSOR0, amdtemp_sysctl, "IK",
+	    "Core 0 / Sensor 0 temperature");
 
 	if (sc->sc_ntemps > 1) {
-		if (sc->sc_ncores > 1)
-			SYSCTL_ADD_PROC(sysctlctx,
-			    SYSCTL_CHILDREN(sysctlnode),
-			    OID_AUTO, "core1", CTLTYPE_INT | CTLFLAG_RD,
-			    dev, SENSOR0_CORE1, amdtemp_sysctl, "IK",
-			    "Sensor 0 / Core 1 temperature");
-
-		sysctlnode = SYSCTL_ADD_NODE(sysctlctx,
-		    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
-		    "sensor1", CTLFLAG_RD, 0, "Sensor 1");
-
 		SYSCTL_ADD_PROC(sysctlctx,
 		    SYSCTL_CHILDREN(sysctlnode),
-		    OID_AUTO, "core0", CTLTYPE_INT | CTLFLAG_RD,
-		    dev, SENSOR1_CORE0, amdtemp_sysctl, "IK",
-		    "Sensor 1 / Core 0 temperature");
+		    OID_AUTO, "sensor1", CTLTYPE_INT | CTLFLAG_RD,
+		    dev, CORE0_SENSOR1, amdtemp_sysctl, "IK",
+		    "Core 0 / Sensor 1 temperature");
+
+		if (sc->sc_ncores > 1) {
+			sysctlnode = SYSCTL_ADD_NODE(sysctlctx,
+			    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+			    OID_AUTO, "core1", CTLFLAG_RD, 0, "Core 1");
 
-		if (sc->sc_ncores > 1)
 			SYSCTL_ADD_PROC(sysctlctx,
 			    SYSCTL_CHILDREN(sysctlnode),
-			    OID_AUTO, "core1", CTLTYPE_INT | CTLFLAG_RD,
-			    dev, SENSOR1_CORE1, amdtemp_sysctl, "IK",
-			    "Sensor 1 / Core 1 temperature");
+			    OID_AUTO, "sensor0", CTLTYPE_INT | CTLFLAG_RD,
+			    dev, CORE1_SENSOR0, amdtemp_sysctl, "IK",
+			    "Core 1 / Sensor 0 temperature");
+
+			SYSCTL_ADD_PROC(sysctlctx,
+			    SYSCTL_CHILDREN(sysctlnode),
+			    OID_AUTO, "sensor1", CTLTYPE_INT | CTLFLAG_RD,
+			    dev, CORE1_SENSOR1, amdtemp_sysctl, "IK",
+			    "Core 1 / Sensor 1 temperature");
+		}
 	}
 
 	/*
@@ -377,7 +439,7 @@ amdtemp_intrhook(void *arg)
 			sysctlctx = device_get_sysctl_ctx(cpu);
 
 			sensor = sc->sc_ntemps > 1 ?
-			    (i == 0 ? CORE0 : CORE1) : SENSOR0_CORE0;
+			    (i == 0 ? CORE0 : CORE1) : CORE0_SENSOR0;
 			sc->sc_sysctl_cpu[i] = SYSCTL_ADD_PROC(sysctlctx,
 			    SYSCTL_CHILDREN(device_get_sysctl_tree(cpu)),
 			    OID_AUTO, "temperature", CTLTYPE_INT | CTLFLAG_RD,
@@ -415,13 +477,13 @@ amdtemp_sysctl(SYSCTL_HANDLER_ARGS)
 
 	switch (sensor) {
 	case CORE0:
-		auxtemp[0] = sc->sc_gettemp(dev, SENSOR0_CORE0);
-		auxtemp[1] = sc->sc_gettemp(dev, SENSOR1_CORE0);
+		auxtemp[0] = sc->sc_gettemp(dev, CORE0_SENSOR0);
+		auxtemp[1] = sc->sc_gettemp(dev, CORE0_SENSOR1);
 		temp = imax(auxtemp[0], auxtemp[1]);
 		break;
 	case CORE1:
-		auxtemp[0] = sc->sc_gettemp(dev, SENSOR0_CORE1);
-		auxtemp[1] = sc->sc_gettemp(dev, SENSOR1_CORE1);
+		auxtemp[0] = sc->sc_gettemp(dev, CORE1_SENSOR0);
+		auxtemp[1] = sc->sc_gettemp(dev, CORE1_SENSOR1);
 		temp = imax(auxtemp[0], auxtemp[1]);
 		break;
 	default:
@@ -439,53 +501,36 @@ static int32_t
 amdtemp_gettemp0f(device_t dev, amdsensor_t sensor)
 {
 	struct amdtemp_softc *sc = device_get_softc(dev);
-	uint32_t mask, temp;
-	int32_t diode_offset, offset;
-	uint8_t cfg, sel;
+	uint32_t mask, offset, temp;
 
 	/* Set Sensor/Core selector. */
-	sel = 0;
+	temp = pci_read_config(dev, AMDTEMP_THERMTP_STAT, 1);
+	temp &= ~(AMDTEMP_TTSR_SELCORE | AMDTEMP_TTSR_SELSENSOR);
 	switch (sensor) {
-	case SENSOR1_CORE0:
-		sel |= AMDTEMP_TTSR_SELSENSOR;
+	case CORE0_SENSOR1:
+		temp |= AMDTEMP_TTSR_SELSENSOR;
 		/* FALLTHROUGH */
-	case SENSOR0_CORE0:
+	case CORE0_SENSOR0:
 	case CORE0:
 		if ((sc->sc_flags & AMDTEMP_FLAG_CS_SWAP) != 0)
-			sel |= AMDTEMP_TTSR_SELCORE;
+			temp |= AMDTEMP_TTSR_SELCORE;
 		break;
-	case SENSOR1_CORE1:
-		sel |= AMDTEMP_TTSR_SELSENSOR;
+	case CORE1_SENSOR1:
+		temp |= AMDTEMP_TTSR_SELSENSOR;
 		/* FALLTHROUGH */
-	case SENSOR0_CORE1:
+	case CORE1_SENSOR0:
 	case CORE1:
 		if ((sc->sc_flags & AMDTEMP_FLAG_CS_SWAP) == 0)
-			sel |= AMDTEMP_TTSR_SELCORE;
+			temp |= AMDTEMP_TTSR_SELCORE;
 		break;
 	}
-	cfg = pci_read_config(dev, AMDTEMP_THERMTP_STAT, 1);
-	cfg &= ~(AMDTEMP_TTSR_SELSENSOR | AMDTEMP_TTSR_SELCORE);
-	pci_write_config(dev, AMDTEMP_THERMTP_STAT, cfg | sel, 1);
-
-	/* CurTmp starts from -49C. */
-	offset = AMDTEMP_ZERO_C_TO_K - 490;
-
-	/* Adjust offset if DiodeOffset is set and valid. */
-	temp = pci_read_config(dev, AMDTEMP_THERMTP_STAT, 4);
-	diode_offset = (temp >> 8) & 0x3f;
-	if ((sc->sc_flags & AMDTEMP_FLAG_DO_ZERO) != 0) {
-		if ((sc->sc_flags & AMDTEMP_FLAG_DO_SIGN) != 0 &&
-		    ((temp >> 24) & 0x1) != 0)
-			diode_offset *= -1;
-		if ((sc->sc_flags & AMDTEMP_FLAG_DO_QUIRK) != 0 &&
-		    ((temp >> 25) & 0xf) <= 2)
-			diode_offset += 10;
-		offset += diode_offset * 10;
-	} else if (diode_offset != 0)
-		offset += (diode_offset - 11) * 10;
+	pci_write_config(dev, AMDTEMP_THERMTP_STAT, temp, 1);
 
 	mask = (sc->sc_flags & AMDTEMP_FLAG_CT_10BIT) != 0 ? 0x3ff : 0x3fc;
-	temp = ((temp >> 14) & mask) * 5 / 2 + offset;
+	offset = (sc->sc_flags & AMDTEMP_FLAG_ALT_OFFSET) != 0 ? 28 : 49;
+	temp = pci_read_config(dev, AMDTEMP_THERMTP_STAT, 4);
+	temp = ((temp >> 14) & mask) * 5 / 2;
+	temp += AMDTEMP_ZERO_C_TO_K + (sc->sc_offset - offset) * 10;
 
 	return (temp);
 }
@@ -493,20 +538,12 @@ amdtemp_gettemp0f(device_t dev, amdsenso
 static int32_t
 amdtemp_gettemp(device_t dev, amdsensor_t sensor)
 {
+	struct amdtemp_softc *sc = device_get_softc(dev);
 	uint32_t temp;
-	int32_t diode_offset, offset;
-
-	/* CurTmp starts from 0C. */
-	offset = AMDTEMP_ZERO_C_TO_K;
-
-	/* Adjust offset if DiodeOffset is set and valid. */
-	temp = pci_read_config(dev, AMDTEMP_THERMTP_STAT, 4);
-	diode_offset = (temp >> 8) & 0x7f;
-	if (diode_offset > 0 && diode_offset < 0x40)
-		offset += (diode_offset - 11) * 10;
 
 	temp = pci_read_config(dev, AMDTEMP_REPTMP_CTRL, 4);
-	temp = ((temp >> 21) & 0x7ff) * 5 / 4 + offset;
+	temp = ((temp >> 21) & 0x7ff) * 5 / 4;
+	temp += AMDTEMP_ZERO_C_TO_K + sc->sc_offset * 10;
 
 	return (temp);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201202240002.q1O02k8w032291>