Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux...
[deliverable/linux.git] / drivers / hwmon / coretemp.c
CommitLineData
bebe4678
RM
1/*
2 * coretemp.c - Linux kernel module for hardware monitoring
3 *
4 * Copyright (C) 2007 Rudolf Marek <r.marek@assembler.cz>
5 *
6 * Inspired from many hwmon drivers
7 *
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.
11 *
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.
16 *
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
20 * 02110-1301 USA.
21 */
22
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>
36#include <asm/msr.h>
37#include <asm/processor.h>
38
39#define DRVNAME "coretemp"
40
41typedef enum { SHOW_TEMP, SHOW_TJMAX, SHOW_LABEL, SHOW_NAME } SHOW;
42
43/*
44 * Functions declaration
45 */
46
47static struct coretemp_data *coretemp_update_device(struct device *dev);
48
49struct coretemp_data {
50 struct class_device *class_dev;
51 struct mutex update_lock;
52 const char *name;
53 u32 id;
54 char valid; /* zero until following fields are valid */
55 unsigned long last_updated; /* in jiffies */
56 int temp;
57 int tjmax;
58 u8 alarm;
59};
60
61static struct coretemp_data *coretemp_update_device(struct device *dev);
62
63/*
64 * Sysfs stuff
65 */
66
67static ssize_t show_name(struct device *dev, struct device_attribute
68 *devattr, char *buf)
69{
70 int ret;
71 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
72 struct coretemp_data *data = dev_get_drvdata(dev);
73
74 if (attr->index == SHOW_NAME)
75 ret = sprintf(buf, "%s\n", data->name);
76 else /* show label */
77 ret = sprintf(buf, "Core %d\n", data->id);
78 return ret;
79}
80
81static ssize_t show_alarm(struct device *dev, struct device_attribute
82 *devattr, char *buf)
83{
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);
87}
88
89static ssize_t show_temp(struct device *dev,
90 struct device_attribute *devattr, char *buf)
91{
92 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
93 struct coretemp_data *data = coretemp_update_device(dev);
94 int err;
95
96 if (attr->index == SHOW_TEMP)
97 err = data->valid ? sprintf(buf, "%d\n", data->temp) : -EAGAIN;
98 else
99 err = sprintf(buf, "%d\n", data->tjmax);
100
101 return err;
102}
103
104static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL,
105 SHOW_TEMP);
106static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp, NULL,
107 SHOW_TJMAX);
108static DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL);
109static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_name, NULL, SHOW_LABEL);
110static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, SHOW_NAME);
111
112static struct attribute *coretemp_attributes[] = {
113 &sensor_dev_attr_name.dev_attr.attr,
114 &sensor_dev_attr_temp1_label.dev_attr.attr,
115 &dev_attr_temp1_crit_alarm.attr,
116 &sensor_dev_attr_temp1_input.dev_attr.attr,
117 &sensor_dev_attr_temp1_crit.dev_attr.attr,
118 NULL
119};
120
121static const struct attribute_group coretemp_group = {
122 .attrs = coretemp_attributes,
123};
124
125static struct coretemp_data *coretemp_update_device(struct device *dev)
126{
127 struct coretemp_data *data = dev_get_drvdata(dev);
128
129 mutex_lock(&data->update_lock);
130
131 if (!data->valid || time_after(jiffies, data->last_updated + HZ)) {
132 u32 eax, edx;
133
134 data->valid = 0;
135 rdmsr_on_cpu(data->id, MSR_IA32_THERM_STATUS, &eax, &edx);
136 data->alarm = (eax >> 5) & 1;
137 /* update only if data has been valid */
138 if (eax & 0x80000000) {
139 data->temp = data->tjmax - (((eax >> 16)
140 & 0x7f) * 1000);
141 data->valid = 1;
142 } else {
143 dev_dbg(dev, "Temperature data invalid (0x%x)\n", eax);
144 }
145 data->last_updated = jiffies;
146 }
147
148 mutex_unlock(&data->update_lock);
149 return data;
150}
151
152static int __devinit coretemp_probe(struct platform_device *pdev)
153{
154 struct coretemp_data *data;
155 struct cpuinfo_x86 *c = &(cpu_data)[pdev->id];
156 int err;
157 u32 eax, edx;
158
159 if (!(data = kzalloc(sizeof(struct coretemp_data), GFP_KERNEL))) {
160 err = -ENOMEM;
161 dev_err(&pdev->dev, "Out of memory\n");
162 goto exit;
163 }
164
165 data->id = pdev->id;
166 data->name = "coretemp";
167 mutex_init(&data->update_lock);
168 /* Tjmax default is 100 degrees C */
169 data->tjmax = 100000;
170
171 /* test if we can access the THERM_STATUS MSR */
172 err = rdmsr_safe_on_cpu(data->id, MSR_IA32_THERM_STATUS, &eax, &edx);
173 if (err) {
174 dev_err(&pdev->dev,
175 "Unable to access THERM_STATUS MSR, giving up\n");
176 goto exit_free;
177 }
178
67f363b1
RM
179 /* Check if we have problem with errata AE18 of Core processors:
180 Readings might stop update when processor visited too deep sleep,
181 fixed for stepping D0 (6EC).
182 */
183
184 if ((c->x86_model == 0xe) && (c->x86_mask < 0xc)) {
185 /* check for microcode update */
186 rdmsr_on_cpu(data->id, MSR_IA32_UCODE_REV, &eax, &edx);
187 if (edx < 0x39) {
188 dev_err(&pdev->dev,
189 "Errata AE18 not fixed, update BIOS or "
190 "microcode of the CPU!\n");
191 goto exit_free;
192 }
193 }
194
bebe4678
RM
195 /* Some processors have Tjmax 85 following magic should detect it
196 Intel won't disclose the information without signed NDA, but
197 individuals cannot sign it. Catch(ed) 22.
198 */
199
200 if (((c->x86_model == 0xf) && (c->x86_mask > 3)) ||
201 (c->x86_model == 0xe)) {
202 err = rdmsr_safe_on_cpu(data->id, 0xee, &eax, &edx);
203 if (err) {
204 dev_warn(&pdev->dev,
205 "Unable to access MSR 0xEE, Tjmax left at %d "
206 "degrees C\n", data->tjmax/1000);
207 } else if (eax & 0x40000000) {
208 data->tjmax = 85000;
209 }
210 }
211
67f363b1
RM
212 /* Intel says that above should not work for desktop Core2 processors,
213 but it seems to work. There is no other way how get the absolute
214 readings. Warn the user about this. First check if are desktop,
215 bit 50 of MSR_IA32_PLATFORM_ID should be 0.
216 */
217
218 rdmsr_safe_on_cpu(data->id, MSR_IA32_PLATFORM_ID, &eax, &edx);
219
220 if ((c->x86_model == 0xf) && (!(edx & 0x00040000))) {
221 dev_warn(&pdev->dev, "Using undocumented features, absolute "
222 "temperature might be wrong!\n");
223 }
224
bebe4678
RM
225 platform_set_drvdata(pdev, data);
226
227 if ((err = sysfs_create_group(&pdev->dev.kobj, &coretemp_group)))
228 goto exit_free;
229
230 data->class_dev = hwmon_device_register(&pdev->dev);
231 if (IS_ERR(data->class_dev)) {
232 err = PTR_ERR(data->class_dev);
233 dev_err(&pdev->dev, "Class registration failed (%d)\n",
234 err);
235 goto exit_class;
236 }
237
238 return 0;
239
240exit_class:
241 sysfs_remove_group(&pdev->dev.kobj, &coretemp_group);
242exit_free:
243 kfree(data);
244exit:
245 return err;
246}
247
248static int __devexit coretemp_remove(struct platform_device *pdev)
249{
250 struct coretemp_data *data = platform_get_drvdata(pdev);
251
252 hwmon_device_unregister(data->class_dev);
253 sysfs_remove_group(&pdev->dev.kobj, &coretemp_group);
254 platform_set_drvdata(pdev, NULL);
255 kfree(data);
256 return 0;
257}
258
259static struct platform_driver coretemp_driver = {
260 .driver = {
261 .owner = THIS_MODULE,
262 .name = DRVNAME,
263 },
264 .probe = coretemp_probe,
265 .remove = __devexit_p(coretemp_remove),
266};
267
268struct pdev_entry {
269 struct list_head list;
270 struct platform_device *pdev;
271 unsigned int cpu;
272};
273
274static LIST_HEAD(pdev_list);
275static DEFINE_MUTEX(pdev_list_mutex);
276
277static int __cpuinit coretemp_device_add(unsigned int cpu)
278{
279 int err;
280 struct platform_device *pdev;
281 struct pdev_entry *pdev_entry;
282
283 pdev = platform_device_alloc(DRVNAME, cpu);
284 if (!pdev) {
285 err = -ENOMEM;
286 printk(KERN_ERR DRVNAME ": Device allocation failed\n");
287 goto exit;
288 }
289
290 pdev_entry = kzalloc(sizeof(struct pdev_entry), GFP_KERNEL);
291 if (!pdev_entry) {
292 err = -ENOMEM;
293 goto exit_device_put;
294 }
295
296 err = platform_device_add(pdev);
297 if (err) {
298 printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
299 err);
300 goto exit_device_free;
301 }
302
303 pdev_entry->pdev = pdev;
304 pdev_entry->cpu = cpu;
305 mutex_lock(&pdev_list_mutex);
306 list_add_tail(&pdev_entry->list, &pdev_list);
307 mutex_unlock(&pdev_list_mutex);
308
309 return 0;
310
311exit_device_free:
312 kfree(pdev_entry);
313exit_device_put:
314 platform_device_put(pdev);
315exit:
316 return err;
317}
318
319#ifdef CONFIG_HOTPLUG_CPU
320void coretemp_device_remove(unsigned int cpu)
321{
322 struct pdev_entry *p, *n;
323 mutex_lock(&pdev_list_mutex);
324 list_for_each_entry_safe(p, n, &pdev_list, list) {
325 if (p->cpu == cpu) {
326 platform_device_unregister(p->pdev);
327 list_del(&p->list);
328 kfree(p);
329 }
330 }
331 mutex_unlock(&pdev_list_mutex);
332}
333
334static int coretemp_cpu_callback(struct notifier_block *nfb,
335 unsigned long action, void *hcpu)
336{
337 unsigned int cpu = (unsigned long) hcpu;
338
339 switch (action) {
340 case CPU_ONLINE:
8bb78442 341 case CPU_ONLINE_FROZEN:
bebe4678
RM
342 coretemp_device_add(cpu);
343 break;
344 case CPU_DEAD:
8bb78442 345 case CPU_DEAD_FROZEN:
bebe4678
RM
346 coretemp_device_remove(cpu);
347 break;
348 }
349 return NOTIFY_OK;
350}
351
352static struct notifier_block __cpuinitdata coretemp_cpu_notifier = {
353 .notifier_call = coretemp_cpu_callback,
354};
355#endif /* !CONFIG_HOTPLUG_CPU */
356
357static int __init coretemp_init(void)
358{
359 int i, err = -ENODEV;
360 struct pdev_entry *p, *n;
361
bebe4678
RM
362 /* quick check if we run Intel */
363 if (cpu_data[0].x86_vendor != X86_VENDOR_INTEL)
364 goto exit;
365
366 err = platform_driver_register(&coretemp_driver);
367 if (err)
368 goto exit;
369
370 for_each_online_cpu(i) {
371 struct cpuinfo_x86 *c = &(cpu_data)[i];
372
373 /* check if family 6, models e, f */
374 if ((c->cpuid_level < 0) || (c->x86 != 0x6) ||
375 !((c->x86_model == 0xe) || (c->x86_model == 0xf))) {
376
377 /* supported CPU not found, but report the unknown
378 family 6 CPU */
379 if ((c->x86 == 0x6) && (c->x86_model > 0xf))
380 printk(KERN_WARNING DRVNAME ": Unknown CPU "
381 "model %x\n", c->x86_model);
382 continue;
383 }
384
385 err = coretemp_device_add(i);
386 if (err)
387 goto exit_devices_unreg;
388 }
389 if (list_empty(&pdev_list)) {
390 err = -ENODEV;
391 goto exit_driver_unreg;
392 }
393
394#ifdef CONFIG_HOTPLUG_CPU
395 register_hotcpu_notifier(&coretemp_cpu_notifier);
396#endif
397 return 0;
398
399exit_devices_unreg:
400 mutex_lock(&pdev_list_mutex);
401 list_for_each_entry_safe(p, n, &pdev_list, list) {
402 platform_device_unregister(p->pdev);
403 list_del(&p->list);
404 kfree(p);
405 }
406 mutex_unlock(&pdev_list_mutex);
407exit_driver_unreg:
408 platform_driver_unregister(&coretemp_driver);
409exit:
410 return err;
411}
412
413static void __exit coretemp_exit(void)
414{
415 struct pdev_entry *p, *n;
416#ifdef CONFIG_HOTPLUG_CPU
417 unregister_hotcpu_notifier(&coretemp_cpu_notifier);
418#endif
419 mutex_lock(&pdev_list_mutex);
420 list_for_each_entry_safe(p, n, &pdev_list, list) {
421 platform_device_unregister(p->pdev);
422 list_del(&p->list);
423 kfree(p);
424 }
425 mutex_unlock(&pdev_list_mutex);
426 platform_driver_unregister(&coretemp_driver);
427}
428
429MODULE_AUTHOR("Rudolf Marek <r.marek@assembler.cz>");
430MODULE_DESCRIPTION("Intel Core temperature monitor");
431MODULE_LICENSE("GPL");
432
433module_init(coretemp_init)
434module_exit(coretemp_exit)
This page took 0.054645 seconds and 5 git commands to generate.