hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/hwmon/k10temp.c
....@@ -1,25 +1,21 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
2
- * k10temp.c - AMD Family 10h/11h/12h/14h/15h/16h processor hardware monitoring
3
+ * k10temp.c - AMD Family 10h/11h/12h/14h/15h/16h/17h
4
+ * processor hardware monitoring
35 *
46 * Copyright (c) 2009 Clemens Ladisch <clemens@ladisch.de>
7
+ * Copyright (c) 2020 Guenter Roeck <linux@roeck-us.net>
58 *
6
- *
7
- * This driver is free software; you can redistribute it and/or
8
- * modify it under the terms of the GNU General Public License; either
9
- * version 2 of the License, or (at your option) any later version.
10
- *
11
- * This driver is distributed in the hope that it will be useful,
12
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
- * See the GNU General Public License for more details.
15
- *
16
- * You should have received a copy of the GNU General Public License
17
- * along with this driver; if not, see <http://www.gnu.org/licenses/>.
9
+ * Implementation notes:
10
+ * - CCD register address information as well as the calculation to
11
+ * convert raw register values is from https://github.com/ocerman/zenpower.
12
+ * The information is not confirmed from chip datasheets, but experiments
13
+ * suggest that it provides reasonable temperature values.
1814 */
1915
16
+#include <linux/bitops.h>
2017 #include <linux/err.h>
2118 #include <linux/hwmon.h>
22
-#include <linux/hwmon-sysfs.h>
2319 #include <linux/init.h>
2420 #include <linux/module.h>
2521 #include <linux/pci.h>
....@@ -43,22 +39,22 @@
4339 #endif
4440
4541 /* CPUID function 0x80000001, ebx */
46
-#define CPUID_PKGTYPE_MASK 0xf0000000
42
+#define CPUID_PKGTYPE_MASK GENMASK(31, 28)
4743 #define CPUID_PKGTYPE_F 0x00000000
4844 #define CPUID_PKGTYPE_AM2R2_AM3 0x10000000
4945
5046 /* DRAM controller (PCI function 2) */
5147 #define REG_DCT0_CONFIG_HIGH 0x094
52
-#define DDR3_MODE 0x00000100
48
+#define DDR3_MODE BIT(8)
5349
5450 /* miscellaneous (PCI function 3) */
5551 #define REG_HARDWARE_THERMAL_CONTROL 0x64
56
-#define HTC_ENABLE 0x00000001
52
+#define HTC_ENABLE BIT(0)
5753
5854 #define REG_REPORTED_TEMPERATURE 0xa4
5955
6056 #define REG_NORTHBRIDGE_CAPABILITIES 0xe8
61
-#define NB_CAP_HTC 0x00000400
57
+#define NB_CAP_HTC BIT(10)
6258
6359 /*
6460 * For F15h M60h and M70h, REG_HARDWARE_THERMAL_CONTROL
....@@ -69,8 +65,36 @@
6965 #define F15H_M60H_HARDWARE_TEMP_CTRL_OFFSET 0xd8200c64
7066 #define F15H_M60H_REPORTED_TEMP_CTRL_OFFSET 0xd8200ca4
7167
72
-/* F17h M01h Access througn SMN */
73
-#define F17H_M01H_REPORTED_TEMP_CTRL_OFFSET 0x00059800
68
+/* Common for Zen CPU families (Family 17h and 18h) */
69
+#define ZEN_REPORTED_TEMP_CTRL_OFFSET 0x00059800
70
+
71
+#define ZEN_CCD_TEMP(x) (0x00059954 + ((x) * 4))
72
+#define ZEN_CCD_TEMP_VALID BIT(11)
73
+#define ZEN_CCD_TEMP_MASK GENMASK(10, 0)
74
+
75
+#define ZEN_CUR_TEMP_SHIFT 21
76
+#define ZEN_CUR_TEMP_RANGE_SEL_MASK BIT(19)
77
+#define ZEN_CUR_TEMP_TJ_SEL_MASK GENMASK(17, 16)
78
+
79
+#define ZEN_SVI_BASE 0x0005A000
80
+
81
+/* F17h thermal registers through SMN */
82
+#define F17H_M01H_SVI_TEL_PLANE0 (ZEN_SVI_BASE + 0xc)
83
+#define F17H_M01H_SVI_TEL_PLANE1 (ZEN_SVI_BASE + 0x10)
84
+#define F17H_M31H_SVI_TEL_PLANE0 (ZEN_SVI_BASE + 0x14)
85
+#define F17H_M31H_SVI_TEL_PLANE1 (ZEN_SVI_BASE + 0x10)
86
+
87
+#define F17H_M01H_CFACTOR_ICORE 1000000 /* 1A / LSB */
88
+#define F17H_M01H_CFACTOR_ISOC 250000 /* 0.25A / LSB */
89
+#define F17H_M31H_CFACTOR_ICORE 1000000 /* 1A / LSB */
90
+#define F17H_M31H_CFACTOR_ISOC 310000 /* 0.31A / LSB */
91
+
92
+/* F19h thermal registers through SMN */
93
+#define F19H_M01_SVI_TEL_PLANE0 (ZEN_SVI_BASE + 0x14)
94
+#define F19H_M01_SVI_TEL_PLANE1 (ZEN_SVI_BASE + 0x10)
95
+
96
+#define F19H_M01H_CFACTOR_ICORE 1000000 /* 1A / LSB */
97
+#define F19H_M01H_CFACTOR_ISOC 310000 /* 0.31A / LSB */
7498
7599 struct k10temp_data {
76100 struct pci_dev *pdev;
....@@ -78,8 +102,16 @@
78102 void (*read_tempreg)(struct pci_dev *pdev, u32 *regval);
79103 int temp_offset;
80104 u32 temp_adjust_mask;
81
- bool show_tdie;
105
+ u32 show_temp;
106
+ bool is_zen;
82107 };
108
+
109
+#define TCTL_BIT 0
110
+#define TDIE_BIT 1
111
+#define TCCD_BIT(x) ((x) + 2)
112
+
113
+#define HAVE_TEMP(d, channel) ((d)->show_temp & BIT(channel))
114
+#define HAVE_TDIE(d) HAVE_TEMP(d, TDIE_BIT)
83115
84116 struct tctl_offset {
85117 u8 model;
....@@ -129,135 +161,157 @@
129161 F15H_M60H_REPORTED_TEMP_CTRL_OFFSET, regval);
130162 }
131163
132
-static void read_tempreg_nb_f17(struct pci_dev *pdev, u32 *regval)
164
+static void read_tempreg_nb_zen(struct pci_dev *pdev, u32 *regval)
133165 {
134166 amd_smn_read(amd_pci_dev_to_node_id(pdev),
135
- F17H_M01H_REPORTED_TEMP_CTRL_OFFSET, regval);
167
+ ZEN_REPORTED_TEMP_CTRL_OFFSET, regval);
136168 }
137169
138
-static unsigned int get_raw_temp(struct k10temp_data *data)
170
+static long get_raw_temp(struct k10temp_data *data)
139171 {
140
- unsigned int temp;
141172 u32 regval;
173
+ long temp;
142174
143175 data->read_tempreg(data->pdev, &regval);
144
- temp = (regval >> 21) * 125;
145
- if (regval & data->temp_adjust_mask)
176
+ temp = (regval >> ZEN_CUR_TEMP_SHIFT) * 125;
177
+ if ((regval & data->temp_adjust_mask) ||
178
+ (regval & ZEN_CUR_TEMP_TJ_SEL_MASK) == ZEN_CUR_TEMP_TJ_SEL_MASK)
146179 temp -= 49000;
147180 return temp;
148181 }
149182
150
-static ssize_t temp1_input_show(struct device *dev,
151
- struct device_attribute *attr, char *buf)
183
+static const char *k10temp_temp_label[] = {
184
+ "Tctl",
185
+ "Tdie",
186
+ "Tccd1",
187
+ "Tccd2",
188
+ "Tccd3",
189
+ "Tccd4",
190
+ "Tccd5",
191
+ "Tccd6",
192
+ "Tccd7",
193
+ "Tccd8",
194
+};
195
+
196
+static int k10temp_read_labels(struct device *dev,
197
+ enum hwmon_sensor_types type,
198
+ u32 attr, int channel, const char **str)
199
+{
200
+ switch (type) {
201
+ case hwmon_temp:
202
+ *str = k10temp_temp_label[channel];
203
+ break;
204
+ default:
205
+ return -EOPNOTSUPP;
206
+ }
207
+ return 0;
208
+}
209
+
210
+static int k10temp_read_temp(struct device *dev, u32 attr, int channel,
211
+ long *val)
152212 {
153213 struct k10temp_data *data = dev_get_drvdata(dev);
154
- unsigned int temp = get_raw_temp(data);
155
-
156
- if (temp > data->temp_offset)
157
- temp -= data->temp_offset;
158
- else
159
- temp = 0;
160
-
161
- return sprintf(buf, "%u\n", temp);
162
-}
163
-
164
-static ssize_t temp2_input_show(struct device *dev,
165
- struct device_attribute *devattr, char *buf)
166
-{
167
- struct k10temp_data *data = dev_get_drvdata(dev);
168
- unsigned int temp = get_raw_temp(data);
169
-
170
- return sprintf(buf, "%u\n", temp);
171
-}
172
-
173
-static ssize_t temp_label_show(struct device *dev,
174
- struct device_attribute *devattr, char *buf)
175
-{
176
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
177
-
178
- return sprintf(buf, "%s\n", attr->index ? "Tctl" : "Tdie");
179
-}
180
-
181
-static ssize_t temp1_max_show(struct device *dev,
182
- struct device_attribute *attr, char *buf)
183
-{
184
- return sprintf(buf, "%d\n", 70 * 1000);
185
-}
186
-
187
-static ssize_t show_temp_crit(struct device *dev,
188
- struct device_attribute *devattr, char *buf)
189
-{
190
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
191
- struct k10temp_data *data = dev_get_drvdata(dev);
192
- int show_hyst = attr->index;
193214 u32 regval;
194
- int value;
195215
196
- data->read_htcreg(data->pdev, &regval);
197
- value = ((regval >> 16) & 0x7f) * 500 + 52000;
198
- if (show_hyst)
199
- value -= ((regval >> 24) & 0xf) * 500;
200
- return sprintf(buf, "%d\n", value);
216
+ switch (attr) {
217
+ case hwmon_temp_input:
218
+ switch (channel) {
219
+ case 0: /* Tctl */
220
+ *val = get_raw_temp(data);
221
+ if (*val < 0)
222
+ *val = 0;
223
+ break;
224
+ case 1: /* Tdie */
225
+ *val = get_raw_temp(data) - data->temp_offset;
226
+ if (*val < 0)
227
+ *val = 0;
228
+ break;
229
+ case 2 ... 9: /* Tccd{1-8} */
230
+ amd_smn_read(amd_pci_dev_to_node_id(data->pdev),
231
+ ZEN_CCD_TEMP(channel - 2), &regval);
232
+ *val = (regval & ZEN_CCD_TEMP_MASK) * 125 - 49000;
233
+ break;
234
+ default:
235
+ return -EOPNOTSUPP;
236
+ }
237
+ break;
238
+ case hwmon_temp_max:
239
+ *val = 70 * 1000;
240
+ break;
241
+ case hwmon_temp_crit:
242
+ data->read_htcreg(data->pdev, &regval);
243
+ *val = ((regval >> 16) & 0x7f) * 500 + 52000;
244
+ break;
245
+ case hwmon_temp_crit_hyst:
246
+ data->read_htcreg(data->pdev, &regval);
247
+ *val = (((regval >> 16) & 0x7f)
248
+ - ((regval >> 24) & 0xf)) * 500 + 52000;
249
+ break;
250
+ default:
251
+ return -EOPNOTSUPP;
252
+ }
253
+ return 0;
201254 }
202255
203
-static DEVICE_ATTR_RO(temp1_input);
204
-static DEVICE_ATTR_RO(temp1_max);
205
-static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0);
206
-static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, show_temp_crit, NULL, 1);
207
-
208
-static SENSOR_DEVICE_ATTR(temp1_label, 0444, temp_label_show, NULL, 0);
209
-static DEVICE_ATTR_RO(temp2_input);
210
-static SENSOR_DEVICE_ATTR(temp2_label, 0444, temp_label_show, NULL, 1);
211
-
212
-static umode_t k10temp_is_visible(struct kobject *kobj,
213
- struct attribute *attr, int index)
256
+static int k10temp_read(struct device *dev, enum hwmon_sensor_types type,
257
+ u32 attr, int channel, long *val)
214258 {
215
- struct device *dev = container_of(kobj, struct device, kobj);
216
- struct k10temp_data *data = dev_get_drvdata(dev);
259
+ switch (type) {
260
+ case hwmon_temp:
261
+ return k10temp_read_temp(dev, attr, channel, val);
262
+ default:
263
+ return -EOPNOTSUPP;
264
+ }
265
+}
266
+
267
+static umode_t k10temp_is_visible(const void *_data,
268
+ enum hwmon_sensor_types type,
269
+ u32 attr, int channel)
270
+{
271
+ const struct k10temp_data *data = _data;
217272 struct pci_dev *pdev = data->pdev;
218273 u32 reg;
219274
220
- switch (index) {
221
- case 0 ... 1: /* temp1_input, temp1_max */
275
+ switch (type) {
276
+ case hwmon_temp:
277
+ switch (attr) {
278
+ case hwmon_temp_input:
279
+ if (!HAVE_TEMP(data, channel))
280
+ return 0;
281
+ break;
282
+ case hwmon_temp_max:
283
+ if (channel || data->is_zen)
284
+ return 0;
285
+ break;
286
+ case hwmon_temp_crit:
287
+ case hwmon_temp_crit_hyst:
288
+ if (channel || !data->read_htcreg)
289
+ return 0;
290
+
291
+ pci_read_config_dword(pdev,
292
+ REG_NORTHBRIDGE_CAPABILITIES,
293
+ &reg);
294
+ if (!(reg & NB_CAP_HTC))
295
+ return 0;
296
+
297
+ data->read_htcreg(data->pdev, &reg);
298
+ if (!(reg & HTC_ENABLE))
299
+ return 0;
300
+ break;
301
+ case hwmon_temp_label:
302
+ /* Show temperature labels only on Zen CPUs */
303
+ if (!data->is_zen || !HAVE_TEMP(data, channel))
304
+ return 0;
305
+ break;
306
+ default:
307
+ return 0;
308
+ }
309
+ break;
222310 default:
223
- break;
224
- case 2 ... 3: /* temp1_crit, temp1_crit_hyst */
225
- if (!data->read_htcreg)
226
- return 0;
227
-
228
- pci_read_config_dword(pdev, REG_NORTHBRIDGE_CAPABILITIES,
229
- &reg);
230
- if (!(reg & NB_CAP_HTC))
231
- return 0;
232
-
233
- data->read_htcreg(data->pdev, &reg);
234
- if (!(reg & HTC_ENABLE))
235
- return 0;
236
- break;
237
- case 4 ... 6: /* temp1_label, temp2_input, temp2_label */
238
- if (!data->show_tdie)
239
- return 0;
240
- break;
311
+ return 0;
241312 }
242
- return attr->mode;
313
+ return 0444;
243314 }
244
-
245
-static struct attribute *k10temp_attrs[] = {
246
- &dev_attr_temp1_input.attr,
247
- &dev_attr_temp1_max.attr,
248
- &sensor_dev_attr_temp1_crit.dev_attr.attr,
249
- &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
250
- &sensor_dev_attr_temp1_label.dev_attr.attr,
251
- &dev_attr_temp2_input.attr,
252
- &sensor_dev_attr_temp2_label.dev_attr.attr,
253
- NULL
254
-};
255
-
256
-static const struct attribute_group k10temp_group = {
257
- .attrs = k10temp_attrs,
258
- .is_visible = k10temp_is_visible,
259
-};
260
-__ATTRIBUTE_GROUPS(k10temp);
261315
262316 static bool has_erratum_319(struct pci_dev *pdev)
263317 {
....@@ -293,8 +347,55 @@
293347 (boot_cpu_data.x86_model == 4 && boot_cpu_data.x86_stepping <= 2);
294348 }
295349
296
-static int k10temp_probe(struct pci_dev *pdev,
297
- const struct pci_device_id *id)
350
+static const struct hwmon_channel_info *k10temp_info[] = {
351
+ HWMON_CHANNEL_INFO(temp,
352
+ HWMON_T_INPUT | HWMON_T_MAX |
353
+ HWMON_T_CRIT | HWMON_T_CRIT_HYST |
354
+ HWMON_T_LABEL,
355
+ HWMON_T_INPUT | HWMON_T_LABEL,
356
+ HWMON_T_INPUT | HWMON_T_LABEL,
357
+ HWMON_T_INPUT | HWMON_T_LABEL,
358
+ HWMON_T_INPUT | HWMON_T_LABEL,
359
+ HWMON_T_INPUT | HWMON_T_LABEL,
360
+ HWMON_T_INPUT | HWMON_T_LABEL,
361
+ HWMON_T_INPUT | HWMON_T_LABEL,
362
+ HWMON_T_INPUT | HWMON_T_LABEL,
363
+ HWMON_T_INPUT | HWMON_T_LABEL),
364
+ HWMON_CHANNEL_INFO(in,
365
+ HWMON_I_INPUT | HWMON_I_LABEL,
366
+ HWMON_I_INPUT | HWMON_I_LABEL),
367
+ HWMON_CHANNEL_INFO(curr,
368
+ HWMON_C_INPUT | HWMON_C_LABEL,
369
+ HWMON_C_INPUT | HWMON_C_LABEL),
370
+ NULL
371
+};
372
+
373
+static const struct hwmon_ops k10temp_hwmon_ops = {
374
+ .is_visible = k10temp_is_visible,
375
+ .read = k10temp_read,
376
+ .read_string = k10temp_read_labels,
377
+};
378
+
379
+static const struct hwmon_chip_info k10temp_chip_info = {
380
+ .ops = &k10temp_hwmon_ops,
381
+ .info = k10temp_info,
382
+};
383
+
384
+static void k10temp_get_ccd_support(struct pci_dev *pdev,
385
+ struct k10temp_data *data, int limit)
386
+{
387
+ u32 regval;
388
+ int i;
389
+
390
+ for (i = 0; i < limit; i++) {
391
+ amd_smn_read(amd_pci_dev_to_node_id(pdev),
392
+ ZEN_CCD_TEMP(i), &regval);
393
+ if (regval & ZEN_CCD_TEMP_VALID)
394
+ data->show_temp |= BIT(TCCD_BIT(i));
395
+ }
396
+}
397
+
398
+static int k10temp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
298399 {
299400 int unreliable = has_erratum_319(pdev);
300401 struct device *dev = &pdev->dev;
....@@ -317,16 +418,42 @@
317418 return -ENOMEM;
318419
319420 data->pdev = pdev;
421
+ data->show_temp |= BIT(TCTL_BIT); /* Always show Tctl */
320422
321423 if (boot_cpu_data.x86 == 0x15 &&
322424 ((boot_cpu_data.x86_model & 0xf0) == 0x60 ||
323425 (boot_cpu_data.x86_model & 0xf0) == 0x70)) {
324426 data->read_htcreg = read_htcreg_nb_f15;
325427 data->read_tempreg = read_tempreg_nb_f15;
326
- } else if (boot_cpu_data.x86 == 0x17) {
327
- data->temp_adjust_mask = 0x80000;
328
- data->read_tempreg = read_tempreg_nb_f17;
329
- data->show_tdie = true;
428
+ } else if (boot_cpu_data.x86 == 0x17 || boot_cpu_data.x86 == 0x18) {
429
+ data->temp_adjust_mask = ZEN_CUR_TEMP_RANGE_SEL_MASK;
430
+ data->read_tempreg = read_tempreg_nb_zen;
431
+ data->show_temp |= BIT(TDIE_BIT); /* show Tdie */
432
+ data->is_zen = true;
433
+
434
+ switch (boot_cpu_data.x86_model) {
435
+ case 0x1: /* Zen */
436
+ case 0x8: /* Zen+ */
437
+ case 0x11: /* Zen APU */
438
+ case 0x18: /* Zen+ APU */
439
+ k10temp_get_ccd_support(pdev, data, 4);
440
+ break;
441
+ case 0x31: /* Zen2 Threadripper */
442
+ case 0x71: /* Zen2 */
443
+ k10temp_get_ccd_support(pdev, data, 8);
444
+ break;
445
+ }
446
+ } else if (boot_cpu_data.x86 == 0x19) {
447
+ data->temp_adjust_mask = ZEN_CUR_TEMP_RANGE_SEL_MASK;
448
+ data->read_tempreg = read_tempreg_nb_zen;
449
+ data->show_temp |= BIT(TDIE_BIT);
450
+ data->is_zen = true;
451
+
452
+ switch (boot_cpu_data.x86_model) {
453
+ case 0x0 ... 0x1: /* Zen3 */
454
+ k10temp_get_ccd_support(pdev, data, 8);
455
+ break;
456
+ }
330457 } else {
331458 data->read_htcreg = read_htcreg_pci;
332459 data->read_tempreg = read_tempreg_pci;
....@@ -342,8 +469,9 @@
342469 }
343470 }
344471
345
- hwmon_dev = devm_hwmon_device_register_with_groups(dev, "k10temp", data,
346
- k10temp_groups);
472
+ hwmon_dev = devm_hwmon_device_register_with_info(dev, "k10temp", data,
473
+ &k10temp_chip_info,
474
+ NULL);
347475 return PTR_ERR_OR_ZERO(hwmon_dev);
348476 }
349477
....@@ -360,6 +488,11 @@
360488 { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F3) },
361489 { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_DF_F3) },
362490 { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_M10H_DF_F3) },
491
+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_M30H_DF_F3) },
492
+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_M60H_DF_F3) },
493
+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_M70H_DF_F3) },
494
+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_19H_DF_F3) },
495
+ { PCI_VDEVICE(HYGON, PCI_DEVICE_ID_AMD_17H_DF_F3) },
363496 {}
364497 };
365498 MODULE_DEVICE_TABLE(pci, k10temp_id_table);