xref: /openbsd-src/sys/dev/pci/pchtemp.c (revision 8d2c75e49a1f1e140a0efd2b93f23844e8cb679f)
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