pppoe: endianness
[linux-2.6] / drivers / hwmon / coretemp.c
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
41 typedef enum { SHOW_TEMP, SHOW_TJMAX, SHOW_LABEL, SHOW_NAME } SHOW;
42
43 /*
44  * Functions declaration
45  */
46
47 static struct coretemp_data *coretemp_update_device(struct device *dev);
48
49 struct 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
61 static struct coretemp_data *coretemp_update_device(struct device *dev);
62
63 /*
64  * Sysfs stuff
65  */
66
67 static 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
81 static 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
89 static 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
104 static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL,
105                           SHOW_TEMP);
106 static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp, NULL,
107                           SHOW_TJMAX);
108 static DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL);
109 static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_name, NULL, SHOW_LABEL);
110 static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, SHOW_NAME);
111
112 static 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
121 static const struct attribute_group coretemp_group = {
122         .attrs = coretemp_attributes,
123 };
124
125 static 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
152 static 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
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                         err = -ENODEV;
189                         dev_err(&pdev->dev,
190                                 "Errata AE18 not fixed, update BIOS or "
191                                 "microcode of the CPU!\n");
192                         goto exit_free;
193                 }
194         }
195
196         /* Some processors have Tjmax 85 following magic should detect it
197            Intel won't disclose the information without signed NDA, but
198            individuals cannot sign it. Catch(ed) 22.
199         */
200
201         if (((c->x86_model == 0xf) && (c->x86_mask > 3)) ||
202                 (c->x86_model == 0xe))  {
203                 err = rdmsr_safe_on_cpu(data->id, 0xee, &eax, &edx);
204                 if (err) {
205                         dev_warn(&pdev->dev,
206                                  "Unable to access MSR 0xEE, Tjmax left at %d "
207                                  "degrees C\n", data->tjmax/1000);
208                 } else if (eax & 0x40000000) {
209                         data->tjmax = 85000;
210                 }
211         }
212
213         /* Intel says that above should not work for desktop Core2 processors,
214            but it seems to work. There is no other way how get the absolute
215            readings. Warn the user about this. First check if are desktop,
216            bit 50 of MSR_IA32_PLATFORM_ID should be 0.
217         */
218
219         rdmsr_safe_on_cpu(data->id, MSR_IA32_PLATFORM_ID, &eax, &edx);
220
221         if ((c->x86_model == 0xf) && (!(edx & 0x00040000))) {
222                 dev_warn(&pdev->dev, "Using undocumented features, absolute "
223                          "temperature might be wrong!\n");
224         }
225
226         platform_set_drvdata(pdev, data);
227
228         if ((err = sysfs_create_group(&pdev->dev.kobj, &coretemp_group)))
229                 goto exit_free;
230
231         data->class_dev = hwmon_device_register(&pdev->dev);
232         if (IS_ERR(data->class_dev)) {
233                 err = PTR_ERR(data->class_dev);
234                 dev_err(&pdev->dev, "Class registration failed (%d)\n",
235                         err);
236                 goto exit_class;
237         }
238
239         return 0;
240
241 exit_class:
242         sysfs_remove_group(&pdev->dev.kobj, &coretemp_group);
243 exit_free:
244         kfree(data);
245 exit:
246         return err;
247 }
248
249 static int __devexit coretemp_remove(struct platform_device *pdev)
250 {
251         struct coretemp_data *data = platform_get_drvdata(pdev);
252
253         hwmon_device_unregister(data->class_dev);
254         sysfs_remove_group(&pdev->dev.kobj, &coretemp_group);
255         platform_set_drvdata(pdev, NULL);
256         kfree(data);
257         return 0;
258 }
259
260 static struct platform_driver coretemp_driver = {
261         .driver = {
262                 .owner = THIS_MODULE,
263                 .name = DRVNAME,
264         },
265         .probe = coretemp_probe,
266         .remove = __devexit_p(coretemp_remove),
267 };
268
269 struct pdev_entry {
270         struct list_head list;
271         struct platform_device *pdev;
272         unsigned int cpu;
273 };
274
275 static LIST_HEAD(pdev_list);
276 static DEFINE_MUTEX(pdev_list_mutex);
277
278 static int __cpuinit coretemp_device_add(unsigned int cpu)
279 {
280         int err;
281         struct platform_device *pdev;
282         struct pdev_entry *pdev_entry;
283
284         pdev = platform_device_alloc(DRVNAME, cpu);
285         if (!pdev) {
286                 err = -ENOMEM;
287                 printk(KERN_ERR DRVNAME ": Device allocation failed\n");
288                 goto exit;
289         }
290
291         pdev_entry = kzalloc(sizeof(struct pdev_entry), GFP_KERNEL);
292         if (!pdev_entry) {
293                 err = -ENOMEM;
294                 goto exit_device_put;
295         }
296
297         err = platform_device_add(pdev);
298         if (err) {
299                 printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
300                        err);
301                 goto exit_device_free;
302         }
303
304         pdev_entry->pdev = pdev;
305         pdev_entry->cpu = cpu;
306         mutex_lock(&pdev_list_mutex);
307         list_add_tail(&pdev_entry->list, &pdev_list);
308         mutex_unlock(&pdev_list_mutex);
309
310         return 0;
311
312 exit_device_free:
313         kfree(pdev_entry);
314 exit_device_put:
315         platform_device_put(pdev);
316 exit:
317         return err;
318 }
319
320 #ifdef CONFIG_HOTPLUG_CPU
321 static void coretemp_device_remove(unsigned int cpu)
322 {
323         struct pdev_entry *p, *n;
324         mutex_lock(&pdev_list_mutex);
325         list_for_each_entry_safe(p, n, &pdev_list, list) {
326                 if (p->cpu == cpu) {
327                         platform_device_unregister(p->pdev);
328                         list_del(&p->list);
329                         kfree(p);
330                 }
331         }
332         mutex_unlock(&pdev_list_mutex);
333 }
334
335 static int coretemp_cpu_callback(struct notifier_block *nfb,
336                                  unsigned long action, void *hcpu)
337 {
338         unsigned int cpu = (unsigned long) hcpu;
339
340         switch (action) {
341         case CPU_ONLINE:
342         case CPU_ONLINE_FROZEN:
343                 coretemp_device_add(cpu);
344                 break;
345         case CPU_DEAD:
346         case CPU_DEAD_FROZEN:
347                 coretemp_device_remove(cpu);
348                 break;
349         }
350         return NOTIFY_OK;
351 }
352
353 static struct notifier_block __cpuinitdata coretemp_cpu_notifier = {
354         .notifier_call = coretemp_cpu_callback,
355 };
356 #endif                          /* !CONFIG_HOTPLUG_CPU */
357
358 static int __init coretemp_init(void)
359 {
360         int i, err = -ENODEV;
361         struct pdev_entry *p, *n;
362
363         /* quick check if we run Intel */
364         if (cpu_data[0].x86_vendor != X86_VENDOR_INTEL)
365                 goto exit;
366
367         err = platform_driver_register(&coretemp_driver);
368         if (err)
369                 goto exit;
370
371         for_each_online_cpu(i) {
372                 struct cpuinfo_x86 *c = &(cpu_data)[i];
373
374                 /* check if family 6, models e, f */
375                 if ((c->cpuid_level < 0) || (c->x86 != 0x6) ||
376                     !((c->x86_model == 0xe) || (c->x86_model == 0xf))) {
377
378                         /* supported CPU not found, but report the unknown
379                            family 6 CPU */
380                         if ((c->x86 == 0x6) && (c->x86_model > 0xf))
381                                 printk(KERN_WARNING DRVNAME ": Unknown CPU "
382                                         "model %x\n", c->x86_model);
383                         continue;
384                 }
385
386                 err = coretemp_device_add(i);
387                 if (err)
388                         goto exit_devices_unreg;
389         }
390         if (list_empty(&pdev_list)) {
391                 err = -ENODEV;
392                 goto exit_driver_unreg;
393         }
394
395 #ifdef CONFIG_HOTPLUG_CPU
396         register_hotcpu_notifier(&coretemp_cpu_notifier);
397 #endif
398         return 0;
399
400 exit_devices_unreg:
401         mutex_lock(&pdev_list_mutex);
402         list_for_each_entry_safe(p, n, &pdev_list, list) {
403                 platform_device_unregister(p->pdev);
404                 list_del(&p->list);
405                 kfree(p);
406         }
407         mutex_unlock(&pdev_list_mutex);
408 exit_driver_unreg:
409         platform_driver_unregister(&coretemp_driver);
410 exit:
411         return err;
412 }
413
414 static void __exit coretemp_exit(void)
415 {
416         struct pdev_entry *p, *n;
417 #ifdef CONFIG_HOTPLUG_CPU
418         unregister_hotcpu_notifier(&coretemp_cpu_notifier);
419 #endif
420         mutex_lock(&pdev_list_mutex);
421         list_for_each_entry_safe(p, n, &pdev_list, list) {
422                 platform_device_unregister(p->pdev);
423                 list_del(&p->list);
424                 kfree(p);
425         }
426         mutex_unlock(&pdev_list_mutex);
427         platform_driver_unregister(&coretemp_driver);
428 }
429
430 MODULE_AUTHOR("Rudolf Marek <r.marek@assembler.cz>");
431 MODULE_DESCRIPTION("Intel Core temperature monitor");
432 MODULE_LICENSE("GPL");
433
434 module_init(coretemp_init)
435 module_exit(coretemp_exit)