2 * coretemp.c - Linux kernel module for hardware monitoring
4 * Copyright (C) 2007 Rudolf Marek <r.marek@assembler.cz>
6 * Inspired from many hwmon drivers
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 #include <linux/module.h>
24 #include <linux/delay.h>
25 #include <linux/init.h>
26 #include <linux/slab.h>
27 #include <linux/jiffies.h>
28 #include <linux/hwmon.h>
29 #include <linux/sysfs.h>
30 #include <linux/hwmon-sysfs.h>
31 #include <linux/err.h>
32 #include <linux/mutex.h>
33 #include <linux/list.h>
34 #include <linux/platform_device.h>
35 #include <linux/cpu.h>
37 #include <asm/processor.h>
39 #define DRVNAME "coretemp"
41 typedef enum { SHOW_TEMP, SHOW_TJMAX, SHOW_TTARGET, SHOW_LABEL,
45 * Functions declaration
48 static struct coretemp_data *coretemp_update_device(struct device *dev);
50 struct coretemp_data {
51 struct device *hwmon_dev;
52 struct mutex update_lock;
55 char valid; /* zero until following fields are valid */
56 unsigned long last_updated; /* in jiffies */
67 static ssize_t show_name(struct device *dev, struct device_attribute
71 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
72 struct coretemp_data *data = dev_get_drvdata(dev);
74 if (attr->index == SHOW_NAME)
75 ret = sprintf(buf, "%s\n", data->name);
77 ret = sprintf(buf, "Core %d\n", data->id);
81 static ssize_t show_alarm(struct device *dev, struct device_attribute
84 struct coretemp_data *data = coretemp_update_device(dev);
85 /* read the Out-of-spec log, never clear */
86 return sprintf(buf, "%d\n", data->alarm);
89 static ssize_t show_temp(struct device *dev,
90 struct device_attribute *devattr, char *buf)
92 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
93 struct coretemp_data *data = coretemp_update_device(dev);
96 if (attr->index == SHOW_TEMP)
97 err = data->valid ? sprintf(buf, "%d\n", data->temp) : -EAGAIN;
98 else if (attr->index == SHOW_TJMAX)
99 err = sprintf(buf, "%d\n", data->tjmax);
101 err = sprintf(buf, "%d\n", data->ttarget);
105 static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL,
107 static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp, NULL,
109 static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp, NULL,
111 static DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL);
112 static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_name, NULL, SHOW_LABEL);
113 static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, SHOW_NAME);
115 static struct attribute *coretemp_attributes[] = {
116 &sensor_dev_attr_name.dev_attr.attr,
117 &sensor_dev_attr_temp1_label.dev_attr.attr,
118 &dev_attr_temp1_crit_alarm.attr,
119 &sensor_dev_attr_temp1_input.dev_attr.attr,
120 &sensor_dev_attr_temp1_crit.dev_attr.attr,
124 static const struct attribute_group coretemp_group = {
125 .attrs = coretemp_attributes,
128 static struct coretemp_data *coretemp_update_device(struct device *dev)
130 struct coretemp_data *data = dev_get_drvdata(dev);
132 mutex_lock(&data->update_lock);
134 if (!data->valid || time_after(jiffies, data->last_updated + HZ)) {
138 rdmsr_on_cpu(data->id, MSR_IA32_THERM_STATUS, &eax, &edx);
139 data->alarm = (eax >> 5) & 1;
140 /* update only if data has been valid */
141 if (eax & 0x80000000) {
142 data->temp = data->tjmax - (((eax >> 16)
146 dev_dbg(dev, "Temperature data invalid (0x%x)\n", eax);
148 data->last_updated = jiffies;
151 mutex_unlock(&data->update_lock);
155 static int __devinit coretemp_probe(struct platform_device *pdev)
157 struct coretemp_data *data;
158 struct cpuinfo_x86 *c = &cpu_data(pdev->id);
162 if (!(data = kzalloc(sizeof(struct coretemp_data), GFP_KERNEL))) {
164 dev_err(&pdev->dev, "Out of memory\n");
169 data->name = "coretemp";
170 mutex_init(&data->update_lock);
171 /* Tjmax default is 100 degrees C */
172 data->tjmax = 100000;
174 /* test if we can access the THERM_STATUS MSR */
175 err = rdmsr_safe_on_cpu(data->id, MSR_IA32_THERM_STATUS, &eax, &edx);
178 "Unable to access THERM_STATUS MSR, giving up\n");
182 /* Check if we have problem with errata AE18 of Core processors:
183 Readings might stop update when processor visited too deep sleep,
184 fixed for stepping D0 (6EC).
187 if ((c->x86_model == 0xe) && (c->x86_mask < 0xc)) {
188 /* check for microcode update */
189 rdmsr_on_cpu(data->id, MSR_IA32_UCODE_REV, &eax, &edx);
193 "Errata AE18 not fixed, update BIOS or "
194 "microcode of the CPU!\n");
199 /* Some processors have Tjmax 85 following magic should detect it
200 Intel won't disclose the information without signed NDA, but
201 individuals cannot sign it. Catch(ed) 22.
204 if (((c->x86_model == 0xf) && (c->x86_mask > 3)) ||
205 (c->x86_model == 0xe)) {
206 err = rdmsr_safe_on_cpu(data->id, 0xee, &eax, &edx);
209 "Unable to access MSR 0xEE, Tjmax left at %d "
210 "degrees C\n", data->tjmax/1000);
211 } else if (eax & 0x40000000) {
216 /* Intel says that above should not work for desktop Core2 processors,
217 but it seems to work. There is no other way how get the absolute
218 readings. Warn the user about this. First check if are desktop,
219 bit 50 of MSR_IA32_PLATFORM_ID should be 0.
222 rdmsr_safe_on_cpu(data->id, MSR_IA32_PLATFORM_ID, &eax, &edx);
224 if ((c->x86_model == 0xf) && (!(edx & 0x00040000))) {
225 dev_warn(&pdev->dev, "Using undocumented features, absolute "
226 "temperature might be wrong!\n");
229 platform_set_drvdata(pdev, data);
231 /* read the still undocumented IA32_TEMPERATURE_TARGET it exists
232 on older CPUs but not in this register */
234 if (c->x86_model > 0xe) {
235 err = rdmsr_safe_on_cpu(data->id, 0x1a2, &eax, &edx);
237 dev_warn(&pdev->dev, "Unable to read"
238 " IA32_TEMPERATURE_TARGET MSR\n");
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);
249 if ((err = sysfs_create_group(&pdev->dev.kobj, &coretemp_group)))
252 data->hwmon_dev = hwmon_device_register(&pdev->dev);
253 if (IS_ERR(data->hwmon_dev)) {
254 err = PTR_ERR(data->hwmon_dev);
255 dev_err(&pdev->dev, "Class registration failed (%d)\n",
263 sysfs_remove_group(&pdev->dev.kobj, &coretemp_group);
265 device_remove_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr);
272 static int __devexit coretemp_remove(struct platform_device *pdev)
274 struct coretemp_data *data = platform_get_drvdata(pdev);
276 hwmon_device_unregister(data->hwmon_dev);
277 sysfs_remove_group(&pdev->dev.kobj, &coretemp_group);
278 device_remove_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr);
279 platform_set_drvdata(pdev, NULL);
284 static struct platform_driver coretemp_driver = {
286 .owner = THIS_MODULE,
289 .probe = coretemp_probe,
290 .remove = __devexit_p(coretemp_remove),
294 struct list_head list;
295 struct platform_device *pdev;
299 static LIST_HEAD(pdev_list);
300 static DEFINE_MUTEX(pdev_list_mutex);
302 static int __cpuinit coretemp_device_add(unsigned int cpu)
305 struct platform_device *pdev;
306 struct pdev_entry *pdev_entry;
308 pdev = platform_device_alloc(DRVNAME, cpu);
311 printk(KERN_ERR DRVNAME ": Device allocation failed\n");
315 pdev_entry = kzalloc(sizeof(struct pdev_entry), GFP_KERNEL);
318 goto exit_device_put;
321 err = platform_device_add(pdev);
323 printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
325 goto exit_device_free;
328 pdev_entry->pdev = pdev;
329 pdev_entry->cpu = cpu;
330 mutex_lock(&pdev_list_mutex);
331 list_add_tail(&pdev_entry->list, &pdev_list);
332 mutex_unlock(&pdev_list_mutex);
339 platform_device_put(pdev);
344 #ifdef CONFIG_HOTPLUG_CPU
345 static void coretemp_device_remove(unsigned int cpu)
347 struct pdev_entry *p, *n;
348 mutex_lock(&pdev_list_mutex);
349 list_for_each_entry_safe(p, n, &pdev_list, list) {
351 platform_device_unregister(p->pdev);
356 mutex_unlock(&pdev_list_mutex);
359 static int coretemp_cpu_callback(struct notifier_block *nfb,
360 unsigned long action, void *hcpu)
362 unsigned int cpu = (unsigned long) hcpu;
366 case CPU_DOWN_FAILED:
367 coretemp_device_add(cpu);
369 case CPU_DOWN_PREPARE:
370 coretemp_device_remove(cpu);
376 static struct notifier_block coretemp_cpu_notifier = {
377 .notifier_call = coretemp_cpu_callback,
379 #endif /* !CONFIG_HOTPLUG_CPU */
381 static int __init coretemp_init(void)
383 int i, err = -ENODEV;
384 struct pdev_entry *p, *n;
386 /* quick check if we run Intel */
387 if (cpu_data(0).x86_vendor != X86_VENDOR_INTEL)
390 err = platform_driver_register(&coretemp_driver);
394 for_each_online_cpu(i) {
395 struct cpuinfo_x86 *c = &cpu_data(i);
397 /* check if family 6, models e, f, 16 */
398 if ((c->cpuid_level < 0) || (c->x86 != 0x6) ||
399 !((c->x86_model == 0xe) || (c->x86_model == 0xf) ||
400 (c->x86_model == 0x16))) {
402 /* supported CPU not found, but report the unknown
404 if ((c->x86 == 0x6) && (c->x86_model > 0xf))
405 printk(KERN_WARNING DRVNAME ": Unknown CPU "
406 "model %x\n", c->x86_model);
410 err = coretemp_device_add(i);
412 goto exit_devices_unreg;
414 if (list_empty(&pdev_list)) {
416 goto exit_driver_unreg;
419 #ifdef CONFIG_HOTPLUG_CPU
420 register_hotcpu_notifier(&coretemp_cpu_notifier);
425 mutex_lock(&pdev_list_mutex);
426 list_for_each_entry_safe(p, n, &pdev_list, list) {
427 platform_device_unregister(p->pdev);
431 mutex_unlock(&pdev_list_mutex);
433 platform_driver_unregister(&coretemp_driver);
438 static void __exit coretemp_exit(void)
440 struct pdev_entry *p, *n;
441 #ifdef CONFIG_HOTPLUG_CPU
442 unregister_hotcpu_notifier(&coretemp_cpu_notifier);
444 mutex_lock(&pdev_list_mutex);
445 list_for_each_entry_safe(p, n, &pdev_list, list) {
446 platform_device_unregister(p->pdev);
450 mutex_unlock(&pdev_list_mutex);
451 platform_driver_unregister(&coretemp_driver);
454 MODULE_AUTHOR("Rudolf Marek <r.marek@assembler.cz>");
455 MODULE_DESCRIPTION("Intel Core temperature monitor");
456 MODULE_LICENSE("GPL");
458 module_init(coretemp_init)
459 module_exit(coretemp_exit)