Phenom II 975 BE shows 0 celsius

Jung-uk Kim jkim at FreeBSD.org
Mon Aug 1 16:24:09 UTC 2011


On Monday 01 August 2011 10:14 am, Andriy Gapon wrote:
> on 01/08/2011 03:28 Mario Lobo said the following:
> > Hi to all
> >
> > In my desktop machine, I had an AM2+ ASROCK mobo with Phenom II
> > 955 BE that showed each core temperature perfectly under FBSD
> > 8-STABLE, via dev.cpu.x.temp. amdtemp.ko loaded.
> >
> > Unfortunately this Mobo died and only found AM3 boards for which
> > my phenom 955 doesn't fit. So I got an ASUS M4A88T-V EVO with a
> > Phenom II 975 BE.
> >
> > Funny thing. An AM3 phenom II fits on an AM2 board but an AM3
> > board doesn't accept an AM2/AM2+ phenom II :(.
> >
> > Anyway, now, under the very same system, it shows 0 degrees on
> > dev.cpu.x.temp for all cores.
>
> Sorry, I've got lost in all the config changes.  So what system do
> you have now? Can please also provide CPU-related information from
> dmesg?
>
> > I've been looking through k8temp and amdtemp src code. I am
> > definitely not sure of this but I believe something might have
> > happened to those:
> >
> > From k8temp.h
> >
> > K10_THERM_REG      0xa4
> > K10_THERMTRIP_REG  0xe4
> > K10_CURTMP(val)    (((val) >> 21) & 0xfff)
> > K10_THERMTRIP(val) ((val >> 1) & 1)
> >
> > From amdtemp.c
> >
> > /*
> >  * Register control (K8 family)
> >  */
> > #define	AMDTEMP_REG0F		0xe4
> > #define	AMDTEMP_REG_SELSENSOR	0x40
> > #define	AMDTEMP_REG_SELCORE	0x04
> >
> > /*
> >  * Register control (K10 & K11) family
> >  */
> > #define	AMDTEMP_REG		0xa4
> >
> >
> > Output of k8temp -dn:
> >
> > CPUID: Vendor: AuthenticAMD, 0x100f43: Model=04 Family=f+1
> > Stepping=3 Advanced Power Management=0x1f9
> >    Temperature sensor: Yes
> >  Frequency ID control: No
> >    Voltage ID control: No
> >     THERMTRIP support: Yes
> >    HW Thermal control: Yes
> >    SW Thermal control: Yes
> >    100MHz multipliers: Yes
> >    HW P-State control: Yes
> >         TSC Invariant: Yes
> > Temp=c0fef
> > ThermTrip=1fc00c30
> > 0
> >
> > I keep a small win7 partition to test little things like this and
> > see if the same thing happens there, and it doesn't, so I
> > concluded that the sensors are there and are working.
> >
> > One thing is worth noting though. I have used a free gadget that
> > shows activity/temp for each core. It worked fine with the
> > previous MB/CPU.That ALSO stopped working with this new MB. Like
> > FBSD, it shows 0 degrees for any core too, although it correctly
> > displays each core load.
>
> Most likely that gadget just re-uses OS-provided information.
>
> > The only windows tool that correctly shows the temperature are
> > the ASUS tools that came with the mobo.
> >
> > Other than that, everything is working fine! The only thing I had
> > to fix was the fstab ada location.
> >
> > I know this is not a big thing but I got accustomed to keeping an
> > eye on those temperatures.
> >
> > I have googled for a few days now searching for Thermal register
> > address or offsets for the Phenom II 975 BE, or anything related
> > to this problem and found nothing. Every search on AMD site was
> > fruitless. I could not find a single bit of tech info on this
> > processor there, or any other tech info for that matter.
>
> http://support.amd.com/us/Processor_TechDocs/31116.pdf
>
> > Would any one have any pointers/clues/suggestions on this?
>
> I would try to add some printfs (or used dtrace - whichever is
> easier for you) to see what's going on.  Or you can even use
> pciconf to directly sneak a peek at what's reported by the
> hardware, e.g.:
> # pciconf -r pci0:0:24:3 0xa4
> 1c881880
>
> You can read the BKDG to see how to interpret the value - search
> for F3xA4.  See F3xE4 for offset calculation.
>
> Hopefully you should be able to see if hardware reports sane value
> and how the amdtemp ends up reporting 0�C.

