summaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/k10temp.c
diff options
context:
space:
mode:
authorGuenter Roeck <linux@roeck-us.net>2018-04-26 15:22:29 -0400
committerGuenter Roeck <linux@roeck-us.net>2018-05-21 10:51:58 -0400
commitf934c0599ecab63ec9cca0000315240c1202d20c (patch)
tree63accb060eb2ff3719d4b35ab34fec163624ab35 /drivers/hwmon/k10temp.c
parentccaf63b4d6eaf3447037cefbb0b1038fa80c6639 (diff)
hwmon: (k10temp) Display both Tctl and Tdie
On some AMD CPUs, there is a different between the die temperature (Tdie) and the reported temperature (Tctl). Tdie is the real measured temperature, and Tctl is used for fan control. Lets report both for affected CPUs. Tested-by: Gabriel Craciunescu <nix.or.die@gmail.com> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Diffstat (limited to 'drivers/hwmon/k10temp.c')
-rw-r--r--drivers/hwmon/k10temp.c55
1 files changed, 48 insertions, 7 deletions
diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c
index e97105ae4158..d3fae5a8e508 100644
--- a/drivers/hwmon/k10temp.c
+++ b/drivers/hwmon/k10temp.c
@@ -85,6 +85,7 @@ struct k10temp_data {
85 void (*read_tempreg)(struct pci_dev *pdev, u32 *regval); 85 void (*read_tempreg)(struct pci_dev *pdev, u32 *regval);
86 int temp_offset; 86 int temp_offset;
87 u32 temp_adjust_mask; 87 u32 temp_adjust_mask;
88 bool show_tdie;
88}; 89};
89 90
90struct tctl_offset { 91struct tctl_offset {
@@ -145,17 +146,24 @@ static void read_tempreg_nb_f17(struct pci_dev *pdev, u32 *regval)
145 F17H_M01H_REPORTED_TEMP_CTRL_OFFSET, regval); 146 F17H_M01H_REPORTED_TEMP_CTRL_OFFSET, regval);
146} 147}
147 148
148static ssize_t temp1_input_show(struct device *dev, 149unsigned int get_raw_temp(struct k10temp_data *data)
149 struct device_attribute *attr, char *buf)
150{ 150{
151 struct k10temp_data *data = dev_get_drvdata(dev);
152 u32 regval;
153 unsigned int temp; 151 unsigned int temp;
152 u32 regval;
154 153
155 data->read_tempreg(data->pdev, &regval); 154 data->read_tempreg(data->pdev, &regval);
156 temp = (regval >> 21) * 125; 155 temp = (regval >> 21) * 125;
157 if (regval & data->temp_adjust_mask) 156 if (regval & data->temp_adjust_mask)
158 temp -= 49000; 157 temp -= 49000;
158 return temp;
159}
160
161static ssize_t temp1_input_show(struct device *dev,
162 struct device_attribute *attr, char *buf)
163{
164 struct k10temp_data *data = dev_get_drvdata(dev);
165 unsigned int temp = get_raw_temp(data);
166
159 if (temp > data->temp_offset) 167 if (temp > data->temp_offset)
160 temp -= data->temp_offset; 168 temp -= data->temp_offset;
161 else 169 else
@@ -164,6 +172,23 @@ static ssize_t temp1_input_show(struct device *dev,
164 return sprintf(buf, "%u\n", temp); 172 return sprintf(buf, "%u\n", temp);
165} 173}
166 174
175static ssize_t temp2_input_show(struct device *dev,
176 struct device_attribute *devattr, char *buf)
177{
178 struct k10temp_data *data = dev_get_drvdata(dev);
179 unsigned int temp = get_raw_temp(data);
180
181 return sprintf(buf, "%u\n", temp);
182}
183
184static ssize_t temp_label_show(struct device *dev,
185 struct device_attribute *devattr, char *buf)
186{
187 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
188
189 return sprintf(buf, "%s\n", attr->index ? "Tctl" : "Tdie");
190}
191
167static ssize_t temp1_max_show(struct device *dev, 192static ssize_t temp1_max_show(struct device *dev,
168 struct device_attribute *attr, char *buf) 193 struct device_attribute *attr, char *buf)
169{ 194{
@@ -191,16 +216,23 @@ static DEVICE_ATTR_RO(temp1_max);
191static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0); 216static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0);
192static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, show_temp_crit, NULL, 1); 217static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, show_temp_crit, NULL, 1);
193 218
219static SENSOR_DEVICE_ATTR(temp1_label, 0444, temp_label_show, NULL, 0);
220static DEVICE_ATTR_RO(temp2_input);
221static SENSOR_DEVICE_ATTR(temp2_label, 0444, temp_label_show, NULL, 1);
222
194static umode_t k10temp_is_visible(struct kobject *kobj, 223static umode_t k10temp_is_visible(struct kobject *kobj,
195 struct attribute *attr, int index) 224 struct attribute *attr, int index)
196{ 225{
197 struct device *dev = container_of(kobj, struct device, kobj); 226 struct device *dev = container_of(kobj, struct device, kobj);
198 struct k10temp_data *data = dev_get_drvdata(dev); 227 struct k10temp_data *data = dev_get_drvdata(dev);
199 struct pci_dev *pdev = data->pdev; 228 struct pci_dev *pdev = data->pdev;
229 u32 reg;
200 230
201 if (index >= 2) { 231 switch (index) {
202 u32 reg; 232 case 0 ... 1: /* temp1_input, temp1_max */
203 233 default:
234 break;
235 case 2 ... 3: /* temp1_crit, temp1_crit_hyst */
204 if (!data->read_htcreg) 236 if (!data->read_htcreg)
205 return 0; 237 return 0;
206 238
@@ -212,6 +244,11 @@ static umode_t k10temp_is_visible(struct kobject *kobj,
212 data->read_htcreg(data->pdev, &reg); 244 data->read_htcreg(data->pdev, &reg);
213 if (!(reg & HTC_ENABLE)) 245 if (!(reg & HTC_ENABLE))
214 return 0; 246 return 0;
247 break;
248 case 4 ... 6: /* temp1_label, temp2_input, temp2_label */
249 if (!data->show_tdie)
250 return 0;
251 break;
215 } 252 }
216 return attr->mode; 253 return attr->mode;
217} 254}
@@ -221,6 +258,9 @@ static struct attribute *k10temp_attrs[] = {
221 &dev_attr_temp1_max.attr, 258 &dev_attr_temp1_max.attr,
222 &sensor_dev_attr_temp1_crit.dev_attr.attr, 259 &sensor_dev_attr_temp1_crit.dev_attr.attr,
223 &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, 260 &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
261 &sensor_dev_attr_temp1_label.dev_attr.attr,
262 &dev_attr_temp2_input.attr,
263 &sensor_dev_attr_temp2_label.dev_attr.attr,
224 NULL 264 NULL
225}; 265};
226 266
@@ -296,6 +336,7 @@ static int k10temp_probe(struct pci_dev *pdev,
296 } else if (boot_cpu_data.x86 == 0x17) { 336 } else if (boot_cpu_data.x86 == 0x17) {
297 data->temp_adjust_mask = 0x80000; 337 data->temp_adjust_mask = 0x80000;
298 data->read_tempreg = read_tempreg_nb_f17; 338 data->read_tempreg = read_tempreg_nb_f17;
339 data->show_tdie = true;
299 } else { 340 } else {
300 data->read_htcreg = read_htcreg_pci; 341 data->read_htcreg = read_htcreg_pci;
301 data->read_tempreg = read_tempreg_pci; 342 data->read_tempreg = read_tempreg_pci;