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