X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=k10temp.c;h=ae512182b9b866bbce47c6e7fd9082a31c2889db;hb=b38f98990dc4407c82bad532fa14f6460e83492a;hp=c62ffe8dd7b16e5c56a922b12d03db5aaa4219fc;hpb=196f6189792206fd9820f640503b01b02374dd17;p=groeck-k10temp diff --git a/k10temp.c b/k10temp.c index c62ffe8..ae51218 100644 --- a/k10temp.c +++ b/k10temp.c @@ -24,6 +24,7 @@ #include #include #include +#include "compat.h" MODULE_DESCRIPTION("AMD Family 10h+ CPU core temperature monitor"); MODULE_AUTHOR("Clemens Ladisch "); @@ -40,6 +41,10 @@ static DEFINE_MUTEX(nb_smu_ind_mutex); #define PCI_DEVICE_ID_AMD_17H_DF_F3 0x1463 #endif +#ifndef PCI_DEVICE_ID_AMD_17H_RR_NB +#define PCI_DEVICE_ID_AMD_17H_RR_NB 0x15d0 +#endif + /* CPUID function 0x80000001, ebx */ #define CPUID_PKGTYPE_MASK 0xf0000000 #define CPUID_PKGTYPE_F 0x00000000 @@ -59,10 +64,12 @@ static DEFINE_MUTEX(nb_smu_ind_mutex); #define NB_CAP_HTC 0x00000400 /* - * For F15h M60h, functionality of REG_REPORTED_TEMPERATURE - * has been moved to D0F0xBC_xD820_0CA4 [Reported Temperature - * Control] + * For F15h M60h, functionality of REG_HARDWARE_THERMAL_CONTROL + * and REG_REPORTED_TEMPERATURE has been moved to + * D0F0xBC_xD820_0C64 [Hardware Temperature Control] + * D0F0xBC_xD820_0CA4 [Reported Temperature Control] */ +#define F15H_M60H_HARDWARE_TEMP_CTRL_OFFSET 0xd8200c64 #define F15H_M60H_REPORTED_TEMP_CTRL_OFFSET 0xd8200ca4 /* F17h M01h Access througn SMN */ @@ -70,8 +77,11 @@ static DEFINE_MUTEX(nb_smu_ind_mutex); struct k10temp_data { struct pci_dev *pdev; + void (*read_htcreg)(struct pci_dev *pdev, u32 *regval); void (*read_tempreg)(struct pci_dev *pdev, u32 *regval); int temp_offset; + u32 temp_adjust_mask; + bool show_tdie; }; struct tctl_offset { @@ -81,9 +91,10 @@ struct tctl_offset { }; static const struct tctl_offset tctl_offset_table[] = { - { 0x17, "AMD Ryzen 7 1600X", 20000 }, + { 0x17, "AMD Ryzen 5 1600X", 20000 }, { 0x17, "AMD Ryzen 7 1700X", 20000 }, { 0x17, "AMD Ryzen 7 1800X", 20000 }, + { 0x17, "AMD Ryzen 7 2700X", 10000 }, { 0x17, "AMD Ryzen Threadripper 1950X", 27000 }, { 0x17, "AMD Ryzen Threadripper 1920X", 27000 }, { 0x17, "AMD Ryzen Threadripper 1900X", 27000 }, @@ -92,6 +103,11 @@ static const struct tctl_offset tctl_offset_table[] = { { 0x17, "AMD Ryzen Threadripper 1910", 10000 }, }; +static void read_htcreg_pci(struct pci_dev *pdev, u32 *regval) +{ + pci_read_config_dword(pdev, REG_HARDWARE_THERMAL_CONTROL, regval); +} + static void read_tempreg_pci(struct pci_dev *pdev, u32 *regval) { pci_read_config_dword(pdev, REG_REPORTED_TEMPERATURE, regval); @@ -108,6 +124,12 @@ static void amd_nb_index_read(struct pci_dev *pdev, unsigned int devfn, mutex_unlock(&nb_smu_ind_mutex); } +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); +} + static void read_tempreg_nb_f15(struct pci_dev *pdev, u32 *regval) { amd_nb_index_read(pdev, PCI_DEVFN(0, 0), 0xb8, @@ -120,20 +142,49 @@ static void read_tempreg_nb_f17(struct pci_dev *pdev, u32 *regval) F17H_M01H_REPORTED_TEMP_CTRL_OFFSET, regval); } -static ssize_t temp1_input_show(struct device *dev, - struct device_attribute *attr, char *buf) +unsigned int get_raw_temp(struct k10temp_data *data) { - struct k10temp_data *data = dev_get_drvdata(dev); - u32 regval; unsigned int temp; + u32 regval; data->read_tempreg(data->pdev, ®val); temp = (regval >> 21) * 125; - temp -= data->temp_offset; + if (regval & data->temp_adjust_mask) + temp -= 49000; + return temp; +} + +static ssize_t temp1_input_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct k10temp_data *data = dev_get_drvdata(dev); + unsigned int temp = get_raw_temp(data); + + if (temp > data->temp_offset) + temp -= data->temp_offset; + else + temp = 0; + + return sprintf(buf, "%u\n", temp); +} + +static ssize_t temp2_input_show(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct k10temp_data *data = dev_get_drvdata(dev); + unsigned int temp = get_raw_temp(data); return sprintf(buf, "%u\n", temp); } +static ssize_t temp_label_show(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + + return sprintf(buf, "%s\n", attr->index ? "Tctl" : "Tdie"); +} + static ssize_t temp1_max_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -162,22 +213,39 @@ static DEVICE_ATTR_RO(temp1_max); static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0); static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, show_temp_crit, NULL, 1); +static SENSOR_DEVICE_ATTR(temp1_label, 0444, temp_label_show, NULL, 0); +static DEVICE_ATTR_RO(temp2_input); +static SENSOR_DEVICE_ATTR(temp2_label, 0444, temp_label_show, NULL, 1); + static umode_t k10temp_is_visible(struct kobject *kobj, struct attribute *attr, int index) { struct device *dev = container_of(kobj, struct device, kobj); struct k10temp_data *data = dev_get_drvdata(dev); struct pci_dev *pdev = data->pdev; - - if (index >= 2) { - u32 reg_caps, reg_htc; + u32 reg; + + switch (index) { + case 0 ... 1: /* temp1_input, temp1_max */ + default: + break; + case 2 ... 3: /* temp1_crit, temp1_crit_hyst */ + if (!data->read_htcreg) + return 0; pci_read_config_dword(pdev, REG_NORTHBRIDGE_CAPABILITIES, - ®_caps); - pci_read_config_dword(pdev, REG_HARDWARE_THERMAL_CONTROL, - ®_htc); - if (!(reg_caps & NB_CAP_HTC) || !(reg_htc & HTC_ENABLE)) + ®); + if (!(reg & NB_CAP_HTC)) return 0; + + data->read_htcreg(data->pdev, ®); + if (!(reg & HTC_ENABLE)) + return 0; + break; + case 4 ... 6: /* temp1_label, temp2_input, temp2_label */ + if (!data->show_tdie) + return 0; + break; } return attr->mode; } @@ -187,6 +255,9 @@ static struct attribute *k10temp_attrs[] = { &dev_attr_temp1_max.attr, &sensor_dev_attr_temp1_crit.dev_attr.attr, &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, + &sensor_dev_attr_temp1_label.dev_attr.attr, + &dev_attr_temp2_input.attr, + &sensor_dev_attr_temp2_label.dev_attr.attr, NULL }; @@ -227,7 +298,7 @@ static bool has_erratum_319(struct pci_dev *pdev) * and AM3 formats, but that's the best we can do. */ return boot_cpu_data.x86_model < 4 || - (boot_cpu_data.x86_model == 4 && boot_cpu_data.x86_mask <= 2); + (boot_cpu_data.x86_model == 4 && boot_cpu_data.x86_stepping <= 2); } static int k10temp_probe(struct pci_dev *pdev, @@ -256,12 +327,17 @@ static int k10temp_probe(struct pci_dev *pdev, data->pdev = pdev; if (boot_cpu_data.x86 == 0x15 && (boot_cpu_data.x86_model == 0x60 || - boot_cpu_data.x86_model == 0x70)) + boot_cpu_data.x86_model == 0x70)) { + data->read_htcreg = read_htcreg_nb_f15; data->read_tempreg = read_tempreg_nb_f15; - else if (boot_cpu_data.x86 == 0x17) + } else if (boot_cpu_data.x86 == 0x17) { + data->temp_adjust_mask = 0x80000; data->read_tempreg = read_tempreg_nb_f17; - else + data->show_tdie = true; + } else { + data->read_htcreg = read_htcreg_pci; data->read_tempreg = read_tempreg_pci; + } for (i = 0; i < ARRAY_SIZE(tctl_offset_table); i++) { const struct tctl_offset *entry = &tctl_offset_table[i]; @@ -289,6 +365,7 @@ static const struct pci_device_id k10temp_id_table[] = { { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F3) }, { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F3) }, { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_DF_F3) }, + { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_RR_NB) }, {} }; MODULE_DEVICE_TABLE(pci, k10temp_id_table);