xref: /dflybsd-src/sys/dev/powermng/memtemp/memtemp_e5.c (revision 7698c759b557c64a0a92f49f667c5ed160088e82)
1*7698c759SSepherosa Ziehau /*
2*7698c759SSepherosa Ziehau  * Copyright (c) 2015 The DragonFly Project.  All rights reserved.
3*7698c759SSepherosa Ziehau  *
4*7698c759SSepherosa Ziehau  * This code is derived from software contributed to The DragonFly Project
5*7698c759SSepherosa Ziehau  * by Sepherosa Ziehau <sepherosa@gmail.com>
6*7698c759SSepherosa Ziehau  *
7*7698c759SSepherosa Ziehau  * Redistribution and use in source and binary forms, with or without
8*7698c759SSepherosa Ziehau  * modification, are permitted provided that the following conditions
9*7698c759SSepherosa Ziehau  * are met:
10*7698c759SSepherosa Ziehau  *
11*7698c759SSepherosa Ziehau  * 1. Redistributions of source code must retain the above copyright
12*7698c759SSepherosa Ziehau  *    notice, this list of conditions and the following disclaimer.
13*7698c759SSepherosa Ziehau  * 2. Redistributions in binary form must reproduce the above copyright
14*7698c759SSepherosa Ziehau  *    notice, this list of conditions and the following disclaimer in
15*7698c759SSepherosa Ziehau  *    the documentation and/or other materials provided with the
16*7698c759SSepherosa Ziehau  *    distribution.
17*7698c759SSepherosa Ziehau  * 3. Neither the name of The DragonFly Project nor the names of its
18*7698c759SSepherosa Ziehau  *    contributors may be used to endorse or promote products derived
19*7698c759SSepherosa Ziehau  *    from this software without specific, prior written permission.
20*7698c759SSepherosa Ziehau  *
21*7698c759SSepherosa Ziehau  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22*7698c759SSepherosa Ziehau  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23*7698c759SSepherosa Ziehau  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24*7698c759SSepherosa Ziehau  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25*7698c759SSepherosa Ziehau  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26*7698c759SSepherosa Ziehau  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27*7698c759SSepherosa Ziehau  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28*7698c759SSepherosa Ziehau  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29*7698c759SSepherosa Ziehau  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30*7698c759SSepherosa Ziehau  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31*7698c759SSepherosa Ziehau  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32*7698c759SSepherosa Ziehau  * SUCH DAMAGE.
33*7698c759SSepherosa Ziehau  */
34*7698c759SSepherosa Ziehau 
35*7698c759SSepherosa Ziehau #include <sys/param.h>
36*7698c759SSepherosa Ziehau #include <sys/systm.h>
37*7698c759SSepherosa Ziehau #include <sys/bitops.h>
38*7698c759SSepherosa Ziehau #include <sys/bus.h>
39*7698c759SSepherosa Ziehau #include <sys/kernel.h>
40*7698c759SSepherosa Ziehau #include <sys/malloc.h>
41*7698c759SSepherosa Ziehau #include <sys/sensors.h>
42*7698c759SSepherosa Ziehau #include <sys/sysctl.h>
43*7698c759SSepherosa Ziehau 
44*7698c759SSepherosa Ziehau #include <bus/pci/pcivar.h>
45*7698c759SSepherosa Ziehau #include <bus/pci/pcireg.h>
46*7698c759SSepherosa Ziehau #include <bus/pci/pcibus.h>
47*7698c759SSepherosa Ziehau #include <bus/pci/pci_cfgreg.h>
48*7698c759SSepherosa Ziehau #include <bus/pci/pcib_private.h>
49*7698c759SSepherosa Ziehau 
50*7698c759SSepherosa Ziehau #include "pcib_if.h"
51*7698c759SSepherosa Ziehau 
52*7698c759SSepherosa Ziehau #include <dev/misc/ecc/ecc_e5_reg.h>
53*7698c759SSepherosa Ziehau 
54*7698c759SSepherosa Ziehau #define UBOX_READ(dev, ofs, w)				\
55*7698c759SSepherosa Ziehau 	pcib_read_config((dev), pci_get_bus((dev)),	\
56*7698c759SSepherosa Ziehau 	    PCISLOT_E5_UBOX0, PCIFUNC_E5_UBOX0, (ofs), w)
57*7698c759SSepherosa Ziehau #define UBOX_READ_2(dev, ofs)		UBOX_READ((dev), (ofs), 2)
58*7698c759SSepherosa Ziehau #define UBOX_READ_4(dev, ofs)		UBOX_READ((dev), (ofs), 4)
59*7698c759SSepherosa Ziehau 
60*7698c759SSepherosa Ziehau #define IMC_CPGC_READ(dev, ofs, w)			\
61*7698c759SSepherosa Ziehau 	pcib_read_config((dev), pci_get_bus((dev)),	\
62*7698c759SSepherosa Ziehau 	    PCISLOT_E5_IMC_CPGC, PCIFUNC_E5_IMC_CPGC, (ofs), w)
63*7698c759SSepherosa Ziehau #define IMC_CPGC_READ_2(dev, ofs)	IMC_CPGC_READ((dev), (ofs), 2)
64*7698c759SSepherosa Ziehau #define IMC_CPGC_READ_4(dev, ofs)	IMC_CPGC_READ((dev), (ofs), 4)
65*7698c759SSepherosa Ziehau 
66*7698c759SSepherosa Ziehau #define IMC_CTAD_READ(dev, c, ofs, w)			\
67*7698c759SSepherosa Ziehau 	pcib_read_config((dev), pci_get_bus((dev)),	\
68*7698c759SSepherosa Ziehau 	    PCISLOT_E5_IMC_CTAD, PCIFUNC_E5_IMC_CTAD((c)), (ofs), w)
69*7698c759SSepherosa Ziehau #define IMC_CTAD_READ_2(dev, c, ofs)	IMC_CTAD_READ((dev), (c), (ofs), 2)
70*7698c759SSepherosa Ziehau #define IMC_CTAD_READ_4(dev, c, ofs)	IMC_CTAD_READ((dev), (c), (ofs), 4)
71*7698c759SSepherosa Ziehau 
72*7698c759SSepherosa Ziehau struct memtemp_e5_type {
73*7698c759SSepherosa Ziehau 	uint16_t	did;
74*7698c759SSepherosa Ziehau 	int		slot;
75*7698c759SSepherosa Ziehau 	int		func;
76*7698c759SSepherosa Ziehau 	int		chan;
77*7698c759SSepherosa Ziehau 	const char	*desc;
78*7698c759SSepherosa Ziehau };
79*7698c759SSepherosa Ziehau 
80*7698c759SSepherosa Ziehau struct memtemp_e5_softc;
81*7698c759SSepherosa Ziehau 
82*7698c759SSepherosa Ziehau struct memtemp_e5_dimm {
83*7698c759SSepherosa Ziehau 	TAILQ_ENTRY(memtemp_e5_dimm) dimm_link;
84*7698c759SSepherosa Ziehau 	struct ksensordev	dimm_sensordev;
85*7698c759SSepherosa Ziehau 	struct ksensor		dimm_sensor;
86*7698c759SSepherosa Ziehau 	struct memtemp_e5_softc	*dimm_parent;
87*7698c759SSepherosa Ziehau 	int			dimm_id;
88*7698c759SSepherosa Ziehau 	int			dimm_extid;
89*7698c759SSepherosa Ziehau };
90*7698c759SSepherosa Ziehau 
91*7698c759SSepherosa Ziehau struct memtemp_e5_softc {
92*7698c759SSepherosa Ziehau 	device_t		temp_dev;
93*7698c759SSepherosa Ziehau 	int			temp_chan;
94*7698c759SSepherosa Ziehau 	int			temp_node;
95*7698c759SSepherosa Ziehau 	TAILQ_HEAD(, memtemp_e5_dimm) temp_dimm;
96*7698c759SSepherosa Ziehau };
97*7698c759SSepherosa Ziehau 
98*7698c759SSepherosa Ziehau static int	memtemp_e5_probe(device_t);
99*7698c759SSepherosa Ziehau static int	memtemp_e5_attach(device_t);
100*7698c759SSepherosa Ziehau static int	memtemp_e5_detach(device_t);
101*7698c759SSepherosa Ziehau 
102*7698c759SSepherosa Ziehau static void	memtemp_e5_sensor_task(void *);
103*7698c759SSepherosa Ziehau 
104*7698c759SSepherosa Ziehau #define MEMTEMP_E5_TYPE_V2(c) \
105*7698c759SSepherosa Ziehau { \
106*7698c759SSepherosa Ziehau 	.did	= PCI_E5_IMC_THERMAL_CHN##c##_DID_ID, \
107*7698c759SSepherosa Ziehau 	.slot	= PCISLOT_E5_IMC_THERMAL, \
108*7698c759SSepherosa Ziehau 	.func	= PCIFUNC_E5_IMC_THERMAL_CHN##c, \
109*7698c759SSepherosa Ziehau 	.chan	= c, \
110*7698c759SSepherosa Ziehau 	.desc	= "Intel E5 v2 memory thermal sensor" \
111*7698c759SSepherosa Ziehau }
112*7698c759SSepherosa Ziehau 
113*7698c759SSepherosa Ziehau #define MEMTEMP_E5_TYPE_END		{ 0, 0, 0, 0, NULL }
114*7698c759SSepherosa Ziehau 
115*7698c759SSepherosa Ziehau static const struct memtemp_e5_type memtemp_types[] = {
116*7698c759SSepherosa Ziehau 	MEMTEMP_E5_TYPE_V2(0),
117*7698c759SSepherosa Ziehau 	MEMTEMP_E5_TYPE_V2(1),
118*7698c759SSepherosa Ziehau 	MEMTEMP_E5_TYPE_V2(2),
119*7698c759SSepherosa Ziehau 	MEMTEMP_E5_TYPE_V2(3),
120*7698c759SSepherosa Ziehau 
121*7698c759SSepherosa Ziehau 	MEMTEMP_E5_TYPE_END
122*7698c759SSepherosa Ziehau };
123*7698c759SSepherosa Ziehau 
124*7698c759SSepherosa Ziehau #undef MEMTEMP_E5_TYPE_V2
125*7698c759SSepherosa Ziehau #undef MEMTEMP_E5_TYPE_END
126*7698c759SSepherosa Ziehau 
127*7698c759SSepherosa Ziehau static device_method_t memtemp_e5_methods[] = {
128*7698c759SSepherosa Ziehau 	/* Device interface */
129*7698c759SSepherosa Ziehau 	DEVMETHOD(device_probe,		memtemp_e5_probe),
130*7698c759SSepherosa Ziehau 	DEVMETHOD(device_attach,	memtemp_e5_attach),
131*7698c759SSepherosa Ziehau 	DEVMETHOD(device_detach,	memtemp_e5_detach),
132*7698c759SSepherosa Ziehau 	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
133*7698c759SSepherosa Ziehau 	DEVMETHOD(device_suspend,	bus_generic_suspend),
134*7698c759SSepherosa Ziehau 	DEVMETHOD(device_resume,	bus_generic_resume),
135*7698c759SSepherosa Ziehau 	DEVMETHOD_END
136*7698c759SSepherosa Ziehau };
137*7698c759SSepherosa Ziehau 
138*7698c759SSepherosa Ziehau static driver_t memtemp_e5_driver = {
139*7698c759SSepherosa Ziehau 	"memtemp",
140*7698c759SSepherosa Ziehau 	memtemp_e5_methods,
141*7698c759SSepherosa Ziehau 	sizeof(struct memtemp_e5_softc)
142*7698c759SSepherosa Ziehau };
143*7698c759SSepherosa Ziehau static devclass_t memtemp_devclass;
144*7698c759SSepherosa Ziehau DRIVER_MODULE(memtemp_e5, pci, memtemp_e5_driver, memtemp_devclass, NULL, NULL);
145*7698c759SSepherosa Ziehau MODULE_DEPEND(memtemp_e5, pci, 1, 1, 1);
146*7698c759SSepherosa Ziehau 
147*7698c759SSepherosa Ziehau static int
148*7698c759SSepherosa Ziehau memtemp_e5_probe(device_t dev)
149*7698c759SSepherosa Ziehau {
150*7698c759SSepherosa Ziehau 	const struct memtemp_e5_type *t;
151*7698c759SSepherosa Ziehau 	uint16_t vid, did;
152*7698c759SSepherosa Ziehau 	int slot, func;
153*7698c759SSepherosa Ziehau 
154*7698c759SSepherosa Ziehau 	vid = pci_get_vendor(dev);
155*7698c759SSepherosa Ziehau 	if (vid != PCI_E5_VID_ID)
156*7698c759SSepherosa Ziehau 		return ENXIO;
157*7698c759SSepherosa Ziehau 
158*7698c759SSepherosa Ziehau 	did = pci_get_device(dev);
159*7698c759SSepherosa Ziehau 	slot = pci_get_slot(dev);
160*7698c759SSepherosa Ziehau 	func = pci_get_function(dev);
161*7698c759SSepherosa Ziehau 
162*7698c759SSepherosa Ziehau 	for (t = memtemp_types; t->desc != NULL; ++t) {
163*7698c759SSepherosa Ziehau 		if (t->did == did && t->slot == slot && t->func == func) {
164*7698c759SSepherosa Ziehau 			struct memtemp_e5_softc *sc = device_get_softc(dev);
165*7698c759SSepherosa Ziehau 			char desc[128];
166*7698c759SSepherosa Ziehau 			uint32_t val;
167*7698c759SSepherosa Ziehau 			int node, dimm;
168*7698c759SSepherosa Ziehau 
169*7698c759SSepherosa Ziehau 			/* Check CPGC vid/did */
170*7698c759SSepherosa Ziehau 			if (IMC_CPGC_READ_2(dev, PCIR_VENDOR) !=
171*7698c759SSepherosa Ziehau 			    PCI_E5_VID_ID ||
172*7698c759SSepherosa Ziehau 			    IMC_CPGC_READ_2(dev, PCIR_DEVICE) !=
173*7698c759SSepherosa Ziehau 			    PCI_E5_IMC_CPGC_DID_ID)
174*7698c759SSepherosa Ziehau 				break;
175*7698c759SSepherosa Ziehau 
176*7698c759SSepherosa Ziehau 			/* Is this channel disabled */
177*7698c759SSepherosa Ziehau 			val = IMC_CPGC_READ_4(dev, PCI_E5_IMC_CPGC_MCMTR);
178*7698c759SSepherosa Ziehau 			if (val & PCI_E5_IMC_CPGC_MCMTR_CHN_DISABLE(t->chan))
179*7698c759SSepherosa Ziehau 				break;
180*7698c759SSepherosa Ziehau 
181*7698c759SSepherosa Ziehau 			/* Check CTAD vid/did */
182*7698c759SSepherosa Ziehau 			if (IMC_CTAD_READ_2(dev, t->chan, PCIR_VENDOR) !=
183*7698c759SSepherosa Ziehau 			    PCI_E5_VID_ID ||
184*7698c759SSepherosa Ziehau 			    IMC_CTAD_READ_2(dev, t->chan, PCIR_DEVICE) !=
185*7698c759SSepherosa Ziehau 			    PCI_E5_IMC_CTAD_DID_ID(t->chan))
186*7698c759SSepherosa Ziehau 				break;
187*7698c759SSepherosa Ziehau 
188*7698c759SSepherosa Ziehau 			/* Are there any DIMMs populated? */
189*7698c759SSepherosa Ziehau 			for (dimm = 0; dimm < PCI_E5_IMC_DIMM_MAX; ++dimm) {
190*7698c759SSepherosa Ziehau 				val = IMC_CTAD_READ_4(dev, t->chan,
191*7698c759SSepherosa Ziehau 				    PCI_E5_IMC_CTAD_DIMMMTR(dimm));
192*7698c759SSepherosa Ziehau 				if (val & PCI_E5_IMC_CTAD_DIMMMTR_DIMM_POP)
193*7698c759SSepherosa Ziehau 					break;
194*7698c759SSepherosa Ziehau 			}
195*7698c759SSepherosa Ziehau 			if (dimm == PCI_E5_IMC_DIMM_MAX)
196*7698c759SSepherosa Ziehau 				break;
197*7698c759SSepherosa Ziehau 
198*7698c759SSepherosa Ziehau 			/* Check UBOX vid/did */
199*7698c759SSepherosa Ziehau 			if (UBOX_READ_2(dev, PCIR_VENDOR) != PCI_E5_VID_ID ||
200*7698c759SSepherosa Ziehau 			    UBOX_READ_2(dev, PCIR_DEVICE) !=
201*7698c759SSepherosa Ziehau 			    PCI_E5_UBOX0_DID_ID)
202*7698c759SSepherosa Ziehau 				break;
203*7698c759SSepherosa Ziehau 
204*7698c759SSepherosa Ziehau 			val = UBOX_READ_4(dev, PCI_E5_UBOX0_CPUNODEID);
205*7698c759SSepherosa Ziehau 			node = __SHIFTOUT(val,
206*7698c759SSepherosa Ziehau 			    PCI_E5_UBOX0_CPUNODEID_LCLNODEID);
207*7698c759SSepherosa Ziehau 
208*7698c759SSepherosa Ziehau 			ksnprintf(desc, sizeof(desc), "%s node%d channel%d",
209*7698c759SSepherosa Ziehau 			    t->desc, node, t->chan);
210*7698c759SSepherosa Ziehau 			device_set_desc_copy(dev, desc);
211*7698c759SSepherosa Ziehau 
212*7698c759SSepherosa Ziehau 			sc->temp_chan = t->chan;
213*7698c759SSepherosa Ziehau 			sc->temp_node = node;
214*7698c759SSepherosa Ziehau 
215*7698c759SSepherosa Ziehau 			return 0;
216*7698c759SSepherosa Ziehau 		}
217*7698c759SSepherosa Ziehau 	}
218*7698c759SSepherosa Ziehau 	return ENXIO;
219*7698c759SSepherosa Ziehau }
220*7698c759SSepherosa Ziehau 
221*7698c759SSepherosa Ziehau static int
222*7698c759SSepherosa Ziehau memtemp_e5_attach(device_t dev)
223*7698c759SSepherosa Ziehau {
224*7698c759SSepherosa Ziehau 	struct memtemp_e5_softc *sc = device_get_softc(dev);
225*7698c759SSepherosa Ziehau 	int dimm;
226*7698c759SSepherosa Ziehau 
227*7698c759SSepherosa Ziehau 	sc->temp_dev = dev;
228*7698c759SSepherosa Ziehau 	TAILQ_INIT(&sc->temp_dimm);
229*7698c759SSepherosa Ziehau 
230*7698c759SSepherosa Ziehau 	for (dimm = 0; dimm < PCI_E5_IMC_DIMM_MAX; ++dimm) {
231*7698c759SSepherosa Ziehau 		struct memtemp_e5_dimm *dimm_sc;
232*7698c759SSepherosa Ziehau 		uint32_t dimmmtr;
233*7698c759SSepherosa Ziehau 
234*7698c759SSepherosa Ziehau 		dimmmtr = IMC_CTAD_READ_4(sc->temp_dev, sc->temp_chan,
235*7698c759SSepherosa Ziehau 		    PCI_E5_IMC_CTAD_DIMMMTR(dimm));
236*7698c759SSepherosa Ziehau 
237*7698c759SSepherosa Ziehau 		if ((dimmmtr & PCI_E5_IMC_CTAD_DIMMMTR_DIMM_POP) == 0)
238*7698c759SSepherosa Ziehau 			continue;
239*7698c759SSepherosa Ziehau 
240*7698c759SSepherosa Ziehau 		dimm_sc = kmalloc(sizeof(*dimm_sc), M_DEVBUF,
241*7698c759SSepherosa Ziehau 		    M_WAITOK | M_ZERO);
242*7698c759SSepherosa Ziehau 		dimm_sc->dimm_id = dimm;
243*7698c759SSepherosa Ziehau 		dimm_sc->dimm_parent = sc;
244*7698c759SSepherosa Ziehau 		dimm_sc->dimm_extid =
245*7698c759SSepherosa Ziehau 		    (sc->temp_node * PCI_E5_IMC_CHN_MAX * PCI_E5_IMC_DIMM_MAX) +
246*7698c759SSepherosa Ziehau 		    (sc->temp_chan * PCI_E5_IMC_DIMM_MAX) + dimm;
247*7698c759SSepherosa Ziehau 
248*7698c759SSepherosa Ziehau 		ksnprintf(dimm_sc->dimm_sensordev.xname,
249*7698c759SSepherosa Ziehau 		    sizeof(dimm_sc->dimm_sensordev.xname),
250*7698c759SSepherosa Ziehau 		    "dimm%d", dimm_sc->dimm_extid);
251*7698c759SSepherosa Ziehau 		dimm_sc->dimm_sensor.type = SENSOR_TEMP;
252*7698c759SSepherosa Ziehau 		sensor_attach(&dimm_sc->dimm_sensordev, &dimm_sc->dimm_sensor);
253*7698c759SSepherosa Ziehau 		if (sensor_task_register(dimm_sc, memtemp_e5_sensor_task, 2)) {
254*7698c759SSepherosa Ziehau 			device_printf(sc->temp_dev, "DIMM%d sensor task "
255*7698c759SSepherosa Ziehau 			    "register failed\n", dimm);
256*7698c759SSepherosa Ziehau 			kfree(dimm_sc, M_DEVBUF);
257*7698c759SSepherosa Ziehau 			continue;
258*7698c759SSepherosa Ziehau 		}
259*7698c759SSepherosa Ziehau 		sensordev_install(&dimm_sc->dimm_sensordev);
260*7698c759SSepherosa Ziehau 
261*7698c759SSepherosa Ziehau 		TAILQ_INSERT_TAIL(&sc->temp_dimm, dimm_sc, dimm_link);
262*7698c759SSepherosa Ziehau 	}
263*7698c759SSepherosa Ziehau 	return 0;
264*7698c759SSepherosa Ziehau }
265*7698c759SSepherosa Ziehau 
266*7698c759SSepherosa Ziehau static int
267*7698c759SSepherosa Ziehau memtemp_e5_detach(device_t dev)
268*7698c759SSepherosa Ziehau {
269*7698c759SSepherosa Ziehau 	struct memtemp_e5_softc *sc = device_get_softc(dev);
270*7698c759SSepherosa Ziehau 	struct memtemp_e5_dimm *dimm_sc;
271*7698c759SSepherosa Ziehau 
272*7698c759SSepherosa Ziehau 	while ((dimm_sc = TAILQ_FIRST(&sc->temp_dimm)) != NULL) {
273*7698c759SSepherosa Ziehau 		TAILQ_REMOVE(&sc->temp_dimm, dimm_sc, dimm_link);
274*7698c759SSepherosa Ziehau 
275*7698c759SSepherosa Ziehau 		sensordev_deinstall(&dimm_sc->dimm_sensordev);
276*7698c759SSepherosa Ziehau 		sensor_task_unregister(dimm_sc);
277*7698c759SSepherosa Ziehau 
278*7698c759SSepherosa Ziehau 		kfree(dimm_sc, M_DEVBUF);
279*7698c759SSepherosa Ziehau 	}
280*7698c759SSepherosa Ziehau 	return 0;
281*7698c759SSepherosa Ziehau }
282*7698c759SSepherosa Ziehau 
283*7698c759SSepherosa Ziehau static void
284*7698c759SSepherosa Ziehau memtemp_e5_sensor_task(void *xdimm_sc)
285*7698c759SSepherosa Ziehau {
286*7698c759SSepherosa Ziehau 	struct memtemp_e5_dimm *dimm_sc = xdimm_sc;
287*7698c759SSepherosa Ziehau 	struct ksensor *sensor = &dimm_sc->dimm_sensor;
288*7698c759SSepherosa Ziehau 	uint32_t val;
289*7698c759SSepherosa Ziehau 	int temp;
290*7698c759SSepherosa Ziehau 
291*7698c759SSepherosa Ziehau 	val = pci_read_config(dimm_sc->dimm_parent->temp_dev,
292*7698c759SSepherosa Ziehau 	    PCI_E5_IMC_THERMAL_DIMMTEMPSTAT(dimm_sc->dimm_id), 4);
293*7698c759SSepherosa Ziehau 	temp = __SHIFTOUT(val, PCI_E5_IMC_THERMAL_DIMMTEMPSTAT_TEMP);
294*7698c759SSepherosa Ziehau 
295*7698c759SSepherosa Ziehau 	sensor->flags &= ~SENSOR_FINVALID;
296*7698c759SSepherosa Ziehau 	sensor->value = (temp * 1000000) + 273150000;
297*7698c759SSepherosa Ziehau }
298