Mon Apr 20 11:03:02 2020 UTC ()
Update to support Family 15h Model 60 temperature sensors.

Changes based on FreeBSD amdtemp driver changes by Conrad Meyer.

XXX: Some code duplication between this driver and amdtemp as
     parts of the 15h refresh code share more in common with
     older CPUs while accessing the device more like 17h.


(simonb)
diff -r1.6 -r1.7 src/sys/arch/x86/pci/amdsmn.c
diff -r1.9 -r1.10 src/sys/arch/x86/pci/amdzentemp.c

cvs diff -r1.6 -r1.7 src/sys/arch/x86/pci/amdsmn.c (expand / switch to unified diff)

--- src/sys/arch/x86/pci/amdsmn.c 2019/08/06 05:32:44 1.6
+++ src/sys/arch/x86/pci/amdsmn.c 2020/04/20 11:03:02 1.7
@@ -1,17 +1,17 @@ @@ -1,17 +1,17 @@
1/* $NetBSD: amdsmn.c,v 1.6 2019/08/06 05:32:44 msaitoh Exp $ */ 1/* $NetBSD: amdsmn.c,v 1.7 2020/04/20 11:03:02 simonb Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2017 Conrad Meyer <cem@FreeBSD.org> 4 * Copyright (c) 2017, 2019 Conrad Meyer <cem@FreeBSD.org>
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * NetBSD port by Ian Clark <mrrooster@gmail.com> 7 * NetBSD port by Ian Clark <mrrooster@gmail.com>
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
17 * 17 *
@@ -19,65 +19,89 @@ @@ -19,65 +19,89 @@
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 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 27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE. 28 * POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31#include <sys/cdefs.h> 31#include <sys/cdefs.h>
32__KERNEL_RCSID(0, "$NetBSD: amdsmn.c,v 1.6 2019/08/06 05:32:44 msaitoh Exp $ "); 32__KERNEL_RCSID(0, "$NetBSD: amdsmn.c,v 1.7 2020/04/20 11:03:02 simonb Exp $ ");
33 33
34/* 34/*
35 * Driver for the AMD Family 17h CPU System Management Network. 35 * Driver for the AMD Family 15h (model 60+) and 17h CPU
 36 * System Management Network.
36 */ 37 */
37 38
38#include <sys/param.h> 39#include <sys/param.h>
39#include <sys/device.h> 40#include <sys/device.h>
40#include <sys/errno.h> 41#include <sys/errno.h>
41#include <sys/mutex.h> 42#include <sys/mutex.h>
42#include <sys/systm.h> 43#include <sys/systm.h>
43#include <sys/cpu.h> 44#include <sys/cpu.h>
44#include <sys/module.h> 45#include <sys/module.h>
45 46
46#include <machine/specialreg.h> 47#include <machine/specialreg.h>
47 48
48#include <dev/pci/pcireg.h> 49#include <dev/pci/pcireg.h>
49#include <dev/pci/pcivar.h> 50#include <dev/pci/pcivar.h>
50#include <dev/pci/pcidevs.h> 51#include <dev/pci/pcidevs.h>
51 52
52#include "amdsmn.h" 53#include "amdsmn.h"
53#include "ioconf.h" 54#include "ioconf.h"
54 55
55#define SMN_ADDR_REG 0x60 56#define F15H_SMN_ADDR_REG 0xb8
56#define SMN_DATA_REG 0x64 57#define F15H_SMN_DATA_REG 0xbc
 58#define F17H_SMN_ADDR_REG 0x60
 59#define F17H_SMN_DATA_REG 0x64
