2019-05-20 15:18:57 +08:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2009-12-17 04:38:25 +08:00
|
|
|
/*
|
2019-12-24 23:20:55 +08:00
|
|
|
* k10temp.c - AMD Family 10h/11h/12h/14h/15h/16h/17h
|
|
|
|
* processor hardware monitoring
|
2009-12-17 04:38:25 +08:00
|
|
|
*
|
|
|
|
* Copyright (c) 2009 Clemens Ladisch <clemens@ladisch.de>
|
2019-12-24 23:20:55 +08:00
|
|
|
* Copyright (c) 2020 Guenter Roeck <linux@roeck-us.net>
|
2020-01-15 09:40:12 +08:00
|
|
|
*
|
|
|
|
* Implementation notes:
|
hwmon: (k10temp) Display up to eight sets of CCD temperatures
In HWiNFO, we see support for Tccd1, Tccd3, Tccd5, and Tccd7 temperature
sensors on Zen2 based Threadripper CPUs. Checking register maps on
Threadripper 3970X confirms SMN register addresses and values for those
sensors.
Register values observed in an idle system:
0x059950: 00000000 00000abc 00000000 00000ad8
0x059960: 00000000 00000ade 00000000 00000ae4
Under load:
0x059950: 00000000 00000c02 00000000 00000c14
0x059960: 00000000 00000c30 00000000 00000c22
More analysis shows that EPYC CPUs support up to 8 CCD temperature
sensors. EPYC 7601 supports three CCD temperature sensors. Unlike
Zen2 CPUs, the register space in Zen1 CPUs supports a maximum of four
sensors, so only search for a maximum of four sensors on Zen1 CPUs.
On top of that, in thm_10_0_sh_mask.h in the Linux kernel, we find
definitions for THM_DIE{1-3}_TEMP__VALID_MASK, set to 0x00000800, as well
as matching SMN addresses. This lets us conclude that bit 11 of the
respective registers is a valid bit. With this assumption, the temperature
offset is now 49 degrees C. This conveniently matches the documented
temperature offset for Tdie, again suggesting that above registers indeed
report temperatures sensor values. Assume that bit 11 is indeed a valid
bit, and add support for the additional sensors.
With this patch applied, output from 3970X (idle) looks as follows:
k10temp-pci-00c3
Adapter: PCI adapter
Tdie: +55.9°C
Tctl: +55.9°C
Tccd1: +39.8°C
Tccd3: +43.8°C
Tccd5: +43.8°C
Tccd7: +44.8°C
Tested-by: Michael Larabel <michael@phoronix.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
2020-01-23 10:41:18 +08:00
|
|
|
* - CCD register address information as well as the calculation to
|
2020-01-15 09:40:12 +08:00
|
|
|
* convert raw register values is from https://github.com/ocerman/zenpower.
|
|
|
|
* The information is not confirmed from chip datasheets, but experiments
|
|
|
|
* suggest that it provides reasonable temperature values.
|
2009-12-17 04:38:25 +08:00
|
|
|
*/
|
|
|
|
|
2018-04-29 23:39:24 +08:00
|
|
|
#include <linux/bitops.h>
|
2009-12-17 04:38:25 +08:00
|
|
|
#include <linux/err.h>
|
|
|
|
#include <linux/hwmon.h>
|
|
|
|
#include <linux/init.h>
|
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/pci.h>
|
2018-11-07 04:08:14 +08:00
|
|
|
#include <linux/pci_ids.h>
|
2018-05-05 04:01:33 +08:00
|
|
|
#include <asm/amd_nb.h>
|
2009-12-17 04:38:25 +08:00
|
|
|
#include <asm/processor.h>
|
|
|
|
|
2011-05-26 02:43:31 +08:00
|
|
|
MODULE_DESCRIPTION("AMD Family 10h+ CPU core temperature monitor");
|
2009-12-17 04:38:25 +08:00
|
|
|
MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
|
|
|
|
MODULE_LICENSE("GPL");
|
|
|
|
|
|
|
|
static bool force;
|
|
|
|
module_param(force, bool, 0444);
|
|
|
|
MODULE_PARM_DESC(force, "force loading on processors with erratum 319");
|
|
|
|
|
2014-08-15 07:15:27 +08:00
|
|
|
/* Provide lock for writing to NB_SMU_IND_ADDR */
|
|
|
|
static DEFINE_MUTEX(nb_smu_ind_mutex);
|
|
|
|
|
2018-04-30 00:16:45 +08:00
|
|
|
#ifndef PCI_DEVICE_ID_AMD_15H_M70H_NB_F3
|
|
|
|
#define PCI_DEVICE_ID_AMD_15H_M70H_NB_F3 0x15b3
|
|
|
|
#endif
|
|
|
|
|
2010-01-11 03:52:34 +08:00
|
|
|
/* CPUID function 0x80000001, ebx */
|
2018-04-29 23:39:24 +08:00
|
|
|
#define CPUID_PKGTYPE_MASK GENMASK(31, 28)
|
2010-01-11 03:52:34 +08:00
|
|
|
#define CPUID_PKGTYPE_F 0x00000000
|
|
|
|
#define CPUID_PKGTYPE_AM2R2_AM3 0x10000000
|
|
|
|
|
|
|
|
/* DRAM controller (PCI function 2) */
|
|
|
|
#define REG_DCT0_CONFIG_HIGH 0x094
|
2018-04-29 23:39:24 +08:00
|
|
|
#define DDR3_MODE BIT(8)
|
2010-01-11 03:52:34 +08:00
|
|
|
|
|
|
|
/* miscellaneous (PCI function 3) */
|
2009-12-17 04:38:25 +08:00
|
|
|
#define REG_HARDWARE_THERMAL_CONTROL 0x64
|
2018-04-29 23:39:24 +08:00
|
|
|
#define HTC_ENABLE BIT(0)
|
2009-12-17 04:38:25 +08:00
|
|
|
|
|
|
|
#define REG_REPORTED_TEMPERATURE 0xa4
|
|
|
|
|
|
|
|
#define REG_NORTHBRIDGE_CAPABILITIES 0xe8
|
2018-04-29 23:39:24 +08:00
|
|
|
#define NB_CAP_HTC BIT(10)
|
2009-12-17 04:38:25 +08:00
|
|
|
|
2014-08-15 07:15:27 +08:00
|
|
|
/*
|
2018-04-29 23:08:24 +08:00
|
|
|
* For F15h M60h and M70h, REG_HARDWARE_THERMAL_CONTROL
|
|
|
|
* and REG_REPORTED_TEMPERATURE have been moved to
|
|
|
|
* D0F0xBC_xD820_0C64 [Hardware Temperature Control]
|
|
|
|
* D0F0xBC_xD820_0CA4 [Reported Temperature Control]
|
2014-08-15 07:15:27 +08:00
|
|
|
*/
|
2018-04-29 23:08:24 +08:00
|
|
|
#define F15H_M60H_HARDWARE_TEMP_CTRL_OFFSET 0xd8200c64
|
2014-08-15 07:15:27 +08:00
|
|
|
#define F15H_M60H_REPORTED_TEMP_CTRL_OFFSET 0xd8200ca4
|
|
|
|
|
2021-08-28 04:15:25 +08:00
|
|
|
/* Common for Zen CPU families (Family 17h and 18h and 19h) */
|
|
|
|
#define ZEN_REPORTED_TEMP_CTRL_BASE 0x00059800
|
hwmon: (k10temp) Display up to eight sets of CCD temperatures
In HWiNFO, we see support for Tccd1, Tccd3, Tccd5, and Tccd7 temperature
sensors on Zen2 based Threadripper CPUs. Checking register maps on
Threadripper 3970X confirms SMN register addresses and values for those
sensors.
Register values observed in an idle system:
0x059950: 00000000 00000abc 00000000 00000ad8
0x059960: 00000000 00000ade 00000000 00000ae4
Under load:
0x059950: 00000000 00000c02 00000000 00000c14
0x059960: 00000000 00000c30 00000000 00000c22
More analysis shows that EPYC CPUs support up to 8 CCD temperature
sensors. EPYC 7601 supports three CCD temperature sensors. Unlike
Zen2 CPUs, the register space in Zen1 CPUs supports a maximum of four
sensors, so only search for a maximum of four sensors on Zen1 CPUs.
On top of that, in thm_10_0_sh_mask.h in the Linux kernel, we find
definitions for THM_DIE{1-3}_TEMP__VALID_MASK, set to 0x00000800, as well
as matching SMN addresses. This lets us conclude that bit 11 of the
respective registers is a valid bit. With this assumption, the temperature
offset is now 49 degrees C. This conveniently matches the documented
temperature offset for Tdie, again suggesting that above registers indeed
report temperatures sensor values. Assume that bit 11 is indeed a valid
bit, and add support for the additional sensors.
With this patch applied, output from 3970X (idle) looks as follows:
k10temp-pci-00c3
Adapter: PCI adapter
Tdie: +55.9°C
Tctl: +55.9°C
Tccd1: +39.8°C
Tccd3: +43.8°C
Tccd5: +43.8°C
Tccd7: +44.8°C
Tested-by: Michael Larabel <michael@phoronix.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
2020-01-23 10:41:18 +08:00
|
|
|
|
2021-08-28 04:15:25 +08:00
|
|
|
#define ZEN_CCD_TEMP(offset, x) (ZEN_REPORTED_TEMP_CTRL_BASE + \
|
|
|
|
(offset) + ((x) * 4))
|
2020-08-27 13:42:41 +08:00
|
|
|
#define ZEN_CCD_TEMP_VALID BIT(11)
|
|
|
|
#define ZEN_CCD_TEMP_MASK GENMASK(10, 0)
|
2017-09-05 09:33:53 +08:00
|
|
|
|
2020-08-27 13:42:41 +08:00
|
|
|
#define ZEN_CUR_TEMP_SHIFT 21
|
|
|
|
#define ZEN_CUR_TEMP_RANGE_SEL_MASK BIT(19)
|
2020-01-15 09:54:05 +08:00
|
|
|
|
2020-08-27 13:42:41 +08:00
|
|
|
#define ZEN_SVI_BASE 0x0005A000
|
2018-04-29 23:39:24 +08:00
|
|
|
|
2020-08-27 13:42:41 +08:00
|
|
|
/* F17h thermal registers through SMN */
|
|
|
|
#define F17H_M01H_SVI_TEL_PLANE0 (ZEN_SVI_BASE + 0xc)
|
|
|
|
#define F17H_M01H_SVI_TEL_PLANE1 (ZEN_SVI_BASE + 0x10)
|
2020-08-27 13:42:42 +08:00
|
|
|
#define F17H_M31H_SVI_TEL_PLANE0 (ZEN_SVI_BASE + 0x14)
|
|
|
|
#define F17H_M31H_SVI_TEL_PLANE1 (ZEN_SVI_BASE + 0x10)
|
2020-08-27 13:42:41 +08:00
|
|
|
|
2020-08-27 13:42:42 +08:00
|
|
|
#define F17H_M01H_CFACTOR_ICORE 1000000 /* 1A / LSB */
|
|
|
|
#define F17H_M01H_CFACTOR_ISOC 250000 /* 0.25A / LSB */
|
|
|
|
#define F17H_M31H_CFACTOR_ICORE 1000000 /* 1A / LSB */
|
|
|
|
#define F17H_M31H_CFACTOR_ISOC 310000 /* 0.31A / LSB */
|
2020-01-15 09:54:05 +08:00
|
|
|
|
2020-09-15 04:07:15 +08:00
|
|
|
/* F19h thermal registers through SMN */
|
|
|
|
#define F19H_M01_SVI_TEL_PLANE0 (ZEN_SVI_BASE + 0x14)
|
|
|
|
#define F19H_M01_SVI_TEL_PLANE1 (ZEN_SVI_BASE + 0x10)
|
|
|
|
|
|
|
|
#define F19H_M01H_CFACTOR_ICORE 1000000 /* 1A / LSB */
|
|
|
|
#define F19H_M01H_CFACTOR_ISOC 310000 /* 0.31A / LSB */
|
|
|
|
|
2017-09-05 09:33:53 +08:00
|
|
|
struct k10temp_data {
|
|
|
|
struct pci_dev *pdev;
|
2018-04-29 23:08:24 +08:00
|
|
|
void (*read_htcreg)(struct pci_dev *pdev, u32 *regval);
|
2017-09-05 09:33:53 +08:00
|
|
|
void (*read_tempreg)(struct pci_dev *pdev, u32 *regval);
|
2017-09-05 09:33:53 +08:00
|
|
|
int temp_offset;
|
2018-04-24 21:55:55 +08:00
|
|
|
u32 temp_adjust_mask;
|
2020-01-24 00:58:22 +08:00
|
|
|
u32 show_temp;
|
|
|
|
bool is_zen;
|
2021-08-28 04:15:25 +08:00
|
|
|
u32 ccd_offset;
|
2017-09-05 09:33:53 +08:00
|
|
|
};
|
|
|
|
|
2020-01-24 00:58:22 +08:00
|
|
|
#define TCTL_BIT 0
|
|
|
|
#define TDIE_BIT 1
|
|
|
|
#define TCCD_BIT(x) ((x) + 2)
|
|
|
|
|
|
|
|
#define HAVE_TEMP(d, channel) ((d)->show_temp & BIT(channel))
|
|
|
|
#define HAVE_TDIE(d) HAVE_TEMP(d, TDIE_BIT)
|
|
|
|
|
2017-09-05 09:33:53 +08:00
|
|
|
struct tctl_offset {
|
|
|
|
u8 model;
|
|
|
|
char const *id;
|
|
|
|
int offset;
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct tctl_offset tctl_offset_table[] = {
|
2017-11-14 04:38:23 +08:00
|
|
|
{ 0x17, "AMD Ryzen 5 1600X", 20000 },
|
2017-09-05 09:33:53 +08:00
|
|
|
{ 0x17, "AMD Ryzen 7 1700X", 20000 },
|
|
|
|
{ 0x17, "AMD Ryzen 7 1800X", 20000 },
|
2018-04-24 21:55:55 +08:00
|
|
|
{ 0x17, "AMD Ryzen 7 2700X", 10000 },
|
2018-08-10 02:50:46 +08:00
|
|
|
{ 0x17, "AMD Ryzen Threadripper 19", 27000 }, /* 19{00,20,50}X */
|
|
|
|
{ 0x17, "AMD Ryzen Threadripper 29", 27000 }, /* 29{20,50,70,90}[W]X */
|
2017-09-05 09:33:53 +08:00
|
|
|
};
|
|
|
|
|
2018-04-29 23:08:24 +08:00
|
|
|
static void read_htcreg_pci(struct pci_dev *pdev, u32 *regval)
|
|
|
|
{
|
|
|
|
pci_read_config_dword(pdev, REG_HARDWARE_THERMAL_CONTROL, regval);
|
|
|
|
}
|
|
|
|
|
2017-09-05 09:33:53 +08:00
|
|
|
static void read_tempreg_pci(struct pci_dev *pdev, u32 *regval)
|
|
|
|
{
|
|
|
|
pci_read_config_dword(pdev, REG_REPORTED_TEMPERATURE, regval);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void amd_nb_index_read(struct pci_dev *pdev, unsigned int devfn,
|
|
|
|
unsigned int base, int offset, u32 *val)
|
2014-08-15 07:15:27 +08:00
|
|
|
{
|
|
|
|
mutex_lock(&nb_smu_ind_mutex);
|
|
|
|
pci_bus_write_config_dword(pdev->bus, devfn,
|
2017-09-05 09:33:53 +08:00
|
|
|
base, offset);
|
2014-08-15 07:15:27 +08:00
|
|
|
pci_bus_read_config_dword(pdev->bus, devfn,
|
2017-09-05 09:33:53 +08:00
|
|
|
base + 4, val);
|
2014-08-15 07:15:27 +08:00
|
|
|
mutex_unlock(&nb_smu_ind_mutex);
|
|
|
|
}
|
|
|
|
|
2018-04-29 23:08:24 +08:00
|
|
|
static void read_htcreg_nb_f15(struct pci_dev *pdev, u32 *regval)
|
|
|
|
{
|
|
|
|
amd_nb_index_read(pdev, PCI_DEVFN(0, 0), 0xb8,
|
|
|
|
F15H_M60H_HARDWARE_TEMP_CTRL_OFFSET, regval);
|
|
|
|
}
|
|
|
|
|
2017-09-05 09:33:53 +08:00
|
|
|
static void read_tempreg_nb_f15(struct pci_dev *pdev, u32 *regval)
|
|
|
|
{
|
|
|
|
amd_nb_index_read(pdev, PCI_DEVFN(0, 0), 0xb8,
|
|
|
|
F15H_M60H_REPORTED_TEMP_CTRL_OFFSET, regval);
|
|
|
|
}
|
|
|
|
|
2020-08-27 13:42:41 +08:00
|
|
|
static void read_tempreg_nb_zen(struct pci_dev *pdev, u32 *regval)
|
2017-09-05 09:33:53 +08:00
|
|
|
{
|
2018-05-05 04:01:33 +08:00
|
|
|
amd_smn_read(amd_pci_dev_to_node_id(pdev),
|
2021-08-28 04:15:25 +08:00
|
|
|
ZEN_REPORTED_TEMP_CTRL_BASE, regval);
|
2017-09-05 09:33:53 +08:00
|
|
|
}
|
|
|
|
|
2019-12-24 23:20:55 +08:00
|
|
|
static long get_raw_temp(struct k10temp_data *data)
|
2009-12-17 04:38:25 +08:00
|
|
|
{
|
2018-04-27 03:22:29 +08:00
|
|
|
u32 regval;
|
2019-12-24 23:20:55 +08:00
|
|
|
long temp;
|
2017-09-05 09:33:53 +08:00
|
|
|
|
|
|
|
data->read_tempreg(data->pdev, ®val);
|
2020-08-27 13:42:41 +08:00
|
|
|
temp = (regval >> ZEN_CUR_TEMP_SHIFT) * 125;
|
2018-04-24 21:55:55 +08:00
|
|
|
if (regval & data->temp_adjust_mask)
|
|
|
|
temp -= 49000;
|
2018-04-27 03:22:29 +08:00
|
|
|
return temp;
|
|
|
|
}
|
|
|
|
|
2020-04-09 16:45:02 +08:00
|
|
|
static const char *k10temp_temp_label[] = {
|
2019-12-24 23:20:55 +08:00
|
|
|
"Tctl",
|
hwmon: (k10temp) Swap Tdie and Tctl on Family 17h CPUs
Traditionally, the temperature displayed by k10temp was Tctl.
On Family 17h CPUs, Tdie was displayed instead. To reduce confusion,
Tctl was added later as second temperature. This resulted in Tdie
being reported as temp1_input, and Tctl as temp2_input. This is
different to non-Ryzen CPUs, where Tctl is displayed as temp1_input.
Swap temp1_input and temp2_input on Family 17h CPUs, such that Tctl
is now reported as temp1_input and Tdie is reported as temp2_input,
to align with other CPUs, streamline the code, and make it less
confusing. Coincidentally, this also aligns the code with its
documentation, which states that Tdie is reported as temp2_input.
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
2020-01-23 23:57:09 +08:00
|
|
|
"Tdie",
|
2020-01-15 09:40:12 +08:00
|
|
|
"Tccd1",
|
|
|
|
"Tccd2",
|
hwmon: (k10temp) Display up to eight sets of CCD temperatures
In HWiNFO, we see support for Tccd1, Tccd3, Tccd5, and Tccd7 temperature
sensors on Zen2 based Threadripper CPUs. Checking register maps on
Threadripper 3970X confirms SMN register addresses and values for those
sensors.
Register values observed in an idle system:
0x059950: 00000000 00000abc 00000000 00000ad8
0x059960: 00000000 00000ade 00000000 00000ae4
Under load:
0x059950: 00000000 00000c02 00000000 00000c14
0x059960: 00000000 00000c30 00000000 00000c22
More analysis shows that EPYC CPUs support up to 8 CCD temperature
sensors. EPYC 7601 supports three CCD temperature sensors. Unlike
Zen2 CPUs, the register space in Zen1 CPUs supports a maximum of four
sensors, so only search for a maximum of four sensors on Zen1 CPUs.
On top of that, in thm_10_0_sh_mask.h in the Linux kernel, we find
definitions for THM_DIE{1-3}_TEMP__VALID_MASK, set to 0x00000800, as well
as matching SMN addresses. This lets us conclude that bit 11 of the
respective registers is a valid bit. With this assumption, the temperature
offset is now 49 degrees C. This conveniently matches the documented
temperature offset for Tdie, again suggesting that above registers indeed
report temperatures sensor values. Assume that bit 11 is indeed a valid
bit, and add support for the additional sensors.
With this patch applied, output from 3970X (idle) looks as follows:
k10temp-pci-00c3
Adapter: PCI adapter
Tdie: +55.9°C
Tctl: +55.9°C
Tccd1: +39.8°C
Tccd3: +43.8°C
Tccd5: +43.8°C
Tccd7: +44.8°C
Tested-by: Michael Larabel <michael@phoronix.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
2020-01-23 10:41:18 +08:00
|
|
|
"Tccd3",
|
|
|
|
"Tccd4",
|
|
|
|
"Tccd5",
|
|
|
|
"Tccd6",
|
|
|
|
"Tccd7",
|
|
|
|
"Tccd8",
|
2019-12-24 23:20:55 +08:00
|
|
|
};
|
2018-04-27 03:22:29 +08:00
|
|
|
|
2019-12-24 23:20:55 +08:00
|
|
|
static int k10temp_read_labels(struct device *dev,
|
|
|
|
enum hwmon_sensor_types type,
|
|
|
|
u32 attr, int channel, const char **str)
|
2009-12-17 04:38:25 +08:00
|
|
|
{
|
2020-01-15 09:54:05 +08:00
|
|
|
switch (type) {
|
|
|
|
case hwmon_temp:
|
|
|
|
*str = k10temp_temp_label[channel];
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return -EOPNOTSUPP;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int k10temp_read_temp(struct device *dev, u32 attr, int channel,
|
|
|
|
long *val)
|
2009-12-17 04:38:25 +08:00
|
|
|
{
|
2017-09-05 09:33:53 +08:00
|
|
|
struct k10temp_data *data = dev_get_drvdata(dev);
|
2009-12-17 04:38:25 +08:00
|
|
|
u32 regval;
|
|
|
|
|
2019-12-24 23:20:55 +08:00
|
|
|
switch (attr) {
|
|
|
|
case hwmon_temp_input:
|
|
|
|
switch (channel) {
|
hwmon: (k10temp) Swap Tdie and Tctl on Family 17h CPUs
Traditionally, the temperature displayed by k10temp was Tctl.
On Family 17h CPUs, Tdie was displayed instead. To reduce confusion,
Tctl was added later as second temperature. This resulted in Tdie
being reported as temp1_input, and Tctl as temp2_input. This is
different to non-Ryzen CPUs, where Tctl is displayed as temp1_input.
Swap temp1_input and temp2_input on Family 17h CPUs, such that Tctl
is now reported as temp1_input and Tdie is reported as temp2_input,
to align with other CPUs, streamline the code, and make it less
confusing. Coincidentally, this also aligns the code with its
documentation, which states that Tdie is reported as temp2_input.
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
2020-01-23 23:57:09 +08:00
|
|
|
case 0: /* Tctl */
|
|
|
|
*val = get_raw_temp(data);
|
2019-12-24 23:20:55 +08:00
|
|
|
if (*val < 0)
|
|
|
|
*val = 0;
|
|
|
|
break;
|
hwmon: (k10temp) Swap Tdie and Tctl on Family 17h CPUs
Traditionally, the temperature displayed by k10temp was Tctl.
On Family 17h CPUs, Tdie was displayed instead. To reduce confusion,
Tctl was added later as second temperature. This resulted in Tdie
being reported as temp1_input, and Tctl as temp2_input. This is
different to non-Ryzen CPUs, where Tctl is displayed as temp1_input.
Swap temp1_input and temp2_input on Family 17h CPUs, such that Tctl
is now reported as temp1_input and Tdie is reported as temp2_input,
to align with other CPUs, streamline the code, and make it less
confusing. Coincidentally, this also aligns the code with its
documentation, which states that Tdie is reported as temp2_input.
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
2020-01-23 23:57:09 +08:00
|
|
|
case 1: /* Tdie */
|
|
|
|
*val = get_raw_temp(data) - data->temp_offset;
|
2019-12-24 23:20:55 +08:00
|
|
|
if (*val < 0)
|
|
|
|
*val = 0;
|
|
|
|
break;
|
hwmon: (k10temp) Display up to eight sets of CCD temperatures
In HWiNFO, we see support for Tccd1, Tccd3, Tccd5, and Tccd7 temperature
sensors on Zen2 based Threadripper CPUs. Checking register maps on
Threadripper 3970X confirms SMN register addresses and values for those
sensors.
Register values observed in an idle system:
0x059950: 00000000 00000abc 00000000 00000ad8
0x059960: 00000000 00000ade 00000000 00000ae4
Under load:
0x059950: 00000000 00000c02 00000000 00000c14
0x059960: 00000000 00000c30 00000000 00000c22
More analysis shows that EPYC CPUs support up to 8 CCD temperature
sensors. EPYC 7601 supports three CCD temperature sensors. Unlike
Zen2 CPUs, the register space in Zen1 CPUs supports a maximum of four
sensors, so only search for a maximum of four sensors on Zen1 CPUs.
On top of that, in thm_10_0_sh_mask.h in the Linux kernel, we find
definitions for THM_DIE{1-3}_TEMP__VALID_MASK, set to 0x00000800, as well
as matching SMN addresses. This lets us conclude that bit 11 of the
respective registers is a valid bit. With this assumption, the temperature
offset is now 49 degrees C. This conveniently matches the documented
temperature offset for Tdie, again suggesting that above registers indeed
report temperatures sensor values. Assume that bit 11 is indeed a valid
bit, and add support for the additional sensors.
With this patch applied, output from 3970X (idle) looks as follows:
k10temp-pci-00c3
Adapter: PCI adapter
Tdie: +55.9°C
Tctl: +55.9°C
Tccd1: +39.8°C
Tccd3: +43.8°C
Tccd5: +43.8°C
Tccd7: +44.8°C
Tested-by: Michael Larabel <michael@phoronix.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
2020-01-23 10:41:18 +08:00
|
|
|
case 2 ... 9: /* Tccd{1-8} */
|
2020-01-15 09:40:12 +08:00
|
|
|
amd_smn_read(amd_pci_dev_to_node_id(data->pdev),
|
2021-08-28 04:15:25 +08:00
|
|
|
ZEN_CCD_TEMP(data->ccd_offset, channel - 2),
|
|
|
|
®val);
|
2020-08-27 13:42:41 +08:00
|
|
|
*val = (regval & ZEN_CCD_TEMP_MASK) * 125 - 49000;
|
2020-01-15 09:40:12 +08:00
|
|
|
break;
|
2019-12-24 23:20:55 +08:00
|
|
|
default:
|
|
|
|
return -EOPNOTSUPP;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case hwmon_temp_max:
|
|
|
|
*val = 70 * 1000;
|
|
|
|
break;
|
|
|
|
case hwmon_temp_crit:
|
|
|
|
data->read_htcreg(data->pdev, ®val);
|
|
|
|
*val = ((regval >> 16) & 0x7f) * 500 + 52000;
|
|
|
|
break;
|
|
|
|
case hwmon_temp_crit_hyst:
|
|
|
|
data->read_htcreg(data->pdev, ®val);
|
|
|
|
*val = (((regval >> 16) & 0x7f)
|
|
|
|
- ((regval >> 24) & 0xf)) * 500 + 52000;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return -EOPNOTSUPP;
|
|
|
|
}
|
|
|
|
return 0;
|
2009-12-17 04:38:25 +08:00
|
|
|
}
|
|
|
|
|
2020-01-15 09:54:05 +08:00
|
|
|
static int k10temp_read(struct device *dev, enum hwmon_sensor_types type,
|
|
|
|
u32 attr, int channel, long *val)
|
|
|
|
{
|
|
|
|
switch (type) {
|
|
|
|
case hwmon_temp:
|
|
|
|
return k10temp_read_temp(dev, attr, channel, val);
|
|
|
|
default:
|
|
|
|
return -EOPNOTSUPP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-24 23:20:55 +08:00
|
|
|
static umode_t k10temp_is_visible(const void *_data,
|
|
|
|
enum hwmon_sensor_types type,
|
|
|
|
u32 attr, int channel)
|
2014-08-16 00:27:03 +08:00
|
|
|
{
|
2019-12-24 23:20:55 +08:00
|
|
|
const struct k10temp_data *data = _data;
|
2017-09-05 09:33:53 +08:00
|
|
|
struct pci_dev *pdev = data->pdev;
|
2018-04-27 03:22:29 +08:00
|
|
|
u32 reg;
|
2014-08-16 00:27:03 +08:00
|
|
|
|
2019-12-24 23:20:55 +08:00
|
|
|
switch (type) {
|
|
|
|
case hwmon_temp:
|
|
|
|
switch (attr) {
|
|
|
|
case hwmon_temp_input:
|
2020-01-24 00:58:22 +08:00
|
|
|
if (!HAVE_TEMP(data, channel))
|
2019-12-24 23:20:55 +08:00
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
case hwmon_temp_max:
|
2020-01-24 00:58:22 +08:00
|
|
|
if (channel || data->is_zen)
|
2019-12-24 23:20:55 +08:00
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
case hwmon_temp_crit:
|
|
|
|
case hwmon_temp_crit_hyst:
|
|
|
|
if (channel || !data->read_htcreg)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
pci_read_config_dword(pdev,
|
|
|
|
REG_NORTHBRIDGE_CAPABILITIES,
|
|
|
|
®);
|
|
|
|
if (!(reg & NB_CAP_HTC))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
data->read_htcreg(data->pdev, ®);
|
|
|
|
if (!(reg & HTC_ENABLE))
|
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
case hwmon_temp_label:
|
2020-01-24 00:58:22 +08:00
|
|
|
/* Show temperature labels only on Zen CPUs */
|
|
|
|
if (!data->is_zen || !HAVE_TEMP(data, channel))
|
2020-01-15 09:40:12 +08:00
|
|
|
return 0;
|
2019-12-24 23:20:55 +08:00
|
|
|
break;
|
|
|
|
default:
|
2018-04-27 03:22:29 +08:00
|
|
|
return 0;
|
2019-12-24 23:20:55 +08:00
|
|
|
}
|
2018-04-27 03:22:29 +08:00
|
|
|
break;
|
2019-12-24 23:20:55 +08:00
|
|
|
default:
|
|
|
|
return 0;
|
2014-08-16 00:27:03 +08:00
|
|
|
}
|
2019-12-24 23:20:55 +08:00
|
|
|
return 0444;
|
2014-08-16 00:27:03 +08:00
|
|
|
}
|
|
|
|
|
2012-11-20 02:22:35 +08:00
|
|
|
static bool has_erratum_319(struct pci_dev *pdev)
|
2009-12-17 04:38:25 +08:00
|
|
|
{
|
2010-01-11 03:52:34 +08:00
|
|
|
u32 pkg_type, reg_dram_cfg;
|
|
|
|
|
|
|
|
if (boot_cpu_data.x86 != 0x10)
|
|
|
|
return false;
|
|
|
|
|
2009-12-17 04:38:25 +08:00
|
|
|
/*
|
2010-01-11 03:52:34 +08:00
|
|
|
* Erratum 319: The thermal sensor of Socket F/AM2+ processors
|
|
|
|
* may be unreliable.
|
2009-12-17 04:38:25 +08:00
|
|
|
*/
|
2010-01-11 03:52:34 +08:00
|
|
|
pkg_type = cpuid_ebx(0x80000001) & CPUID_PKGTYPE_MASK;
|
|
|
|
if (pkg_type == CPUID_PKGTYPE_F)
|
|
|
|
return true;
|
|
|
|
if (pkg_type != CPUID_PKGTYPE_AM2R2_AM3)
|
|
|
|
return false;
|
|
|
|
|
2010-06-20 15:22:31 +08:00
|
|
|
/* DDR3 memory implies socket AM3, which is good */
|
2010-01-11 03:52:34 +08:00
|
|
|
pci_bus_read_config_dword(pdev->bus,
|
|
|
|
PCI_DEVFN(PCI_SLOT(pdev->devfn), 2),
|
|
|
|
REG_DCT0_CONFIG_HIGH, ®_dram_cfg);
|
2010-06-20 15:22:31 +08:00
|
|
|
if (reg_dram_cfg & DDR3_MODE)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Unfortunately it is possible to run a socket AM3 CPU with DDR2
|
|
|
|
* memory. We blacklist all the cores which do exist in socket AM2+
|
|
|
|
* format. It still isn't perfect, as RB-C2 cores exist in both AM2+
|
|
|
|
* and AM3 formats, but that's the best we can do.
|
|
|
|
*/
|
|
|
|
return boot_cpu_data.x86_model < 4 ||
|
2018-01-01 09:52:10 +08:00
|
|
|
(boot_cpu_data.x86_model == 4 && boot_cpu_data.x86_stepping <= 2);
|
2009-12-17 04:38:25 +08:00
|
|
|
}
|
|
|
|
|
2019-12-24 23:20:55 +08:00
|
|
|
static const struct hwmon_channel_info *k10temp_info[] = {
|
|
|
|
HWMON_CHANNEL_INFO(temp,
|
|
|
|
HWMON_T_INPUT | HWMON_T_MAX |
|
|
|
|
HWMON_T_CRIT | HWMON_T_CRIT_HYST |
|
|
|
|
HWMON_T_LABEL,
|
2020-01-15 09:40:12 +08:00
|
|
|
HWMON_T_INPUT | HWMON_T_LABEL,
|
|
|
|
HWMON_T_INPUT | HWMON_T_LABEL,
|
hwmon: (k10temp) Display up to eight sets of CCD temperatures
In HWiNFO, we see support for Tccd1, Tccd3, Tccd5, and Tccd7 temperature
sensors on Zen2 based Threadripper CPUs. Checking register maps on
Threadripper 3970X confirms SMN register addresses and values for those
sensors.
Register values observed in an idle system:
0x059950: 00000000 00000abc 00000000 00000ad8
0x059960: 00000000 00000ade 00000000 00000ae4
Under load:
0x059950: 00000000 00000c02 00000000 00000c14
0x059960: 00000000 00000c30 00000000 00000c22
More analysis shows that EPYC CPUs support up to 8 CCD temperature
sensors. EPYC 7601 supports three CCD temperature sensors. Unlike
Zen2 CPUs, the register space in Zen1 CPUs supports a maximum of four
sensors, so only search for a maximum of four sensors on Zen1 CPUs.
On top of that, in thm_10_0_sh_mask.h in the Linux kernel, we find
definitions for THM_DIE{1-3}_TEMP__VALID_MASK, set to 0x00000800, as well
as matching SMN addresses. This lets us conclude that bit 11 of the
respective registers is a valid bit. With this assumption, the temperature
offset is now 49 degrees C. This conveniently matches the documented
temperature offset for Tdie, again suggesting that above registers indeed
report temperatures sensor values. Assume that bit 11 is indeed a valid
bit, and add support for the additional sensors.
With this patch applied, output from 3970X (idle) looks as follows:
k10temp-pci-00c3
Adapter: PCI adapter
Tdie: +55.9°C
Tctl: +55.9°C
Tccd1: +39.8°C
Tccd3: +43.8°C
Tccd5: +43.8°C
Tccd7: +44.8°C
Tested-by: Michael Larabel <michael@phoronix.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
2020-01-23 10:41:18 +08:00
|
|
|
HWMON_T_INPUT | HWMON_T_LABEL,
|
|
|
|
HWMON_T_INPUT | HWMON_T_LABEL,
|
|
|
|
HWMON_T_INPUT | HWMON_T_LABEL,
|
|
|
|
HWMON_T_INPUT | HWMON_T_LABEL,
|
|
|
|
HWMON_T_INPUT | HWMON_T_LABEL,
|
|
|
|
HWMON_T_INPUT | HWMON_T_LABEL,
|
2019-12-24 23:20:55 +08:00
|
|
|
HWMON_T_INPUT | HWMON_T_LABEL),
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct hwmon_ops k10temp_hwmon_ops = {
|
|
|
|
.is_visible = k10temp_is_visible,
|
|
|
|
.read = k10temp_read,
|
|
|
|
.read_string = k10temp_read_labels,
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct hwmon_chip_info k10temp_chip_info = {
|
|
|
|
.ops = &k10temp_hwmon_ops,
|
|
|
|
.info = k10temp_info,
|
|
|
|
};
|
|
|
|
|
hwmon: (k10temp) Display up to eight sets of CCD temperatures
In HWiNFO, we see support for Tccd1, Tccd3, Tccd5, and Tccd7 temperature
sensors on Zen2 based Threadripper CPUs. Checking register maps on
Threadripper 3970X confirms SMN register addresses and values for those
sensors.
Register values observed in an idle system:
0x059950: 00000000 00000abc 00000000 00000ad8
0x059960: 00000000 00000ade 00000000 00000ae4
Under load:
0x059950: 00000000 00000c02 00000000 00000c14
0x059960: 00000000 00000c30 00000000 00000c22
More analysis shows that EPYC CPUs support up to 8 CCD temperature
sensors. EPYC 7601 supports three CCD temperature sensors. Unlike
Zen2 CPUs, the register space in Zen1 CPUs supports a maximum of four
sensors, so only search for a maximum of four sensors on Zen1 CPUs.
On top of that, in thm_10_0_sh_mask.h in the Linux kernel, we find
definitions for THM_DIE{1-3}_TEMP__VALID_MASK, set to 0x00000800, as well
as matching SMN addresses. This lets us conclude that bit 11 of the
respective registers is a valid bit. With this assumption, the temperature
offset is now 49 degrees C. This conveniently matches the documented
temperature offset for Tdie, again suggesting that above registers indeed
report temperatures sensor values. Assume that bit 11 is indeed a valid
bit, and add support for the additional sensors.
With this patch applied, output from 3970X (idle) looks as follows:
k10temp-pci-00c3
Adapter: PCI adapter
Tdie: +55.9°C
Tctl: +55.9°C
Tccd1: +39.8°C
Tccd3: +43.8°C
Tccd5: +43.8°C
Tccd7: +44.8°C
Tested-by: Michael Larabel <michael@phoronix.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
2020-01-23 10:41:18 +08:00
|
|
|
static void k10temp_get_ccd_support(struct pci_dev *pdev,
|
|
|
|
struct k10temp_data *data, int limit)
|
|
|
|
{
|
|
|
|
u32 regval;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < limit; i++) {
|
|
|
|
amd_smn_read(amd_pci_dev_to_node_id(pdev),
|
2021-08-28 04:15:25 +08:00
|
|
|
ZEN_CCD_TEMP(data->ccd_offset, i), ®val);
|
2020-08-27 13:42:41 +08:00
|
|
|
if (regval & ZEN_CCD_TEMP_VALID)
|
2020-01-24 00:58:22 +08:00
|
|
|
data->show_temp |= BIT(TCCD_BIT(i));
|
hwmon: (k10temp) Display up to eight sets of CCD temperatures
In HWiNFO, we see support for Tccd1, Tccd3, Tccd5, and Tccd7 temperature
sensors on Zen2 based Threadripper CPUs. Checking register maps on
Threadripper 3970X confirms SMN register addresses and values for those
sensors.
Register values observed in an idle system:
0x059950: 00000000 00000abc 00000000 00000ad8
0x059960: 00000000 00000ade 00000000 00000ae4
Under load:
0x059950: 00000000 00000c02 00000000 00000c14
0x059960: 00000000 00000c30 00000000 00000c22
More analysis shows that EPYC CPUs support up to 8 CCD temperature
sensors. EPYC 7601 supports three CCD temperature sensors. Unlike
Zen2 CPUs, the register space in Zen1 CPUs supports a maximum of four
sensors, so only search for a maximum of four sensors on Zen1 CPUs.
On top of that, in thm_10_0_sh_mask.h in the Linux kernel, we find
definitions for THM_DIE{1-3}_TEMP__VALID_MASK, set to 0x00000800, as well
as matching SMN addresses. This lets us conclude that bit 11 of the
respective registers is a valid bit. With this assumption, the temperature
offset is now 49 degrees C. This conveniently matches the documented
temperature offset for Tdie, again suggesting that above registers indeed
report temperatures sensor values. Assume that bit 11 is indeed a valid
bit, and add support for the additional sensors.
With this patch applied, output from 3970X (idle) looks as follows:
k10temp-pci-00c3
Adapter: PCI adapter
Tdie: +55.9°C
Tctl: +55.9°C
Tccd1: +39.8°C
Tccd3: +43.8°C
Tccd5: +43.8°C
Tccd7: +44.8°C
Tested-by: Michael Larabel <michael@phoronix.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
2020-01-23 10:41:18 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-24 23:20:55 +08:00
|
|
|
static int k10temp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
2009-12-17 04:38:25 +08:00
|
|
|
{
|
2010-01-11 03:52:34 +08:00
|
|
|
int unreliable = has_erratum_319(pdev);
|
2014-08-16 00:27:03 +08:00
|
|
|
struct device *dev = &pdev->dev;
|
2017-09-05 09:33:53 +08:00
|
|
|
struct k10temp_data *data;
|
2014-08-16 00:27:03 +08:00
|
|
|
struct device *hwmon_dev;
|
2017-09-05 09:33:53 +08:00
|
|
|
int i;
|
2009-12-17 04:38:25 +08:00
|
|
|
|
2014-08-16 00:27:03 +08:00
|
|
|
if (unreliable) {
|
|
|
|
if (!force) {
|
|
|
|
dev_err(dev,
|
|
|
|
"unreliable CPU thermal sensor; monitoring disabled\n");
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
dev_warn(dev,
|
2009-12-17 04:38:25 +08:00
|
|
|
"unreliable CPU thermal sensor; check erratum 319\n");
|
2014-08-16 00:27:03 +08:00
|
|
|
}
|
2009-12-17 04:38:25 +08:00
|
|
|
|
2017-09-05 09:33:53 +08:00
|
|
|
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
|
|
|
|
if (!data)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
data->pdev = pdev;
|
2020-01-24 00:58:22 +08:00
|
|
|
data->show_temp |= BIT(TCTL_BIT); /* Always show Tctl */
|
2017-09-05 09:33:53 +08:00
|
|
|
|
2018-09-03 03:02:53 +08:00
|
|
|
if (boot_cpu_data.x86 == 0x15 &&
|
|
|
|
((boot_cpu_data.x86_model & 0xf0) == 0x60 ||
|
|
|
|
(boot_cpu_data.x86_model & 0xf0) == 0x70)) {
|
2018-04-29 23:08:24 +08:00
|
|
|
data->read_htcreg = read_htcreg_nb_f15;
|
2017-09-05 09:33:53 +08:00
|
|
|
data->read_tempreg = read_tempreg_nb_f15;
|
2018-12-08 14:33:28 +08:00
|
|
|
} else if (boot_cpu_data.x86 == 0x17 || boot_cpu_data.x86 == 0x18) {
|
2020-08-27 13:42:41 +08:00
|
|
|
data->temp_adjust_mask = ZEN_CUR_TEMP_RANGE_SEL_MASK;
|
|
|
|
data->read_tempreg = read_tempreg_nb_zen;
|
2020-01-24 00:58:22 +08:00
|
|
|
data->is_zen = true;
|
2020-01-15 09:40:12 +08:00
|
|
|
|
|
|
|
switch (boot_cpu_data.x86_model) {
|
|
|
|
case 0x1: /* Zen */
|
|
|
|
case 0x8: /* Zen+ */
|
|
|
|
case 0x11: /* Zen APU */
|
|
|
|
case 0x18: /* Zen+ APU */
|
2021-08-28 04:15:25 +08:00
|
|
|
data->ccd_offset = 0x154;
|
hwmon: (k10temp) Display up to eight sets of CCD temperatures
In HWiNFO, we see support for Tccd1, Tccd3, Tccd5, and Tccd7 temperature
sensors on Zen2 based Threadripper CPUs. Checking register maps on
Threadripper 3970X confirms SMN register addresses and values for those
sensors.
Register values observed in an idle system:
0x059950: 00000000 00000abc 00000000 00000ad8
0x059960: 00000000 00000ade 00000000 00000ae4
Under load:
0x059950: 00000000 00000c02 00000000 00000c14
0x059960: 00000000 00000c30 00000000 00000c22
More analysis shows that EPYC CPUs support up to 8 CCD temperature
sensors. EPYC 7601 supports three CCD temperature sensors. Unlike
Zen2 CPUs, the register space in Zen1 CPUs supports a maximum of four
sensors, so only search for a maximum of four sensors on Zen1 CPUs.
On top of that, in thm_10_0_sh_mask.h in the Linux kernel, we find
definitions for THM_DIE{1-3}_TEMP__VALID_MASK, set to 0x00000800, as well
as matching SMN addresses. This lets us conclude that bit 11 of the
respective registers is a valid bit. With this assumption, the temperature
offset is now 49 degrees C. This conveniently matches the documented
temperature offset for Tdie, again suggesting that above registers indeed
report temperatures sensor values. Assume that bit 11 is indeed a valid
bit, and add support for the additional sensors.
With this patch applied, output from 3970X (idle) looks as follows:
k10temp-pci-00c3
Adapter: PCI adapter
Tdie: +55.9°C
Tctl: +55.9°C
Tccd1: +39.8°C
Tccd3: +43.8°C
Tccd5: +43.8°C
Tccd7: +44.8°C
Tested-by: Michael Larabel <michael@phoronix.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
2020-01-23 10:41:18 +08:00
|
|
|
k10temp_get_ccd_support(pdev, data, 4);
|
2020-01-15 09:40:12 +08:00
|
|
|
break;
|
|
|
|
case 0x31: /* Zen2 Threadripper */
|
2021-08-27 02:40:52 +08:00
|
|
|
case 0x60: /* Renoir */
|
|
|
|
case 0x68: /* Lucienne */
|
2020-01-15 09:40:12 +08:00
|
|
|
case 0x71: /* Zen2 */
|
2021-08-28 04:15:25 +08:00
|
|
|
data->ccd_offset = 0x154;
|
hwmon: (k10temp) Display up to eight sets of CCD temperatures
In HWiNFO, we see support for Tccd1, Tccd3, Tccd5, and Tccd7 temperature
sensors on Zen2 based Threadripper CPUs. Checking register maps on
Threadripper 3970X confirms SMN register addresses and values for those
sensors.
Register values observed in an idle system:
0x059950: 00000000 00000abc 00000000 00000ad8
0x059960: 00000000 00000ade 00000000 00000ae4
Under load:
0x059950: 00000000 00000c02 00000000 00000c14
0x059960: 00000000 00000c30 00000000 00000c22
More analysis shows that EPYC CPUs support up to 8 CCD temperature
sensors. EPYC 7601 supports three CCD temperature sensors. Unlike
Zen2 CPUs, the register space in Zen1 CPUs supports a maximum of four
sensors, so only search for a maximum of four sensors on Zen1 CPUs.
On top of that, in thm_10_0_sh_mask.h in the Linux kernel, we find
definitions for THM_DIE{1-3}_TEMP__VALID_MASK, set to 0x00000800, as well
as matching SMN addresses. This lets us conclude that bit 11 of the
respective registers is a valid bit. With this assumption, the temperature
offset is now 49 degrees C. This conveniently matches the documented
temperature offset for Tdie, again suggesting that above registers indeed
report temperatures sensor values. Assume that bit 11 is indeed a valid
bit, and add support for the additional sensors.
With this patch applied, output from 3970X (idle) looks as follows:
k10temp-pci-00c3
Adapter: PCI adapter
Tdie: +55.9°C
Tctl: +55.9°C
Tccd1: +39.8°C
Tccd3: +43.8°C
Tccd5: +43.8°C
Tccd7: +44.8°C
Tested-by: Michael Larabel <michael@phoronix.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
2020-01-23 10:41:18 +08:00
|
|
|
k10temp_get_ccd_support(pdev, data, 8);
|
2020-01-15 09:40:12 +08:00
|
|
|
break;
|
|
|
|
}
|
2020-09-15 04:07:15 +08:00
|
|
|
} else if (boot_cpu_data.x86 == 0x19) {
|
|
|
|
data->temp_adjust_mask = ZEN_CUR_TEMP_RANGE_SEL_MASK;
|
|
|
|
data->read_tempreg = read_tempreg_nb_zen;
|
|
|
|
data->is_zen = true;
|
|
|
|
|
|
|
|
switch (boot_cpu_data.x86_model) {
|
2020-12-23 08:53:15 +08:00
|
|
|
case 0x0 ... 0x1: /* Zen3 SP3/TR */
|
|
|
|
case 0x21: /* Zen3 Ryzen Desktop */
|
2021-08-27 02:40:52 +08:00
|
|
|
case 0x50 ... 0x5f: /* Green Sardine */
|
2021-08-28 04:15:25 +08:00
|
|
|
data->ccd_offset = 0x154;
|
2020-09-15 04:07:15 +08:00
|
|
|
k10temp_get_ccd_support(pdev, data, 8);
|
|
|
|
break;
|
2021-08-28 04:15:26 +08:00
|
|
|
case 0x40 ... 0x4f: /* Yellow Carp */
|
|
|
|
data->ccd_offset = 0x300;
|
|
|
|
k10temp_get_ccd_support(pdev, data, 8);
|
|
|
|
break;
|
2020-09-15 04:07:15 +08:00
|
|
|
}
|
2018-04-24 21:55:55 +08:00
|
|
|
} else {
|
2018-04-29 23:08:24 +08:00
|
|
|
data->read_htcreg = read_htcreg_pci;
|
2017-09-05 09:33:53 +08:00
|
|
|
data->read_tempreg = read_tempreg_pci;
|
2018-04-24 21:55:55 +08:00
|
|
|
}
|
2017-09-05 09:33:53 +08:00
|
|
|
|
2017-09-05 09:33:53 +08:00
|
|
|
for (i = 0; i < ARRAY_SIZE(tctl_offset_table); i++) {
|
|
|
|
const struct tctl_offset *entry = &tctl_offset_table[i];
|
|
|
|
|
|
|
|
if (boot_cpu_data.x86 == entry->model &&
|
|
|
|
strstr(boot_cpu_data.x86_model_id, entry->id)) {
|
2021-08-27 02:40:56 +08:00
|
|
|
data->show_temp |= BIT(TDIE_BIT); /* show Tdie */
|
2017-09-05 09:33:53 +08:00
|
|
|
data->temp_offset = entry->offset;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-24 23:20:55 +08:00
|
|
|
hwmon_dev = devm_hwmon_device_register_with_info(dev, "k10temp", data,
|
|
|
|
&k10temp_chip_info,
|
|
|
|
NULL);
|
2020-09-09 01:13:45 +08:00
|
|
|
return PTR_ERR_OR_ZERO(hwmon_dev);
|
2009-12-17 04:38:25 +08:00
|
|
|
}
|
|
|
|
|
2013-12-03 15:10:29 +08:00
|
|
|
static const struct pci_device_id k10temp_id_table[] = {
|
2009-12-17 04:38:25 +08:00
|
|
|
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) },
|
|
|
|
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_11H_NB_MISC) },
|
2011-02-17 16:22:40 +08:00
|
|
|
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CNB17H_F3) },
|
2011-05-26 02:43:31 +08:00
|
|
|
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F3) },
|
2012-05-05 00:28:21 +08:00
|
|
|
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M10H_F3) },
|
2014-01-15 02:46:46 +08:00
|
|
|
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M30H_NB_F3) },
|
2014-08-15 07:15:27 +08:00
|
|
|
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M60H_NB_F3) },
|
2018-04-30 00:16:45 +08:00
|
|
|
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M70H_NB_F3) },
|
2013-08-24 04:14:03 +08:00
|
|
|
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F3) },
|
2014-03-12 05:25:59 +08:00
|
|
|
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F3) },
|
2017-09-05 09:33:53 +08:00
|
|
|
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_DF_F3) },
|
2018-05-05 04:01:33 +08:00
|
|
|
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_M10H_DF_F3) },
|
2018-11-07 04:08:21 +08:00
|
|
|
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_M30H_DF_F3) },
|
2020-05-11 04:48:41 +08:00
|
|
|
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_M60H_DF_F3) },
|
2019-07-23 01:46:53 +08:00
|
|
|
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_M70H_DF_F3) },
|
2020-09-15 04:07:15 +08:00
|
|
|
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_19H_DF_F3) },
|
2021-08-28 04:15:26 +08:00
|
|
|
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_19H_M40H_DF_F3) },
|
2021-05-17 14:41:31 +08:00
|
|
|
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_19H_M50H_DF_F3) },
|
2018-12-08 14:33:28 +08:00
|
|
|
{ PCI_VDEVICE(HYGON, PCI_DEVICE_ID_AMD_17H_DF_F3) },
|
2009-12-17 04:38:25 +08:00
|
|
|
{}
|
|
|
|
};
|
|
|
|
MODULE_DEVICE_TABLE(pci, k10temp_id_table);
|
|
|
|
|
|
|
|
static struct pci_driver k10temp_driver = {
|
|
|
|
.name = "k10temp",
|
|
|
|
.id_table = k10temp_id_table,
|
|
|
|
.probe = k10temp_probe,
|
|
|
|
};
|
|
|
|
|
2012-04-03 09:25:46 +08:00
|
|
|
module_pci_driver(k10temp_driver);
|