aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/hwmon/k10temp60
-rw-r--r--drivers/hwmon/Kconfig12
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/k10temp.c197
4 files changed, 270 insertions, 0 deletions
diff --git a/Documentation/hwmon/k10temp b/Documentation/hwmon/k10temp
new file mode 100644
index 000000000000..a7a18d453a51
--- /dev/null
+++ b/Documentation/hwmon/k10temp
@@ -0,0 +1,60 @@
1Kernel driver k10temp
2=====================
3
4Supported chips:
5* AMD Family 10h processors:
6 Socket F: Quad-Core/Six-Core/Embedded Opteron
7 Socket AM2+: Opteron, Phenom (II) X3/X4
8 Socket AM3: Quad-Core Opteron, Athlon/Phenom II X2/X3/X4, Sempron II
9 Socket S1G3: Athlon II, Sempron, Turion II
10* AMD Family 11h processors:
11 Socket S1G2: Athlon (X2), Sempron (X2), Turion X2 (Ultra)
12
13 Prefix: 'k10temp'
14 Addresses scanned: PCI space
15 Datasheets:
16 BIOS and Kernel Developer's Guide (BKDG) For AMD Family 10h Processors:
17 http://support.amd.com/us/Processor_TechDocs/31116.pdf
18 BIOS and Kernel Developer's Guide (BKDG) for AMD Family 11h Processors:
19 http://support.amd.com/us/Processor_TechDocs/41256.pdf
20 Revision Guide for AMD Family 10h Processors:
21 http://support.amd.com/us/Processor_TechDocs/41322.pdf
22 Revision Guide for AMD Family 11h Processors:
23 http://support.amd.com/us/Processor_TechDocs/41788.pdf
24 AMD Family 11h Processor Power and Thermal Data Sheet for Notebooks:
25 http://support.amd.com/us/Processor_TechDocs/43373.pdf
26 AMD Family 10h Server and Workstation Processor Power and Thermal Data Sheet:
27 http://support.amd.com/us/Processor_TechDocs/43374.pdf
28 AMD Family 10h Desktop Processor Power and Thermal Data Sheet:
29 http://support.amd.com/us/Processor_TechDocs/43375.pdf
30
31Author: Clemens Ladisch <clemens@ladisch.de>
32
33Description
34-----------
35
36This driver permits reading of the internal temperature sensor of AMD
37Family 10h and 11h processors.
38
39All these processors have a sensor, but on older revisions of Family 10h
40processors, the sensor may return inconsistent values (erratum 319). The
41driver will refuse to load on these revisions unless you specify the
42"force=1" module parameter.
43
44There is one temperature measurement value, available as temp1_input in
45sysfs. It is measured in degrees Celsius with a resolution of 1/8th degree.
46Please note that it is defined as a relative value; to quote the AMD manual:
47
48 Tctl is the processor temperature control value, used by the platform to
49 control cooling systems. Tctl is a non-physical temperature on an
50 arbitrary scale measured in degrees. It does _not_ represent an actual
51 physical temperature like die or case temperature. Instead, it specifies
52 the processor temperature relative to the point at which the system must
53 supply the maximum cooling for the processor's specified maximum case
54 temperature and maximum thermal power dissipation.
55
56The maximum value for Tctl is available in the file temp1_max.
57
58If the BIOS has enabled hardware temperature control, the threshold at
59which the processor will throttle itself to avoid damage is available in
60temp1_crit and temp1_crit_hyst.
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 95ccbe377f9c..665947fbcdcb 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -228,6 +228,18 @@ config SENSORS_K8TEMP
228 This driver can also be built as a module. If so, the module 228 This driver can also be built as a module. If so, the module
229 will be called k8temp. 229 will be called k8temp.
230 230
231config SENSORS_K10TEMP
232 tristate "AMD Phenom/Sempron/Turion/Opteron temperature sensor"
233 depends on X86 && PCI
234 help
235 If you say yes here you get support for the temperature
236 sensor(s) inside your CPU. Supported are later revisions of
237 the AMD Family 10h and all revisions of the AMD Family 11h
238 microarchitectures.
239
240 This driver can also be built as a module. If so, the module
241 will be called k10temp.
242
231config SENSORS_AMS 243config SENSORS_AMS
232 tristate "Apple Motion Sensor driver" 244 tristate "Apple Motion Sensor driver"
233 depends on PPC_PMAC && !PPC64 && INPUT && ((ADB_PMU && I2C = y) || (ADB_PMU && !I2C) || I2C) && EXPERIMENTAL 245 depends on PPC_PMAC && !PPC64 && INPUT && ((ADB_PMU && I2C = y) || (ADB_PMU && !I2C) || I2C) && EXPERIMENTAL
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 33c2ee105284..da84a6a69593 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -53,6 +53,7 @@ obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o
53obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o 53obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o
54obj-$(CONFIG_SENSORS_IT87) += it87.o 54obj-$(CONFIG_SENSORS_IT87) += it87.o
55obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o 55obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o
56obj-$(CONFIG_SENSORS_K10TEMP) += k10temp.o
56obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o hp_accel.o 57obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o hp_accel.o
57obj-$(CONFIG_SENSORS_LIS3_SPI) += lis3lv02d.o lis3lv02d_spi.o 58obj-$(CONFIG_SENSORS_LIS3_SPI) += lis3lv02d.o lis3lv02d_spi.o
58obj-$(CONFIG_SENSORS_LM63) += lm63.o 59obj-$(CONFIG_SENSORS_LM63) += lm63.o
diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c
new file mode 100644
index 000000000000..d8a26d16d948
--- /dev/null
+++ b/drivers/hwmon/k10temp.c
@@ -0,0 +1,197 @@
1/*
2 * k10temp.c - AMD Family 10h/11h processor hardware monitoring
3 *
4 * Copyright (c) 2009 Clemens Ladisch <clemens@ladisch.de>
5 *
6 *
7 * This driver is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This driver is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this driver; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <linux/err.h>
21#include <linux/hwmon.h>
22#include <linux/hwmon-sysfs.h>
23#include <linux/init.h>
24#include <linux/module.h>
25#include <linux/pci.h>
26#include <asm/processor.h>
27
28MODULE_DESCRIPTION("AMD Family 10h/11h CPU core temperature monitor");
29MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
30MODULE_LICENSE("GPL");
31
32static bool force;
33module_param(force, bool, 0444);
34MODULE_PARM_DESC(force, "force loading on processors with erratum 319");
35
36#define REG_HARDWARE_THERMAL_CONTROL 0x64
37#define HTC_ENABLE 0x00000001
38
39#define REG_REPORTED_TEMPERATURE 0xa4
40
41#define REG_NORTHBRIDGE_CAPABILITIES 0xe8
42#define NB_CAP_HTC 0x00000400
43
44static ssize_t show_temp(struct device *dev,
45 struct device_attribute *attr, char *buf)
46{
47 u32 regval;
48
49 pci_read_config_dword(to_pci_dev(dev),
50 REG_REPORTED_TEMPERATURE, &regval);
51 return sprintf(buf, "%u\n", (regval >> 21) * 125);
52}
53
54static ssize_t show_temp_max(struct device *dev,
55 struct device_attribute *attr, char *buf)
56{
57 return sprintf(buf, "%d\n", 70 * 1000);
58}
59
60static ssize_t show_temp_crit(struct device *dev,
61 struct device_attribute *devattr, char *buf)
62{
63 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
64 int show_hyst = attr->index;
65 u32 regval;
66 int value;
67
68 pci_read_config_dword(to_pci_dev(dev),
69 REG_HARDWARE_THERMAL_CONTROL, &regval);
70 value = ((regval >> 16) & 0x7f) * 500 + 52000;
71 if (show_hyst)
72 value -= ((regval >> 24) & 0xf) * 500;
73 return sprintf(buf, "%d\n", value);
74}
75
76static ssize_t show_name(struct device *dev,
77 struct device_attribute *attr, char *buf)
78{
79 return sprintf(buf, "k10temp\n");
80}
81
82static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL);
83static DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_max, NULL);
84static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0);
85static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, show_temp_crit, NULL, 1);
86static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
87
88static bool __devinit has_erratum_319(void)
89{
90 /*
91 * Erratum 319: The thermal sensor of older Family 10h processors
92 * (B steppings) may be unreliable.
93 */
94 return boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model <= 2;
95}
96
97static int __devinit k10temp_probe(struct pci_dev *pdev,
98 const struct pci_device_id *id)
99{
100 struct device *hwmon_dev;
101 u32 reg_caps, reg_htc;
102 int err;
103
104 if (has_erratum_319() && !force) {
105 dev_err(&pdev->dev,
106 "unreliable CPU thermal sensor; monitoring disabled\n");
107 err = -ENODEV;
108 goto exit;
109 }
110
111 err = device_create_file(&pdev->dev, &dev_attr_temp1_input);
112 if (err)
113 goto exit;
114 err = device_create_file(&pdev->dev, &dev_attr_temp1_max);
115 if (err)
116 goto exit_remove;
117
118 pci_read_config_dword(pdev, REG_NORTHBRIDGE_CAPABILITIES, &reg_caps);
119 pci_read_config_dword(pdev, REG_HARDWARE_THERMAL_CONTROL, &reg_htc);
120 if ((reg_caps & NB_CAP_HTC) && (reg_htc & HTC_ENABLE)) {
121 err = device_create_file(&pdev->dev,
122 &sensor_dev_attr_temp1_crit.dev_attr);
123 if (err)
124 goto exit_remove;
125 err = device_create_file(&pdev->dev,
126 &sensor_dev_attr_temp1_crit_hyst.dev_attr);
127 if (err)
128 goto exit_remove;
129 }
130
131 err = device_create_file(&pdev->dev, &dev_attr_name);
132 if (err)
133 goto exit_remove;
134
135 hwmon_dev = hwmon_device_register(&pdev->dev);
136 if (IS_ERR(hwmon_dev)) {
137 err = PTR_ERR(hwmon_dev);
138 goto exit_remove;
139 }
140 dev_set_drvdata(&pdev->dev, hwmon_dev);
141
142 if (has_erratum_319() && force)
143 dev_warn(&pdev->dev,
144 "unreliable CPU thermal sensor; check erratum 319\n");
145 return 0;
146
147exit_remove:
148 device_remove_file(&pdev->dev, &dev_attr_name);
149 device_remove_file(&pdev->dev, &dev_attr_temp1_input);
150 device_remove_file(&pdev->dev, &dev_attr_temp1_max);
151 device_remove_file(&pdev->dev,
152 &sensor_dev_attr_temp1_crit.dev_attr);
153 device_remove_file(&pdev->dev,
154 &sensor_dev_attr_temp1_crit_hyst.dev_attr);
155exit:
156 return err;
157}
158
159static void __devexit k10temp_remove(struct pci_dev *pdev)
160{
161 hwmon_device_unregister(dev_get_drvdata(&pdev->dev));
162 device_remove_file(&pdev->dev, &dev_attr_name);
163 device_remove_file(&pdev->dev, &dev_attr_temp1_input);
164 device_remove_file(&pdev->dev, &dev_attr_temp1_max);
165 device_remove_file(&pdev->dev,
166 &sensor_dev_attr_temp1_crit.dev_attr);
167 device_remove_file(&pdev->dev,
168 &sensor_dev_attr_temp1_crit_hyst.dev_attr);
169 dev_set_drvdata(&pdev->dev, NULL);
170}
171
172static struct pci_device_id k10temp_id_table[] = {
173 { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) },
174 { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_11H_NB_MISC) },
175 {}
176};
177MODULE_DEVICE_TABLE(pci, k10temp_id_table);
178
179static struct pci_driver k10temp_driver = {
180 .name = "k10temp",
181 .id_table = k10temp_id_table,
182 .probe = k10temp_probe,
183 .remove = __devexit_p(k10temp_remove),
184};
185
186static int __init k10temp_init(void)
187{
188 return pci_register_driver(&k10temp_driver);
189}
190
191static void __exit k10temp_exit(void)
192{
193 pci_unregister_driver(&k10temp_driver);
194}
195
196module_init(k10temp_init)
197module_exit(k10temp_exit)