Fri Jul 28 02:05:26 2023 UTC ()
Add Zen2 Mendocino APU support.


(msaitoh)
diff -r1.19 -r1.20 src/sys/arch/x86/pci/amdzentemp.c

cvs diff -r1.19 -r1.20 src/sys/arch/x86/pci/amdzentemp.c (switch to unified diff)

--- src/sys/arch/x86/pci/amdzentemp.c 2023/07/28 00:11:15 1.19
+++ src/sys/arch/x86/pci/amdzentemp.c 2023/07/28 02:05:26 1.20
@@ -1,498 +1,502 @@ @@ -1,498 +1,502 @@
1/* $NetBSD: amdzentemp.c,v 1.19 2023/07/28 00:11:15 msaitoh Exp $ */ 1/* $NetBSD: amdzentemp.c,v 1.20 2023/07/28 02:05:26 msaitoh 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, 2020 The NetBSD Foundation, Inc. 5 * Copyright (c) 2008, 2020 The NetBSD Foundation, Inc.
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
8 * Copyright (c) 2019 Conrad Meyer <cem@FreeBSD.org> 8 * Copyright (c) 2019 Conrad Meyer <cem@FreeBSD.org>
9 * All rights reserved. 9 * All rights reserved.
10 * 10 *
11 * This code is derived from software contributed to The NetBSD Foundation 11 * This code is derived from software contributed to The NetBSD Foundation
12 * by Christoph Egger. 12 * by Christoph Egger.
13 * 13 *
14 * NetBSD port by Ian Clark <mrrooster@gmail.com> 14 * NetBSD port by Ian Clark <mrrooster@gmail.com>
15 * 15 *
16 * Redistribution and use in source and binary forms, with or without 16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions 17 * modification, are permitted provided that the following conditions
18 * are met: 18 * are met:
19 * 1. Redistributions of source code must retain the above copyright 19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer. 20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright 21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the 22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution. 23 * documentation and/or other materials provided with the distribution.
24 * 24 *
25 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 25 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
26 * ``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
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * 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
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * 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
35 * POSSIBILITY OF SUCH DAMAGE. 35 * POSSIBILITY OF SUCH DAMAGE.
36 */ 36 */
37 37
38/* 38/*
39 * Copyright (c) 2008 Constantine A. Murenin <cnst+openbsd@bugmail.mojo.ru> 39 * Copyright (c) 2008 Constantine A. Murenin <cnst+openbsd@bugmail.mojo.ru>
40 * 40 *
41 * Permission to use, copy, modify, and distribute this software for any 41 * Permission to use, copy, modify, and distribute this software for any
42 * 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
43 * copyright notice and this permission notice appear in all copies. 43 * copyright notice and this permission notice appear in all copies.
44 * 44 *
45 * 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
46 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 46 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
47 * 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
48 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 48 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
49 * 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
50 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 50 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
51 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 51 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
52 */ 52 */
53 53
54 54
55#include <sys/cdefs.h> 55#include <sys/cdefs.h>
56__KERNEL_RCSID(0, "$NetBSD: amdzentemp.c,v 1.19 2023/07/28 00:11:15 msaitoh Exp $ "); 56__KERNEL_RCSID(0, "$NetBSD: amdzentemp.c,v 1.20 2023/07/28 02:05:26 msaitoh Exp $ ");
57 57
58#include <sys/param.h> 58#include <sys/param.h>
59#include <sys/bus.h> 59#include <sys/bus.h>
60#include <sys/cpu.h> 60#include <sys/cpu.h>
61#include <sys/systm.h> 61#include <sys/systm.h>
62#include <sys/device.h> 62#include <sys/device.h>
63#include <sys/kmem.h> 63#include <sys/kmem.h>
64#include <sys/module.h> 64#include <sys/module.h>
65 65
66#include <machine/specialreg.h> 66#include <machine/specialreg.h>
67 67
68#include <dev/pci/pcireg.h> 68#include <dev/pci/pcireg.h>
69#include <dev/pci/pcivar.h> 69#include <dev/pci/pcivar.h>
70#include <dev/pci/pcidevs.h> 70#include <dev/pci/pcidevs.h>
71 71
72#include <dev/sysmon/sysmonvar.h> 72#include <dev/sysmon/sysmonvar.h>
73 73
74#include "amdsmn.h" 74#include "amdsmn.h"
75 75
76#define AMD_CURTMP_RANGE_ADJUST 49000000 /* in microKelvins (ie, 49C) */ 76#define AMD_CURTMP_RANGE_ADJUST 49000000 /* in microKelvins (ie, 49C) */
77#define F10_TEMP_CURTMP __BITS(31,21) /* XXX same as amdtemp.c */ 77#define F10_TEMP_CURTMP __BITS(31,21) /* XXX same as amdtemp.c */
78#define F10_TEMP_CURTMP_MASK 0x7ff 78#define F10_TEMP_CURTMP_MASK 0x7ff
79#define F15M60_CURTMP_TJSEL __BITS(17,16) 79#define F15M60_CURTMP_TJSEL __BITS(17,16)
80 80
81/* 81/*
82 * Reported Temperature, Family 15h, M60+ 82 * Reported Temperature, Family 15h, M60+
83 * 83 *
84 * Same register bit definitions as other Family 15h CPUs, but access is 84 * Same register bit definitions as other Family 15h CPUs, but access is
85 * indirect via SMN, like Family 17h. 85 * indirect via SMN, like Family 17h.
86 */ 86 */
87#define AMD_15H_M60H_REPTMP_CTRL 0xd8200ca4 87#define AMD_15H_M60H_REPTMP_CTRL 0xd8200ca4
88 88
89/* 89/*
90 * Reported Temperature, Family 17h 90 * Reported Temperature, Family 17h
91 * 91 *
92 * According to AMD OSRR for 17H, section 4.2.1, bits 31-21 of this register 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 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 94 * a range 0.."225C" (probable typo for 255C), and when set changes the range
95 * to -49..206C. 95 * to -49..206C.
96 */ 96 */
97#define AMD_17H_CUR_TMP 0x59800 97#define AMD_17H_CUR_TMP 0x59800
98#define AMD_17H_CUR_TMP_RANGE_SEL __BIT(19) 98#define AMD_17H_CUR_TMP_RANGE_SEL __BIT(19)
99#define AMD_17H_CCD_TMP_VALID __BIT(11) 99#define AMD_17H_CCD_TMP_VALID __BIT(11)
100 100
101struct amdzentemp_softc { 101struct amdzentemp_softc {
102 device_t sc_dev; 102 device_t sc_dev;
103 struct sysmon_envsys *sc_sme; 103 struct sysmon_envsys *sc_sme;
104 device_t sc_smn; 104 device_t sc_smn;
105 envsys_data_t *sc_sensor; 105 envsys_data_t *sc_sensor;
106 size_t sc_sensor_len; 106 size_t sc_sensor_len;
107 size_t sc_numsensors; 107 size_t sc_numsensors;
108 int32_t sc_offset; 108 int32_t sc_offset;
109 int32_t sc_ccd_offset; 109 int32_t sc_ccd_offset;
110}; 110};
111 111
112enum { 112enum {
113 NOSENSOR = 0, 113 NOSENSOR = 0,
114 CORE0_SENSOR0, 114 CORE0_SENSOR0,
115 CCD_BASE, 115 CCD_BASE,
116 CCD0 = CCD_BASE, 116 CCD0 = CCD_BASE,
117 CCD1, 117 CCD1,
118 CCD2, 118 CCD2,
119 CCD3, 119 CCD3,
120 CCD4, 120 CCD4,
121 CCD5, 121 CCD5,
122 CCD6, 122 CCD6,
123 CCD7, 123 CCD7,
124 CCD8, 124 CCD8,
125 CCD9, 125 CCD9,
126 CCD10, 126 CCD10,
127 CCD11, 127 CCD11,
128 CCD_MAX, 128 CCD_MAX,
129 NUM_CCDS = CCD_MAX - CCD_BASE 129 NUM_CCDS = CCD_MAX - CCD_BASE
130}; 130};
131 131
132 132
133static int amdzentemp_match(device_t, cfdata_t, void *); 133static int amdzentemp_match(device_t, cfdata_t, void *);
134static void amdzentemp_attach(device_t, device_t, void *); 134static void amdzentemp_attach(device_t, device_t, void *);
135static int amdzentemp_detach(device_t, int); 135static int amdzentemp_detach(device_t, int);
136 136
137static void amdzentemp_init(struct amdzentemp_softc *, int, int); 137static void amdzentemp_init(struct amdzentemp_softc *, int, int);
138static void amdzentemp_setup_sensors(struct amdzentemp_softc *); 138static void amdzentemp_setup_sensors(struct amdzentemp_softc *);
139static void amdzentemp_family15_refresh(struct sysmon_envsys *, envsys_data_t *); 139static void amdzentemp_family15_refresh(struct sysmon_envsys *, envsys_data_t *);
140static void amdzentemp_family17_refresh(struct sysmon_envsys *, envsys_data_t *); 140static void amdzentemp_family17_refresh(struct sysmon_envsys *, envsys_data_t *);
141static int amdzentemp_probe_ccd_sensors(struct amdzentemp_softc *, int, int); 141static int amdzentemp_probe_ccd_sensors(struct amdzentemp_softc *, int, int);
142static void amdzentemp_setup_ccd_sensors(struct amdzentemp_softc *); 142static void amdzentemp_setup_ccd_sensors(struct amdzentemp_softc *);
143 143
144CFATTACH_DECL_NEW(amdzentemp, sizeof(struct amdzentemp_softc), 144CFATTACH_DECL_NEW(amdzentemp, sizeof(struct amdzentemp_softc),
145 amdzentemp_match, amdzentemp_attach, amdzentemp_detach, NULL); 145 amdzentemp_match, amdzentemp_attach, amdzentemp_detach, NULL);
146 146
147static int 147static int
148amdzentemp_match(device_t parent, cfdata_t match, void *aux) 148amdzentemp_match(device_t parent, cfdata_t match, void *aux)
149{ 149{
150 struct pci_attach_args *pa __diagused = aux; 150 struct pci_attach_args *pa __diagused = aux;
151 151
152 KASSERT(PCI_VENDOR(pa->pa_id) == PCI_VENDOR_AMD); 152 KASSERT(PCI_VENDOR(pa->pa_id) == PCI_VENDOR_AMD);
153 153
154 cfdata_t parent_cfdata = device_cfdata(parent); 154 cfdata_t parent_cfdata = device_cfdata(parent);
155 155
156 /* Got AMD family 17h system management network */ 156 /* Got AMD family 17h system management network */
157 return parent_cfdata->cf_name && 157 return parent_cfdata->cf_name &&
158 memcmp(parent_cfdata->cf_name, "amdsmn", 6) == 0; 158 memcmp(parent_cfdata->cf_name, "amdsmn", 6) == 0;
159} 159}
160 160
161static void 161static void
162amdzentemp_attach(device_t parent, device_t self, void *aux) 162amdzentemp_attach(device_t parent, device_t self, void *aux)
163{ 163{
164 struct amdzentemp_softc *sc = device_private(self); 164 struct amdzentemp_softc *sc = device_private(self);
165 struct cpu_info *ci = curcpu(); 165 struct cpu_info *ci = curcpu();
166 int family, model; 166 int family, model;
167 int error; 167 int error;
168 size_t i; 168 size_t i;
169 169
170 sc->sc_dev = self; 170 sc->sc_dev = self;
171 171
172 family = CPUID_TO_FAMILY(ci->ci_signature); 172 family = CPUID_TO_FAMILY(ci->ci_signature);
173 model = CPUID_TO_MODEL(ci->ci_signature); 173 model = CPUID_TO_MODEL(ci->ci_signature);
174 aprint_naive("\n"); 174 aprint_naive("\n");
175 aprint_normal(": AMD CPU Temperature Sensors (Family%xh)", family); 175 aprint_normal(": AMD CPU Temperature Sensors (Family%xh)", family);
176 176
177 sc->sc_smn = parent; 177 sc->sc_smn = parent;
178 178
179 amdzentemp_init(sc, family, model); 179 amdzentemp_init(sc, family, model);
180 180
181 aprint_normal("\n"); 181 aprint_normal("\n");
182 182
183 sc->sc_sme = sysmon_envsys_create(); 183 sc->sc_sme = sysmon_envsys_create();
184 sc->sc_sensor_len = sizeof(envsys_data_t) * sc->sc_numsensors; 184 sc->sc_sensor_len = sizeof(envsys_data_t) * sc->sc_numsensors;
185 sc->sc_sensor = kmem_zalloc(sc->sc_sensor_len, KM_SLEEP); 185 sc->sc_sensor = kmem_zalloc(sc->sc_sensor_len, KM_SLEEP);
186 186
187 amdzentemp_setup_sensors(sc); 187 amdzentemp_setup_sensors(sc);
188 188
189 /* 189 /*
190 * Set properties in sensors. 190 * Set properties in sensors.
191 */ 191 */
192 for (i = 0; i < sc->sc_numsensors; i++) { 192 for (i = 0; i < sc->sc_numsensors; i++) {
193 if (sc->sc_sensor[i].private == NOSENSOR) 193 if (sc->sc_sensor[i].private == NOSENSOR)
194 continue; 194 continue;
195 if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[i])) 195 if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[i]))
196 goto bad; 196 goto bad;
197 } 197 }
198 198
199 /* 199 /*
200 * Register the sysmon_envsys device. 200 * Register the sysmon_envsys device.
201 */ 201 */
202 sc->sc_sme->sme_name = device_xname(self); 202 sc->sc_sme->sme_name = device_xname(self);
203 sc->sc_sme->sme_cookie = sc; 203 sc->sc_sme->sme_cookie = sc;
204 204
205 switch (family) { 205 switch (family) {
206 case 0x15: 206 case 0x15:
207 sc->sc_sme->sme_refresh = amdzentemp_family15_refresh; 207 sc->sc_sme->sme_refresh = amdzentemp_family15_refresh;
208 break; 208 break;
209 case 0x17: 209 case 0x17:
210 case 0x19: 210 case 0x19:
211 sc->sc_sme->sme_refresh = amdzentemp_family17_refresh; 211 sc->sc_sme->sme_refresh = amdzentemp_family17_refresh;
212 break; 212 break;
213 default: 213 default:
214 /* XXX panic */ 214 /* XXX panic */
215 break; 215 break;
216 } 216 }
217 217
218 error = sysmon_envsys_register(sc->sc_sme); 218 error = sysmon_envsys_register(sc->sc_sme);
219 if (error) { 219 if (error) {
220 aprint_error_dev(self, "unable to register with sysmon " 220 aprint_error_dev(self, "unable to register with sysmon "
221 "(error=%d)\n", error); 221 "(error=%d)\n", error);
222 goto bad; 222 goto bad;
223 } 223 }
224 224
225 (void)pmf_device_register(self, NULL, NULL); 225 (void)pmf_device_register(self, NULL, NULL);
226 226
227 return; 227 return;
228 228
229bad: 229bad:
230 if (sc->sc_sme != NULL) { 230 if (sc->sc_sme != NULL) {
231 sysmon_envsys_destroy(sc->sc_sme); 231 sysmon_envsys_destroy(sc->sc_sme);
232 sc->sc_sme = NULL; 232 sc->sc_sme = NULL;
233 } 233 }
234 234
235 kmem_free(sc->sc_sensor, sc->sc_sensor_len); 235 kmem_free(sc->sc_sensor, sc->sc_sensor_len);
236 sc->sc_sensor = NULL; 236 sc->sc_sensor = NULL;
237} 237}
238 238
239static int 239static int
240amdzentemp_detach(device_t self, int flags) 240amdzentemp_detach(device_t self, int flags)
241{ 241{
242 struct amdzentemp_softc *sc = device_private(self); 242 struct amdzentemp_softc *sc = device_private(self);
243 243
244 pmf_device_deregister(self); 244 pmf_device_deregister(self);
245 if (sc->sc_sme != NULL) 245 if (sc->sc_sme != NULL)
246 sysmon_envsys_unregister(sc->sc_sme); 246 sysmon_envsys_unregister(sc->sc_sme);
247 247
248 if (sc->sc_sensor != NULL) 248 if (sc->sc_sensor != NULL)
249 kmem_free(sc->sc_sensor, sc->sc_sensor_len); 249 kmem_free(sc->sc_sensor, sc->sc_sensor_len);
250 250
251 return 0; 251 return 0;
252} 252}
253 253
254 254
255static void 255static void
256amdzentemp_init(struct amdzentemp_softc *sc, int family, int model) 256amdzentemp_init(struct amdzentemp_softc *sc, int family, int model)
257{ 257{
258 258
259 sc->sc_numsensors = 1 + amdzentemp_probe_ccd_sensors(sc, family, model); 259 sc->sc_numsensors = 1 + amdzentemp_probe_ccd_sensors(sc, family, model);
260 sc->sc_offset = 0; 260 sc->sc_offset = 0;
261 261
262 if (strstr(cpu_brand_string, "AMD Ryzen 5 1600X") 262 if (strstr(cpu_brand_string, "AMD Ryzen 5 1600X")
263 || strstr(cpu_brand_string, "AMD Ryzen 7 1700X") 263 || strstr(cpu_brand_string, "AMD Ryzen 7 1700X")
264 || strstr(cpu_brand_string, "AMD Ryzen 7 1800X")) 264 || strstr(cpu_brand_string, "AMD Ryzen 7 1800X"))
265 sc->sc_offset = -20000000; 265 sc->sc_offset = -20000000;
266 else if (strstr(cpu_brand_string, "AMD Ryzen 7 2700X")) 266 else if (strstr(cpu_brand_string, "AMD Ryzen 7 2700X"))
267 sc->sc_offset = -10000000; 267 sc->sc_offset = -10000000;
268 else if (strstr(cpu_brand_string, "AMD Ryzen Threadripper 19") 268 else if (strstr(cpu_brand_string, "AMD Ryzen Threadripper 19")
269 || strstr(cpu_brand_string, "AMD Ryzen Threadripper 29")) 269 || strstr(cpu_brand_string, "AMD Ryzen Threadripper 29"))
270 sc->sc_offset = -27000000; 270 sc->sc_offset = -27000000;
271} 271}
272 272
273static void 273static void
274amdzentemp_setup_sensors(struct amdzentemp_softc *sc) 274amdzentemp_setup_sensors(struct amdzentemp_softc *sc)
275{ 275{
276 sc->sc_sensor[0].units = ENVSYS_STEMP; 276 sc->sc_sensor[0].units = ENVSYS_STEMP;
277 sc->sc_sensor[0].state = ENVSYS_SVALID; 277 sc->sc_sensor[0].state = ENVSYS_SVALID;
278 sc->sc_sensor[0].flags = ENVSYS_FHAS_ENTROPY; 278 sc->sc_sensor[0].flags = ENVSYS_FHAS_ENTROPY;
279 sc->sc_sensor[0].private = CORE0_SENSOR0; 279 sc->sc_sensor[0].private = CORE0_SENSOR0;
280 280
281 snprintf(sc->sc_sensor[0].desc, sizeof(sc->sc_sensor[0].desc), 281 snprintf(sc->sc_sensor[0].desc, sizeof(sc->sc_sensor[0].desc),
282 "cpu%u temperature", device_unit(sc->sc_dev)); 282 "cpu%u temperature", device_unit(sc->sc_dev));
283 283
284 if (sc->sc_numsensors > 1) 284 if (sc->sc_numsensors > 1)
285 amdzentemp_setup_ccd_sensors(sc); 285 amdzentemp_setup_ccd_sensors(sc);
286} 286}
287 287
288static void 288static void
289amdzentemp_family15_refresh(struct sysmon_envsys *sme, 289amdzentemp_family15_refresh(struct sysmon_envsys *sme,
290 envsys_data_t *edata) 290 envsys_data_t *edata)
291{ 291{
292 struct amdzentemp_softc *sc = sme->sme_cookie; 292 struct amdzentemp_softc *sc = sme->sme_cookie;
293 uint32_t val, temp; 293 uint32_t val, temp;
294 int error; 294 int error;
295 295
296 error = amdsmn_read(sc->sc_smn, AMD_15H_M60H_REPTMP_CTRL, &val); 296 error = amdsmn_read(sc->sc_smn, AMD_15H_M60H_REPTMP_CTRL, &val);
297 if (error) { 297 if (error) {
298 edata->state = ENVSYS_SINVALID; 298 edata->state = ENVSYS_SINVALID;
299 return; 299 return;
300 } 300 }
301 301
302 /* from amdtemp.c:amdtemp_family10_refresh() */ 302 /* from amdtemp.c:amdtemp_family10_refresh() */
303 temp = __SHIFTOUT(val, F10_TEMP_CURTMP); 303 temp = __SHIFTOUT(val, F10_TEMP_CURTMP);
304 304
305 /* From Celsius to micro-Kelvin. */ 305 /* From Celsius to micro-Kelvin. */
306 edata->value_cur = (temp * 125000) + 273150000; 306 edata->value_cur = (temp * 125000) + 273150000;
307 307
308 /* 308 /*
309 * On Family 15h and higher, if CurTmpTjSel is 11b, the range is 309 * On Family 15h and higher, if CurTmpTjSel is 11b, the range is
310 * adjusted down by 49.0 degrees Celsius. (This adjustment is not 310 * adjusted down by 49.0 degrees Celsius. (This adjustment is not
311 * documented in BKDGs prior to family 15h model 00h.) 311 * documented in BKDGs prior to family 15h model 00h.)
312 * 312 *
313 * XXX should be in amdtemp.c:amdtemp_family10_refresh() for f15 313 * XXX should be in amdtemp.c:amdtemp_family10_refresh() for f15
314 * as well?? 314 * as well??
315 */ 315 */
316 if (__SHIFTOUT(val, F15M60_CURTMP_TJSEL) == 0x3) 316 if (__SHIFTOUT(val, F15M60_CURTMP_TJSEL) == 0x3)
317 edata->value_cur -= AMD_CURTMP_RANGE_ADJUST; 317 edata->value_cur -= AMD_CURTMP_RANGE_ADJUST;
318 318
319 edata->state = ENVSYS_SVALID; 319 edata->state = ENVSYS_SVALID;
320} 320}
321 321
322static void 322static void
323amdzentemp_family17_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 323amdzentemp_family17_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
324{ 324{
325 struct amdzentemp_softc *sc = sme->sme_cookie; 325 struct amdzentemp_softc *sc = sme->sme_cookie;
326 uint32_t temp; 326 uint32_t temp;
327 bool minus49; 327 bool minus49;
328 int i, error; 328 int i, error;
329 329
330 switch (edata->private) { 330 switch (edata->private) {
331 case CORE0_SENSOR0: 331 case CORE0_SENSOR0:
332 /* Tctl */ 332 /* Tctl */
333 error = amdsmn_read(sc->sc_smn, AMD_17H_CUR_TMP, &temp); 333 error = amdsmn_read(sc->sc_smn, AMD_17H_CUR_TMP, &temp);
334 if (error) { 334 if (error) {
335 edata->state = ENVSYS_SINVALID; 335 edata->state = ENVSYS_SINVALID;
336 return; 336 return;
337 } 337 }
338 minus49 = (temp & AMD_17H_CUR_TMP_RANGE_SEL) ? 338 minus49 = (temp & AMD_17H_CUR_TMP_RANGE_SEL) ?
339 true : false; 339 true : false;
340 temp = __SHIFTOUT(temp, F10_TEMP_CURTMP); 340 temp = __SHIFTOUT(temp, F10_TEMP_CURTMP);
341 break; 341 break;
342 case CCD_BASE ... (CCD_MAX - 1): 342 case CCD_BASE ... (CCD_MAX - 1):
343 /* Tccd */ 343 /* Tccd */
344 i = edata->private - CCD_BASE; 344 i = edata->private - CCD_BASE;
345 error = amdsmn_read(sc->sc_smn, 345 error = amdsmn_read(sc->sc_smn,
346 AMD_17H_CUR_TMP + sc->sc_ccd_offset + (i * sizeof(temp)), 346 AMD_17H_CUR_TMP + sc->sc_ccd_offset + (i * sizeof(temp)),
347 &temp); 347 &temp);
348 if (error || !ISSET(temp, AMD_17H_CCD_TMP_VALID)) { 348 if (error || !ISSET(temp, AMD_17H_CCD_TMP_VALID)) {
349 edata->state = ENVSYS_SINVALID; 349 edata->state = ENVSYS_SINVALID;
350 return; 350 return;
351 } 351 }
352 minus49 = true; 352 minus49 = true;
353 temp &= F10_TEMP_CURTMP_MASK; 353 temp &= F10_TEMP_CURTMP_MASK;
354 break; 354 break;
355 default: 355 default:
356 edata->state = ENVSYS_SINVALID; 356 edata->state = ENVSYS_SINVALID;
357 return; 357 return;
358 } 358 }
359 edata->state = ENVSYS_SVALID; 359 edata->state = ENVSYS_SVALID;
360 /* From C to uK. */ 360 /* From C to uK. */
361 edata->value_cur = (temp * 125000) + 273150000; 361 edata->value_cur = (temp * 125000) + 273150000;
362 /* adjust for possible offset of 49K */ 362 /* adjust for possible offset of 49K */
363 if (minus49) 363 if (minus49)
364 edata->value_cur -= AMD_CURTMP_RANGE_ADJUST; 364 edata->value_cur -= AMD_CURTMP_RANGE_ADJUST;
365 edata->value_cur += sc->sc_offset; 365 edata->value_cur += sc->sc_offset;
366} 366}
367 367
368static int 368static int
369amdzentemp_probe_ccd_sensors17h(struct amdzentemp_softc *sc, int model) 369amdzentemp_probe_ccd_sensors17h(struct amdzentemp_softc *sc, int model)
370{ 370{
371 int maxreg; 371 int maxreg;
372 372
373 sc->sc_ccd_offset = 0x154; 
374 
375 switch (model) { 373 switch (model) {
376 case 0x00 ... 0x2f: /* Zen1, Zen+ */ 374 case 0x00 ... 0x2f: /* Zen1, Zen+ */
 375 sc->sc_ccd_offset = 0x154;
377 maxreg = 4; 376 maxreg = 4;
378 break; 377 break;
379 case 0x30 ... 0x3f: /* Zen2 TR (Castle Peak)/EPYC (Rome) */ 378 case 0x30 ... 0x3f: /* Zen2 TR (Castle Peak)/EPYC (Rome) */
380 case 0x60 ... 0x7f: /* Zen2 Ryzen (Renoir APU, Matisse) */ 379 case 0x60 ... 0x7f: /* Zen2 Ryzen (Renoir APU, Matisse) */
381 case 0x90 ... 0x9f: /* Zen2 Ryzen (Van Gogh APU) */ 380 case 0x90 ... 0x9f: /* Zen2 Ryzen (Van Gogh APU) */
 381 sc->sc_ccd_offset = 0x154;
 382 maxreg = 8;
 383 break;
 384 case 0xa0 ... 0xaf: /* Zen2 Ryzen (Mendocino APU) */
 385 sc->sc_ccd_offset = 0x300;
382 maxreg = 8; 386 maxreg = 8;
383 break; 387 break;
384 default: 388 default:
385 aprint_error_dev(sc->sc_dev, 389 aprint_error_dev(sc->sc_dev,
386 "Unrecognized Family 17h Model: %02xh\n", model); 390 "Unrecognized Family 17h Model: %02xh\n", model);
387 return 0; 391 return 0;
388 } 392 }
389 393
390 return maxreg; 394 return maxreg;
391} 395}
392 396
393static int 397static int
394amdzentemp_probe_ccd_sensors19h(struct amdzentemp_softc *sc, int model) 398amdzentemp_probe_ccd_sensors19h(struct amdzentemp_softc *sc, int model)
395{ 399{
396 int maxreg; 400 int maxreg;
397 401
398 switch (model) { 402 switch (model) {
399 case 0x00 ... 0x0f: /* Zen3 EPYC "Milan" */ 403 case 0x00 ... 0x0f: /* Zen3 EPYC "Milan" */
400 case 0x20 ... 0x2f: /* Zen3 Ryzen "Vermeer" */ 404 case 0x20 ... 0x2f: /* Zen3 Ryzen "Vermeer" */
401 case 0x50 ... 0x5f: /* Zen3 Ryzen "Cezanne" */ 405 case 0x50 ... 0x5f: /* Zen3 Ryzen "Cezanne" */
402 sc->sc_ccd_offset = 0x154; 406 sc->sc_ccd_offset = 0x154;
403 maxreg = 8; 407 maxreg = 8;
404 break; 408 break;
405 case 0x60 ... 0x6f: /* Zen4 Ryzen "Raphael" */ 409 case 0x60 ... 0x6f: /* Zen4 Ryzen "Raphael" */
406 case 0x70 ... 0x7f: /* Zen4 Ryzen "Phoenix" */ 410 case 0x70 ... 0x7f: /* Zen4 Ryzen "Phoenix" */
407 sc->sc_ccd_offset = 0x308; 411 sc->sc_ccd_offset = 0x308;
408 maxreg = 8; 412 maxreg = 8;
409 break; 413 break;
410 case 0x40 ... 0x4f: /* Zen3+ "Rembrandt" */ 414 case 0x40 ... 0x4f: /* Zen3+ "Rembrandt" */
411 sc->sc_ccd_offset = 0x300; 415 sc->sc_ccd_offset = 0x300;
412 maxreg = 8; 416 maxreg = 8;
413 break; 417 break;
414 case 0x10 ... 0x1f: /* Zen4 "Genoa" */ 418 case 0x10 ... 0x1f: /* Zen4 "Genoa" */
415 sc->sc_ccd_offset = 0x300; 419 sc->sc_ccd_offset = 0x300;
416 maxreg = 12; 420 maxreg = 12;
417 break; 421 break;
418 default: 422 default:
419 aprint_error_dev(sc->sc_dev, 423 aprint_error_dev(sc->sc_dev,
420 "Unrecognized Family 19h Model: %02xh\n", model); 424 "Unrecognized Family 19h Model: %02xh\n", model);
421 return 0; 425 return 0;
422 } 426 }
423 427
424 return maxreg; 428 return maxreg;
425} 429}
426 430
427static int 431static int
428amdzentemp_probe_ccd_sensors(struct amdzentemp_softc *sc, int family, int model) 432amdzentemp_probe_ccd_sensors(struct amdzentemp_softc *sc, int family, int model)
429{ 433{
430 int nccd; 434 int nccd;
431 435
432 switch (family) { 436 switch (family) {
433 case 0x17: 437 case 0x17:
434 nccd = amdzentemp_probe_ccd_sensors17h(sc, model); 438 nccd = amdzentemp_probe_ccd_sensors17h(sc, model);
435 break; 439 break;
436 case 0x19: 440 case 0x19:
437 nccd = amdzentemp_probe_ccd_sensors19h(sc, model); 441 nccd = amdzentemp_probe_ccd_sensors19h(sc, model);
438 break; 442 break;
439 default: 443 default:
440 return 0; 444 return 0;
441 } 445 }
442 446
443 return nccd; 447 return nccd;
444} 448}
445 449
446static void 450static void
447amdzentemp_setup_ccd_sensors(struct amdzentemp_softc *sc) 451amdzentemp_setup_ccd_sensors(struct amdzentemp_softc *sc)
448{ 452{
449 envsys_data_t *edata; 453 envsys_data_t *edata;
450 size_t i; 454 size_t i;
451 uint32_t temp; 455 uint32_t temp;
452 int error; 456 int error;
453 457
454 for (i = 0; i < sc->sc_numsensors - 1; i++) { 458 for (i = 0; i < sc->sc_numsensors - 1; i++) {
455 error = amdsmn_read(sc->sc_smn, 459 error = amdsmn_read(sc->sc_smn,
456 AMD_17H_CUR_TMP + sc->sc_ccd_offset + (i * sizeof(temp)), 460 AMD_17H_CUR_TMP + sc->sc_ccd_offset + (i * sizeof(temp)),
457 &temp); 461 &temp);
458 if (error || !ISSET(temp, AMD_17H_CCD_TMP_VALID)) 462 if (error || !ISSET(temp, AMD_17H_CCD_TMP_VALID))
459 continue; 463 continue;
460 464
461 edata = &sc->sc_sensor[1 + i]; 465 edata = &sc->sc_sensor[1 + i];
462 edata->units = ENVSYS_STEMP; 466 edata->units = ENVSYS_STEMP;
463 edata->state = ENVSYS_SVALID; 467 edata->state = ENVSYS_SVALID;
464 edata->flags = ENVSYS_FHAS_ENTROPY; 468 edata->flags = ENVSYS_FHAS_ENTROPY;
465 edata->private = CCD_BASE + i; 469 edata->private = CCD_BASE + i;
466 snprintf(edata->desc, sizeof(edata->desc), 470 snprintf(edata->desc, sizeof(edata->desc),
467 "cpu%u ccd%zu temperature", device_unit(sc->sc_dev), i); 471 "cpu%u ccd%zu temperature", device_unit(sc->sc_dev), i);
468 } 472 }
469} 473}
470 474
471MODULE(MODULE_CLASS_DRIVER, amdzentemp, "sysmon_envsys,amdsmn"); 475MODULE(MODULE_CLASS_DRIVER, amdzentemp, "sysmon_envsys,amdsmn");
472 476
473#ifdef _MODULE 477#ifdef _MODULE
474#include "ioconf.c" 478#include "ioconf.c"
475#endif 479#endif
476 480
477static int 481static int
478amdzentemp_modcmd(modcmd_t cmd, void *aux) 482amdzentemp_modcmd(modcmd_t cmd, void *aux)
479{ 483{
480 int error = 0; 484 int error = 0;
481 485
482 switch (cmd) { 486 switch (cmd) {
483 case MODULE_CMD_INIT: 487 case MODULE_CMD_INIT:
484#ifdef _MODULE 488#ifdef _MODULE
485 error = config_init_component(cfdriver_ioconf_amdzentemp, 489 error = config_init_component(cfdriver_ioconf_amdzentemp,
486 cfattach_ioconf_amdzentemp, cfdata_ioconf_amdzentemp); 490 cfattach_ioconf_amdzentemp, cfdata_ioconf_amdzentemp);
487#endif 491#endif
488 return error; 492 return error;
489 case MODULE_CMD_FINI: 493 case MODULE_CMD_FINI:
490#ifdef _MODULE 494#ifdef _MODULE
491 error = config_fini_component(cfdriver_ioconf_amdzentemp, 495 error = config_fini_component(cfdriver_ioconf_amdzentemp,
492 cfattach_ioconf_amdzentemp, cfdata_ioconf_amdzentemp); 496 cfattach_ioconf_amdzentemp, cfdata_ioconf_amdzentemp);
493#endif 497#endif
494 return error; 498 return error;
495 default: 499 default:
496 return ENOTTY; 500 return ENOTTY;
497 } 501 }
498} 502}