57 60
58struct amdsmn_softc { 61struct amdsmn_softc {
59 kmutex_t smn_lock; 62 kmutex_t smn_lock;
 63 uint8_t smn_addr_reg;
 64 uint8_t smn_data_reg;
60 struct pci_attach_args pa; 65 struct pci_attach_args pa;
61 pci_chipset_tag_t pc; 66 pci_chipset_tag_t pc;
62 pcitag_t pcitag; 67 pcitag_t pcitag;
63}; 68};
64 69
65static const struct pciid { 70static const struct pciid {
66 uint16_t amdsmn_deviceid; 71 uint16_t amdsmn_deviceid;
 72 uint8_t amdsmn_addr_reg;
 73 uint8_t amdsmn_data_reg;
67} amdsmn_ids[] = { 74} amdsmn_ids[] = {
68 { PCI_PRODUCT_AMD_F17_RC }, 75 {
69 { PCI_PRODUCT_AMD_F17_1X_RC }, 76 .amdsmn_deviceid = PCI_PRODUCT_AMD_F15_60_RC,
70 { PCI_PRODUCT_AMD_F17_7X_RC }, 77 .amdsmn_addr_reg = F15H_SMN_ADDR_REG,
 78 .amdsmn_data_reg = F15H_SMN_DATA_REG,
 79 },
 80 {
 81 .amdsmn_deviceid = PCI_PRODUCT_AMD_F17_RC,
 82 .amdsmn_addr_reg = F17H_SMN_ADDR_REG,
 83 .amdsmn_data_reg = F17H_SMN_DATA_REG,
 84 },
 85 {
 86 .amdsmn_deviceid = PCI_PRODUCT_AMD_F17_1X_RC,
 87 .amdsmn_addr_reg = F17H_SMN_ADDR_REG,
 88 .amdsmn_data_reg = F17H_SMN_DATA_REG,
 89 },
 90 {
 91 .amdsmn_deviceid = PCI_PRODUCT_AMD_F17_7X_RC,
 92 .amdsmn_addr_reg = F17H_SMN_ADDR_REG,
 93 .amdsmn_data_reg = F17H_SMN_DATA_REG,
 94 },
71}; 95};
72 96
73static int amdsmn_match(device_t, cfdata_t, void *); 97static int amdsmn_match(device_t, cfdata_t, void *);
74static void amdsmn_attach(device_t, device_t, void *); 98static void amdsmn_attach(device_t, device_t, void *);
75static int amdsmn_rescan(device_t, const char *, const int *); 99static int amdsmn_rescan(device_t, const char *, const int *);
76static int amdsmn_detach(device_t, int); 100static int amdsmn_detach(device_t, int);
77static int amdsmn_misc_search(device_t, cfdata_t, const int *, void *); 101static int amdsmn_misc_search(device_t, cfdata_t, const int *, void *);
78 102
79CFATTACH_DECL3_NEW(amdsmn, sizeof(struct amdsmn_softc), amdsmn_match, 103CFATTACH_DECL3_NEW(amdsmn, sizeof(struct amdsmn_softc), amdsmn_match,
80 amdsmn_attach, amdsmn_detach, NULL, amdsmn_rescan, NULL, 0); 104 amdsmn_attach, amdsmn_detach, NULL, amdsmn_rescan, NULL, 0);
81 105
82static int 106static int
83amdsmn_match(device_t parent, cfdata_t match, void *aux) 107amdsmn_match(device_t parent, cfdata_t match, void *aux)
@@ -100,32 +124,41 @@ amdsmn_misc_search(device_t parent, cfda @@ -100,32 +124,41 @@ amdsmn_misc_search(device_t parent, cfda
100{ 124{
101 if (config_match(parent, cf, aux)) 125 if (config_match(parent, cf, aux))
102 config_attach_loc(parent, cf, locs, aux, NULL); 126 config_attach_loc(parent, cf, locs, aux, NULL);
103 127
104 return 0; 128 return 0;
105} 129}
106 130
107static void 131static void
108amdsmn_attach(device_t parent, device_t self, void *aux) 132amdsmn_attach(device_t parent, device_t self, void *aux)
109{ 133{
110 struct amdsmn_softc *sc = device_private(self); 134 struct amdsmn_softc *sc = device_private(self);
111 struct pci_attach_args *pa = aux; 135 struct pci_attach_args *pa = aux;
112 int flags = 0; 136 int flags = 0;
 137 int i;
113 138
114 mutex_init(&sc->smn_lock, MUTEX_DEFAULT, IPL_NONE); 139 mutex_init(&sc->smn_lock, MUTEX_DEFAULT, IPL_NONE);
115 sc->pa = *pa; 140 sc->pa = *pa;
116 sc->pc = pa->pa_pc; 141 sc->pc = pa->pa_pc;
117 sc->pcitag = pa->pa_tag; 142 sc->pcitag = pa->pa_tag;
118 aprint_normal(": AMD Family 17h System Management Network\n"); 143
 144 for (i = 0; i < __arraycount(amdsmn_ids); i++)
 145 if (PCI_PRODUCT(pa->pa_id) == amdsmn_ids[i].amdsmn_deviceid) {
 146 sc->smn_addr_reg = amdsmn_ids[i].amdsmn_addr_reg;
 147 sc->smn_data_reg = amdsmn_ids[i].amdsmn_data_reg;
 148 }
 149
 150 // aprint_normal(": AMD Family 17h System Management Network\n");
 151 aprint_normal(": AMD System Management Network\n");
119 amdsmn_rescan(self, "amdsmnbus", &flags); 152 amdsmn_rescan(self, "amdsmnbus", &flags);
120} 153}
121 154
122static int 155static int
123amdsmn_rescan(device_t self, const char *ifattr, const int *flags) 156amdsmn_rescan(device_t self, const char *ifattr, const int *flags)
124{ 157{
125 struct amdsmn_softc *sc = device_private(self); 158 struct amdsmn_softc *sc = device_private(self);
126 159
127 config_search_loc(amdsmn_misc_search, self, ifattr, NULL, &sc->pa); 160 config_search_loc(amdsmn_misc_search, self, ifattr, NULL, &sc->pa);
128 161
129 return 0; 162 return 0;
130} 163}
131 164
@@ -136,41 +169,41 @@ amdsmn_detach(device_t self, int flags) @@ -136,41 +169,41 @@ amdsmn_detach(device_t self, int flags)
136 169
137 mutex_destroy(&sc->smn_lock); 170 mutex_destroy(&sc->smn_lock);
138 aprint_normal_dev(self,"detach!\n"); 171 aprint_normal_dev(self,"detach!\n");
139 172
140 return 0; 173 return 0;
141} 174}
142 175
143int 176int
144amdsmn_read(device_t dev, uint32_t addr, uint32_t *value) 177amdsmn_read(device_t dev, uint32_t addr, uint32_t *value)
145{ 178{
146 struct amdsmn_softc *sc = device_private(dev); 179 struct amdsmn_softc *sc = device_private(dev);
147 180
148 mutex_enter(&sc->smn_lock); 181 mutex_enter(&sc->smn_lock);
149 pci_conf_write(sc->pc, sc->pcitag, SMN_ADDR_REG, addr); 182 pci_conf_write(sc->pc, sc->pcitag, sc->smn_addr_reg, addr);
150 *value = pci_conf_read(sc->pc, sc->pcitag, SMN_DATA_REG); 183 *value = pci_conf_read(sc->pc, sc->pcitag, sc->smn_data_reg);
151 mutex_exit(&sc->smn_lock); 184 mutex_exit(&sc->smn_lock);
152 185
153 return 0; 186 return 0;
154} 187}
155 188
156int 189int
157amdsmn_write(device_t dev, uint32_t addr, uint32_t value) 190amdsmn_write(device_t dev, uint32_t addr, uint32_t value)
158{ 191{
159 struct amdsmn_softc *sc = device_private(dev); 192 struct amdsmn_softc *sc = device_private(dev);
160 193
161 mutex_enter(&sc->smn_lock); 194 mutex_enter(&sc->smn_lock);
162 pci_conf_write(sc->pc, sc->pcitag, SMN_ADDR_REG, addr); 195 pci_conf_write(sc->pc, sc->pcitag, sc->smn_addr_reg, addr);
163 pci_conf_write(sc->pc, sc->pcitag, SMN_DATA_REG, value); 196 pci_conf_write(sc->pc, sc->pcitag, sc->smn_data_reg, value);
164 mutex_exit(&sc->smn_lock); 197 mutex_exit(&sc->smn_lock);
165 198
166 return 0; 199 return 0;
167} 200}
168 201
169MODULE(MODULE_CLASS_DRIVER, amdsmn, "pci"); 202MODULE(MODULE_CLASS_DRIVER, amdsmn, "pci");
170 203
171#ifdef _MODULE 204#ifdef _MODULE
172#include "ioconf.c" 205#include "ioconf.c"
173#endif 206#endif
174 207
175static int 208static int
176amdsmn_modcmd(modcmd_t cmd, void *opaque) 209amdsmn_modcmd(modcmd_t cmd, void *opaque)

