| @@ -1,269 +1,335 @@ | | | @@ -1,269 +1,335 @@ |
1 | /* $NetBSD: amdzentemp.c,v 1.9 2019/06/16 09:12:51 mlelstv Exp $ */ | | 1 | /* $NetBSD: amdzentemp.c,v 1.10 2020/04/20 11:03:02 simonb Exp $ */ |
2 | /* $OpenBSD: kate.c,v 1.2 2008/03/27 04:52:03 cnst Exp $ */ | | 2 | /* $OpenBSD: kate.c,v 1.2 2008/03/27 04:52:03 cnst Exp $ */ |
3 | | | 3 | |
4 | /* | | 4 | /* |
5 | * Copyright (c) 2008 The NetBSD Foundation, Inc. | | 5 | * Copyright (c) 2008, 2020 The NetBSD Foundation, Inc. |
| | | 6 | * All rights reserved. |
| | | 7 | * |
| | | 8 | * Copyright (c) 2019 Conrad Meyer <cem@FreeBSD.org> |
6 | * All rights reserved. | | 9 | * All rights reserved. |
7 | * | | 10 | * |
8 | * This code is derived from software contributed to The NetBSD Foundation | | 11 | * This code is derived from software contributed to The NetBSD Foundation |
9 | * by Christoph Egger. | | 12 | * by Christoph Egger. |
10 | * | | 13 | * |
11 | * NetBSD port by Ian Clark <mrrooster@gmail.com> | | 14 | * NetBSD port by Ian Clark <mrrooster@gmail.com> |
12 | * | | 15 | * |
13 | * Redistribution and use in source and binary forms, with or without | | 16 | * Redistribution and use in source and binary forms, with or without |
14 | * modification, are permitted provided that the following conditions | | 17 | * modification, are permitted provided that the following conditions |
15 | * are met: | | 18 | * are met: |
16 | * 1. Redistributions of source code must retain the above copyright | | 19 | * 1. Redistributions of source code must retain the above copyright |
17 | * notice, this list of conditions and the following disclaimer. | | 20 | * notice, this list of conditions and the following disclaimer. |
18 | * 2. Redistributions in binary form must reproduce the above copyright | | 21 | * 2. Redistributions in binary form must reproduce the above copyright |
19 | * notice, this list of conditions and the following disclaimer in the | | 22 | * notice, this list of conditions and the following disclaimer in the |
20 | * documentation and/or other materials provided with the distribution. | | 23 | * documentation and/or other materials provided with the distribution. |
21 | * | | 24 | * |
22 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 25 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
23 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 26 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
24 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 27 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
25 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 28 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
26 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 29 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 30 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 31 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 32 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 33 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 34 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
32 | * POSSIBILITY OF SUCH DAMAGE. | | 35 | * POSSIBILITY OF SUCH DAMAGE. |
33 | */ | | 36 | */ |
34 | | | 37 | |
35 | /* | | 38 | /* |
36 | * Copyright (c) 2008 Constantine A. Murenin <cnst+openbsd@bugmail.mojo.ru> | | 39 | * Copyright (c) 2008 Constantine A. Murenin <cnst+openbsd@bugmail.mojo.ru> |
37 | * | | 40 | * |
38 | * Permission to use, copy, modify, and distribute this software for any | | 41 | * Permission to use, copy, modify, and distribute this software for any |
39 | * purpose with or without fee is hereby granted, provided that the above | | 42 | * purpose with or without fee is hereby granted, provided that the above |
40 | * copyright notice and this permission notice appear in all copies. | | 43 | * copyright notice and this permission notice appear in all copies. |
41 | * | | 44 | * |
42 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | | 45 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
43 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | | 46 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
44 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | | 47 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
45 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | | 48 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
46 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | | 49 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
47 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | | 50 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
48 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | | 51 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
49 | */ | | 52 | */ |
50 | | | 53 | |
51 | | | 54 | |
52 | #include <sys/cdefs.h> | | 55 | #include <sys/cdefs.h> |
53 | __KERNEL_RCSID(0, "$NetBSD: amdzentemp.c,v 1.9 2019/06/16 09:12:51 mlelstv Exp $ "); | | 56 | __KERNEL_RCSID(0, "$NetBSD: amdzentemp.c,v 1.10 2020/04/20 11:03:02 simonb Exp $ "); |
54 | | | 57 | |
55 | #include <sys/param.h> | | 58 | #include <sys/param.h> |
56 | #include <sys/bus.h> | | 59 | #include <sys/bus.h> |
57 | #include <sys/cpu.h> | | 60 | #include <sys/cpu.h> |
58 | #include <sys/systm.h> | | 61 | #include <sys/systm.h> |
59 | #include <sys/device.h> | | 62 | #include <sys/device.h> |
60 | #include <sys/kmem.h> | | 63 | #include <sys/kmem.h> |
61 | #include <sys/module.h> | | 64 | #include <sys/module.h> |
62 | | | 65 | |
63 | #include <machine/specialreg.h> | | 66 | #include <machine/specialreg.h> |
64 | | | 67 | |
65 | #include <dev/pci/pcireg.h> | | 68 | #include <dev/pci/pcireg.h> |
66 | #include <dev/pci/pcivar.h> | | 69 | #include <dev/pci/pcivar.h> |
67 | #include <dev/pci/pcidevs.h> | | 70 | #include <dev/pci/pcidevs.h> |
68 | | | 71 | |
69 | #include <dev/sysmon/sysmonvar.h> | | 72 | #include <dev/sysmon/sysmonvar.h> |
70 | | | 73 | |
71 | #include "amdsmn.h" | | 74 | #include "amdsmn.h" |
72 | | | 75 | |
73 | /* Address to query for temp on family 17h */ | | 76 | #define AMD_CURTMP_RANGE_ADJUST 49000000 /* in microKelvins (ie, 49C) */ |
74 | #define AMD_17H_CUR_TMP 0x59800 | | 77 | #define AMD_CURTMP_RANGE_CHECK __BIT(19) |
| | | 78 | #define F10_TEMP_CURTMP __BITS(31,21) /* XXX same as amdtemp.c */ |
| | | 79 | #define F15M60_CURTMP_TJSEL __BITS(17,16) |
| | | 80 | |
| | | 81 | /* |
| | | 82 | * Reported Temperature, Family 15h, M60+ |
| | | 83 | * |
| | | 84 | * Same register bit definitions as other Family 15h CPUs, but access is |
| | | 85 | * indirect via SMN, like Family 17h. |
| | | 86 | */ |
| | | 87 | #define AMD_15H_M60H_REPTMP_CTRL 0xd8200ca4 |
| | | 88 | |
| | | 89 | /* |
| | | 90 | * Reported Temperature, Family 17h |
| | | 91 | * |
| | | 92 | * According to AMD OSRR for 17H, section 4.2.1, bits 31-21 of this register |
| | | 93 | * provide the current temp. bit 19, when clear, means the temp is reported in |
| | | 94 | * a range 0.."225C" (probable typo for 255C), and when set changes the range |
| | | 95 | * to -49..206C. |
| | | 96 | */ |
| | | 97 | #define AMD_17H_CUR_TMP 0x59800 |
75 | | | 98 | |
76 | struct amdzentemp_softc { | | 99 | struct amdzentemp_softc { |
77 | pci_chipset_tag_t sc_pc; | | | |
78 | pcitag_t sc_pcitag; | | | |
79 | struct sysmon_envsys *sc_sme; | | 100 | struct sysmon_envsys *sc_sme; |
80 | device_t sc_smn; | | 101 | device_t sc_smn; |
81 | envsys_data_t *sc_sensor; | | 102 | envsys_data_t *sc_sensor; |
82 | size_t sc_sensor_len; | | 103 | size_t sc_sensor_len; |
83 | size_t sc_numsensors; | | 104 | size_t sc_numsensors; |
84 | int32_t sc_offset; | | 105 | int32_t sc_offset; |
85 | }; | | 106 | }; |
86 | | | 107 | |
87 | | | 108 | |
88 | static int amdzentemp_match(device_t, cfdata_t, void *); | | 109 | static int amdzentemp_match(device_t, cfdata_t, void *); |
89 | static void amdzentemp_attach(device_t, device_t, void *); | | 110 | static void amdzentemp_attach(device_t, device_t, void *); |
90 | static int amdzentemp_detach(device_t, int); | | 111 | static int amdzentemp_detach(device_t, int); |
91 | | | 112 | |
92 | static void amdzentemp_family17_init(struct amdzentemp_softc *); | | 113 | static void amdzentemp_init(struct amdzentemp_softc *); |
93 | static void amdzentemp_family17_setup_sensors(struct amdzentemp_softc *, int); | | 114 | static void amdzentemp_setup_sensors(struct amdzentemp_softc *, int); |
| | | 115 | static void amdzentemp_family15_refresh(struct sysmon_envsys *, envsys_data_t *); |
94 | static void amdzentemp_family17_refresh(struct sysmon_envsys *, envsys_data_t *); | | 116 | static void amdzentemp_family17_refresh(struct sysmon_envsys *, envsys_data_t *); |
95 | | | 117 | |
96 | CFATTACH_DECL_NEW(amdzentemp, sizeof(struct amdzentemp_softc), | | 118 | CFATTACH_DECL_NEW(amdzentemp, sizeof(struct amdzentemp_softc), |
97 | amdzentemp_match, amdzentemp_attach, amdzentemp_detach, NULL); | | 119 | amdzentemp_match, amdzentemp_attach, amdzentemp_detach, NULL); |
98 | | | 120 | |
99 | static int | | 121 | static int |
100 | amdzentemp_match(device_t parent, cfdata_t match, void *aux) | | 122 | amdzentemp_match(device_t parent, cfdata_t match, void *aux) |
101 | { | | 123 | { |
102 | struct pci_attach_args *pa __diagused = aux; | | 124 | struct pci_attach_args *pa __diagused = aux; |
103 | | | 125 | |
104 | KASSERT(PCI_VENDOR(pa->pa_id) == PCI_VENDOR_AMD); | | 126 | KASSERT(PCI_VENDOR(pa->pa_id) == PCI_VENDOR_AMD); |
105 | | | 127 | |
106 | cfdata_t parent_cfdata = device_cfdata(parent); | | 128 | cfdata_t parent_cfdata = device_cfdata(parent); |
107 | | | 129 | |
108 | /* Got AMD family 17h system management network */ | | 130 | /* Got AMD family 17h system management network */ |
109 | return parent_cfdata->cf_name && | | 131 | return parent_cfdata->cf_name && |
110 | memcmp(parent_cfdata->cf_name, "amdsmn", 6) == 0; | | 132 | memcmp(parent_cfdata->cf_name, "amdsmn", 6) == 0; |
111 | } | | 133 | } |
112 | | | 134 | |
113 | static void | | 135 | static void |
114 | amdzentemp_attach(device_t parent, device_t self, void *aux) | | 136 | amdzentemp_attach(device_t parent, device_t self, void *aux) |
115 | { | | 137 | { |
116 | struct amdzentemp_softc *sc = device_private(self); | | 138 | struct amdzentemp_softc *sc = device_private(self); |
117 | struct pci_attach_args *pa = aux; | | 139 | struct cpu_info *ci = curcpu(); |
| | | 140 | int family; |
118 | int error; | | 141 | int error; |
119 | size_t i; | | 142 | size_t i; |
120 | | | 143 | |
| | | 144 | family = CPUID_TO_FAMILY(ci->ci_signature); |
121 | aprint_naive("\n"); | | 145 | aprint_naive("\n"); |
122 | aprint_normal(": AMD CPU Temperature Sensors (Family17h)"); | | 146 | aprint_normal(": AMD CPU Temperature Sensors (Family%xh)", |
| | | 147 | family); |
123 | | | 148 | |
124 | sc->sc_pc = pa->pa_pc; | | | |
125 | sc->sc_pcitag = pa->pa_tag; | | | |
126 | sc->sc_smn = parent; | | 149 | sc->sc_smn = parent; |
127 | | | 150 | |
128 | amdzentemp_family17_init(sc); | | 151 | amdzentemp_init(sc); |
129 | | | 152 | |
130 | aprint_normal("\n"); | | 153 | aprint_normal("\n"); |
131 | | | 154 | |
132 | sc->sc_sme = sysmon_envsys_create(); | | 155 | sc->sc_sme = sysmon_envsys_create(); |
133 | sc->sc_sensor_len = sizeof(envsys_data_t) * sc->sc_numsensors; | | 156 | sc->sc_sensor_len = sizeof(envsys_data_t) * sc->sc_numsensors; |
134 | sc->sc_sensor = kmem_zalloc(sc->sc_sensor_len, KM_SLEEP); | | 157 | sc->sc_sensor = kmem_zalloc(sc->sc_sensor_len, KM_SLEEP); |
135 | | | 158 | |
136 | amdzentemp_family17_setup_sensors(sc, device_unit(self)); | | 159 | amdzentemp_setup_sensors(sc, device_unit(self)); |
137 | | | 160 | |
138 | /* | | 161 | /* |
139 | * Set properties in sensors. | | 162 | * Set properties in sensors. |
140 | */ | | 163 | */ |
141 | for (i = 0; i < sc->sc_numsensors; i++) { | | 164 | for (i = 0; i < sc->sc_numsensors; i++) { |
142 | if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[i])) | | 165 | if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[i])) |
143 | goto bad; | | 166 | goto bad; |
144 | } | | 167 | } |
145 | | | 168 | |
146 | /* | | 169 | /* |
147 | * Register the sysmon_envsys device. | | 170 | * Register the sysmon_envsys device. |
148 | */ | | 171 | */ |
149 | sc->sc_sme->sme_name = device_xname(self); | | 172 | sc->sc_sme->sme_name = device_xname(self); |
150 | sc->sc_sme->sme_cookie = sc; | | 173 | sc->sc_sme->sme_cookie = sc; |
151 | | | 174 | |
152 | sc->sc_sme->sme_refresh = amdzentemp_family17_refresh; | | 175 | switch (family) { |
| | | 176 | case 0x15: |
| | | 177 | sc->sc_sme->sme_refresh = amdzentemp_family15_refresh; |
| | | 178 | break; |
| | | 179 | case 0x17: |
| | | 180 | sc->sc_sme->sme_refresh = amdzentemp_family17_refresh; |
| | | 181 | break; |
| | | 182 | default: |
| | | 183 | /* XXX panic */ |
| | | 184 | break; |
| | | 185 | } |
153 | | | 186 | |
154 | error = sysmon_envsys_register(sc->sc_sme); | | 187 | error = sysmon_envsys_register(sc->sc_sme); |
155 | if (error) { | | 188 | if (error) { |
156 | aprint_error_dev(self, "unable to register with sysmon " | | 189 | aprint_error_dev(self, "unable to register with sysmon " |
157 | "(error=%d)\n", error); | | 190 | "(error=%d)\n", error); |
158 | goto bad; | | 191 | goto bad; |
159 | } | | 192 | } |
160 | | | 193 | |
161 | (void)pmf_device_register(self, NULL, NULL); | | 194 | (void)pmf_device_register(self, NULL, NULL); |
162 | | | 195 | |
163 | return; | | 196 | return; |
164 | | | 197 | |
165 | bad: | | 198 | bad: |
166 | if (sc->sc_sme != NULL) { | | 199 | if (sc->sc_sme != NULL) { |
167 | sysmon_envsys_destroy(sc->sc_sme); | | 200 | sysmon_envsys_destroy(sc->sc_sme); |
168 | sc->sc_sme = NULL; | | 201 | sc->sc_sme = NULL; |
169 | } | | 202 | } |
170 | | | 203 | |
171 | kmem_free(sc->sc_sensor, sc->sc_sensor_len); | | 204 | kmem_free(sc->sc_sensor, sc->sc_sensor_len); |
172 | sc->sc_sensor = NULL; | | 205 | sc->sc_sensor = NULL; |
173 | } | | 206 | } |
174 | | | 207 | |
175 | static int | | 208 | static int |
176 | amdzentemp_detach(device_t self, int flags) | | 209 | amdzentemp_detach(device_t self, int flags) |
177 | { | | 210 | { |
178 | struct amdzentemp_softc *sc = device_private(self); | | 211 | struct amdzentemp_softc *sc = device_private(self); |
179 | | | 212 | |
180 | pmf_device_deregister(self); | | 213 | pmf_device_deregister(self); |
181 | if (sc->sc_sme != NULL) | | 214 | if (sc->sc_sme != NULL) |
182 | sysmon_envsys_unregister(sc->sc_sme); | | 215 | sysmon_envsys_unregister(sc->sc_sme); |
183 | | | 216 | |
184 | if (sc->sc_sensor != NULL) | | 217 | if (sc->sc_sensor != NULL) |
185 | kmem_free(sc->sc_sensor, sc->sc_sensor_len); | | 218 | kmem_free(sc->sc_sensor, sc->sc_sensor_len); |
186 | | | 219 | |
187 | return 0; | | 220 | return 0; |
188 | } | | 221 | } |
189 | | | 222 | |
190 | | | 223 | |
191 | static void | | 224 | static void |
192 | amdzentemp_family17_init(struct amdzentemp_softc *sc) | | 225 | amdzentemp_init(struct amdzentemp_softc *sc) |
193 | { | | 226 | { |
194 | | | 227 | |
195 | sc->sc_numsensors = 1; | | 228 | sc->sc_numsensors = 1; |
196 | sc->sc_offset = 0; | | 229 | sc->sc_offset = 0; |
197 | | | 230 | |
198 | if (strstr(cpu_brand_string, "AMD Ryzen 5 1600X") | | 231 | if (strstr(cpu_brand_string, "AMD Ryzen 5 1600X") |
199 | || strstr(cpu_brand_string, "AMD Ryzen 7 1700X") | | 232 | || strstr(cpu_brand_string, "AMD Ryzen 7 1700X") |
200 | || strstr(cpu_brand_string, "AMD Ryzen 7 1800X")) | | 233 | || strstr(cpu_brand_string, "AMD Ryzen 7 1800X")) |
201 | sc->sc_offset = -20000000; | | 234 | sc->sc_offset = -20000000; |
202 | else if (strstr(cpu_brand_string, "AMD Ryzen 7 2700X")) | | 235 | else if (strstr(cpu_brand_string, "AMD Ryzen 7 2700X")) |
203 | sc->sc_offset = -10000000; | | 236 | sc->sc_offset = -10000000; |
204 | else if (strstr(cpu_brand_string, "AMD Ryzen Threadripper 19") | | 237 | else if (strstr(cpu_brand_string, "AMD Ryzen Threadripper 19") |
205 | || strstr(cpu_brand_string, "AMD Ryzen Threadripper 29")) | | 238 | || strstr(cpu_brand_string, "AMD Ryzen Threadripper 29")) |
206 | sc->sc_offset = -27000000; | | 239 | sc->sc_offset = -27000000; |
207 | } | | 240 | } |
208 | | | 241 | |
209 | static void | | 242 | static void |
210 | amdzentemp_family17_setup_sensors(struct amdzentemp_softc *sc, int dv_unit) | | 243 | amdzentemp_setup_sensors(struct amdzentemp_softc *sc, int dv_unit) |
211 | { | | 244 | { |
212 | sc->sc_sensor[0].units = ENVSYS_STEMP; | | 245 | sc->sc_sensor[0].units = ENVSYS_STEMP; |
213 | sc->sc_sensor[0].state = ENVSYS_SVALID; | | 246 | sc->sc_sensor[0].state = ENVSYS_SVALID; |
214 | sc->sc_sensor[0].flags = ENVSYS_FHAS_ENTROPY; | | 247 | sc->sc_sensor[0].flags = ENVSYS_FHAS_ENTROPY; |
215 | | | 248 | |
216 | snprintf(sc->sc_sensor[0].desc, sizeof(sc->sc_sensor[0].desc), | | 249 | snprintf(sc->sc_sensor[0].desc, sizeof(sc->sc_sensor[0].desc), |
217 | "cpu%u temperature", dv_unit); | | 250 | "cpu%u temperature", dv_unit); |
218 | } | | 251 | } |
219 | | | 252 | |
220 | static void | | 253 | static void |
| | | 254 | amdzentemp_family15_refresh(struct sysmon_envsys *sme, |
| | | 255 | envsys_data_t *edata) |
| | | 256 | { |
| | | 257 | struct amdzentemp_softc *sc = sme->sme_cookie; |
| | | 258 | uint32_t val, temp; |
| | | 259 | int error; |
| | | 260 | |
| | | 261 | error = amdsmn_read(sc->sc_smn, AMD_15H_M60H_REPTMP_CTRL, &val); |
| | | 262 | if (error) { |
| | | 263 | edata->state = ENVSYS_SINVALID; |
| | | 264 | return; |
| | | 265 | } |
| | | 266 | |
| | | 267 | /* from amdtemp.c:amdtemp_family10_refresh() */ |
| | | 268 | temp = __SHIFTOUT(val, F10_TEMP_CURTMP); |
| | | 269 | |
| | | 270 | /* From Celsius to micro-Kelvin. */ |
| | | 271 | edata->value_cur = (temp * 125000) + 273150000; |
| | | 272 | |
| | | 273 | /* |
| | | 274 | * On Family 15h and higher, if CurTmpTjSel is 11b, the range is |
| | | 275 | * adjusted down by 49.0 degrees Celsius. (This adjustment is not |
| | | 276 | * documented in BKDGs prior to family 15h model 00h.) |
| | | 277 | * |
| | | 278 | * XXX should be in amdtemp.c:amdtemp_family10_refresh() for f15 |
| | | 279 | * as well?? |
| | | 280 | */ |
| | | 281 | if (__SHIFTOUT(val, F15M60_CURTMP_TJSEL) == 0x3) |
| | | 282 | edata->value_cur -= AMD_CURTMP_RANGE_ADJUST; |
| | | 283 | |
| | | 284 | edata->state = ENVSYS_SVALID; |
| | | 285 | } |
| | | 286 | |
| | | 287 | static void |
221 | amdzentemp_family17_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) | | 288 | amdzentemp_family17_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) |
222 | { | | 289 | { |
223 | struct amdzentemp_softc *sc = sme->sme_cookie; | | 290 | struct amdzentemp_softc *sc = sme->sme_cookie; |
224 | uint32_t temp; | | 291 | uint32_t temp; |
225 | int error; | | 292 | int error; |
226 | | | 293 | |
227 | error = amdsmn_read(sc->sc_smn, AMD_17H_CUR_TMP, &temp); | | 294 | error = amdsmn_read(sc->sc_smn, AMD_17H_CUR_TMP, &temp); |
228 | if (error) { | | 295 | if (error) { |
229 | edata->state = ENVSYS_SINVALID; | | 296 | edata->state = ENVSYS_SINVALID; |
230 | return; | | 297 | return; |
231 | } | | 298 | } |
232 | edata->state = ENVSYS_SVALID; | | 299 | edata->state = ENVSYS_SVALID; |
233 | /* From C to uK. */ | | 300 | /* From C to uK. */ |
234 | edata->value_cur = ((temp >> 21) * 125000) + 273150000; | | 301 | edata->value_cur = ((temp >> 21) * 125000) + 273150000; |
235 | /* adjust for possible offset of 49K */ | | 302 | /* adjust for possible offset of 49K */ |
236 | if (temp & 0x80000) | | 303 | if (temp & AMD_CURTMP_RANGE_CHECK) |
237 | edata->value_cur -= 49000000; | | 304 | edata->value_cur -= AMD_CURTMP_RANGE_ADJUST; |
238 | edata->value_cur += sc->sc_offset; | | 305 | edata->value_cur += sc->sc_offset; |
239 | } | | 306 | } |
240 | | | 307 | |
241 | MODULE(MODULE_CLASS_DRIVER, amdzentemp, "sysmon_envsys,amdsmn"); | | 308 | MODULE(MODULE_CLASS_DRIVER, amdzentemp, "sysmon_envsys,amdsmn"); |
242 | | | 309 | |
243 | #ifdef _MODULE | | 310 | #ifdef _MODULE |
244 | #include "ioconf.c" | | 311 | #include "ioconf.c" |
245 | #endif | | 312 | #endif |
246 | | | 313 | |
247 | static int | | 314 | static int |
248 | amdzentemp_modcmd(modcmd_t cmd, void *aux) | | 315 | amdzentemp_modcmd(modcmd_t cmd, void *aux) |
249 | { | | 316 | { |
250 | int error = 0; | | 317 | int error = 0; |
251 | | | 318 | |
252 | switch (cmd) { | | 319 | switch (cmd) { |
253 | case MODULE_CMD_INIT: | | 320 | case MODULE_CMD_INIT: |
254 | #ifdef _MODULE | | 321 | #ifdef _MODULE |
255 | error = config_init_component(cfdriver_ioconf_amdzentemp, | | 322 | error = config_init_component(cfdriver_ioconf_amdzentemp, |
256 | cfattach_ioconf_amdzentemp, cfdata_ioconf_amdzentemp); | | 323 | cfattach_ioconf_amdzentemp, cfdata_ioconf_amdzentemp); |
257 | #endif | | 324 | #endif |
258 | return error; | | 325 | return error; |
259 | case MODULE_CMD_FINI: | | 326 | case MODULE_CMD_FINI: |
260 | #ifdef _MODULE | | 327 | #ifdef _MODULE |
261 | error = config_fini_component(cfdriver_ioconf_amdzentemp, | | 328 | error = config_fini_component(cfdriver_ioconf_amdzentemp, |
262 | cfattach_ioconf_amdzentemp, cfdata_ioconf_amdzentemp); | | 329 | cfattach_ioconf_amdzentemp, cfdata_ioconf_amdzentemp); |
263 | #endif | | 330 | #endif |
264 | return error; | | 331 | return error; |
265 | default: | | 332 | default: |
266 | return ENOTTY; | | 333 | return ENOTTY; |
267 | } | | 334 | } |
268 | } | | 335 | } |
269 | | | | |