I gave up the DiodeOffset recently because a lot of BIOSes do not set 
any meaningful values.  Instead, I added a tunable for that.  Please 
see the attached patch, which is also available from here:

http://people.freebsd.org/~jkim/amdtemp.diff

Jung-uk Kim
-------------- next part --------------
Index: share/man/man4/amdtemp.4
===================================================================
--- share/man/man4/amdtemp.4	(revision 221788)
+++ share/man/man4/amdtemp.4	(working copy)
@@ -25,12 +25,14 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd April 8, 2008
+.Dd May 11, 2011
 .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,48 @@ 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, and 14h 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, and 14h 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 LOADER TUNABLES
+The following tunable can be set at the
+.Xr loader 8
+prompt before booting the kernel, or stored in
+.Xr loader.conf 5 .
+.Bl -tag -width indent
+.It Va hw.amdtemp.force_enable
+.El
+Set to a non-zero value to force enabling the driver for Family 10h Socket
+AM2+ and Socket F package processors.
+.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 +102,19 @@ driver first appeared in
 .Sh AUTHORS
 .An Rui Paulo Aq rpaulo at FreeBSD.org
 .An Norikatsu Shigemura Aq nork at FreeBSD.org
-.Sh BUGS
-AMD K9 is not supported because temperature reporting has been replaced
-by Maltese.
+.An Jung-uk Kim Aq jkim at 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
Index: sys/dev/amdtemp/amdtemp.c
===================================================================
--- sys/dev/amdtemp/amdtemp.c	(revision 221788)
+++ sys/dev/amdtemp/amdtemp.c	(working copy)
@@ -1,7 +1,7 @@
 /*-
  * Copyright (c) 2008, 2009 Rui Paulo <rpaulo at FreeBSD.org>
  * Copyright (c) 2009 Norikatsu Shigemura <nork at FreeBSD.org>
- * Copyright (c) 2009 Jung-uk Kim <jkim at FreeBSD.org>
+ * Copyright (c) 2009-2011 Jung-uk Kim <jkim at 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.
  */
 
@@ -42,17 +42,23 @@ __FBSDID("$FreeBSD$");
 #include <sys/sysctl.h>
 #include <sys/systm.h>
 
-#include <machine/cpufunc.h>
 #include <machine/md_var.h>
 #include <machine/specialreg.h>
 
 #include <dev/pci/pcivar.h>
 
+static int	amdtemp_force_enable;
+TUNABLE_INT("hw.amdtemp.force_enable", &amdtemp_force_enable);
+SYSCTL_NODE(_hw, OID_AUTO, amdtemp, CTLFLAG_RD, 0, "amdtemp driver parameters");
+SYSCTL_INT(_hw_amdtemp, OID_AUTO, force_enable, CTLFLAG_RDTUN,
+    &amdtemp_force_enable, 0,
+    "Force enabling on Family 10h Socket AM2+ and F package processors");
+
 typedef enum {
-	SENSOR0_CORE0,
-	SENSOR0_CORE1,
-	SENSOR1_CORE0,
-	SENSOR1_CORE1,
+	CORE0_SENSOR0,
+	CORE0_SENSOR1,
+	CORE1_SENSOR0,
+	CORE1_SENSOR1,
 	CORE0,
 	CORE1
 } amdsensor_t;
