Chinese: add translation of oops-tracing.txt
[pv_ops_mirror.git] / drivers / hwmon / smsc47m1.c
bloba10a380868e2640b6d424e682e7400988a3e8ede
1 /*
2 smsc47m1.c - Part of lm_sensors, Linux kernel modules
3 for hardware monitoring
5 Supports the SMSC LPC47B27x, LPC47M10x, LPC47M112, LPC47M13x,
6 LPC47M14x, LPC47M15x, LPC47M192, LPC47M292 and LPC47M997
7 Super-I/O chips.
9 Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
10 Copyright (C) 2004-2007 Jean Delvare <khali@linux-fr.org>
11 Ported to Linux 2.6 by Gabriele Gorla <gorlik@yahoo.com>
12 and Jean Delvare
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 #include <linux/module.h>
30 #include <linux/slab.h>
31 #include <linux/ioport.h>
32 #include <linux/jiffies.h>
33 #include <linux/platform_device.h>
34 #include <linux/hwmon.h>
35 #include <linux/hwmon-sysfs.h>
36 #include <linux/err.h>
37 #include <linux/init.h>
38 #include <linux/mutex.h>
39 #include <linux/sysfs.h>
40 #include <asm/io.h>
42 static struct platform_device *pdev;
44 #define DRVNAME "smsc47m1"
45 enum chips { smsc47m1, smsc47m2 };
47 /* Super-I/0 registers and commands */
49 #define REG 0x2e /* The register to read/write */
50 #define VAL 0x2f /* The value to read/write */
52 static inline void
53 superio_outb(int reg, int val)
55 outb(reg, REG);
56 outb(val, VAL);
59 static inline int
60 superio_inb(int reg)
62 outb(reg, REG);
63 return inb(VAL);
66 /* logical device for fans is 0x0A */
67 #define superio_select() superio_outb(0x07, 0x0A)
69 static inline void
70 superio_enter(void)
72 outb(0x55, REG);
75 static inline void
76 superio_exit(void)
78 outb(0xAA, REG);
81 #define SUPERIO_REG_ACT 0x30
82 #define SUPERIO_REG_BASE 0x60
83 #define SUPERIO_REG_DEVID 0x20
85 /* Logical device registers */
87 #define SMSC_EXTENT 0x80
89 /* nr is 0 or 1 in the macros below */
90 #define SMSC47M1_REG_ALARM 0x04
91 #define SMSC47M1_REG_TPIN(nr) (0x34 - (nr))
92 #define SMSC47M1_REG_PPIN(nr) (0x36 - (nr))
93 #define SMSC47M1_REG_FANDIV 0x58
95 static const u8 SMSC47M1_REG_FAN[3] = { 0x59, 0x5a, 0x6b };
96 static const u8 SMSC47M1_REG_FAN_PRELOAD[3] = { 0x5b, 0x5c, 0x6c };
97 static const u8 SMSC47M1_REG_PWM[3] = { 0x56, 0x57, 0x69 };
99 #define SMSC47M2_REG_ALARM6 0x09
100 #define SMSC47M2_REG_TPIN1 0x38
101 #define SMSC47M2_REG_TPIN2 0x37
102 #define SMSC47M2_REG_TPIN3 0x2d
103 #define SMSC47M2_REG_PPIN3 0x2c
104 #define SMSC47M2_REG_FANDIV3 0x6a
106 #define MIN_FROM_REG(reg,div) ((reg)>=192 ? 0 : \
107 983040/((192-(reg))*(div)))
108 #define FAN_FROM_REG(reg,div,preload) ((reg)<=(preload) || (reg)==255 ? 0 : \
109 983040/(((reg)-(preload))*(div)))
110 #define DIV_FROM_REG(reg) (1 << (reg))
111 #define PWM_FROM_REG(reg) (((reg) & 0x7E) << 1)
112 #define PWM_EN_FROM_REG(reg) ((~(reg)) & 0x01)
113 #define PWM_TO_REG(reg) (((reg) >> 1) & 0x7E)
115 struct smsc47m1_data {
116 unsigned short addr;
117 const char *name;
118 enum chips type;
119 struct device *hwmon_dev;
121 struct mutex update_lock;
122 unsigned long last_updated; /* In jiffies */
124 u8 fan[3]; /* Register value */
125 u8 fan_preload[3]; /* Register value */
126 u8 fan_div[3]; /* Register encoding, shifted right */
127 u8 alarms; /* Register encoding */
128 u8 pwm[3]; /* Register value (bit 0 is disable) */
131 struct smsc47m1_sio_data {
132 enum chips type;
136 static int smsc47m1_probe(struct platform_device *pdev);
137 static int __devexit smsc47m1_remove(struct platform_device *pdev);
138 static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
139 int init);
141 static inline int smsc47m1_read_value(struct smsc47m1_data *data, u8 reg)
143 return inb_p(data->addr + reg);
146 static inline void smsc47m1_write_value(struct smsc47m1_data *data, u8 reg,
147 u8 value)
149 outb_p(value, data->addr + reg);
152 static struct platform_driver smsc47m1_driver = {
153 .driver = {
154 .owner = THIS_MODULE,
155 .name = DRVNAME,
157 .probe = smsc47m1_probe,
158 .remove = __devexit_p(smsc47m1_remove),
161 static ssize_t get_fan(struct device *dev, struct device_attribute
162 *devattr, char *buf)
164 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
165 struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
166 int nr = attr->index;
167 /* This chip (stupidly) stops monitoring fan speed if PWM is
168 enabled and duty cycle is 0%. This is fine if the monitoring
169 and control concern the same fan, but troublesome if they are
170 not (which could as well happen). */
171 int rpm = (data->pwm[nr] & 0x7F) == 0x00 ? 0 :
172 FAN_FROM_REG(data->fan[nr],
173 DIV_FROM_REG(data->fan_div[nr]),
174 data->fan_preload[nr]);
175 return sprintf(buf, "%d\n", rpm);
178 static ssize_t get_fan_min(struct device *dev, struct device_attribute
179 *devattr, char *buf)
181 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
182 struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
183 int nr = attr->index;
184 int rpm = MIN_FROM_REG(data->fan_preload[nr],
185 DIV_FROM_REG(data->fan_div[nr]));
186 return sprintf(buf, "%d\n", rpm);
189 static ssize_t get_fan_div(struct device *dev, struct device_attribute
190 *devattr, char *buf)
192 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
193 struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
194 return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[attr->index]));
197 static ssize_t get_pwm(struct device *dev, struct device_attribute
198 *devattr, char *buf)
200 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
201 struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
202 return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm[attr->index]));
205 static ssize_t get_pwm_en(struct device *dev, struct device_attribute
206 *devattr, char *buf)
208 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
209 struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
210 return sprintf(buf, "%d\n", PWM_EN_FROM_REG(data->pwm[attr->index]));
213 static ssize_t get_alarms(struct device *dev, struct device_attribute
214 *devattr, char *buf)
216 struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
217 return sprintf(buf, "%d\n", data->alarms);
220 static ssize_t set_fan_min(struct device *dev, struct device_attribute
221 *devattr, const char *buf, size_t count)
223 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
224 struct smsc47m1_data *data = dev_get_drvdata(dev);
225 int nr = attr->index;
226 long rpmdiv, val = simple_strtol(buf, NULL, 10);
228 mutex_lock(&data->update_lock);
229 rpmdiv = val * DIV_FROM_REG(data->fan_div[nr]);
231 if (983040 > 192 * rpmdiv || 2 * rpmdiv > 983040) {
232 mutex_unlock(&data->update_lock);
233 return -EINVAL;
236 data->fan_preload[nr] = 192 - ((983040 + rpmdiv / 2) / rpmdiv);
237 smsc47m1_write_value(data, SMSC47M1_REG_FAN_PRELOAD[nr],
238 data->fan_preload[nr]);
239 mutex_unlock(&data->update_lock);
241 return count;
244 /* Note: we save and restore the fan minimum here, because its value is
245 determined in part by the fan clock divider. This follows the principle
246 of least surprise; the user doesn't expect the fan minimum to change just
247 because the divider changed. */
248 static ssize_t set_fan_div(struct device *dev, struct device_attribute
249 *devattr, const char *buf, size_t count)
251 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
252 struct smsc47m1_data *data = dev_get_drvdata(dev);
253 int nr = attr->index;
254 long new_div = simple_strtol(buf, NULL, 10), tmp;
255 u8 old_div = DIV_FROM_REG(data->fan_div[nr]);
257 if (new_div == old_div) /* No change */
258 return count;
260 mutex_lock(&data->update_lock);
261 switch (new_div) {
262 case 1: data->fan_div[nr] = 0; break;
263 case 2: data->fan_div[nr] = 1; break;
264 case 4: data->fan_div[nr] = 2; break;
265 case 8: data->fan_div[nr] = 3; break;
266 default:
267 mutex_unlock(&data->update_lock);
268 return -EINVAL;
271 switch (nr) {
272 case 0:
273 case 1:
274 tmp = smsc47m1_read_value(data, SMSC47M1_REG_FANDIV)
275 & ~(0x03 << (4 + 2 * nr));
276 tmp |= data->fan_div[nr] << (4 + 2 * nr);
277 smsc47m1_write_value(data, SMSC47M1_REG_FANDIV, tmp);
278 break;
279 case 2:
280 tmp = smsc47m1_read_value(data, SMSC47M2_REG_FANDIV3) & 0xCF;
281 tmp |= data->fan_div[2] << 4;
282 smsc47m1_write_value(data, SMSC47M2_REG_FANDIV3, tmp);
283 break;
286 /* Preserve fan min */
287 tmp = 192 - (old_div * (192 - data->fan_preload[nr])
288 + new_div / 2) / new_div;
289 data->fan_preload[nr] = SENSORS_LIMIT(tmp, 0, 191);
290 smsc47m1_write_value(data, SMSC47M1_REG_FAN_PRELOAD[nr],
291 data->fan_preload[nr]);
292 mutex_unlock(&data->update_lock);
294 return count;
297 static ssize_t set_pwm(struct device *dev, struct device_attribute
298 *devattr, const char *buf, size_t count)
300 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
301 struct smsc47m1_data *data = dev_get_drvdata(dev);
302 int nr = attr->index;
303 long val = simple_strtol(buf, NULL, 10);
305 if (val < 0 || val > 255)
306 return -EINVAL;
308 mutex_lock(&data->update_lock);
309 data->pwm[nr] &= 0x81; /* Preserve additional bits */
310 data->pwm[nr] |= PWM_TO_REG(val);
311 smsc47m1_write_value(data, SMSC47M1_REG_PWM[nr],
312 data->pwm[nr]);
313 mutex_unlock(&data->update_lock);
315 return count;
318 static ssize_t set_pwm_en(struct device *dev, struct device_attribute
319 *devattr, const char *buf, size_t count)
321 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
322 struct smsc47m1_data *data = dev_get_drvdata(dev);
323 int nr = attr->index;
324 long val = simple_strtol(buf, NULL, 10);
326 if (val != 0 && val != 1)
327 return -EINVAL;
329 mutex_lock(&data->update_lock);
330 data->pwm[nr] &= 0xFE; /* preserve the other bits */
331 data->pwm[nr] |= !val;
332 smsc47m1_write_value(data, SMSC47M1_REG_PWM[nr],
333 data->pwm[nr]);
334 mutex_unlock(&data->update_lock);
336 return count;
339 #define fan_present(offset) \
340 static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, get_fan, \
341 NULL, offset - 1); \
342 static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
343 get_fan_min, set_fan_min, offset - 1); \
344 static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \
345 get_fan_div, set_fan_div, offset - 1); \
346 static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \
347 get_pwm, set_pwm, offset - 1); \
348 static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \
349 get_pwm_en, set_pwm_en, offset - 1)
351 fan_present(1);
352 fan_present(2);
353 fan_present(3);
355 static DEVICE_ATTR(alarms, S_IRUGO, get_alarms, NULL);
357 static ssize_t show_name(struct device *dev, struct device_attribute
358 *devattr, char *buf)
360 struct smsc47m1_data *data = dev_get_drvdata(dev);
362 return sprintf(buf, "%s\n", data->name);
364 static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
366 /* Almost all sysfs files may or may not be created depending on the chip
367 setup so we create them individually. It is still convenient to define a
368 group to remove them all at once. */
369 static struct attribute *smsc47m1_attributes[] = {
370 &sensor_dev_attr_fan1_input.dev_attr.attr,
371 &sensor_dev_attr_fan1_min.dev_attr.attr,
372 &sensor_dev_attr_fan1_div.dev_attr.attr,
373 &sensor_dev_attr_fan2_input.dev_attr.attr,
374 &sensor_dev_attr_fan2_min.dev_attr.attr,
375 &sensor_dev_attr_fan2_div.dev_attr.attr,
376 &sensor_dev_attr_fan3_input.dev_attr.attr,
377 &sensor_dev_attr_fan3_min.dev_attr.attr,
378 &sensor_dev_attr_fan3_div.dev_attr.attr,
380 &sensor_dev_attr_pwm1.dev_attr.attr,
381 &sensor_dev_attr_pwm1_enable.dev_attr.attr,
382 &sensor_dev_attr_pwm2.dev_attr.attr,
383 &sensor_dev_attr_pwm2_enable.dev_attr.attr,
384 &sensor_dev_attr_pwm3.dev_attr.attr,
385 &sensor_dev_attr_pwm3_enable.dev_attr.attr,
387 &dev_attr_alarms.attr,
388 &dev_attr_name.attr,
389 NULL
392 static const struct attribute_group smsc47m1_group = {
393 .attrs = smsc47m1_attributes,
396 static int __init smsc47m1_find(unsigned short *addr,
397 struct smsc47m1_sio_data *sio_data)
399 u8 val;
401 superio_enter();
402 val = superio_inb(SUPERIO_REG_DEVID);
405 * SMSC LPC47M10x/LPC47M112/LPC47M13x (device id 0x59), LPC47M14x
406 * (device id 0x5F) and LPC47B27x (device id 0x51) have fan control.
407 * The LPC47M15x and LPC47M192 chips "with hardware monitoring block"
408 * can do much more besides (device id 0x60).
409 * The LPC47M997 is undocumented, but seems to be compatible with
410 * the LPC47M192, and has the same device id.
411 * The LPC47M292 (device id 0x6B) is somewhat compatible, but it
412 * supports a 3rd fan, and the pin configuration registers are
413 * unfortunately different.
415 switch (val) {
416 case 0x51:
417 pr_info(DRVNAME ": Found SMSC LPC47B27x\n");
418 sio_data->type = smsc47m1;
419 break;
420 case 0x59:
421 pr_info(DRVNAME ": Found SMSC LPC47M10x/LPC47M112/LPC47M13x\n");
422 sio_data->type = smsc47m1;
423 break;
424 case 0x5F:
425 pr_info(DRVNAME ": Found SMSC LPC47M14x\n");
426 sio_data->type = smsc47m1;
427 break;
428 case 0x60:
429 pr_info(DRVNAME ": Found SMSC LPC47M15x/LPC47M192/LPC47M997\n");
430 sio_data->type = smsc47m1;
431 break;
432 case 0x6B:
433 pr_info(DRVNAME ": Found SMSC LPC47M292\n");
434 sio_data->type = smsc47m2;
435 break;
436 default:
437 superio_exit();
438 return -ENODEV;
441 superio_select();
442 *addr = (superio_inb(SUPERIO_REG_BASE) << 8)
443 | superio_inb(SUPERIO_REG_BASE + 1);
444 val = superio_inb(SUPERIO_REG_ACT);
445 if (*addr == 0 || (val & 0x01) == 0) {
446 pr_info(DRVNAME ": Device is disabled, will not use\n");
447 superio_exit();
448 return -ENODEV;
451 superio_exit();
452 return 0;
455 static int __devinit smsc47m1_probe(struct platform_device *pdev)
457 struct device *dev = &pdev->dev;
458 struct smsc47m1_sio_data *sio_data = dev->platform_data;
459 struct smsc47m1_data *data;
460 struct resource *res;
461 int err = 0;
462 int fan1, fan2, fan3, pwm1, pwm2, pwm3;
464 static const char *names[] = {
465 "smsc47m1",
466 "smsc47m2",
469 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
470 if (!request_region(res->start, SMSC_EXTENT, DRVNAME)) {
471 dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
472 (unsigned long)res->start,
473 (unsigned long)res->end);
474 return -EBUSY;
477 if (!(data = kzalloc(sizeof(struct smsc47m1_data), GFP_KERNEL))) {
478 err = -ENOMEM;
479 goto error_release;
482 data->addr = res->start;
483 data->type = sio_data->type;
484 data->name = names[sio_data->type];
485 mutex_init(&data->update_lock);
486 platform_set_drvdata(pdev, data);
488 /* If no function is properly configured, there's no point in
489 actually registering the chip. */
490 pwm1 = (smsc47m1_read_value(data, SMSC47M1_REG_PPIN(0)) & 0x05)
491 == 0x04;
492 pwm2 = (smsc47m1_read_value(data, SMSC47M1_REG_PPIN(1)) & 0x05)
493 == 0x04;
494 if (data->type == smsc47m2) {
495 fan1 = (smsc47m1_read_value(data, SMSC47M2_REG_TPIN1)
496 & 0x0d) == 0x09;
497 fan2 = (smsc47m1_read_value(data, SMSC47M2_REG_TPIN2)
498 & 0x0d) == 0x09;
499 fan3 = (smsc47m1_read_value(data, SMSC47M2_REG_TPIN3)
500 & 0x0d) == 0x0d;
501 pwm3 = (smsc47m1_read_value(data, SMSC47M2_REG_PPIN3)
502 & 0x0d) == 0x08;
503 } else {
504 fan1 = (smsc47m1_read_value(data, SMSC47M1_REG_TPIN(0))
505 & 0x05) == 0x05;
506 fan2 = (smsc47m1_read_value(data, SMSC47M1_REG_TPIN(1))
507 & 0x05) == 0x05;
508 fan3 = 0;
509 pwm3 = 0;
511 if (!(fan1 || fan2 || fan3 || pwm1 || pwm2 || pwm3)) {
512 dev_warn(dev, "Device not configured, will not use\n");
513 err = -ENODEV;
514 goto error_free;
517 /* Some values (fan min, clock dividers, pwm registers) may be
518 needed before any update is triggered, so we better read them
519 at least once here. We don't usually do it that way, but in
520 this particular case, manually reading 5 registers out of 8
521 doesn't make much sense and we're better using the existing
522 function. */
523 smsc47m1_update_device(dev, 1);
525 /* Register sysfs hooks */
526 if (fan1) {
527 if ((err = device_create_file(dev,
528 &sensor_dev_attr_fan1_input.dev_attr))
529 || (err = device_create_file(dev,
530 &sensor_dev_attr_fan1_min.dev_attr))
531 || (err = device_create_file(dev,
532 &sensor_dev_attr_fan1_div.dev_attr)))
533 goto error_remove_files;
534 } else
535 dev_dbg(dev, "Fan 1 not enabled by hardware, skipping\n");
537 if (fan2) {
538 if ((err = device_create_file(dev,
539 &sensor_dev_attr_fan2_input.dev_attr))
540 || (err = device_create_file(dev,
541 &sensor_dev_attr_fan2_min.dev_attr))
542 || (err = device_create_file(dev,
543 &sensor_dev_attr_fan2_div.dev_attr)))
544 goto error_remove_files;
545 } else
546 dev_dbg(dev, "Fan 2 not enabled by hardware, skipping\n");
548 if (fan3) {
549 if ((err = device_create_file(dev,
550 &sensor_dev_attr_fan3_input.dev_attr))
551 || (err = device_create_file(dev,
552 &sensor_dev_attr_fan3_min.dev_attr))
553 || (err = device_create_file(dev,
554 &sensor_dev_attr_fan3_div.dev_attr)))
555 goto error_remove_files;
556 } else if (data->type == smsc47m2)
557 dev_dbg(dev, "Fan 3 not enabled by hardware, skipping\n");
559 if (pwm1) {
560 if ((err = device_create_file(dev,
561 &sensor_dev_attr_pwm1.dev_attr))
562 || (err = device_create_file(dev,
563 &sensor_dev_attr_pwm1_enable.dev_attr)))
564 goto error_remove_files;
565 } else
566 dev_dbg(dev, "PWM 1 not enabled by hardware, skipping\n");
568 if (pwm2) {
569 if ((err = device_create_file(dev,
570 &sensor_dev_attr_pwm2.dev_attr))
571 || (err = device_create_file(dev,
572 &sensor_dev_attr_pwm2_enable.dev_attr)))
573 goto error_remove_files;
574 } else
575 dev_dbg(dev, "PWM 2 not enabled by hardware, skipping\n");
577 if (pwm3) {
578 if ((err = device_create_file(dev,
579 &sensor_dev_attr_pwm3.dev_attr))
580 || (err = device_create_file(dev,
581 &sensor_dev_attr_pwm3_enable.dev_attr)))
582 goto error_remove_files;
583 } else if (data->type == smsc47m2)
584 dev_dbg(dev, "PWM 3 not enabled by hardware, skipping\n");
586 if ((err = device_create_file(dev, &dev_attr_alarms)))
587 goto error_remove_files;
588 if ((err = device_create_file(dev, &dev_attr_name)))
589 goto error_remove_files;
591 data->hwmon_dev = hwmon_device_register(dev);
592 if (IS_ERR(data->hwmon_dev)) {
593 err = PTR_ERR(data->hwmon_dev);
594 goto error_remove_files;
597 return 0;
599 error_remove_files:
600 sysfs_remove_group(&dev->kobj, &smsc47m1_group);
601 error_free:
602 platform_set_drvdata(pdev, NULL);
603 kfree(data);
604 error_release:
605 release_region(res->start, SMSC_EXTENT);
606 return err;
609 static int __devexit smsc47m1_remove(struct platform_device *pdev)
611 struct smsc47m1_data *data = platform_get_drvdata(pdev);
612 struct resource *res;
614 hwmon_device_unregister(data->hwmon_dev);
615 sysfs_remove_group(&pdev->dev.kobj, &smsc47m1_group);
617 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
618 release_region(res->start, SMSC_EXTENT);
619 platform_set_drvdata(pdev, NULL);
620 kfree(data);
622 return 0;
625 static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
626 int init)
628 struct smsc47m1_data *data = dev_get_drvdata(dev);
630 mutex_lock(&data->update_lock);
632 if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || init) {
633 int i, fan_nr;
634 fan_nr = data->type == smsc47m2 ? 3 : 2;
636 for (i = 0; i < fan_nr; i++) {
637 data->fan[i] = smsc47m1_read_value(data,
638 SMSC47M1_REG_FAN[i]);
639 data->fan_preload[i] = smsc47m1_read_value(data,
640 SMSC47M1_REG_FAN_PRELOAD[i]);
641 data->pwm[i] = smsc47m1_read_value(data,
642 SMSC47M1_REG_PWM[i]);
645 i = smsc47m1_read_value(data, SMSC47M1_REG_FANDIV);
646 data->fan_div[0] = (i >> 4) & 0x03;
647 data->fan_div[1] = i >> 6;
649 data->alarms = smsc47m1_read_value(data,
650 SMSC47M1_REG_ALARM) >> 6;
651 /* Clear alarms if needed */
652 if (data->alarms)
653 smsc47m1_write_value(data, SMSC47M1_REG_ALARM, 0xC0);
655 if (fan_nr >= 3) {
656 data->fan_div[2] = (smsc47m1_read_value(data,
657 SMSC47M2_REG_FANDIV3) >> 4) & 0x03;
658 data->alarms |= (smsc47m1_read_value(data,
659 SMSC47M2_REG_ALARM6) & 0x40) >> 4;
660 /* Clear alarm if needed */
661 if (data->alarms & 0x04)
662 smsc47m1_write_value(data,
663 SMSC47M2_REG_ALARM6,
664 0x40);
667 data->last_updated = jiffies;
670 mutex_unlock(&data->update_lock);
671 return data;
674 static int __init smsc47m1_device_add(unsigned short address,
675 const struct smsc47m1_sio_data *sio_data)
677 struct resource res = {
678 .start = address,
679 .end = address + SMSC_EXTENT - 1,
680 .name = DRVNAME,
681 .flags = IORESOURCE_IO,
683 int err;
685 pdev = platform_device_alloc(DRVNAME, address);
686 if (!pdev) {
687 err = -ENOMEM;
688 printk(KERN_ERR DRVNAME ": Device allocation failed\n");
689 goto exit;
692 err = platform_device_add_resources(pdev, &res, 1);
693 if (err) {
694 printk(KERN_ERR DRVNAME ": Device resource addition failed "
695 "(%d)\n", err);
696 goto exit_device_put;
699 err = platform_device_add_data(pdev, sio_data,
700 sizeof(struct smsc47m1_sio_data));
701 if (err) {
702 printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
703 goto exit_device_put;
706 err = platform_device_add(pdev);
707 if (err) {
708 printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
709 err);
710 goto exit_device_put;
713 return 0;
715 exit_device_put:
716 platform_device_put(pdev);
717 exit:
718 return err;
721 static int __init sm_smsc47m1_init(void)
723 int err;
724 unsigned short address;
725 struct smsc47m1_sio_data sio_data;
727 if (smsc47m1_find(&address, &sio_data))
728 return -ENODEV;
730 err = platform_driver_register(&smsc47m1_driver);
731 if (err)
732 goto exit;
734 /* Sets global pdev as a side effect */
735 err = smsc47m1_device_add(address, &sio_data);
736 if (err)
737 goto exit_driver;
739 return 0;
741 exit_driver:
742 platform_driver_unregister(&smsc47m1_driver);
743 exit:
744 return err;
747 static void __exit sm_smsc47m1_exit(void)
749 platform_device_unregister(pdev);
750 platform_driver_unregister(&smsc47m1_driver);
753 MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>");
754 MODULE_DESCRIPTION("SMSC LPC47M1xx fan sensors driver");
755 MODULE_LICENSE("GPL");
757 module_init(sm_smsc47m1_init);
758 module_exit(sm_smsc47m1_exit);