diff options
-rw-r--r-- | share/man/man4/Makefile | 4 | ||||
-rw-r--r-- | share/man/man4/itherm.4 | 68 | ||||
-rw-r--r-- | sys/arch/amd64/conf/GENERIC | 3 | ||||
-rw-r--r-- | sys/arch/i386/conf/GENERIC | 3 | ||||
-rw-r--r-- | sys/dev/pci/files.pci | 7 | ||||
-rw-r--r-- | sys/dev/pci/itherm.c | 387 |
6 files changed, 467 insertions, 5 deletions
diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 9888f9a4d37..1344f4c5894 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.508 2010/06/03 16:15:00 naddy Exp $ +# $OpenBSD: Makefile,v 1.509 2010/07/03 01:02:25 mlarkin Exp $ MAN= aac.4 ac97.4 acphy.4 \ acpi.4 acpiac.4 acpiasus.4 acpibat.4 acpibtn.4 acpicpu.4 acpidock.4 \ @@ -27,7 +27,7 @@ MAN= aac.4 ac97.4 acphy.4 \ ichiic.4 ichwdt.4 icmp.4 icmp6.4 icsphy.4 ifmedia.4 \ iha.4 iic.4 inet.4 inet6.4 inphy.4 iop.4 iophy.4 ioprbs.4 \ iopsp.4 ip.4 ip6.4 ipcomp.4 ipgphy.4 ipmi.4 ips.4 ipsec.4 ipw.4 \ - isa.4 isagpio.4 isapnp.4 isp.4 it.4 iwi.4 iwn.4 ix.4 ixgb.4 \ + isa.4 isagpio.4 isapnp.4 isp.4 it.4 itherm.4 iwi.4 iwn.4 ix.4 ixgb.4 \ jmb.4 jme.4 jmphy.4 \ kate.4 km.4 ksyms.4 kue.4 lc.4 lge.4 lii.4 lisa.4 lkm.4 lm.4 \ lmc.4 lmenv.4 lmn.4 lmtemp.4 lo.4 lofn.4 lpt.4 lxtphy.4 luphy.4 \ diff --git a/share/man/man4/itherm.4 b/share/man/man4/itherm.4 new file mode 100644 index 00000000000..c7f7b65545f --- /dev/null +++ b/share/man/man4/itherm.4 @@ -0,0 +1,68 @@ +.\" +.\" Copyright (c) 2010 Mike Larkin <mlarkin@openbsd.org> +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.Dd $Mdocdate: July 3 2010 $ +.Dt ITHERM 4 +.Os +.Sh NAME +.Nm itherm +.Nd Intel 3400 Thermal Sensor +.Sh SYNOPSIS +.Cd "itherm* at pci?" +.Sh DESCRIPTION +The +.Nm +driver provides support for several sensors found in Intel 3400 and 5 series +chipsets. +.Pp +The sensors currently exposed via the +.Xr sysctl 8 +interface are: +.Bl -column "Sensor " "Units" "Typical" -offset indent +.It Sy "Sensor" Ta Sy "Units" Ta Sy "Typical Use" +.It Li "Thermometer" Ta "degC" Ta "Temperature" +.It Li "Core 1" Ta "degC" Ta "Temperature" +.It Li "Core 2" Ta "degC" Ta "Temperature" +.It Li "CPU power cons." Ta "Watts" Ta "Power usage" +.It Li "CPU/GPU Max" Ta "degC" Ta "Temperature" +.It Li "DIMM 1" Ta "degC" Ta "Temperature" +.It Li "DIMM 2" Ta "degC" Ta "Temperature" +.It Li "DIMM 3" Ta "degC" Ta "Temperature" +.It Li "DIMM 4" Ta "degC" Ta "Temperature" +.It Li "GPU abs." Ta "degC" Ta "Temperature" +.It Li "PCH abs." Ta "degC" Ta "Temperature" +.El +.Sh SEE ALSO +.Xr pci 4 , +.Xr sensorsd 8 , +.Xr sysctl 8 +.Sh HISTORY +The +.Nm +driver first appeared in +.Ox 4.8 . +.Sh AUTHORS +The +.Nm +driver was written by +.An Mike Larkin Aq mlarkin@openbsd.org . +.Sh CAVEATS +Not all sensors are wired on every machine, so the list of +sensors shown in +.Xr sysctl 8 +may not show all the sensors listed above. +Further, the +.Nm +driver will flag sensors as invalid if they report bogus data. diff --git a/sys/arch/amd64/conf/GENERIC b/sys/arch/amd64/conf/GENERIC index f9853c899f8..c6b26ccd4bc 100644 --- a/sys/arch/amd64/conf/GENERIC +++ b/sys/arch/amd64/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.290 2010/06/27 21:00:22 kettenis Exp $ +# $OpenBSD: GENERIC,v 1.291 2010/07/03 01:02:25 mlarkin Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -113,6 +113,7 @@ iic* at nviic? amdpm* at pci? # AMD-7xx/8111 and NForce SMBus controller iic* at amdpm? +itherm* at pci? # Intel 3400 Thermal Sensor adc* at iic? # Analog Devices AD7416/AD7417/7418 adl* at iic? # Andigilog aSC7621 admtemp* at iic? # Analog Devices ADM1021 diff --git a/sys/arch/i386/conf/GENERIC b/sys/arch/i386/conf/GENERIC index 7babe24783f..a280478ecfb 100644 --- a/sys/arch/i386/conf/GENERIC +++ b/sys/arch/i386/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.685 2010/07/01 17:30:25 tedu Exp $ +# $OpenBSD: GENERIC,v 1.686 2010/07/03 01:02:25 mlarkin Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -152,6 +152,7 @@ fins0 at isa? port 0x4e # Fintek F71805 Super I/O aps0 at isa? port 0x1600 # ThinkPad Active Protection System +itherm* at pci? # Intel 3400 Thermal Sensor adc* at iic? # Analog Devices AD7416/AD7417/7418 andl* at iic? # Andigilog aSC7611 adl* at iic? # Andigilog aSC7621 diff --git a/sys/dev/pci/files.pci b/sys/dev/pci/files.pci index 2d7b76f24e2..a713c49394d 100644 --- a/sys/dev/pci/files.pci +++ b/sys/dev/pci/files.pci @@ -1,4 +1,4 @@ -# $OpenBSD: files.pci,v 1.272 2010/06/27 01:47:36 dlg Exp $ +# $OpenBSD: files.pci,v 1.273 2010/07/03 01:02:25 mlarkin Exp $ # $NetBSD: files.pci,v 1.20 1996/09/24 17:47:15 christos Exp $ # # Config file and device description for machine-independent PCI code. @@ -806,3 +806,8 @@ device auglx: audio, ac97 attach auglx at pci file dev/pci/auglx.c auglx +# Intel 3400 Thermal +device itherm +attach itherm at pci +file dev/pci/itherm.c itherm + diff --git a/sys/dev/pci/itherm.c b/sys/dev/pci/itherm.c new file mode 100644 index 00000000000..839668e3431 --- /dev/null +++ b/sys/dev/pci/itherm.c @@ -0,0 +1,387 @@ +/* + * Copyright (c) 2010 Mike Larkin <mlarkin@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Intel 3400 thermal sensor controller driver + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/sensors.h> + +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> +#include <dev/pci/pcidevs.h> + +#define ITHERM_NUM_SENSORS 12 +#define ITHERM_SENSOR_THERMOMETER 0 +#define ITHERM_SENSOR_CORETEMP1 1 +#define ITHERM_SENSOR_CORETEMP2 2 +#define ITHERM_SENSOR_COREENERGY 3 +#define ITHERM_SENSOR_GPUTEMP 4 +#define ITHERM_SENSOR_MAXPROCTEMP 5 +#define ITHERM_SENSOR_DIMMTEMP1 6 +#define ITHERM_SENSOR_DIMMTEMP2 7 +#define ITHERM_SENSOR_DIMMTEMP3 8 +#define ITHERM_SENSOR_DIMMTEMP4 9 +#define ITHERM_SENSOR_GPUTEMP_ABSOLUTE 10 +#define ITHERM_SENSOR_PCHTEMP_ABSOLUTE 11 + +/* Intel 3400 Thermal Sensor Data */ +#define ITHERM_TSE 0x1 +#define ITHERM_TSTR 0x3 +#define ITHERM_TRC 0x1A +#define ITHERM_CTV1 0x30 +#define ITHERM_CTV2 0x32 +#define ITHERM_CEV1 0x34 +#define ITHERM_MGTV 0x58 +#define ITHERM_PTV 0x60 +#define ITHERM_DTV 0xAC +#define ITHERM_ITV 0xD8 + +#define ITHERM_TEMP_READ_ENABLE 0xFF +#define ITHERM_TDR_ENABLE 0x1000 +#define ITHERM_SECOND_CORE_ENABLE 0x8000 + +#define ITHERM_TSE_ENABLE 0xB8 + +#define ITHERM_CTV_INVALID 0x8000 +#define ITHERM_CTV_INT_MASK 0x1FE0 +#define ITHERM_CTV_FRAC_MASK 0x001F + +#define ITHERM_REFRESH_INTERVAL 5 + +struct itherm_softc { + struct device sc_dev; + + bus_addr_t sc_addr; + bus_space_tag_t iot; + bus_space_handle_t ioh; + bus_size_t size; + + int64_t energy_prev; + + struct ksensor sensors[ITHERM_NUM_SENSORS]; + struct ksensordev sensordev; + void (*refresh_sensor_data)(struct itherm_softc *); +}; + +#define IREAD1(sc, a) bus_space_read_1((sc)->iot, (sc)->ioh, (a)) +#define IREAD2(sc, a) bus_space_read_2((sc)->iot, (sc)->ioh, (a)) +#define IREAD4(sc, a) bus_space_read_4((sc)->iot, (sc)->ioh, (a)) +#define IWRITE1(sc, a, x) bus_space_write_1((sc)->iot, (sc)->ioh, (a), (x)) +#define IWRITE2(sc, a, x) bus_space_write_2((sc)->iot, (sc)->ioh, (a), (x)) + +int itherm_probe(struct device *, void *, void *); +void itherm_attach(struct device *, struct device *, void *); +void itherm_refresh(void *); +void itherm_enable(struct itherm_softc *); +void itherm_refresh_sensor_data(struct itherm_softc *); +int itherm_activate(struct device *, int); +void itherm_bias_temperature_sensor(struct ksensor *); + +const struct pci_matchid itherm_devices[] = { + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_3400_THERMAL } +}; + +struct cfdriver itherm_cd = { + NULL, "itherm", DV_DULL +}; + +struct cfattach itherm_ca = { + sizeof(struct itherm_softc), itherm_probe, itherm_attach, NULL, + itherm_activate +}; + +int +itherm_probe(struct device *parent, void *match, void *aux) +{ + return (pci_matchbyid((struct pci_attach_args *)aux, itherm_devices, + sizeof(itherm_devices)/sizeof(itherm_devices[0]))); +} + +void +itherm_attach(struct device *parent, struct device *self, void *aux) +{ + struct itherm_softc *sc = (struct itherm_softc *)self; + struct pci_attach_args *pa = aux; + int i; + pcireg_t v; + + v = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_MAPREG_START); + v &= PCI_MAPREG_TYPE_MASK | PCI_MAPREG_MEM_TYPE_MASK; + if (pci_mapreg_map(pa, PCI_MAPREG_START, + v, 0, &sc->iot, &sc->ioh, NULL, &sc->size, 0)) { + printf(": can't map mem space\n"); + return; + } + + sc->sensors[ITHERM_SENSOR_THERMOMETER].type = SENSOR_TEMP; + sc->sensors[ITHERM_SENSOR_CORETEMP1].type = SENSOR_TEMP; + sc->sensors[ITHERM_SENSOR_CORETEMP2].type = SENSOR_TEMP; + sc->sensors[ITHERM_SENSOR_COREENERGY].type = SENSOR_WATTS; + sc->sensors[ITHERM_SENSOR_GPUTEMP].type = SENSOR_TEMP; + sc->sensors[ITHERM_SENSOR_MAXPROCTEMP].type = SENSOR_TEMP; + sc->sensors[ITHERM_SENSOR_DIMMTEMP1].type = SENSOR_TEMP; + sc->sensors[ITHERM_SENSOR_DIMMTEMP2].type = SENSOR_TEMP; + sc->sensors[ITHERM_SENSOR_DIMMTEMP3].type = SENSOR_TEMP; + sc->sensors[ITHERM_SENSOR_DIMMTEMP4].type = SENSOR_TEMP; + sc->sensors[ITHERM_SENSOR_GPUTEMP_ABSOLUTE].type = SENSOR_TEMP; + sc->sensors[ITHERM_SENSOR_PCHTEMP_ABSOLUTE].type = SENSOR_TEMP; + + strlcpy(sc->sensors[ITHERM_SENSOR_THERMOMETER].desc, + "Thermometer", + sizeof(sc->sensors[ITHERM_SENSOR_THERMOMETER].desc)); + + strlcpy(sc->sensors[ITHERM_SENSOR_CORETEMP1].desc, + "Core 1", + sizeof(sc->sensors[ITHERM_SENSOR_CORETEMP1].desc)); + + strlcpy(sc->sensors[ITHERM_SENSOR_CORETEMP2].desc, + "Core 2", + sizeof(sc->sensors[ITHERM_SENSOR_CORETEMP2].desc)); + + strlcpy(sc->sensors[ITHERM_SENSOR_COREENERGY].desc, + "CPU power consumption", + sizeof(sc->sensors[ITHERM_SENSOR_COREENERGY].desc)); + + strlcpy(sc->sensors[ITHERM_SENSOR_GPUTEMP].desc, + "GPU/Memory Controller Temp", + sizeof(sc->sensors[ITHERM_SENSOR_GPUTEMP].desc)); + + strlcpy(sc->sensors[ITHERM_SENSOR_MAXPROCTEMP].desc, + "CPU/GPU Max temp", + sizeof(sc->sensors[ITHERM_SENSOR_MAXPROCTEMP].desc)); + + strlcpy(sc->sensors[ITHERM_SENSOR_DIMMTEMP1].desc, + "DIMM 1", + sizeof(sc->sensors[ITHERM_SENSOR_DIMMTEMP1].desc)); + + strlcpy(sc->sensors[ITHERM_SENSOR_DIMMTEMP2].desc, + "DIMM 2", + sizeof(sc->sensors[ITHERM_SENSOR_DIMMTEMP2].desc)); + + strlcpy(sc->sensors[ITHERM_SENSOR_DIMMTEMP3].desc, + "DIMM 3", + sizeof(sc->sensors[ITHERM_SENSOR_DIMMTEMP3].desc)); + + strlcpy(sc->sensors[ITHERM_SENSOR_DIMMTEMP4].desc, + "DIMM 4", + sizeof(sc->sensors[ITHERM_SENSOR_DIMMTEMP4].desc)); + + strlcpy(sc->sensors[ITHERM_SENSOR_GPUTEMP_ABSOLUTE].desc, + "GPU/Memory controller abs.", + sizeof(sc->sensors[ITHERM_SENSOR_GPUTEMP_ABSOLUTE].desc)); + + strlcpy(sc->sensors[ITHERM_SENSOR_PCHTEMP_ABSOLUTE].desc, + "PCH abs.", + sizeof(sc->sensors[ITHERM_SENSOR_PCHTEMP_ABSOLUTE].desc)); + + strlcpy(sc->sensordev.xname, sc->sc_dev.dv_xname, + sizeof(sc->sensordev.xname)); + + itherm_enable(sc); + + for (i=0; i < ITHERM_NUM_SENSORS; i++) + sensor_attach(&sc->sensordev, &sc->sensors[i]); + + sensordev_install(&sc->sensordev); + sensor_task_register(sc, itherm_refresh, ITHERM_REFRESH_INTERVAL); + + printf("\n"); + + return; +} + +void +itherm_enable(struct itherm_softc *sc) +{ + sc->energy_prev = 0; + + /* Enable thermal sensor */ + IWRITE1(sc, ITHERM_TSE, ITHERM_TSE_ENABLE); + + /* Enable thermal reporting */ + IWRITE2(sc, ITHERM_TRC, (ITHERM_TEMP_READ_ENABLE | + ITHERM_TDR_ENABLE | ITHERM_SECOND_CORE_ENABLE)); +} + +int +itherm_activate(struct device *self, int act) +{ + struct itherm_softc *sc = (struct itherm_softc *)self; + + switch(act) { + case DVACT_RESUME: + itherm_enable(sc); + } + + return (0); +} + +void +itherm_refresh_sensor_data(struct itherm_softc *sc) +{ + u_int16_t data; + int64_t energy; + u_int32_t i; + + /* Thermometer sensor */ + sc->sensors[ITHERM_SENSOR_THERMOMETER].value = + IREAD1(sc, ITHERM_TSTR); + + itherm_bias_temperature_sensor( + &sc->sensors[ITHERM_SENSOR_THERMOMETER]); + + /* + * The Intel 3400 Thermal Sensor has separate sensors for each + * core, reported as a 16 bit value. Bits 13:6 are the integer + * part of the temperature in C and bits 5:0 are the fractional + * part of the temperature, in 1/64 degree C intervals. + * Bit 15 is used to indicate an invalid temperature + */ + + /* Core 1 temperature */ + data = IREAD2(sc, ITHERM_CTV1); + if (data & ITHERM_CTV_INVALID) + sc->sensors[ITHERM_SENSOR_CORETEMP1].flags |= + SENSOR_FINVALID; + else { + sc->sensors[ITHERM_SENSOR_CORETEMP1].flags &= + ~SENSOR_FINVALID; + sc->sensors[ITHERM_SENSOR_CORETEMP1].value = + (data & ITHERM_CTV_INT_MASK) >> 6; + sc->sensors[ITHERM_SENSOR_CORETEMP1].value *= + 1000000; + data &= ITHERM_CTV_FRAC_MASK; + data *= 1000000 / 64; + sc->sensors[ITHERM_SENSOR_CORETEMP1].value += + data; + } + + /* Core 2 temperature */ + data = IREAD2(sc, ITHERM_CTV2); + if (data & ITHERM_CTV_INVALID) + sc->sensors[ITHERM_SENSOR_CORETEMP2].flags |= + SENSOR_FINVALID; + else { + sc->sensors[ITHERM_SENSOR_CORETEMP2].flags &= + ~SENSOR_FINVALID; + sc->sensors[ITHERM_SENSOR_CORETEMP2].value = + (data & ITHERM_CTV_INT_MASK) >> 6; + sc->sensors[ITHERM_SENSOR_CORETEMP2].value *= + 1000000; + data &= ITHERM_CTV_FRAC_MASK; + data *= 1000000 / 64; + sc->sensors[ITHERM_SENSOR_CORETEMP2].value += + data; + } + + /* + * The core energy sensor reports the number of Joules + * of energy consumed by the processor since powerup. + * This number is scaled by 65535 and is continually + * increasing, so we save the old value and compute + * the difference for the Watt sensor value. + */ + + i = IREAD4(sc, ITHERM_CEV1); + /* Convert to Joules per interval */ + energy = (i / 65535); + energy = energy - sc->energy_prev; + sc->energy_prev = (i / 65535); + /* Convert to Joules per second */ + energy = energy / ITHERM_REFRESH_INTERVAL; + /* Convert to micro Joules per second (micro Watts) */ + energy = energy * 1000 * 1000; + + sc->sensors[ITHERM_SENSOR_COREENERGY].value = energy; + + /* + * XXX - the GPU temp is reported as a 64 bit value with no + * documented structure. Disabled for now + */ + sc->sensors[ITHERM_SENSOR_GPUTEMP].flags |= SENSOR_FINVALID; +#if 0 + bus_space_read_multi_4(sc->iot, sc->ioh, ITHERM_MGTV, + (u_int32_t *)&sc->sensors[ITHERM_SENSOR_GPUTEMP].value, 2); + sc->sensors[ITHERM_SENSOR_GPUTEMP].value *= 1000000; + sc->sensors[ITHERM_SENSOR_GPUTEMP].value += 273150000; +#endif + + /* Max processor temperature */ + sc->sensors[ITHERM_SENSOR_MAXPROCTEMP].value = + IREAD1(sc, ITHERM_PTV) * 1000000; + itherm_bias_temperature_sensor( + &sc->sensors[ITHERM_SENSOR_MAXPROCTEMP]); + + /* DIMM 1 */ + sc->sensors[ITHERM_SENSOR_DIMMTEMP1].value = + IREAD1(sc, ITHERM_DTV) * 1000000; + itherm_bias_temperature_sensor( + &sc->sensors[ITHERM_SENSOR_DIMMTEMP1]); + + /* DIMM 2 */ + sc->sensors[ITHERM_SENSOR_DIMMTEMP2].value = + IREAD1(sc, ITHERM_DTV+1) * 1000000; + itherm_bias_temperature_sensor( + &sc->sensors[ITHERM_SENSOR_DIMMTEMP2]); + + /* DIMM 3 */ + sc->sensors[ITHERM_SENSOR_DIMMTEMP3].value = + IREAD1(sc, ITHERM_DTV+2) * 1000000; + itherm_bias_temperature_sensor( + &sc->sensors[ITHERM_SENSOR_DIMMTEMP3]); + + /* DIMM 4 */ + sc->sensors[ITHERM_SENSOR_DIMMTEMP4].value = + IREAD1(sc, ITHERM_DTV+3) * 1000000; + itherm_bias_temperature_sensor( + &sc->sensors[ITHERM_SENSOR_DIMMTEMP4]); + + /* GPU Temperature */ + sc->sensors[ITHERM_SENSOR_GPUTEMP_ABSOLUTE].value = + IREAD1(sc, ITHERM_ITV+1) * 1000000; + itherm_bias_temperature_sensor( + &sc->sensors[ITHERM_SENSOR_GPUTEMP_ABSOLUTE]); + + /* PCH Temperature */ + sc->sensors[ITHERM_SENSOR_PCHTEMP_ABSOLUTE].value = + IREAD1(sc, ITHERM_ITV) * 1000000; + itherm_bias_temperature_sensor( + &sc->sensors[ITHERM_SENSOR_PCHTEMP_ABSOLUTE]); +} + +void +itherm_bias_temperature_sensor(struct ksensor *sensor) +{ + if (sensor->value == 0 || sensor->value == 0xff) + sensor->flags |= SENSOR_FINVALID; + else + sensor->flags &= ~SENSOR_FINVALID; + + /* Bias anyway from degC to degK, even if invalid */ + sensor->value += 273150000; +} + +void +itherm_refresh(void *arg) +{ + struct itherm_softc *sc = (struct itherm_softc *)arg; + + itherm_refresh_sensor_data(sc); +} |