1*8d2c75e4Smpi /* $OpenBSD: pchtemp.c,v 1.7 2022/03/11 18:00:51 mpi Exp $ */
24a460151Skettenis /*
34a460151Skettenis * Copyright (c) 2015 Mark Kettenis
44a460151Skettenis *
54a460151Skettenis * Permission to use, copy, modify, and distribute this software for any
64a460151Skettenis * purpose with or without fee is hereby granted, provided that the above
74a460151Skettenis * copyright notice and this permission notice appear in all copies.
84a460151Skettenis *
94a460151Skettenis * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
104a460151Skettenis * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
114a460151Skettenis * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
124a460151Skettenis * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
134a460151Skettenis * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
144a460151Skettenis * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
154a460151Skettenis * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
164a460151Skettenis */
174a460151Skettenis
184a460151Skettenis /*
198696ffcaSkettenis * Intel X99, C610, 9 Series and 100 Series PCH thermal sensor
208696ffcaSkettenis * controller driver
214a460151Skettenis */
224a460151Skettenis
234a460151Skettenis #include <sys/param.h>
244a460151Skettenis #include <sys/systm.h>
254a460151Skettenis #include <sys/device.h>
264a460151Skettenis #include <sys/sensors.h>
274a460151Skettenis
284a460151Skettenis #include <dev/pci/pcireg.h>
294a460151Skettenis #include <dev/pci/pcivar.h>
304a460151Skettenis #include <dev/pci/pcidevs.h>
314a460151Skettenis
324a460151Skettenis #define PCHTEMP_PCI_TBAR 0x10
334a460151Skettenis
344a460151Skettenis #define PCHTEMP_TEMP 0x00
354a460151Skettenis #define PCHTEMP_TSEL 0x08
364a460151Skettenis #define PCHTEMP_TSEL_ETS 0x01
374a460151Skettenis
384a460151Skettenis struct pchtemp_softc {
394a460151Skettenis struct device sc_dev;
404a460151Skettenis
414a460151Skettenis bus_space_tag_t sc_memt;
424a460151Skettenis bus_space_handle_t sc_memh;
434a460151Skettenis bus_size_t sc_mems;
444a460151Skettenis
454a460151Skettenis struct ksensor sc_sensor;
464a460151Skettenis struct ksensordev sc_sensordev;
474a460151Skettenis };
484a460151Skettenis
494a460151Skettenis int pchtemp_match(struct device *, void *, void *);
504a460151Skettenis void pchtemp_attach(struct device *, struct device *, void *);
514a460151Skettenis void pchtemp_refresh(void *);
524a460151Skettenis
534a460151Skettenis struct cfdriver pchtemp_cd = {
544a460151Skettenis NULL, "pchtemp", DV_DULL
554a460151Skettenis };
564a460151Skettenis
57*8d2c75e4Smpi const struct cfattach pchtemp_ca = {
584a460151Skettenis sizeof(struct pchtemp_softc), pchtemp_match, pchtemp_attach
594a460151Skettenis };
604a460151Skettenis
614a460151Skettenis const struct pci_matchid pchtemp_devices[] = {
62f07b1ca9Sdaniel { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_C610_THERM },
63d8e9eaf6Sjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_8SERIES_LP_THERM },
648696ffcaSkettenis { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_9SERIES_LP_THERM },
65f07b1ca9Sdaniel { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_100SERIES_THERM },
661aadbb50Sreyk { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_100SERIES_LP_THERM },
67d8e9eaf6Sjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_300SERIES_THERM },
68f5ce8749Sderaadt { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_300SERIES_U_THERM },
69d8e9eaf6Sjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_400SERIES_THERM },
70d8e9eaf6Sjsg { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_400SERIES_LP_THERM },
714a460151Skettenis };
724a460151Skettenis
734a460151Skettenis int
pchtemp_match(struct device * parent,void * match,void * aux)744a460151Skettenis pchtemp_match(struct device *parent, void *match, void *aux)
754a460151Skettenis {
764a460151Skettenis return (pci_matchbyid(aux, pchtemp_devices, nitems(pchtemp_devices)));
774a460151Skettenis }
784a460151Skettenis
794a460151Skettenis void
pchtemp_attach(struct device * parent,struct device * self,void * aux)804a460151Skettenis pchtemp_attach(struct device *parent, struct device *self, void *aux)
814a460151Skettenis {
824a460151Skettenis struct pchtemp_softc *sc = (struct pchtemp_softc *)self;
834a460151Skettenis struct pci_attach_args *pa = aux;
844a460151Skettenis pcireg_t memtype;
854a460151Skettenis uint8_t tsel;
864a460151Skettenis
874a460151Skettenis memtype = PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT;
884a460151Skettenis if (pci_mapreg_map(pa, PCHTEMP_PCI_TBAR, memtype, 0,
894a460151Skettenis &sc->sc_memt, &sc->sc_memh, NULL, &sc->sc_mems, 0)) {
904a460151Skettenis printf(": can't map registers\n");
914a460151Skettenis return;
924a460151Skettenis }
934a460151Skettenis
944a460151Skettenis tsel = bus_space_read_1(sc->sc_memt, sc->sc_memh, PCHTEMP_TSEL);
954a460151Skettenis if ((tsel & PCHTEMP_TSEL_ETS) == 0) {
964a460151Skettenis printf(": disabled\n");
974a460151Skettenis goto unmap;
984a460151Skettenis }
994a460151Skettenis
1004a460151Skettenis pchtemp_refresh(sc);
1014a460151Skettenis
1024a460151Skettenis strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
1034a460151Skettenis sizeof(sc->sc_sensordev.xname));
1044a460151Skettenis
1054a460151Skettenis sc->sc_sensor.type = SENSOR_TEMP;
1064a460151Skettenis sensor_attach(&sc->sc_sensordev, &sc->sc_sensor);
1074a460151Skettenis
1084a460151Skettenis if (sensor_task_register(sc, pchtemp_refresh, 5) == NULL) {
1094a460151Skettenis printf(": can't register update task\n");
1104a460151Skettenis goto unmap;
1114a460151Skettenis }
1124a460151Skettenis
1134a460151Skettenis sensordev_install(&sc->sc_sensordev);
1144a460151Skettenis
1154a460151Skettenis printf("\n");
1164a460151Skettenis return;
1174a460151Skettenis
1184a460151Skettenis unmap:
1194a460151Skettenis bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_mems);
1204a460151Skettenis }
1214a460151Skettenis
1224a460151Skettenis void
pchtemp_refresh(void * arg)1234a460151Skettenis pchtemp_refresh(void *arg)
1244a460151Skettenis {
1254a460151Skettenis struct pchtemp_softc *sc = arg;
1264a460151Skettenis uint16_t temp;
1274a460151Skettenis
1284a460151Skettenis temp = bus_space_read_2(sc->sc_memt, sc->sc_memh, PCHTEMP_TEMP);
1294a460151Skettenis sc->sc_sensor.value = (temp * 500000 - 50000000) + 273150000;
1304a460151Skettenis }
131