blob: 29354fa26f81e3578b7db2dd6b4cc188f4fafff8 [file] [log] [blame]
Jean Delvareba224e22006-12-12 18:18:29 +01001/*
2 * pc87427.c - hardware monitoring driver for the
3 * National Semiconductor PC87427 Super-I/O chip
4 * Copyright (C) 2006 Jean Delvare <khali@linux-fr.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * Supports the following chips:
16 *
17 * Chip #vin #fan #pwm #temp devid
18 * PC87427 - 8 - - 0xF2
19 *
20 * This driver assumes that no more than one chip is present.
21 * Only fan inputs are supported so far, although the chip can do much more.
22 */
23
24#include <linux/module.h>
25#include <linux/init.h>
26#include <linux/slab.h>
27#include <linux/jiffies.h>
28#include <linux/platform_device.h>
29#include <linux/hwmon.h>
30#include <linux/hwmon-sysfs.h>
31#include <linux/err.h>
32#include <linux/mutex.h>
33#include <linux/sysfs.h>
Jean Delvarece7ee4e2007-05-08 17:21:59 +020034#include <linux/ioport.h>
Jean Delvareba224e22006-12-12 18:18:29 +010035#include <asm/io.h>
36
37static struct platform_device *pdev;
38
39#define DRVNAME "pc87427"
40
41/* The lock mutex protects both the I/O accesses (needed because the
42 device is using banked registers) and the register cache (needed to keep
43 the data in the registers and the cache in sync at any time). */
44struct pc87427_data {
45 struct class_device *class_dev;
46 struct mutex lock;
47 int address[2];
48 const char *name;
49
50 unsigned long last_updated; /* in jiffies */
51 u8 fan_enabled; /* bit vector */
52 u16 fan[8]; /* register values */
53 u16 fan_min[8]; /* register values */
54 u8 fan_status[8]; /* register values */
55};
56
57/*
58 * Super-I/O registers and operations
59 */
60
61#define SIOREG_LDSEL 0x07 /* Logical device select */
62#define SIOREG_DEVID 0x20 /* Device ID */
63#define SIOREG_ACT 0x30 /* Device activation */
64#define SIOREG_MAP 0x50 /* I/O or memory mapping */
65#define SIOREG_IOBASE 0x60 /* I/O base address */
66
67static const u8 logdev[2] = { 0x09, 0x14 };
68static const char *logdev_str[2] = { DRVNAME " FMC", DRVNAME " HMC" };
69#define LD_FAN 0
70#define LD_IN 1
71#define LD_TEMP 1
72
73static inline void superio_outb(int sioaddr, int reg, int val)
74{
75 outb(reg, sioaddr);
76 outb(val, sioaddr + 1);
77}
78
79static inline int superio_inb(int sioaddr, int reg)
80{
81 outb(reg, sioaddr);
82 return inb(sioaddr + 1);
83}
84
85static inline void superio_exit(int sioaddr)
86{
87 outb(0x02, sioaddr);
88 outb(0x02, sioaddr + 1);
89}
90
91/*
92 * Logical devices
93 */
94
95#define REGION_LENGTH 32
96#define PC87427_REG_BANK 0x0f
97#define BANK_FM(nr) (nr)
98#define BANK_FT(nr) (0x08 + (nr))
99#define BANK_FC(nr) (0x10 + (nr) * 2)
100
101/*
102 * I/O access functions
103 */
104
105/* ldi is the logical device index */
106static inline int pc87427_read8(struct pc87427_data *data, u8 ldi, u8 reg)
107{
108 return inb(data->address[ldi] + reg);
109}
110
111/* Must be called with data->lock held, except during init */
112static inline int pc87427_read8_bank(struct pc87427_data *data, u8 ldi,
113 u8 bank, u8 reg)
114{
115 outb(bank, data->address[ldi] + PC87427_REG_BANK);
116 return inb(data->address[ldi] + reg);
117}
118
119/* Must be called with data->lock held, except during init */
120static inline void pc87427_write8_bank(struct pc87427_data *data, u8 ldi,
121 u8 bank, u8 reg, u8 value)
122{
123 outb(bank, data->address[ldi] + PC87427_REG_BANK);
124 outb(value, data->address[ldi] + reg);
125}
126
127/*
128 * Fan registers and conversions
129 */
130
131/* fan data registers are 16-bit wide */
132#define PC87427_REG_FAN 0x12
133#define PC87427_REG_FAN_MIN 0x14
134#define PC87427_REG_FAN_STATUS 0x10
135
136#define FAN_STATUS_STALL (1 << 3)
137#define FAN_STATUS_LOSPD (1 << 1)
138#define FAN_STATUS_MONEN (1 << 0)
139
140/* Dedicated function to read all registers related to a given fan input.
141 This saves us quite a few locks and bank selections.
142 Must be called with data->lock held.
143 nr is from 0 to 7 */
144static void pc87427_readall_fan(struct pc87427_data *data, u8 nr)
145{
146 int iobase = data->address[LD_FAN];
147
148 outb(BANK_FM(nr), iobase + PC87427_REG_BANK);
149 data->fan[nr] = inw(iobase + PC87427_REG_FAN);
150 data->fan_min[nr] = inw(iobase + PC87427_REG_FAN_MIN);
151 data->fan_status[nr] = inb(iobase + PC87427_REG_FAN_STATUS);
152 /* Clear fan alarm bits */
153 outb(data->fan_status[nr], iobase + PC87427_REG_FAN_STATUS);
154}
155
156/* The 2 LSB of fan speed registers are used for something different.
157 The actual 2 LSB of the measurements are not available. */
158static inline unsigned long fan_from_reg(u16 reg)
159{
160 reg &= 0xfffc;
161 if (reg == 0x0000 || reg == 0xfffc)
162 return 0;
163 return 5400000UL / reg;
164}
165
166/* The 2 LSB of the fan speed limit registers are not significant. */
167static inline u16 fan_to_reg(unsigned long val)
168{
169 if (val < 83UL)
170 return 0xffff;
171 if (val >= 1350000UL)
172 return 0x0004;
173 return ((1350000UL + val / 2) / val) << 2;
174}
175
176/*
177 * Data interface
178 */
179
180static struct pc87427_data *pc87427_update_device(struct device *dev)
181{
182 struct pc87427_data *data = dev_get_drvdata(dev);
183 int i;
184
185 mutex_lock(&data->lock);
186 if (!time_after(jiffies, data->last_updated + HZ)
187 && data->last_updated)
188 goto done;
189
190 /* Fans */
191 for (i = 0; i < 8; i++) {
192 if (!(data->fan_enabled & (1 << i)))
193 continue;
194 pc87427_readall_fan(data, i);
195 }
196 data->last_updated = jiffies;
197
198done:
199 mutex_unlock(&data->lock);
200 return data;
201}
202
203static ssize_t show_fan_input(struct device *dev, struct device_attribute
204 *devattr, char *buf)
205{
206 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
207 struct pc87427_data *data = pc87427_update_device(dev);
208 int nr = attr->index;
209
210 return sprintf(buf, "%lu\n", fan_from_reg(data->fan[nr]));
211}
212
213static ssize_t show_fan_min(struct device *dev, struct device_attribute
214 *devattr, char *buf)
215{
216 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
217 struct pc87427_data *data = pc87427_update_device(dev);
218 int nr = attr->index;
219
220 return sprintf(buf, "%lu\n", fan_from_reg(data->fan_min[nr]));
221}
222
223static ssize_t show_fan_alarm(struct device *dev, struct device_attribute
224 *devattr, char *buf)
225{
226 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
227 struct pc87427_data *data = pc87427_update_device(dev);
228 int nr = attr->index;
229
230 return sprintf(buf, "%d\n", !!(data->fan_status[nr]
231 & FAN_STATUS_LOSPD));
232}
233
234static ssize_t show_fan_fault(struct device *dev, struct device_attribute
235 *devattr, char *buf)
236{
237 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
238 struct pc87427_data *data = pc87427_update_device(dev);
239 int nr = attr->index;
240
241 return sprintf(buf, "%d\n", !!(data->fan_status[nr]
242 & FAN_STATUS_STALL));
243}
244
245static ssize_t set_fan_min(struct device *dev, struct device_attribute
246 *devattr, const char *buf, size_t count)
247{
248 struct pc87427_data *data = dev_get_drvdata(dev);
249 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
250 int nr = attr->index;
251 unsigned long val = simple_strtoul(buf, NULL, 10);
252 int iobase = data->address[LD_FAN];
253
254 mutex_lock(&data->lock);
255 outb(BANK_FM(nr), iobase + PC87427_REG_BANK);
256 /* The low speed limit registers are read-only while monitoring
257 is enabled, so we have to disable monitoring, then change the
258 limit, and finally enable monitoring again. */
259 outb(0, iobase + PC87427_REG_FAN_STATUS);
260 data->fan_min[nr] = fan_to_reg(val);
261 outw(data->fan_min[nr], iobase + PC87427_REG_FAN_MIN);
262 outb(FAN_STATUS_MONEN, iobase + PC87427_REG_FAN_STATUS);
263 mutex_unlock(&data->lock);
264
265 return count;
266}
267
268static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0);
269static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1);
270static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan_input, NULL, 2);
271static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan_input, NULL, 3);
272static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan_input, NULL, 4);
273static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan_input, NULL, 5);
274static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan_input, NULL, 6);
275static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_fan_input, NULL, 7);
276
277static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO,
278 show_fan_min, set_fan_min, 0);
279static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO,
280 show_fan_min, set_fan_min, 1);
281static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO,
282 show_fan_min, set_fan_min, 2);
283static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO,
284 show_fan_min, set_fan_min, 3);
285static SENSOR_DEVICE_ATTR(fan5_min, S_IWUSR | S_IRUGO,
286 show_fan_min, set_fan_min, 4);
287static SENSOR_DEVICE_ATTR(fan6_min, S_IWUSR | S_IRUGO,
288 show_fan_min, set_fan_min, 5);
289static SENSOR_DEVICE_ATTR(fan7_min, S_IWUSR | S_IRUGO,
290 show_fan_min, set_fan_min, 6);
291static SENSOR_DEVICE_ATTR(fan8_min, S_IWUSR | S_IRUGO,
292 show_fan_min, set_fan_min, 7);
293
294static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0);
295static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 1);
296static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 2);
297static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 3);
298static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_fan_alarm, NULL, 4);
299static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_fan_alarm, NULL, 5);
300static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_fan_alarm, NULL, 6);
301static SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO, show_fan_alarm, NULL, 7);
302
303static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_fan_fault, NULL, 0);
304static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_fan_fault, NULL, 1);
305static SENSOR_DEVICE_ATTR(fan3_fault, S_IRUGO, show_fan_fault, NULL, 2);
306static SENSOR_DEVICE_ATTR(fan4_fault, S_IRUGO, show_fan_fault, NULL, 3);
307static SENSOR_DEVICE_ATTR(fan5_fault, S_IRUGO, show_fan_fault, NULL, 4);
308static SENSOR_DEVICE_ATTR(fan6_fault, S_IRUGO, show_fan_fault, NULL, 5);
309static SENSOR_DEVICE_ATTR(fan7_fault, S_IRUGO, show_fan_fault, NULL, 6);
310static SENSOR_DEVICE_ATTR(fan8_fault, S_IRUGO, show_fan_fault, NULL, 7);
311
312static struct attribute *pc87427_attributes_fan[8][5] = {
313 {
314 &sensor_dev_attr_fan1_input.dev_attr.attr,
315 &sensor_dev_attr_fan1_min.dev_attr.attr,
316 &sensor_dev_attr_fan1_alarm.dev_attr.attr,
317 &sensor_dev_attr_fan1_fault.dev_attr.attr,
318 NULL
319 }, {
320 &sensor_dev_attr_fan2_input.dev_attr.attr,
321 &sensor_dev_attr_fan2_min.dev_attr.attr,
322 &sensor_dev_attr_fan2_alarm.dev_attr.attr,
323 &sensor_dev_attr_fan2_fault.dev_attr.attr,
324 NULL
325 }, {
326 &sensor_dev_attr_fan3_input.dev_attr.attr,
327 &sensor_dev_attr_fan3_min.dev_attr.attr,
328 &sensor_dev_attr_fan3_alarm.dev_attr.attr,
329 &sensor_dev_attr_fan3_fault.dev_attr.attr,
330 NULL
331 }, {
332 &sensor_dev_attr_fan4_input.dev_attr.attr,
333 &sensor_dev_attr_fan4_min.dev_attr.attr,
334 &sensor_dev_attr_fan4_alarm.dev_attr.attr,
335 &sensor_dev_attr_fan4_fault.dev_attr.attr,
336 NULL
337 }, {
338 &sensor_dev_attr_fan5_input.dev_attr.attr,
339 &sensor_dev_attr_fan5_min.dev_attr.attr,
340 &sensor_dev_attr_fan5_alarm.dev_attr.attr,
341 &sensor_dev_attr_fan5_fault.dev_attr.attr,
342 NULL
343 }, {
344 &sensor_dev_attr_fan6_input.dev_attr.attr,
345 &sensor_dev_attr_fan6_min.dev_attr.attr,
346 &sensor_dev_attr_fan6_alarm.dev_attr.attr,
347 &sensor_dev_attr_fan6_fault.dev_attr.attr,
348 NULL
349 }, {
350 &sensor_dev_attr_fan7_input.dev_attr.attr,
351 &sensor_dev_attr_fan7_min.dev_attr.attr,
352 &sensor_dev_attr_fan7_alarm.dev_attr.attr,
353 &sensor_dev_attr_fan7_fault.dev_attr.attr,
354 NULL
355 }, {
356 &sensor_dev_attr_fan8_input.dev_attr.attr,
357 &sensor_dev_attr_fan8_min.dev_attr.attr,
358 &sensor_dev_attr_fan8_alarm.dev_attr.attr,
359 &sensor_dev_attr_fan8_fault.dev_attr.attr,
360 NULL
361 }
362};
363
364static const struct attribute_group pc87427_group_fan[8] = {
365 { .attrs = pc87427_attributes_fan[0] },
366 { .attrs = pc87427_attributes_fan[1] },
367 { .attrs = pc87427_attributes_fan[2] },
368 { .attrs = pc87427_attributes_fan[3] },
369 { .attrs = pc87427_attributes_fan[4] },
370 { .attrs = pc87427_attributes_fan[5] },
371 { .attrs = pc87427_attributes_fan[6] },
372 { .attrs = pc87427_attributes_fan[7] },
373};
374
375static ssize_t show_name(struct device *dev, struct device_attribute
376 *devattr, char *buf)
377{
378 struct pc87427_data *data = dev_get_drvdata(dev);
379
380 return sprintf(buf, "%s\n", data->name);
381}
382static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
383
384
385/*
386 * Device detection, attach and detach
387 */
388
389static void __devinit pc87427_init_device(struct device *dev)
390{
391 struct pc87427_data *data = dev_get_drvdata(dev);
392 int i;
393 u8 reg;
394
395 /* The FMC module should be ready */
396 reg = pc87427_read8(data, LD_FAN, PC87427_REG_BANK);
397 if (!(reg & 0x80))
398 dev_warn(dev, "FMC module not ready!\n");
399
400 /* Check which fans are enabled */
401 for (i = 0; i < 8; i++) {
402 reg = pc87427_read8_bank(data, LD_FAN, BANK_FM(i),
403 PC87427_REG_FAN_STATUS);
404 if (reg & FAN_STATUS_MONEN)
405 data->fan_enabled |= (1 << i);
406 }
407
408 if (!data->fan_enabled) {
409 dev_dbg(dev, "Enabling all fan inputs\n");
410 for (i = 0; i < 8; i++)
411 pc87427_write8_bank(data, LD_FAN, BANK_FM(i),
412 PC87427_REG_FAN_STATUS,
413 FAN_STATUS_MONEN);
414 data->fan_enabled = 0xff;
415 }
416}
417
418static int __devinit pc87427_probe(struct platform_device *pdev)
419{
420 struct pc87427_data *data;
421 struct resource *res;
422 int i, err;
423
424 if (!(data = kzalloc(sizeof(struct pc87427_data), GFP_KERNEL))) {
425 err = -ENOMEM;
426 printk(KERN_ERR DRVNAME ": Out of memory\n");
427 goto exit;
428 }
429
430 /* This will need to be revisited when we add support for
431 temperature and voltage monitoring. */
432 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
Jean Delvarece7ee4e2007-05-08 17:21:59 +0200433 if (!request_region(res->start, res->end - res->start + 1, DRVNAME)) {
434 err = -EBUSY;
435 dev_err(&pdev->dev, "Failed to request region 0x%lx-0x%lx\n",
436 (unsigned long)res->start, (unsigned long)res->end);
437 goto exit_kfree;
438 }
Jean Delvareba224e22006-12-12 18:18:29 +0100439 data->address[0] = res->start;
440
441 mutex_init(&data->lock);
442 data->name = "pc87427";
443 platform_set_drvdata(pdev, data);
444 pc87427_init_device(&pdev->dev);
445
446 /* Register sysfs hooks */
447 if ((err = device_create_file(&pdev->dev, &dev_attr_name)))
Jean Delvarece7ee4e2007-05-08 17:21:59 +0200448 goto exit_release_region;
Jean Delvareba224e22006-12-12 18:18:29 +0100449 for (i = 0; i < 8; i++) {
450 if (!(data->fan_enabled & (1 << i)))
451 continue;
452 if ((err = sysfs_create_group(&pdev->dev.kobj,
453 &pc87427_group_fan[i])))
454 goto exit_remove_files;
455 }
456
457 data->class_dev = hwmon_device_register(&pdev->dev);
458 if (IS_ERR(data->class_dev)) {
459 err = PTR_ERR(data->class_dev);
460 dev_err(&pdev->dev, "Class registration failed (%d)\n", err);
461 goto exit_remove_files;
462 }
463
464 return 0;
465
466exit_remove_files:
467 for (i = 0; i < 8; i++) {
468 if (!(data->fan_enabled & (1 << i)))
469 continue;
470 sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]);
471 }
Jean Delvarece7ee4e2007-05-08 17:21:59 +0200472exit_release_region:
473 release_region(res->start, res->end - res->start + 1);
Jean Delvareba224e22006-12-12 18:18:29 +0100474exit_kfree:
475 platform_set_drvdata(pdev, NULL);
476 kfree(data);
477exit:
478 return err;
479}
480
481static int __devexit pc87427_remove(struct platform_device *pdev)
482{
483 struct pc87427_data *data = platform_get_drvdata(pdev);
Jean Delvarece7ee4e2007-05-08 17:21:59 +0200484 struct resource *res;
Jean Delvareba224e22006-12-12 18:18:29 +0100485 int i;
486
487 platform_set_drvdata(pdev, NULL);
488 hwmon_device_unregister(data->class_dev);
489 device_remove_file(&pdev->dev, &dev_attr_name);
490 for (i = 0; i < 8; i++) {
491 if (!(data->fan_enabled & (1 << i)))
492 continue;
493 sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]);
494 }
495 kfree(data);
496
Jean Delvarece7ee4e2007-05-08 17:21:59 +0200497 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
498 release_region(res->start, res->end - res->start + 1);
499
Jean Delvareba224e22006-12-12 18:18:29 +0100500 return 0;
501}
502
503
504static struct platform_driver pc87427_driver = {
505 .driver = {
506 .owner = THIS_MODULE,
507 .name = DRVNAME,
508 },
509 .probe = pc87427_probe,
510 .remove = __devexit_p(pc87427_remove),
511};
512
513static int __init pc87427_device_add(unsigned short address)
514{
515 struct resource res = {
516 .start = address,
517 .end = address + REGION_LENGTH - 1,
518 .name = logdev_str[0],
519 .flags = IORESOURCE_IO,
520 };
521 int err;
522
523 pdev = platform_device_alloc(DRVNAME, address);
524 if (!pdev) {
525 err = -ENOMEM;
526 printk(KERN_ERR DRVNAME ": Device allocation failed\n");
527 goto exit;
528 }
529
530 err = platform_device_add_resources(pdev, &res, 1);
531 if (err) {
532 printk(KERN_ERR DRVNAME ": Device resource addition failed "
533 "(%d)\n", err);
534 goto exit_device_put;
535 }
536
537 err = platform_device_add(pdev);
538 if (err) {
539 printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
540 err);
541 goto exit_device_put;
542 }
543
544 return 0;
545
546exit_device_put:
547 platform_device_put(pdev);
548exit:
549 return err;
550}
551
552static int __init pc87427_find(int sioaddr, unsigned short *address)
553{
554 u16 val;
555 int i, err = 0;
556
557 /* Identify device */
558 val = superio_inb(sioaddr, SIOREG_DEVID);
559 if (val != 0xf2) { /* PC87427 */
560 err = -ENODEV;
561 goto exit;
562 }
563
564 for (i = 0; i < 2; i++) {
565 address[i] = 0;
566 /* Select logical device */
567 superio_outb(sioaddr, SIOREG_LDSEL, logdev[i]);
568
569 val = superio_inb(sioaddr, SIOREG_ACT);
570 if (!(val & 0x01)) {
571 printk(KERN_INFO DRVNAME ": Logical device 0x%02x "
572 "not activated\n", logdev[i]);
573 continue;
574 }
575
576 val = superio_inb(sioaddr, SIOREG_MAP);
577 if (val & 0x01) {
578 printk(KERN_WARNING DRVNAME ": Logical device 0x%02x "
579 "is memory-mapped, can't use\n", logdev[i]);
580 continue;
581 }
582
583 val = (superio_inb(sioaddr, SIOREG_IOBASE) << 8)
584 | superio_inb(sioaddr, SIOREG_IOBASE + 1);
585 if (!val) {
586 printk(KERN_INFO DRVNAME ": I/O base address not set "
587 "for logical device 0x%02x\n", logdev[i]);
588 continue;
589 }
590 address[i] = val;
591 }
592
593exit:
594 superio_exit(sioaddr);
595 return err;
596}
597
598static int __init pc87427_init(void)
599{
600 int err;
601 unsigned short address[2];
602
603 if (pc87427_find(0x2e, address)
604 && pc87427_find(0x4e, address))
605 return -ENODEV;
606
607 /* For now the driver only handles fans so we only care about the
608 first address. */
609 if (!address[0])
610 return -ENODEV;
611
612 err = platform_driver_register(&pc87427_driver);
613 if (err)
614 goto exit;
615
616 /* Sets global pdev as a side effect */
617 err = pc87427_device_add(address[0]);
618 if (err)
619 goto exit_driver;
620
621 return 0;
622
623exit_driver:
624 platform_driver_unregister(&pc87427_driver);
625exit:
626 return err;
627}
628
629static void __exit pc87427_exit(void)
630{
631 platform_device_unregister(pdev);
632 platform_driver_unregister(&pc87427_driver);
633}
634
635MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
636MODULE_DESCRIPTION("PC87427 hardware monitoring driver");
637MODULE_LICENSE("GPL");
638
639module_init(pc87427_init);
640module_exit(pc87427_exit);