xref: /dflybsd-src/sys/dev/powermng/memtemp/memtemp_e5.c (revision 0c1d7dca433e727c476aff53acb839b357a28ef6)
17698c759SSepherosa Ziehau /*
27698c759SSepherosa Ziehau  * Copyright (c) 2015 The DragonFly Project.  All rights reserved.
37698c759SSepherosa Ziehau  *
47698c759SSepherosa Ziehau  * This code is derived from software contributed to The DragonFly Project
57698c759SSepherosa Ziehau  * by Sepherosa Ziehau <sepherosa@gmail.com>
67698c759SSepherosa Ziehau  *
77698c759SSepherosa Ziehau  * Redistribution and use in source and binary forms, with or without
87698c759SSepherosa Ziehau  * modification, are permitted provided that the following conditions
97698c759SSepherosa Ziehau  * are met:
107698c759SSepherosa Ziehau  *
117698c759SSepherosa Ziehau  * 1. Redistributions of source code must retain the above copyright
127698c759SSepherosa Ziehau  *    notice, this list of conditions and the following disclaimer.
137698c759SSepherosa Ziehau  * 2. Redistributions in binary form must reproduce the above copyright
147698c759SSepherosa Ziehau  *    notice, this list of conditions and the following disclaimer in
157698c759SSepherosa Ziehau  *    the documentation and/or other materials provided with the
167698c759SSepherosa Ziehau  *    distribution.
177698c759SSepherosa Ziehau  * 3. Neither the name of The DragonFly Project nor the names of its
187698c759SSepherosa Ziehau  *    contributors may be used to endorse or promote products derived
197698c759SSepherosa Ziehau  *    from this software without specific, prior written permission.
207698c759SSepherosa Ziehau  *
217698c759SSepherosa Ziehau  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
227698c759SSepherosa Ziehau  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
237698c759SSepherosa Ziehau  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
247698c759SSepherosa Ziehau  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
257698c759SSepherosa Ziehau  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
267698c759SSepherosa Ziehau  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
277698c759SSepherosa Ziehau  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
287698c759SSepherosa Ziehau  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
297698c759SSepherosa Ziehau  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
307698c759SSepherosa Ziehau  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
317698c759SSepherosa Ziehau  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
327698c759SSepherosa Ziehau  * SUCH DAMAGE.
337698c759SSepherosa Ziehau  */
347698c759SSepherosa Ziehau 
357698c759SSepherosa Ziehau #include <sys/param.h>
367698c759SSepherosa Ziehau #include <sys/systm.h>
377698c759SSepherosa Ziehau #include <sys/bitops.h>
387698c759SSepherosa Ziehau #include <sys/bus.h>
39*7769f1bbSSepherosa Ziehau #include <sys/cpu_topology.h>
407698c759SSepherosa Ziehau #include <sys/kernel.h>
417698c759SSepherosa Ziehau #include <sys/malloc.h>
427698c759SSepherosa Ziehau #include <sys/sensors.h>
437698c759SSepherosa Ziehau #include <sys/sysctl.h>
447698c759SSepherosa Ziehau 
457698c759SSepherosa Ziehau #include <bus/pci/pcivar.h>
467698c759SSepherosa Ziehau #include <bus/pci/pcireg.h>
477698c759SSepherosa Ziehau #include <bus/pci/pci_cfgreg.h>
487698c759SSepherosa Ziehau #include <bus/pci/pcib_private.h>
497698c759SSepherosa Ziehau 
507698c759SSepherosa Ziehau #include "pcib_if.h"
517698c759SSepherosa Ziehau 
52881f7bffSSepherosa Ziehau #include <dev/misc/dimm/dimm.h>
530c543cddSSepherosa Ziehau #include <dev/misc/ecc/e5_imc_reg.h>
540c543cddSSepherosa Ziehau #include <dev/misc/ecc/e5_imc_var.h>
557698c759SSepherosa Ziehau 
56254817bdSSepherosa Ziehau #define MEMTEMP_E5_DIMM_TEMP_HIWAT	85	/* spec default TEMPLO */
57254817bdSSepherosa Ziehau #define MEMTEMP_E5_DIMM_TEMP_STEP	5	/* spec TEMPLO/MID/HI step */
58254817bdSSepherosa Ziehau 
597698c759SSepherosa Ziehau struct memtemp_e5_softc;
607698c759SSepherosa Ziehau 
617698c759SSepherosa Ziehau struct memtemp_e5_dimm {
627698c759SSepherosa Ziehau 	TAILQ_ENTRY(memtemp_e5_dimm)	dimm_link;
637698c759SSepherosa Ziehau 	struct ksensor			dimm_sensor;
647698c759SSepherosa Ziehau 	struct memtemp_e5_softc		*dimm_parent;
657698c759SSepherosa Ziehau 	int				dimm_id;
66254817bdSSepherosa Ziehau 	int				dimm_flags;
67881f7bffSSepherosa Ziehau 
68881f7bffSSepherosa Ziehau 	struct dimm_softc		*dimm_softc;
69*7769f1bbSSepherosa Ziehau 	struct sensor_task		*dimm_senstask;
707698c759SSepherosa Ziehau };
717698c759SSepherosa Ziehau 
72254817bdSSepherosa Ziehau #define MEMTEMP_E5_DIMM_FLAG_CRIT	0x1
73254817bdSSepherosa Ziehau 
747698c759SSepherosa Ziehau struct memtemp_e5_softc {
757698c759SSepherosa Ziehau 	device_t			temp_dev;
760c543cddSSepherosa Ziehau 	const struct e5_imc_chan	*temp_chan;
777698c759SSepherosa Ziehau 	int				temp_node;
787698c759SSepherosa Ziehau 	TAILQ_HEAD(, memtemp_e5_dimm)	temp_dimm;
797698c759SSepherosa Ziehau };
807698c759SSepherosa Ziehau 
817698c759SSepherosa Ziehau static int	memtemp_e5_probe(device_t);
827698c759SSepherosa Ziehau static int	memtemp_e5_attach(device_t);
837698c759SSepherosa Ziehau static int	memtemp_e5_detach(device_t);
847698c759SSepherosa Ziehau 
85254817bdSSepherosa Ziehau static int	memtemp_e5_tempth_adjust(int);
86254817bdSSepherosa Ziehau static void	memtemp_e5_tempth_str(int, char *, int);
877698c759SSepherosa Ziehau static void	memtemp_e5_sensor_task(void *);
887698c759SSepherosa Ziehau 
890c543cddSSepherosa Ziehau #define MEMTEMP_E5_CHAN(v, imc, c, c_ext)			\
907698c759SSepherosa Ziehau {								\
910c543cddSSepherosa Ziehau 	.did		= PCI_E5V##v##_IMC##imc##_THERMAL_CHN##c##_DID_ID, \
920c543cddSSepherosa Ziehau 	.slot		= PCISLOT_E5V##v##_IMC##imc##_THERMAL_CHN##c, \
930c543cddSSepherosa Ziehau 	.func		= PCIFUNC_E5V##v##_IMC##imc##_THERMAL_CHN##c, \
940c543cddSSepherosa Ziehau 	.desc		= "Intel E5 v" #v " memory thermal sensor", \
950c543cddSSepherosa Ziehau 								\
960c543cddSSepherosa Ziehau 	E5_IMC_CHAN_FIELDS(v, imc, c, c_ext)			\
977698c759SSepherosa Ziehau }
987698c759SSepherosa Ziehau 
990c543cddSSepherosa Ziehau #define MEMTEMP_E5_CHAN_V2(c)		MEMTEMP_E5_CHAN(2, 0, c, c)
100acbc630dSSepherosa Ziehau #define MEMTEMP_E5_CHAN_IMC0_V3(c)	MEMTEMP_E5_CHAN(3, 0, c, c)
101acbc630dSSepherosa Ziehau #define MEMTEMP_E5_CHAN_IMC1_V3(c, c_ext) \
102acbc630dSSepherosa Ziehau 					MEMTEMP_E5_CHAN(3, 1, c, c_ext)
1030c543cddSSepherosa Ziehau #define MEMTEMP_E5_CHAN_END		E5_IMC_CHAN_END
1047698c759SSepherosa Ziehau 
1050c543cddSSepherosa Ziehau static const struct e5_imc_chan memtemp_e5_chans[] = {
1060c543cddSSepherosa Ziehau 	MEMTEMP_E5_CHAN_V2(0),
1070c543cddSSepherosa Ziehau 	MEMTEMP_E5_CHAN_V2(1),
1080c543cddSSepherosa Ziehau 	MEMTEMP_E5_CHAN_V2(2),
1090c543cddSSepherosa Ziehau 	MEMTEMP_E5_CHAN_V2(3),
1107698c759SSepherosa Ziehau 
111acbc630dSSepherosa Ziehau 	MEMTEMP_E5_CHAN_IMC0_V3(0),
112acbc630dSSepherosa Ziehau 	MEMTEMP_E5_CHAN_IMC0_V3(1),
113acbc630dSSepherosa Ziehau 	MEMTEMP_E5_CHAN_IMC0_V3(2),
114acbc630dSSepherosa Ziehau 	MEMTEMP_E5_CHAN_IMC0_V3(3),
115acbc630dSSepherosa Ziehau 	MEMTEMP_E5_CHAN_IMC1_V3(0, 2),	/* IMC1 chan0 -> channel2 */
116acbc630dSSepherosa Ziehau 	MEMTEMP_E5_CHAN_IMC1_V3(1, 3),	/* IMC1 chan1 -> channel3 */
117acbc630dSSepherosa Ziehau 
1180c543cddSSepherosa Ziehau 	MEMTEMP_E5_CHAN_END
1197698c759SSepherosa Ziehau };
1207698c759SSepherosa Ziehau 
1210c543cddSSepherosa Ziehau #undef MEMTEMP_E5_CHAN_END
1220c543cddSSepherosa Ziehau #undef MEMTEMP_E5_CHAN_V2
1230c543cddSSepherosa Ziehau #undef MEMTEMP_E5_CHAN
1247698c759SSepherosa Ziehau 
1257698c759SSepherosa Ziehau static device_method_t memtemp_e5_methods[] = {
1267698c759SSepherosa Ziehau 	/* Device interface */
1277698c759SSepherosa Ziehau 	DEVMETHOD(device_probe,		memtemp_e5_probe),
1287698c759SSepherosa Ziehau 	DEVMETHOD(device_attach,	memtemp_e5_attach),
1297698c759SSepherosa Ziehau 	DEVMETHOD(device_detach,	memtemp_e5_detach),
1307698c759SSepherosa Ziehau 	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
1317698c759SSepherosa Ziehau 	DEVMETHOD(device_suspend,	bus_generic_suspend),
1327698c759SSepherosa Ziehau 	DEVMETHOD(device_resume,	bus_generic_resume),
1337698c759SSepherosa Ziehau 	DEVMETHOD_END
1347698c759SSepherosa Ziehau };
1357698c759SSepherosa Ziehau 
1367698c759SSepherosa Ziehau static driver_t memtemp_e5_driver = {
1377698c759SSepherosa Ziehau 	"memtemp",
1387698c759SSepherosa Ziehau 	memtemp_e5_methods,
1397698c759SSepherosa Ziehau 	sizeof(struct memtemp_e5_softc)
1407698c759SSepherosa Ziehau };
1417698c759SSepherosa Ziehau static devclass_t memtemp_devclass;
1427698c759SSepherosa Ziehau DRIVER_MODULE(memtemp_e5, pci, memtemp_e5_driver, memtemp_devclass, NULL, NULL);
1437698c759SSepherosa Ziehau MODULE_DEPEND(memtemp_e5, pci, 1, 1, 1);
144881f7bffSSepherosa Ziehau MODULE_DEPEND(memtemp_e5, dimm, 1, 1, 1);
1457698c759SSepherosa Ziehau 
1467698c759SSepherosa Ziehau static int
memtemp_e5_probe(device_t dev)1477698c759SSepherosa Ziehau memtemp_e5_probe(device_t dev)
1487698c759SSepherosa Ziehau {
1490c543cddSSepherosa Ziehau 	const struct e5_imc_chan *c;
1507698c759SSepherosa Ziehau 	uint16_t vid, did;
1517698c759SSepherosa Ziehau 	int slot, func;
1527698c759SSepherosa Ziehau 
1537698c759SSepherosa Ziehau 	vid = pci_get_vendor(dev);
1540c543cddSSepherosa Ziehau 	if (vid != PCI_E5_IMC_VID_ID)
1557698c759SSepherosa Ziehau 		return ENXIO;
1567698c759SSepherosa Ziehau 
1577698c759SSepherosa Ziehau 	did = pci_get_device(dev);
1587698c759SSepherosa Ziehau 	slot = pci_get_slot(dev);
1597698c759SSepherosa Ziehau 	func = pci_get_function(dev);
1607698c759SSepherosa Ziehau 
1610c543cddSSepherosa Ziehau 	for (c = memtemp_e5_chans; c->desc != NULL; ++c) {
1620c543cddSSepherosa Ziehau 		if (c->did == did && c->slot == slot && c->func == func) {
1637698c759SSepherosa Ziehau 			struct memtemp_e5_softc *sc = device_get_softc(dev);
1646682d8f0SSepherosa Ziehau 			uint32_t cfg;
1650c543cddSSepherosa Ziehau 			int node;
1667698c759SSepherosa Ziehau 
1670c543cddSSepherosa Ziehau 			node = e5_imc_node_probe(dev, c);
1680c543cddSSepherosa Ziehau 			if (node < 0)
1697698c759SSepherosa Ziehau 				break;
1707698c759SSepherosa Ziehau 
1716682d8f0SSepherosa Ziehau 			/*
1726682d8f0SSepherosa Ziehau 			 * XXX
1736682d8f0SSepherosa Ziehau 			 * It seems that memory thermal sensor is available,
1746682d8f0SSepherosa Ziehau 			 * only if CLTT is set (OLTT_EN does not seem matter).
1756682d8f0SSepherosa Ziehau 			 */
1766682d8f0SSepherosa Ziehau 			cfg = pci_read_config(dev,
1776682d8f0SSepherosa Ziehau 			    PCI_E5_IMC_THERMAL_CHN_TEMP_CFG, 4);
1786682d8f0SSepherosa Ziehau 			if ((cfg & PCI_E5_IMC_THERMAL_CHN_TEMP_CFG_CLTT) == 0)
1796682d8f0SSepherosa Ziehau 				break;
1806682d8f0SSepherosa Ziehau 
181881f7bffSSepherosa Ziehau 			device_set_desc(dev, c->desc);
1827698c759SSepherosa Ziehau 
1830c543cddSSepherosa Ziehau 			sc->temp_chan = c;
1847698c759SSepherosa Ziehau 			sc->temp_node = node;
1857698c759SSepherosa Ziehau 
1867698c759SSepherosa Ziehau 			return 0;
1877698c759SSepherosa Ziehau 		}
1887698c759SSepherosa Ziehau 	}
1897698c759SSepherosa Ziehau 	return ENXIO;
1907698c759SSepherosa Ziehau }
1917698c759SSepherosa Ziehau 
1927698c759SSepherosa Ziehau static int
memtemp_e5_tempth_adjust(int temp)193254817bdSSepherosa Ziehau memtemp_e5_tempth_adjust(int temp)
194254817bdSSepherosa Ziehau {
195254817bdSSepherosa Ziehau 	if (temp == PCI_E5_IMC_THERMAL_DIMM_TEMP_TH_DISABLE)
196254817bdSSepherosa Ziehau 		return 0;
197254817bdSSepherosa Ziehau 	else if (temp < PCI_E5_IMC_THERMAL_DIMM_TEMP_TH_TEMPMIN ||
198254817bdSSepherosa Ziehau 	    temp >= PCI_E5_IMC_THERMAL_DIMM_TEMP_TH_TEMPMAX)
199254817bdSSepherosa Ziehau 		return -1;
200254817bdSSepherosa Ziehau 	return temp;
201254817bdSSepherosa Ziehau }
202254817bdSSepherosa Ziehau 
203254817bdSSepherosa Ziehau static void
memtemp_e5_tempth_str(int temp,char * temp_str,int temp_strlen)204254817bdSSepherosa Ziehau memtemp_e5_tempth_str(int temp, char *temp_str, int temp_strlen)
205254817bdSSepherosa Ziehau {
206254817bdSSepherosa Ziehau 	if (temp < 0)
207254817bdSSepherosa Ziehau 		strlcpy(temp_str, "reserved", temp_strlen);
208254817bdSSepherosa Ziehau 	else if (temp == 0)
209254817bdSSepherosa Ziehau 		strlcpy(temp_str, "disabled", temp_strlen);
210254817bdSSepherosa Ziehau 	else
211254817bdSSepherosa Ziehau 		ksnprintf(temp_str, temp_strlen, "%dC", temp);
212254817bdSSepherosa Ziehau }
213254817bdSSepherosa Ziehau 
214254817bdSSepherosa Ziehau static int
memtemp_e5_attach(device_t dev)2157698c759SSepherosa Ziehau memtemp_e5_attach(device_t dev)
2167698c759SSepherosa Ziehau {
2177698c759SSepherosa Ziehau 	struct memtemp_e5_softc *sc = device_get_softc(dev);
218*7769f1bbSSepherosa Ziehau 	const cpu_node_t *node;
219*7769f1bbSSepherosa Ziehau 	int dimm, cpuid = -1;
2207698c759SSepherosa Ziehau 
2217698c759SSepherosa Ziehau 	sc->temp_dev = dev;
2227698c759SSepherosa Ziehau 	TAILQ_INIT(&sc->temp_dimm);
2237698c759SSepherosa Ziehau 
224*7769f1bbSSepherosa Ziehau 	node = get_cpu_node_by_chipid(sc->temp_node);
225*7769f1bbSSepherosa Ziehau 	if (node != NULL && node->child_no > 0) {
226*7769f1bbSSepherosa Ziehau 		cpuid = BSRCPUMASK(node->members);
227*7769f1bbSSepherosa Ziehau 		if (bootverbose) {
228*7769f1bbSSepherosa Ziehau 			device_printf(dev, "node%d chan%d -> cpu%d\n",
229*7769f1bbSSepherosa Ziehau 			    sc->temp_node, sc->temp_chan->chan_ext, cpuid);
230*7769f1bbSSepherosa Ziehau 		}
231*7769f1bbSSepherosa Ziehau 	}
232*7769f1bbSSepherosa Ziehau 
2330c543cddSSepherosa Ziehau 	for (dimm = 0; dimm < PCI_E5_IMC_CHN_DIMM_MAX; ++dimm) {
234254817bdSSepherosa Ziehau 		char temp_lostr[16], temp_midstr[16], temp_histr[16];
2357698c759SSepherosa Ziehau 		struct memtemp_e5_dimm *dimm_sc;
236881f7bffSSepherosa Ziehau 		int temp_lo, temp_mid, temp_hi;
237881f7bffSSepherosa Ziehau 		int temp_hiwat, temp_lowat, has_temp_thresh = 1;
238254817bdSSepherosa Ziehau 		uint32_t dimmmtr, temp_th;
239881f7bffSSepherosa Ziehau 		struct ksensor *sens;
2407698c759SSepherosa Ziehau 
241254817bdSSepherosa Ziehau 		dimmmtr = IMC_CTAD_READ_4(dev, sc->temp_chan,
2427698c759SSepherosa Ziehau 		    PCI_E5_IMC_CTAD_DIMMMTR(dimm));
2437698c759SSepherosa Ziehau 
2447698c759SSepherosa Ziehau 		if ((dimmmtr & PCI_E5_IMC_CTAD_DIMMMTR_DIMM_POP) == 0)
2457698c759SSepherosa Ziehau 			continue;
2467698c759SSepherosa Ziehau 
2477698c759SSepherosa Ziehau 		dimm_sc = kmalloc(sizeof(*dimm_sc), M_DEVBUF,
2487698c759SSepherosa Ziehau 		    M_WAITOK | M_ZERO);
2497698c759SSepherosa Ziehau 		dimm_sc->dimm_id = dimm;
2507698c759SSepherosa Ziehau 		dimm_sc->dimm_parent = sc;
251254817bdSSepherosa Ziehau 
252254817bdSSepherosa Ziehau 		temp_th = pci_read_config(dev,
253254817bdSSepherosa Ziehau 		    PCI_E5_IMC_THERMAL_DIMM_TEMP_TH(dimm), 4);
254254817bdSSepherosa Ziehau 
255254817bdSSepherosa Ziehau 		temp_lo = __SHIFTOUT(temp_th,
256254817bdSSepherosa Ziehau 		    PCI_E5_IMC_THERMAL_DIMM_TEMP_TH_TEMPLO);
257254817bdSSepherosa Ziehau 		temp_lo = memtemp_e5_tempth_adjust(temp_lo);
258254817bdSSepherosa Ziehau 		memtemp_e5_tempth_str(temp_lo, temp_lostr, sizeof(temp_lostr));
259254817bdSSepherosa Ziehau 
260254817bdSSepherosa Ziehau 		temp_mid = __SHIFTOUT(temp_th,
261254817bdSSepherosa Ziehau 		    PCI_E5_IMC_THERMAL_DIMM_TEMP_TH_TEMPMID);
262254817bdSSepherosa Ziehau 		temp_mid = memtemp_e5_tempth_adjust(temp_mid);
263254817bdSSepherosa Ziehau 		memtemp_e5_tempth_str(temp_mid, temp_midstr,
264254817bdSSepherosa Ziehau 		    sizeof(temp_midstr));
265254817bdSSepherosa Ziehau 
266254817bdSSepherosa Ziehau 		temp_hi = __SHIFTOUT(temp_th,
267254817bdSSepherosa Ziehau 		    PCI_E5_IMC_THERMAL_DIMM_TEMP_TH_TEMPHI);
268254817bdSSepherosa Ziehau 		temp_hi = memtemp_e5_tempth_adjust(temp_hi);
269254817bdSSepherosa Ziehau 		memtemp_e5_tempth_str(temp_hi, temp_histr, sizeof(temp_histr));
270254817bdSSepherosa Ziehau 
271254817bdSSepherosa Ziehau 		/*
272254817bdSSepherosa Ziehau 		 * NOTE:
273254817bdSSepherosa Ziehau 		 * - TEMPHI initiates THRTCRIT.
274254817bdSSepherosa Ziehau 		 * - TEMPMID initiates THRTHI, so it is also taken into
275254817bdSSepherosa Ziehau 		 *   consideration.
276254817bdSSepherosa Ziehau 		 * - Some BIOSes program temp_lo to a rediculous low value,
277254817bdSSepherosa Ziehau 		 *   so ignore TEMPLO here.
278254817bdSSepherosa Ziehau 		 */
279254817bdSSepherosa Ziehau 		if (temp_mid <= 0) {
280881f7bffSSepherosa Ziehau 			if (temp_hi <= 0) {
281881f7bffSSepherosa Ziehau 				temp_hiwat = MEMTEMP_E5_DIMM_TEMP_HIWAT;
282881f7bffSSepherosa Ziehau 				has_temp_thresh = 0;
283254817bdSSepherosa Ziehau 			} else {
284881f7bffSSepherosa Ziehau 				temp_hiwat = temp_hi;
285254817bdSSepherosa Ziehau 			}
286881f7bffSSepherosa Ziehau 		} else {
287881f7bffSSepherosa Ziehau 			temp_hiwat = temp_mid;
288881f7bffSSepherosa Ziehau 		}
289881f7bffSSepherosa Ziehau 		if (temp_hiwat < MEMTEMP_E5_DIMM_TEMP_STEP) {
290881f7bffSSepherosa Ziehau 			temp_hiwat = MEMTEMP_E5_DIMM_TEMP_HIWAT;
291881f7bffSSepherosa Ziehau 			has_temp_thresh = 0;
292881f7bffSSepherosa Ziehau 		}
293881f7bffSSepherosa Ziehau 		temp_lowat = temp_hiwat - MEMTEMP_E5_DIMM_TEMP_STEP;
294254817bdSSepherosa Ziehau 
295881f7bffSSepherosa Ziehau 		if (bootverbose) {
296254817bdSSepherosa Ziehau 			device_printf(dev, "DIMM%d "
297254817bdSSepherosa Ziehau 			    "temp_hi %s, temp_mid %s, temp_lo %s\n", dimm,
298254817bdSSepherosa Ziehau 			    temp_histr, temp_midstr, temp_lostr);
299881f7bffSSepherosa Ziehau 		}
30065c1e3ddSSepherosa Ziehau 
301881f7bffSSepherosa Ziehau 		dimm_sc->dimm_softc = dimm_create(sc->temp_node,
302881f7bffSSepherosa Ziehau 		    sc->temp_chan->chan_ext, dimm);
303881f7bffSSepherosa Ziehau 
304881f7bffSSepherosa Ziehau 		if (has_temp_thresh) {
305881f7bffSSepherosa Ziehau 			if (bootverbose) {
306881f7bffSSepherosa Ziehau 				device_printf(dev, "DIMM%d "
307881f7bffSSepherosa Ziehau 				    "hiwat %dC, lowat %dC\n",
308881f7bffSSepherosa Ziehau 				    dimm, temp_hiwat, temp_lowat);
309881f7bffSSepherosa Ziehau 			}
310881f7bffSSepherosa Ziehau 			dimm_set_temp_thresh(dimm_sc->dimm_softc,
311881f7bffSSepherosa Ziehau 			    temp_hiwat, temp_lowat);
312881f7bffSSepherosa Ziehau 		}
313881f7bffSSepherosa Ziehau 
314881f7bffSSepherosa Ziehau 		sens = &dimm_sc->dimm_sensor;
315881f7bffSSepherosa Ziehau 		ksnprintf(sens->desc, sizeof(sens->desc),
31614387d56SSepherosa Ziehau 		    "node%d chan%d DIMM%d temp",
317881f7bffSSepherosa Ziehau 		    sc->temp_node, sc->temp_chan->chan_ext, dimm);
318881f7bffSSepherosa Ziehau 		sens->type = SENSOR_TEMP;
3197273d7b8SSepherosa Ziehau 		sensor_set_unknown(sens);
320881f7bffSSepherosa Ziehau 		dimm_sensor_attach(dimm_sc->dimm_softc, sens);
321*7769f1bbSSepherosa Ziehau 		dimm_sc->dimm_senstask = sensor_task_register2(dimm_sc,
322*7769f1bbSSepherosa Ziehau 		    memtemp_e5_sensor_task, 5, cpuid);
32365c1e3ddSSepherosa Ziehau 
32465c1e3ddSSepherosa Ziehau 		TAILQ_INSERT_TAIL(&sc->temp_dimm, dimm_sc, dimm_link);
3257698c759SSepherosa Ziehau 	}
3267698c759SSepherosa Ziehau 	return 0;
3277698c759SSepherosa Ziehau }
3287698c759SSepherosa Ziehau 
3297698c759SSepherosa Ziehau static int
memtemp_e5_detach(device_t dev)3307698c759SSepherosa Ziehau memtemp_e5_detach(device_t dev)
3317698c759SSepherosa Ziehau {
3327698c759SSepherosa Ziehau 	struct memtemp_e5_softc *sc = device_get_softc(dev);
3337698c759SSepherosa Ziehau 	struct memtemp_e5_dimm *dimm_sc;
3347698c759SSepherosa Ziehau 
3357698c759SSepherosa Ziehau 	while ((dimm_sc = TAILQ_FIRST(&sc->temp_dimm)) != NULL) {
3367698c759SSepherosa Ziehau 		TAILQ_REMOVE(&sc->temp_dimm, dimm_sc, dimm_link);
3377698c759SSepherosa Ziehau 
338*7769f1bbSSepherosa Ziehau 		sensor_task_unregister2(dimm_sc->dimm_senstask);
339881f7bffSSepherosa Ziehau 		dimm_sensor_detach(dimm_sc->dimm_softc, &dimm_sc->dimm_sensor);
340881f7bffSSepherosa Ziehau 		dimm_destroy(dimm_sc->dimm_softc);
3417698c759SSepherosa Ziehau 
3427698c759SSepherosa Ziehau 		kfree(dimm_sc, M_DEVBUF);
3437698c759SSepherosa Ziehau 	}
3447698c759SSepherosa Ziehau 	return 0;
3457698c759SSepherosa Ziehau }
3467698c759SSepherosa Ziehau 
3477698c759SSepherosa Ziehau static void
memtemp_e5_sensor_task(void * xdimm_sc)3487698c759SSepherosa Ziehau memtemp_e5_sensor_task(void *xdimm_sc)
3497698c759SSepherosa Ziehau {
3507698c759SSepherosa Ziehau 	struct memtemp_e5_dimm *dimm_sc = xdimm_sc;
3517698c759SSepherosa Ziehau 	struct ksensor *sensor = &dimm_sc->dimm_sensor;
352254817bdSSepherosa Ziehau 	device_t dev = dimm_sc->dimm_parent->temp_dev;
3537698c759SSepherosa Ziehau 	uint32_t val;
354254817bdSSepherosa Ziehau 	int temp, reg;
3557698c759SSepherosa Ziehau 
356881f7bffSSepherosa Ziehau 	reg = PCI_E5_IMC_THERMAL_DIMMTEMPSTAT(dimm_sc->dimm_id);
357254817bdSSepherosa Ziehau 
358254817bdSSepherosa Ziehau 	val = pci_read_config(dev, reg, 4);
359254817bdSSepherosa Ziehau 	if (val & (PCI_E5_IMC_THERMAL_DIMMTEMPSTAT_TEMPHI |
360254817bdSSepherosa Ziehau 	    PCI_E5_IMC_THERMAL_DIMMTEMPSTAT_TEMPMID |
361254817bdSSepherosa Ziehau 	    PCI_E5_IMC_THERMAL_DIMMTEMPSTAT_TEMPLO))
362254817bdSSepherosa Ziehau 		pci_write_config(dev, reg, val, 4);
363254817bdSSepherosa Ziehau 
3647698c759SSepherosa Ziehau 	temp = __SHIFTOUT(val, PCI_E5_IMC_THERMAL_DIMMTEMPSTAT_TEMP);
365254817bdSSepherosa Ziehau 	if (temp < PCI_E5_IMC_THERMAL_DIMMTEMPSTAT_TEMPMIN ||
366254817bdSSepherosa Ziehau 	    temp >= PCI_E5_IMC_THERMAL_DIMMTEMPSTAT_TEMPMAX) {
367254817bdSSepherosa Ziehau 		sensor->status = SENSOR_S_UNSPEC;
368254817bdSSepherosa Ziehau 		sensor->flags |= SENSOR_FINVALID;
369254817bdSSepherosa Ziehau 		sensor->value = 0;
370254817bdSSepherosa Ziehau 		return;
371254817bdSSepherosa Ziehau 	}
372881f7bffSSepherosa Ziehau 	dimm_sensor_temp(dimm_sc->dimm_softc, sensor, temp);
3737698c759SSepherosa Ziehau }
374