summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2015-12-31 13:06:50 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2015-12-31 13:06:50 +0000
commit8eda5d96920a8a82a75b71f6d4a1a7c01be2b367 (patch)
tree4b4ef36569243cfdc60825caa9fda0f9627db763 /sys/dev/pci
parentabe7f2dd3289f65b15fe446e9f1597c6259a98e9 (diff)
Add pchtemp(4) a driver for the thermal sensor on recent Intel PCHs.
Diffstat (limited to 'sys/dev/pci')
-rw-r--r--sys/dev/pci/files.pci7
-rw-r--r--sys/dev/pci/pchtemp.c121
2 files changed, 127 insertions, 1 deletions
diff --git a/sys/dev/pci/files.pci b/sys/dev/pci/files.pci
index 0629f6bdb95..0614e568d71 100644
--- a/sys/dev/pci/files.pci
+++ b/sys/dev/pci/files.pci
@@ -1,4 +1,4 @@
-# $OpenBSD: files.pci,v 1.321 2015/12/21 22:15:53 sf Exp $
+# $OpenBSD: files.pci,v 1.322 2015/12/31 13:06:49 kettenis 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.
@@ -793,6 +793,11 @@ device itherm
attach itherm at pci
file dev/pci/itherm.c itherm
+# Intel C610 temperature sensor
+device pchtemp
+attach pchtemp at pci
+file dev/pci/pchtemp.c pchtemp
+
# AMD Geode CS5536 PCI-ISA bridge
device glxpcib{}: isabus, gpiobus, i2cbus
attach glxpcib at pci
diff --git a/sys/dev/pci/pchtemp.c b/sys/dev/pci/pchtemp.c
new file mode 100644
index 00000000000..7f51686f135
--- /dev/null
+++ b/sys/dev/pci/pchtemp.c
@@ -0,0 +1,121 @@
+/* $OpenBSD: pchtemp.c,v 1.1 2015/12/31 13:06:49 kettenis Exp $ */
+/*
+ * Copyright (c) 2015 Mark Kettenis
+ *
+ * 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 X99 and C610 PCH 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 PCHTEMP_PCI_TBAR 0x10
+
+#define PCHTEMP_TEMP 0x00
+#define PCHTEMP_TSEL 0x08
+#define PCHTEMP_TSEL_ETS 0x01
+
+struct pchtemp_softc {
+ struct device sc_dev;
+
+ bus_space_tag_t sc_memt;
+ bus_space_handle_t sc_memh;
+ bus_size_t sc_mems;
+
+ struct ksensor sc_sensor;
+ struct ksensordev sc_sensordev;
+};
+
+int pchtemp_match(struct device *, void *, void *);
+void pchtemp_attach(struct device *, struct device *, void *);
+void pchtemp_refresh(void *);
+
+struct cfdriver pchtemp_cd = {
+ NULL, "pchtemp", DV_DULL
+};
+
+struct cfattach pchtemp_ca = {
+ sizeof(struct pchtemp_softc), pchtemp_match, pchtemp_attach
+};
+
+const struct pci_matchid pchtemp_devices[] = {
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C610_THERM }
+};
+
+int
+pchtemp_match(struct device *parent, void *match, void *aux)
+{
+ return (pci_matchbyid(aux, pchtemp_devices, nitems(pchtemp_devices)));
+}
+
+void
+pchtemp_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct pchtemp_softc *sc = (struct pchtemp_softc *)self;
+ struct pci_attach_args *pa = aux;
+ pcireg_t memtype;
+ uint8_t tsel;
+
+ memtype = PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT;
+ if (pci_mapreg_map(pa, PCHTEMP_PCI_TBAR, memtype, 0,
+ &sc->sc_memt, &sc->sc_memh, NULL, &sc->sc_mems, 0)) {
+ printf(": can't map registers\n");
+ return;
+ }
+
+ tsel = bus_space_read_1(sc->sc_memt, sc->sc_memh, PCHTEMP_TSEL);
+ if ((tsel & PCHTEMP_TSEL_ETS) == 0) {
+ printf(": disabled\n");
+ goto unmap;
+ }
+
+ pchtemp_refresh(sc);
+
+ strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
+ sizeof(sc->sc_sensordev.xname));
+
+ sc->sc_sensor.type = SENSOR_TEMP;
+ sensor_attach(&sc->sc_sensordev, &sc->sc_sensor);
+
+ if (sensor_task_register(sc, pchtemp_refresh, 5) == NULL) {
+ printf(": can't register update task\n");
+ goto unmap;
+ }
+
+ sensordev_install(&sc->sc_sensordev);
+
+ printf("\n");
+ return;
+
+ unmap:
+ bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_mems);
+}
+
+void
+pchtemp_refresh(void *arg)
+{
+ struct pchtemp_softc *sc = arg;
+ uint16_t temp;
+
+ temp = bus_space_read_2(sc->sc_memt, sc->sc_memh, PCHTEMP_TEMP);
+ sc->sc_sensor.value = (temp * 500000 - 50000000) + 273150000;
+}