@@ -62,11 +68,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 +81,7 @@ struct amdtemp_softc {
 #define	DEVICEID_AMD_MISC0F	0x1103
 #define	DEVICEID_AMD_MISC10	0x1203
 #define	DEVICEID_AMD_MISC11	0x1303
+#define	DEVICEID_AMD_MISC14	0x1703
 
 static struct amdtemp_product {
 	uint16_t	amdtemp_vendorid;
@@ -84,11 +90,12 @@ static struct amdtemp_product {
 	{ VENDORID_AMD,	DEVICEID_AMD_MISC0F },
 	{ VENDORID_AMD,	DEVICEID_AMD_MISC10 },
 	{ VENDORID_AMD,	DEVICEID_AMD_MISC11 },
+	{ VENDORID_AMD,	DEVICEID_AMD_MISC14 },
 	{ 0, 0 }
 };
 
 /*
- * Reported Temperature Control Register (Family 10h/11h only)
+ * Reported Temperature Control Register
  */
 #define	AMDTEMP_REPTMP_CTRL	0xa4
 
@@ -100,6 +107,12 @@ static struct amdtemp_product {
 #define	AMDTEMP_TTSR_SELSENSOR	0x40	/* Family 0Fh only */
 
 /*
+ * DRAM Configuration High Register
+ */
+#define	AMDTEMP_DRAM_CONF_HIGH	0x94	/* Function 2 */
+#define	AMDTEMP_DRAM_MODE_DDR3	0x0100
+
+/*
  * CPU Family/Model Register
  */
 #define	AMDTEMP_CPUID		0xfc
@@ -117,6 +130,9 @@ static int32_t	amdtemp_gettemp0f(device_t dev, amd
 static int32_t	amdtemp_gettemp(device_t dev, amdsensor_t sensor);
 static int	amdtemp_sysctl(SYSCTL_HANDLER_ARGS);
 
+/* XXX */
+extern uint32_t	pci_cfgregread(int, int, int, int, int);
+
 static device_method_t amdtemp_methods[] = {
 	/* Device interface */
 	DEVMETHOD(device_identify,	amdtemp_identify),
@@ -173,6 +189,7 @@ amdtemp_identify(driver_t *driver, device_t parent
 static int
 amdtemp_probe(device_t dev)
 {
+	u_int regs[4];
 	uint32_t family, model;
 
 	if (resource_disabled("amdtemp", 0))
@@ -188,7 +205,30 @@ amdtemp_probe(device_t dev)
 			return (ENXIO);
 		break;
 	case 0x10:
+		if (amdtemp_force_enable)
+			break;
+		/*
+		 * 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 */
+			return (ENXIO);
+		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 && (cpu_id & CPUID_STEPPING) >= 3))
+				break;
+			/* XXX 00100F42h (RB-C2) exists in both formats. */
+			return (ENXIO);
+		}
+		break;
 	case 0x11:
+	case 0x12:
+	case 0x14:
 		break;
 	default:
 		return (ENXIO);
@@ -201,22 +241,14 @@ amdtemp_probe(device_t dev)
 static int
 amdtemp_attach(device_t dev)
 {
+	char tn[32];
 	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;
+	int 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;
-	}
-
-	/*
 	 * CPUID Register is available from Revision F.
 	 */
 	family = CPUID_TO_FAMILY(cpu_id);
@@ -232,11 +264,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 +281,39 @@ 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) {
+			u_int regs[4], bid;
+
+			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;
 		}
 
 		/*
@@ -274,6 +325,8 @@ amdtemp_attach(device_t dev)
 		break;
 	case 0x10:
 	case 0x11:
+	case 0x12:
+	case 0x14:
 		/*
 		 * There is only one sensor per package.
 		 */
@@ -297,41 +350,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)
+		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");
+
 			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 +438,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 +476,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,74 +500,49 @@ 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);
+	pci_write_config(dev, AMDTEMP_THERMTP_STAT, temp, 1);
 
-	/* CurTmp starts from -49C. */
-	offset = AMDTEMP_ZERO_C_TO_K - 490;
-
-	/* Adjust offset if DiodeOffset is set and valid. */
+	mask = (sc->sc_flags & AMDTEMP_FLAG_CT_10BIT) != 0 ? 0x3ff : 0x3fc;
+	offset = (sc->sc_flags & AMDTEMP_FLAG_ALT_OFFSET) != 0 ? 28 : 49;
 	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;
+	temp = ((temp >> 14) & mask) * 5 / 2;
+	temp += AMDTEMP_ZERO_C_TO_K + (sc->sc_offset - offset) * 10;
 
-	mask = (sc->sc_flags & AMDTEMP_FLAG_CT_10BIT) != 0 ? 0x3ff : 0x3fc;
-	temp = ((temp >> 14) & mask) * 5 / 2 + offset;
-
 	return (temp);
 }
 
 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);
 }


More information about the freebsd-questions mailing list