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