cvs diff -r1.9 -r1.10 src/sys/arch/x86/pci/amdzentemp.c (expand / switch to unified diff)

--- src/sys/arch/x86/pci/amdzentemp.c 2019/06/16 09:12:51 1.9
+++ src/sys/arch/x86/pci/amdzentemp.c 2020/04/20 11:03:02 1.10
@@ -1,18 +1,21 @@ @@ -1,18 +1,21 @@
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
@@ -40,126 +43,156 @@ @@ -40,126 +43,156 @@
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
76struct amdzentemp_softc { 99struct 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
88static int amdzentemp_match(device_t, cfdata_t, void *); 109static int amdzentemp_match(device_t, cfdata_t, void *);
89static void amdzentemp_attach(device_t, device_t, void *); 110static void amdzentemp_attach(device_t, device_t, void *);
90static int amdzentemp_detach(device_t, int); 111static int amdzentemp_detach(device_t, int);
91 112
92static void amdzentemp_family17_init(struct amdzentemp_softc *); 113static void amdzentemp_init(struct amdzentemp_softc *);
93static void amdzentemp_family17_setup_sensors(struct amdzentemp_softc *, int); 114static void amdzentemp_setup_sensors(struct amdzentemp_softc *, int);
 115static void amdzentemp_family15_refresh(struct sysmon_envsys *, envsys_data_t *);
94static void amdzentemp_family17_refresh(struct sysmon_envsys *, envsys_data_t *); 116static void amdzentemp_family17_refresh(struct sysmon_envsys *, envsys_data_t *);
95 117
96CFATTACH_DECL_NEW(amdzentemp, sizeof(struct amdzentemp_softc), 118CFATTACH_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
99static int 121static int
100amdzentemp_match(device_t parent, cfdata_t match, void *aux) 122amdzentemp_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
113static void 135static void
114amdzentemp_attach(device_t parent, device_t self, void *aux) 136amdzentemp_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
165bad: 198bad:
@@ -179,72 +212,106 @@ amdzentemp_detach(device_t self, int fla @@ -179,72 +212,106 @@ amdzentemp_detach(device_t self, int fla
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
191static void 224static void
192amdzentemp_family17_init(struct amdzentemp_softc *sc)  225amdzentemp_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
209static void 242static void
210amdzentemp_family17_setup_sensors(struct amdzentemp_softc *sc, int dv_unit)  243amdzentemp_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
220static void 253static void
 254amdzentemp_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
 287static void
221amdzentemp_family17_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)  288amdzentemp_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
241MODULE(MODULE_CLASS_DRIVER, amdzentemp, "sysmon_envsys,amdsmn"); 308MODULE(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
247static int 314static int
248amdzentemp_modcmd(modcmd_t cmd, void *aux) 315amdzentemp_modcmd(modcmd_t cmd, void *aux)
249{ 316{
250 int error = 0; 317 int error = 0;
@@ -256,14 +323,13 @@ amdzentemp_modcmd(modcmd_t cmd, void *au @@ -256,14 +323,13 @@ amdzentemp_modcmd(modcmd_t cmd, void *au
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