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