diff options
author | Rudolf Marek <r.marek@assembler.cz> | 2008-01-17 18:42:54 -0500 |
---|---|---|
committer | Mark M. Hoffman <mhoffman@lightlink.com> | 2008-02-17 10:21:39 -0500 |
commit | 6369a2887a1b35fde91573adc650528e3efea8e9 (patch) | |
tree | c1e9d888a20c2070c549934ee02b7d02218ed468 /drivers/hwmon | |
parent | 1d5f2c16c6125ae6da1435ac5a190ae08429902a (diff) |
hwmon: (coretemp) Add maximum cooling temperature readout
Following patch will add reporting of maximum temperature, at which all fans
should spin full speed. It may be non-physical temperature on Desktop/Server CPUs.
Signed-off-by: Rudolf Marek <r.marek@assembler.cz>
Acked-by: Jean Delvare <khali@linux-fr.org>
Signed-off-by: Mark M. Hoffman <mhoffman@lightlink.com>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r-- | drivers/hwmon/coretemp.c | 34 |
1 files changed, 30 insertions, 4 deletions
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 3ee60d26e3a2..52914e95e9dc 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c | |||
@@ -38,7 +38,8 @@ | |||
38 | 38 | ||
39 | #define DRVNAME "coretemp" | 39 | #define DRVNAME "coretemp" |
40 | 40 | ||
41 | typedef enum { SHOW_TEMP, SHOW_TJMAX, SHOW_LABEL, SHOW_NAME } SHOW; | 41 | typedef enum { SHOW_TEMP, SHOW_TJMAX, SHOW_TTARGET, SHOW_LABEL, |
42 | SHOW_NAME } SHOW; | ||
42 | 43 | ||
43 | /* | 44 | /* |
44 | * Functions declaration | 45 | * Functions declaration |
@@ -55,6 +56,7 @@ struct coretemp_data { | |||
55 | unsigned long last_updated; /* in jiffies */ | 56 | unsigned long last_updated; /* in jiffies */ |
56 | int temp; | 57 | int temp; |
57 | int tjmax; | 58 | int tjmax; |
59 | int ttarget; | ||
58 | u8 alarm; | 60 | u8 alarm; |
59 | }; | 61 | }; |
60 | 62 | ||
@@ -93,9 +95,10 @@ static ssize_t show_temp(struct device *dev, | |||
93 | 95 | ||
94 | if (attr->index == SHOW_TEMP) | 96 | if (attr->index == SHOW_TEMP) |
95 | err = data->valid ? sprintf(buf, "%d\n", data->temp) : -EAGAIN; | 97 | err = data->valid ? sprintf(buf, "%d\n", data->temp) : -EAGAIN; |
96 | else | 98 | else if (attr->index == SHOW_TJMAX) |
97 | err = sprintf(buf, "%d\n", data->tjmax); | 99 | err = sprintf(buf, "%d\n", data->tjmax); |
98 | 100 | else | |
101 | err = sprintf(buf, "%d\n", data->ttarget); | ||
99 | return err; | 102 | return err; |
100 | } | 103 | } |
101 | 104 | ||
@@ -103,6 +106,8 @@ static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, | |||
103 | SHOW_TEMP); | 106 | SHOW_TEMP); |
104 | static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp, NULL, | 107 | static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp, NULL, |
105 | SHOW_TJMAX); | 108 | SHOW_TJMAX); |
109 | static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp, NULL, | ||
110 | SHOW_TTARGET); | ||
106 | static DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL); | 111 | static DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL); |
107 | static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_name, NULL, SHOW_LABEL); | 112 | static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_name, NULL, SHOW_LABEL); |
108 | static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, SHOW_NAME); | 113 | static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, SHOW_NAME); |
@@ -223,8 +228,26 @@ static int __devinit coretemp_probe(struct platform_device *pdev) | |||
223 | 228 | ||
224 | platform_set_drvdata(pdev, data); | 229 | platform_set_drvdata(pdev, data); |
225 | 230 | ||
231 | /* read the still undocumented IA32_TEMPERATURE_TARGET it exists | ||
232 | on older CPUs but not in this register */ | ||
233 | |||
234 | if (c->x86_model > 0xe) { | ||
235 | err = rdmsr_safe_on_cpu(data->id, 0x1a2, &eax, &edx); | ||
236 | if (err) { | ||
237 | dev_warn(&pdev->dev, "Unable to read" | ||
238 | " IA32_TEMPERATURE_TARGET MSR\n"); | ||
239 | } else { | ||
240 | data->ttarget = data->tjmax - | ||
241 | (((eax >> 8) & 0xff) * 1000); | ||
242 | err = device_create_file(&pdev->dev, | ||
243 | &sensor_dev_attr_temp1_max.dev_attr); | ||
244 | if (err) | ||
245 | goto exit_free; | ||
246 | } | ||
247 | } | ||
248 | |||
226 | if ((err = sysfs_create_group(&pdev->dev.kobj, &coretemp_group))) | 249 | if ((err = sysfs_create_group(&pdev->dev.kobj, &coretemp_group))) |
227 | goto exit_free; | 250 | goto exit_dev; |
228 | 251 | ||
229 | data->hwmon_dev = hwmon_device_register(&pdev->dev); | 252 | data->hwmon_dev = hwmon_device_register(&pdev->dev); |
230 | if (IS_ERR(data->hwmon_dev)) { | 253 | if (IS_ERR(data->hwmon_dev)) { |
@@ -238,6 +261,8 @@ static int __devinit coretemp_probe(struct platform_device *pdev) | |||
238 | 261 | ||
239 | exit_class: | 262 | exit_class: |
240 | sysfs_remove_group(&pdev->dev.kobj, &coretemp_group); | 263 | sysfs_remove_group(&pdev->dev.kobj, &coretemp_group); |
264 | exit_dev: | ||
265 | device_remove_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr); | ||
241 | exit_free: | 266 | exit_free: |
242 | kfree(data); | 267 | kfree(data); |
243 | exit: | 268 | exit: |
@@ -250,6 +275,7 @@ static int __devexit coretemp_remove(struct platform_device *pdev) | |||
250 | 275 | ||
251 | hwmon_device_unregister(data->hwmon_dev); | 276 | hwmon_device_unregister(data->hwmon_dev); |
252 | sysfs_remove_group(&pdev->dev.kobj, &coretemp_group); | 277 | sysfs_remove_group(&pdev->dev.kobj, &coretemp_group); |
278 | device_remove_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr); | ||
253 | platform_set_drvdata(pdev, NULL); | 279 | platform_set_drvdata(pdev, NULL); |
254 | kfree(data); | 280 | kfree(data); |
255 | return 0; | 281 | return 0; |