]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/amdtemp/amdtemp.c
Remove unused and easy to misuse PNP macro parameter
[FreeBSD/FreeBSD.git] / sys / dev / amdtemp / amdtemp.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2008, 2009 Rui Paulo <rpaulo@FreeBSD.org>
5  * Copyright (c) 2009 Norikatsu Shigemura <nork@FreeBSD.org>
6  * Copyright (c) 2009-2012 Jung-uk Kim <jkim@FreeBSD.org>
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
22  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 /*
32  * Driver for the AMD CPU on-die thermal sensors.
33  * Initially based on the k8temp Linux driver.
34  */
35
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
38
39 #include <sys/param.h>
40 #include <sys/bus.h>
41 #include <sys/conf.h>
42 #include <sys/kernel.h>
43 #include <sys/module.h>
44 #include <sys/sysctl.h>
45 #include <sys/systm.h>
46
47 #include <machine/cpufunc.h>
48 #include <machine/md_var.h>
49 #include <machine/specialreg.h>
50
51 #include <dev/pci/pcivar.h>
52 #include <x86/pci_cfgreg.h>
53
54 #include <dev/amdsmn/amdsmn.h>
55
56 typedef enum {
57         CORE0_SENSOR0,
58         CORE0_SENSOR1,
59         CORE1_SENSOR0,
60         CORE1_SENSOR1,
61         CORE0,
62         CORE1
63 } amdsensor_t;
64
65 struct amdtemp_softc {
66         int             sc_ncores;
67         int             sc_ntemps;
68         int             sc_flags;
69 #define AMDTEMP_FLAG_CS_SWAP    0x01    /* ThermSenseCoreSel is inverted. */
70 #define AMDTEMP_FLAG_CT_10BIT   0x02    /* CurTmp is 10-bit wide. */
71 #define AMDTEMP_FLAG_ALT_OFFSET 0x04    /* CurTmp starts at -28C. */
72         int32_t         sc_offset;
73         int32_t         (*sc_gettemp)(device_t, amdsensor_t);
74         struct sysctl_oid *sc_sysctl_cpu[MAXCPU];
75         struct intr_config_hook sc_ich;
76         device_t        sc_smn;
77 };
78
79 #define VENDORID_AMD            0x1022
80 #define DEVICEID_AMD_MISC0F     0x1103
81 #define DEVICEID_AMD_MISC10     0x1203
82 #define DEVICEID_AMD_MISC11     0x1303
83 #define DEVICEID_AMD_MISC12     0x1403
84 #define DEVICEID_AMD_MISC14     0x1703
85 #define DEVICEID_AMD_MISC15     0x1603
86 #define DEVICEID_AMD_MISC16     0x1533
87 #define DEVICEID_AMD_MISC16_M30H        0x1583
88 #define DEVICEID_AMD_MISC17     0x141d
89 #define DEVICEID_AMD_HOSTB17H   0x1450
90
91 static struct amdtemp_product {
92         uint16_t        amdtemp_vendorid;
93         uint16_t        amdtemp_deviceid;
94 } amdtemp_products[] = {
95         { VENDORID_AMD, DEVICEID_AMD_MISC0F },
96         { VENDORID_AMD, DEVICEID_AMD_MISC10 },
97         { VENDORID_AMD, DEVICEID_AMD_MISC11 },
98         { VENDORID_AMD, DEVICEID_AMD_MISC12 },
99         { VENDORID_AMD, DEVICEID_AMD_MISC14 },
100         { VENDORID_AMD, DEVICEID_AMD_MISC15 },
101         { VENDORID_AMD, DEVICEID_AMD_MISC16 },
102         { VENDORID_AMD, DEVICEID_AMD_MISC16_M30H },
103         { VENDORID_AMD, DEVICEID_AMD_MISC17 },
104         { VENDORID_AMD, DEVICEID_AMD_HOSTB17H },
105 };
106
107 /*
108  * Reported Temperature Control Register
109  */
110 #define AMDTEMP_REPTMP_CTRL     0xa4
111
112 /*
113  * Reported Temperature, Family 17h
114  */
115 #define AMDTEMP_17H_CUR_TMP     0x59800
116
117 /*
118  * Thermaltrip Status Register (Family 0Fh only)
119  */
120 #define AMDTEMP_THERMTP_STAT    0xe4
121 #define AMDTEMP_TTSR_SELCORE    0x04
122 #define AMDTEMP_TTSR_SELSENSOR  0x40
123
124 /*
125  * DRAM Configuration High Register
126  */
127 #define AMDTEMP_DRAM_CONF_HIGH  0x94    /* Function 2 */
128 #define AMDTEMP_DRAM_MODE_DDR3  0x0100
129
130 /*
131  * CPU Family/Model Register
132  */
133 #define AMDTEMP_CPUID           0xfc
134
135 /*
136  * Device methods.
137  */
138 static void     amdtemp_identify(driver_t *driver, device_t parent);
139 static int      amdtemp_probe(device_t dev);
140 static int      amdtemp_attach(device_t dev);
141 static void     amdtemp_intrhook(void *arg);
142 static int      amdtemp_detach(device_t dev);
143 static int      amdtemp_match(device_t dev);
144 static int32_t  amdtemp_gettemp0f(device_t dev, amdsensor_t sensor);
145 static int32_t  amdtemp_gettemp(device_t dev, amdsensor_t sensor);
146 static int32_t  amdtemp_gettemp17h(device_t dev, amdsensor_t sensor);
147 static int      amdtemp_sysctl(SYSCTL_HANDLER_ARGS);
148
149 static device_method_t amdtemp_methods[] = {
150         /* Device interface */
151         DEVMETHOD(device_identify,      amdtemp_identify),
152         DEVMETHOD(device_probe,         amdtemp_probe),
153         DEVMETHOD(device_attach,        amdtemp_attach),
154         DEVMETHOD(device_detach,        amdtemp_detach),
155
156         DEVMETHOD_END
157 };
158
159 static driver_t amdtemp_driver = {
160         "amdtemp",
161         amdtemp_methods,
162         sizeof(struct amdtemp_softc),
163 };
164
165 static devclass_t amdtemp_devclass;
166 DRIVER_MODULE(amdtemp, hostb, amdtemp_driver, amdtemp_devclass, NULL, NULL);
167 MODULE_VERSION(amdtemp, 1);
168 MODULE_DEPEND(amdtemp, amdsmn, 1, 1, 1);
169 MODULE_PNP_INFO("U16:vendor;U16:device", pci, amdtemp, amdtemp_products,
170     nitems(amdtemp_products));
171
172 static int
173 amdtemp_match(device_t dev)
174 {
175         int i;
176         uint16_t vendor, devid;
177
178         vendor = pci_get_vendor(dev);
179         devid = pci_get_device(dev);
180
181         for (i = 0; i < nitems(amdtemp_products); i++) {
182                 if (vendor == amdtemp_products[i].amdtemp_vendorid &&
183                     devid == amdtemp_products[i].amdtemp_deviceid)
184                         return (1);
185         }
186
187         return (0);
188 }
189
190 static void
191 amdtemp_identify(driver_t *driver, device_t parent)
192 {
193         device_t child;
194
195         /* Make sure we're not being doubly invoked. */
196         if (device_find_child(parent, "amdtemp", -1) != NULL)
197                 return;
198
199         if (amdtemp_match(parent)) {
200                 child = device_add_child(parent, "amdtemp", -1);
201                 if (child == NULL)
202                         device_printf(parent, "add amdtemp child failed\n");
203         }
204 }
205
206 static int
207 amdtemp_probe(device_t dev)
208 {
209         uint32_t family, model;
210
211         if (resource_disabled("amdtemp", 0))
212                 return (ENXIO);
213         if (!amdtemp_match(device_get_parent(dev)))
214                 return (ENXIO);
215
216         family = CPUID_TO_FAMILY(cpu_id);
217         model = CPUID_TO_MODEL(cpu_id);
218
219         switch (family) {
220         case 0x0f:
221                 if ((model == 0x04 && (cpu_id & CPUID_STEPPING) == 0) ||
222                     (model == 0x05 && (cpu_id & CPUID_STEPPING) <= 1))
223                         return (ENXIO);
224                 break;
225         case 0x10:
226         case 0x11:
227         case 0x12:
228         case 0x14:
229         case 0x15:
230         case 0x16:
231         case 0x17:
232                 break;
233         default:
234                 return (ENXIO);
235         }
236         device_set_desc(dev, "AMD CPU On-Die Thermal Sensors");
237
238         return (BUS_PROBE_GENERIC);
239 }
240
241 static int
242 amdtemp_attach(device_t dev)
243 {
244         char tn[32];
245         u_int regs[4];
246         struct amdtemp_softc *sc = device_get_softc(dev);
247         struct sysctl_ctx_list *sysctlctx;
248         struct sysctl_oid *sysctlnode;
249         uint32_t cpuid, family, model;
250         u_int bid;
251         int erratum319, unit;
252
253         erratum319 = 0;
254
255         /*
256          * CPUID Register is available from Revision F.
257          */
258         cpuid = cpu_id;
259         family = CPUID_TO_FAMILY(cpuid);
260         model = CPUID_TO_MODEL(cpuid);
261         if ((family != 0x0f || model >= 0x40) && family != 0x17) {
262                 cpuid = pci_read_config(dev, AMDTEMP_CPUID, 4);
263                 family = CPUID_TO_FAMILY(cpuid);
264                 model = CPUID_TO_MODEL(cpuid);
265         }
266
267         switch (family) {
268         case 0x0f:
269                 /*
270                  * Thermaltrip Status Register
271                  *
272                  * - ThermSenseCoreSel
273                  *
274                  * Revision F & G:      0 - Core1, 1 - Core0
275                  * Other:               0 - Core0, 1 - Core1
276                  *
277                  * - CurTmp
278                  *
279                  * Revision G:          bits 23-14
280                  * Other:               bits 23-16
281                  *
282                  * XXX According to the BKDG, CurTmp, ThermSenseSel and
283                  * ThermSenseCoreSel bits were introduced in Revision F
284                  * but CurTmp seems working fine as early as Revision C.
285                  * However, it is not clear whether ThermSenseSel and/or
286                  * ThermSenseCoreSel work in undocumented cases as well.
287                  * In fact, the Linux driver suggests it may not work but
288                  * we just assume it does until we find otherwise.
289                  *
290                  * XXX According to Linux, CurTmp starts at -28C on
291                  * Socket AM2 Revision G processors, which is not
292                  * documented anywhere.
293                  */
294                 if (model >= 0x40)
295                         sc->sc_flags |= AMDTEMP_FLAG_CS_SWAP;
296                 if (model >= 0x60 && model != 0xc1) {
297                         do_cpuid(0x80000001, regs);
298                         bid = (regs[1] >> 9) & 0x1f;
299                         switch (model) {
300                         case 0x68: /* Socket S1g1 */
301                         case 0x6c:
302                         case 0x7c:
303                                 break;
304                         case 0x6b: /* Socket AM2 and ASB1 (2 cores) */
305                                 if (bid != 0x0b && bid != 0x0c)
306                                         sc->sc_flags |=
307                                             AMDTEMP_FLAG_ALT_OFFSET;
308                                 break;
309                         case 0x6f: /* Socket AM2 and ASB1 (1 core) */
310                         case 0x7f:
311                                 if (bid != 0x07 && bid != 0x09 &&
312                                     bid != 0x0c)
313                                         sc->sc_flags |=
314                                             AMDTEMP_FLAG_ALT_OFFSET;
315                                 break;
316                         default:
317                                 sc->sc_flags |= AMDTEMP_FLAG_ALT_OFFSET;
318                         }
319                         sc->sc_flags |= AMDTEMP_FLAG_CT_10BIT;
320                 }
321
322                 /*
323                  * There are two sensors per core.
324                  */
325                 sc->sc_ntemps = 2;
326
327                 sc->sc_gettemp = amdtemp_gettemp0f;
328                 break;
329         case 0x10:
330                 /*
331                  * Erratum 319 Inaccurate Temperature Measurement
332                  *
333                  * http://support.amd.com/us/Processor_TechDocs/41322.pdf
334                  */
335                 do_cpuid(0x80000001, regs);
336                 switch ((regs[1] >> 28) & 0xf) {
337                 case 0: /* Socket F */
338                         erratum319 = 1;
339                         break;
340                 case 1: /* Socket AM2+ or AM3 */
341                         if ((pci_cfgregread(pci_get_bus(dev),
342                             pci_get_slot(dev), 2, AMDTEMP_DRAM_CONF_HIGH, 2) &
343                             AMDTEMP_DRAM_MODE_DDR3) != 0 || model > 0x04 ||
344                             (model == 0x04 && (cpuid & CPUID_STEPPING) >= 3))
345                                 break;
346                         /* XXX 00100F42h (RB-C2) exists in both formats. */
347                         erratum319 = 1;
348                         break;
349                 }
350                 /* FALLTHROUGH */
351         case 0x11:
352         case 0x12:
353         case 0x14:
354         case 0x15:
355         case 0x16:
356                 /*
357                  * There is only one sensor per package.
358                  */
359                 sc->sc_ntemps = 1;
360
361                 sc->sc_gettemp = amdtemp_gettemp;
362                 break;
363         case 0x17:
364                 sc->sc_ntemps = 1;
365                 sc->sc_gettemp = amdtemp_gettemp17h;
366                 sc->sc_smn = device_find_child(
367                     device_get_parent(dev), "amdsmn", -1);
368                 if (sc->sc_smn == NULL) {
369                         if (bootverbose)
370                                 device_printf(dev, "No SMN device found\n");
371                         return (ENXIO);
372                 }
373                 break;
374         }
375
376         /* Find number of cores per package. */
377         sc->sc_ncores = (amd_feature2 & AMDID2_CMP) != 0 ?
378             (cpu_procinfo2 & AMDID_CMP_CORES) + 1 : 1;
379         if (sc->sc_ncores > MAXCPU)
380                 return (ENXIO);
381
382         if (erratum319)
383                 device_printf(dev,
384                     "Erratum 319: temperature measurement may be inaccurate\n");
385         if (bootverbose)
386                 device_printf(dev, "Found %d cores and %d sensors.\n",
387                     sc->sc_ncores,
388                     sc->sc_ntemps > 1 ? sc->sc_ntemps * sc->sc_ncores : 1);
389
390         /*
391          * dev.amdtemp.N tree.
392          */
393         unit = device_get_unit(dev);
394         snprintf(tn, sizeof(tn), "dev.amdtemp.%d.sensor_offset", unit);
395         TUNABLE_INT_FETCH(tn, &sc->sc_offset);
396
397         sysctlctx = device_get_sysctl_ctx(dev);
398         SYSCTL_ADD_INT(sysctlctx,
399             SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
400             "sensor_offset", CTLFLAG_RW, &sc->sc_offset, 0,
401             "Temperature sensor offset");
402         sysctlnode = SYSCTL_ADD_NODE(sysctlctx,
403             SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
404             "core0", CTLFLAG_RD, 0, "Core 0");
405
406         SYSCTL_ADD_PROC(sysctlctx,
407             SYSCTL_CHILDREN(sysctlnode),
408             OID_AUTO, "sensor0", CTLTYPE_INT | CTLFLAG_RD,
409             dev, CORE0_SENSOR0, amdtemp_sysctl, "IK",
410             "Core 0 / Sensor 0 temperature");
411
412         if (sc->sc_ntemps > 1) {
413                 SYSCTL_ADD_PROC(sysctlctx,
414                     SYSCTL_CHILDREN(sysctlnode),
415                     OID_AUTO, "sensor1", CTLTYPE_INT | CTLFLAG_RD,
416                     dev, CORE0_SENSOR1, amdtemp_sysctl, "IK",
417                     "Core 0 / Sensor 1 temperature");
418
419                 if (sc->sc_ncores > 1) {
420                         sysctlnode = SYSCTL_ADD_NODE(sysctlctx,
421                             SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
422                             OID_AUTO, "core1", CTLFLAG_RD, 0, "Core 1");
423
424                         SYSCTL_ADD_PROC(sysctlctx,
425                             SYSCTL_CHILDREN(sysctlnode),
426                             OID_AUTO, "sensor0", CTLTYPE_INT | CTLFLAG_RD,
427                             dev, CORE1_SENSOR0, amdtemp_sysctl, "IK",
428                             "Core 1 / Sensor 0 temperature");
429
430                         SYSCTL_ADD_PROC(sysctlctx,
431                             SYSCTL_CHILDREN(sysctlnode),
432                             OID_AUTO, "sensor1", CTLTYPE_INT | CTLFLAG_RD,
433                             dev, CORE1_SENSOR1, amdtemp_sysctl, "IK",
434                             "Core 1 / Sensor 1 temperature");
435                 }
436         }
437
438         /*
439          * Try to create dev.cpu sysctl entries and setup intrhook function.
440          * This is needed because the cpu driver may be loaded late on boot,
441          * after us.
442          */
443         amdtemp_intrhook(dev);
444         sc->sc_ich.ich_func = amdtemp_intrhook;
445         sc->sc_ich.ich_arg = dev;
446         if (config_intrhook_establish(&sc->sc_ich) != 0) {
447                 device_printf(dev, "config_intrhook_establish failed!\n");
448                 return (ENXIO);
449         }
450
451         return (0);
452 }
453
454 void
455 amdtemp_intrhook(void *arg)
456 {
457         struct amdtemp_softc *sc;
458         struct sysctl_ctx_list *sysctlctx;
459         device_t dev = (device_t)arg;
460         device_t acpi, cpu, nexus;
461         amdsensor_t sensor;
462         int i;
463
464         sc = device_get_softc(dev);
465
466         /*
467          * dev.cpu.N.temperature.
468          */
469         nexus = device_find_child(root_bus, "nexus", 0);
470         acpi = device_find_child(nexus, "acpi", 0);
471
472         for (i = 0; i < sc->sc_ncores; i++) {
473                 if (sc->sc_sysctl_cpu[i] != NULL)
474                         continue;
475                 cpu = device_find_child(acpi, "cpu",
476                     device_get_unit(dev) * sc->sc_ncores + i);
477                 if (cpu != NULL) {
478                         sysctlctx = device_get_sysctl_ctx(cpu);
479
480                         sensor = sc->sc_ntemps > 1 ?
481                             (i == 0 ? CORE0 : CORE1) : CORE0_SENSOR0;
482                         sc->sc_sysctl_cpu[i] = SYSCTL_ADD_PROC(sysctlctx,
483                             SYSCTL_CHILDREN(device_get_sysctl_tree(cpu)),
484                             OID_AUTO, "temperature", CTLTYPE_INT | CTLFLAG_RD,
485                             dev, sensor, amdtemp_sysctl, "IK",
486                             "Current temparature");
487                 }
488         }
489         if (sc->sc_ich.ich_arg != NULL)
490                 config_intrhook_disestablish(&sc->sc_ich);
491 }
492
493 int
494 amdtemp_detach(device_t dev)
495 {
496         struct amdtemp_softc *sc = device_get_softc(dev);
497         int i;
498
499         for (i = 0; i < sc->sc_ncores; i++)
500                 if (sc->sc_sysctl_cpu[i] != NULL)
501                         sysctl_remove_oid(sc->sc_sysctl_cpu[i], 1, 0);
502
503         /* NewBus removes the dev.amdtemp.N tree by itself. */
504
505         return (0);
506 }
507
508 static int
509 amdtemp_sysctl(SYSCTL_HANDLER_ARGS)
510 {
511         device_t dev = (device_t)arg1;
512         struct amdtemp_softc *sc = device_get_softc(dev);
513         amdsensor_t sensor = (amdsensor_t)arg2;
514         int32_t auxtemp[2], temp;
515         int error;
516
517         switch (sensor) {
518         case CORE0:
519                 auxtemp[0] = sc->sc_gettemp(dev, CORE0_SENSOR0);
520                 auxtemp[1] = sc->sc_gettemp(dev, CORE0_SENSOR1);
521                 temp = imax(auxtemp[0], auxtemp[1]);
522                 break;
523         case CORE1:
524                 auxtemp[0] = sc->sc_gettemp(dev, CORE1_SENSOR0);
525                 auxtemp[1] = sc->sc_gettemp(dev, CORE1_SENSOR1);
526                 temp = imax(auxtemp[0], auxtemp[1]);
527                 break;
528         default:
529                 temp = sc->sc_gettemp(dev, sensor);
530                 break;
531         }
532         error = sysctl_handle_int(oidp, &temp, 0, req);
533
534         return (error);
535 }
536
537 #define AMDTEMP_ZERO_C_TO_K     2731
538
539 static int32_t
540 amdtemp_gettemp0f(device_t dev, amdsensor_t sensor)
541 {
542         struct amdtemp_softc *sc = device_get_softc(dev);
543         uint32_t mask, offset, temp;
544
545         /* Set Sensor/Core selector. */
546         temp = pci_read_config(dev, AMDTEMP_THERMTP_STAT, 1);
547         temp &= ~(AMDTEMP_TTSR_SELCORE | AMDTEMP_TTSR_SELSENSOR);
548         switch (sensor) {
549         case CORE0_SENSOR1:
550                 temp |= AMDTEMP_TTSR_SELSENSOR;
551                 /* FALLTHROUGH */
552         case CORE0_SENSOR0:
553         case CORE0:
554                 if ((sc->sc_flags & AMDTEMP_FLAG_CS_SWAP) != 0)
555                         temp |= AMDTEMP_TTSR_SELCORE;
556                 break;
557         case CORE1_SENSOR1:
558                 temp |= AMDTEMP_TTSR_SELSENSOR;
559                 /* FALLTHROUGH */
560         case CORE1_SENSOR0:
561         case CORE1:
562                 if ((sc->sc_flags & AMDTEMP_FLAG_CS_SWAP) == 0)
563                         temp |= AMDTEMP_TTSR_SELCORE;
564                 break;
565         }
566         pci_write_config(dev, AMDTEMP_THERMTP_STAT, temp, 1);
567
568         mask = (sc->sc_flags & AMDTEMP_FLAG_CT_10BIT) != 0 ? 0x3ff : 0x3fc;
569         offset = (sc->sc_flags & AMDTEMP_FLAG_ALT_OFFSET) != 0 ? 28 : 49;
570         temp = pci_read_config(dev, AMDTEMP_THERMTP_STAT, 4);
571         temp = ((temp >> 14) & mask) * 5 / 2;
572         temp += AMDTEMP_ZERO_C_TO_K + (sc->sc_offset - offset) * 10;
573
574         return (temp);
575 }
576
577 static int32_t
578 amdtemp_gettemp(device_t dev, amdsensor_t sensor)
579 {
580         struct amdtemp_softc *sc = device_get_softc(dev);
581         uint32_t temp;
582
583         temp = pci_read_config(dev, AMDTEMP_REPTMP_CTRL, 4);
584         temp = ((temp >> 21) & 0x7ff) * 5 / 4;
585         temp += AMDTEMP_ZERO_C_TO_K + sc->sc_offset * 10;
586
587         return (temp);
588 }
589
590 static int32_t
591 amdtemp_gettemp17h(device_t dev, amdsensor_t sensor)
592 {
593         struct amdtemp_softc *sc = device_get_softc(dev);
594         uint32_t temp;
595         int error;
596
597         error = amdsmn_read(sc->sc_smn, AMDTEMP_17H_CUR_TMP, &temp);
598         KASSERT(error == 0, ("amdsmn_read"));
599
600         temp = ((temp >> 21) & 0x7ff) * 5 / 4;
601         temp += AMDTEMP_ZERO_C_TO_K + sc->sc_offset * 10;
602
603         return (temp);
604 }