From owner-svn-src-all@FreeBSD.ORG Fri Feb 24 00:02:46 2012 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id A82A9106564A; Fri, 24 Feb 2012 00:02:46 +0000 (UTC) (envelope-from jkim@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 95CAE8FC0C; Fri, 24 Feb 2012 00:02:46 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q1O02k1I032294; Fri, 24 Feb 2012 00:02:46 GMT (envelope-from jkim@svn.freebsd.org) Received: (from jkim@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q1O02k8w032291; Fri, 24 Feb 2012 00:02:46 GMT (envelope-from jkim@svn.freebsd.org) Message-Id: <201202240002.q1O02k8w032291@svn.freebsd.org> From: Jung-uk Kim Date: Fri, 24 Feb 2012 00:02:46 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r232090 - in head: share/man/man4 sys/dev/amdtemp X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 24 Feb 2012 00:02:46 -0000 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 * Copyright (c) 2009 Norikatsu Shigemura - * Copyright (c) 2009 Jung-uk Kim + * Copyright (c) 2009-2012 Jung-uk Kim * 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 #include +#include 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); }