Skip to content

Commit c757938

Browse files
committed
hwmon: (k10temp) Report temperatures per CPU die
Zen2 reports reporting temperatures per CPU die (called Core Complex Dies, or CCD, by AMD). Add support for it to the k10temp driver. Tested-by: Brad Campbell <[email protected]> Tested-by: Bernhard Gebetsberger <[email protected]> Tested-by: Holger Kiehl <[email protected]> Tested-by: Michael Larabel <[email protected]> Tested-by: Jonathan McDowell <[email protected]> Tested-by: Ken Moffat <[email protected]> Tested-by: Darren Salt <[email protected]> Signed-off-by: Guenter Roeck <[email protected]>
1 parent d547552 commit c757938

File tree

1 file changed

+79
-1
lines changed

1 file changed

+79
-1
lines changed

drivers/hwmon/k10temp.c

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@
55
*
66
* Copyright (c) 2009 Clemens Ladisch <[email protected]>
77
* Copyright (c) 2020 Guenter Roeck <[email protected]>
8+
*
9+
* Implementation notes:
10+
* - CCD1 and CCD2 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.
814
*/
915

1016
#include <linux/bitops.h>
@@ -61,6 +67,8 @@ static DEFINE_MUTEX(nb_smu_ind_mutex);
6167

6268
/* F17h M01h Access througn SMN */
6369
#define F17H_M01H_REPORTED_TEMP_CTRL_OFFSET 0x00059800
70+
#define F17H_M70H_CCD1_TEMP 0x00059954
71+
#define F17H_M70H_CCD2_TEMP 0x00059958
6472

6573
#define CUR_TEMP_SHIFT 21
6674
#define CUR_TEMP_RANGE_SEL_MASK BIT(19)
@@ -72,6 +80,8 @@ struct k10temp_data {
7280
int temp_offset;
7381
u32 temp_adjust_mask;
7482
bool show_tdie;
83+
bool show_tccd1;
84+
bool show_tccd2;
7585
};
7686

7787
struct tctl_offset {
@@ -143,6 +153,8 @@ static long get_raw_temp(struct k10temp_data *data)
143153
const char *k10temp_temp_label[] = {
144154
"Tdie",
145155
"Tctl",
156+
"Tccd1",
157+
"Tccd2",
146158
};
147159

148160
static int k10temp_read_labels(struct device *dev,
@@ -172,6 +184,16 @@ static int k10temp_read(struct device *dev, enum hwmon_sensor_types type,
172184
if (*val < 0)
173185
*val = 0;
174186
break;
187+
case 2: /* Tccd1 */
188+
amd_smn_read(amd_pci_dev_to_node_id(data->pdev),
189+
F17H_M70H_CCD1_TEMP, &regval);
190+
*val = (regval & 0xfff) * 125 - 305000;
191+
break;
192+
case 3: /* Tccd2 */
193+
amd_smn_read(amd_pci_dev_to_node_id(data->pdev),
194+
F17H_M70H_CCD2_TEMP, &regval);
195+
*val = (regval & 0xfff) * 125 - 305000;
196+
break;
175197
default:
176198
return -EOPNOTSUPP;
177199
}
@@ -206,8 +228,24 @@ static umode_t k10temp_is_visible(const void *_data,
206228
case hwmon_temp:
207229
switch (attr) {
208230
case hwmon_temp_input:
209-
if (channel && !data->show_tdie)
231+
switch (channel) {
232+
case 0: /* Tdie, or Tctl if we don't show it */
233+
break;
234+
case 1: /* Tctl */
235+
if (!data->show_tdie)
236+
return 0;
237+
break;
238+
case 2: /* Tccd1 */
239+
if (!data->show_tccd1)
240+
return 0;
241+
break;
242+
case 3: /* Tccd2 */
243+
if (!data->show_tccd2)
244+
return 0;
245+
break;
246+
default:
210247
return 0;
248+
}
211249
break;
212250
case hwmon_temp_max:
213251
if (channel)
@@ -229,8 +267,24 @@ static umode_t k10temp_is_visible(const void *_data,
229267
return 0;
230268
break;
231269
case hwmon_temp_label:
270+
/* No labels if we don't show the die temperature */
232271
if (!data->show_tdie)
233272
return 0;
273+
switch (channel) {
274+
case 0: /* Tdie */
275+
case 1: /* Tctl */
276+
break;
277+
case 2: /* Tccd1 */
278+
if (!data->show_tccd1)
279+
return 0;
280+
break;
281+
case 3: /* Tccd2 */
282+
if (!data->show_tccd2)
283+
return 0;
284+
break;
285+
default:
286+
return 0;
287+
}
234288
break;
235289
default:
236290
return 0;
@@ -281,6 +335,8 @@ static const struct hwmon_channel_info *k10temp_info[] = {
281335
HWMON_T_INPUT | HWMON_T_MAX |
282336
HWMON_T_CRIT | HWMON_T_CRIT_HYST |
283337
HWMON_T_LABEL,
338+
HWMON_T_INPUT | HWMON_T_LABEL,
339+
HWMON_T_INPUT | HWMON_T_LABEL,
284340
HWMON_T_INPUT | HWMON_T_LABEL),
285341
NULL
286342
};
@@ -326,9 +382,31 @@ static int k10temp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
326382
data->read_htcreg = read_htcreg_nb_f15;
327383
data->read_tempreg = read_tempreg_nb_f15;
328384
} else if (boot_cpu_data.x86 == 0x17 || boot_cpu_data.x86 == 0x18) {
385+
u32 regval;
386+
329387
data->temp_adjust_mask = CUR_TEMP_RANGE_SEL_MASK;
330388
data->read_tempreg = read_tempreg_nb_f17;
331389
data->show_tdie = true;
390+
391+
switch (boot_cpu_data.x86_model) {
392+
case 0x1: /* Zen */
393+
case 0x8: /* Zen+ */
394+
case 0x11: /* Zen APU */
395+
case 0x18: /* Zen+ APU */
396+
break;
397+
case 0x31: /* Zen2 Threadripper */
398+
case 0x71: /* Zen2 */
399+
amd_smn_read(amd_pci_dev_to_node_id(pdev),
400+
F17H_M70H_CCD1_TEMP, &regval);
401+
if (regval & 0xfff)
402+
data->show_tccd1 = true;
403+
404+
amd_smn_read(amd_pci_dev_to_node_id(pdev),
405+
F17H_M70H_CCD2_TEMP, &regval);
406+
if (regval & 0xfff)
407+
data->show_tccd2 = true;
408+
break;
409+
}
332410
} else {
333411
data->read_htcreg = read_htcreg_pci;
334412
data->read_tempreg = read_tempreg_pci;

0 commit comments

Comments
 (0)