]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/hwmon/pc87427.c
hwmon: (pc87427) Minor style cleanups
[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 pc87427_data *data = pc87427_update_device(dev);
221         int nr = to_sensor_dev_attr(devattr)->index;
222
223         return sprintf(buf, "%lu\n", fan_from_reg(data->fan[nr]));
224 }
225
226 static ssize_t show_fan_min(struct device *dev, struct device_attribute
227                             *devattr, char *buf)
228 {
229         struct pc87427_data *data = pc87427_update_device(dev);
230         int nr = to_sensor_dev_attr(devattr)->index;
231
232         return sprintf(buf, "%lu\n", fan_from_reg(data->fan_min[nr]));
233 }
234
235 static ssize_t show_fan_alarm(struct device *dev, struct device_attribute
236                               *devattr, char *buf)
237 {
238         struct pc87427_data *data = pc87427_update_device(dev);
239         int nr = to_sensor_dev_attr(devattr)->index;
240
241         return sprintf(buf, "%d\n", !!(data->fan_status[nr]
242                                        & FAN_STATUS_LOSPD));
243 }
244
245 static ssize_t show_fan_fault(struct device *dev, struct device_attribute
246                               *devattr, char *buf)
247 {
248         struct pc87427_data *data = pc87427_update_device(dev);
249         int nr = to_sensor_dev_attr(devattr)->index;
250
251         return sprintf(buf, "%d\n", !!(data->fan_status[nr]
252                                        & FAN_STATUS_STALL));
253 }
254
255 static ssize_t set_fan_min(struct device *dev, struct device_attribute
256                            *devattr, const char *buf, size_t count)
257 {
258         struct pc87427_data *data = dev_get_drvdata(dev);
259         int nr = to_sensor_dev_attr(devattr)->index;
260         unsigned long val;
261         int iobase = data->address[LD_FAN];
262
263         if (strict_strtoul(buf, 10, &val) < 0)
264                 return -EINVAL;
265
266         mutex_lock(&data->lock);
267         outb(BANK_FM(nr), iobase + PC87427_REG_BANK);
268         /* The low speed limit registers are read-only while monitoring
269            is enabled, so we have to disable monitoring, then change the
270            limit, and finally enable monitoring again. */
271         outb(0, iobase + PC87427_REG_FAN_STATUS);
272         data->fan_min[nr] = fan_to_reg(val);
273         outw(data->fan_min[nr], iobase + PC87427_REG_FAN_MIN);
274         outb(FAN_STATUS_MONEN, iobase + PC87427_REG_FAN_STATUS);
275         mutex_unlock(&data->lock);
276
277         return count;
278 }
279
280 static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0);
281 static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1);
282 static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan_input, NULL, 2);
283 static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan_input, NULL, 3);
284 static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan_input, NULL, 4);
285 static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan_input, NULL, 5);
286 static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan_input, NULL, 6);
287 static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_fan_input, NULL, 7);
288
289 static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO,
290                           show_fan_min, set_fan_min, 0);
291 static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO,
292                           show_fan_min, set_fan_min, 1);
293 static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO,
294                           show_fan_min, set_fan_min, 2);
295 static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO,
296                           show_fan_min, set_fan_min, 3);
297 static SENSOR_DEVICE_ATTR(fan5_min, S_IWUSR | S_IRUGO,
298                           show_fan_min, set_fan_min, 4);
299 static SENSOR_DEVICE_ATTR(fan6_min, S_IWUSR | S_IRUGO,
300                           show_fan_min, set_fan_min, 5);
301 static SENSOR_DEVICE_ATTR(fan7_min, S_IWUSR | S_IRUGO,
302                           show_fan_min, set_fan_min, 6);
303 static SENSOR_DEVICE_ATTR(fan8_min, S_IWUSR | S_IRUGO,
304                           show_fan_min, set_fan_min, 7);
305
306 static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0);
307 static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 1);
308 static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 2);
309 static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 3);
310 static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_fan_alarm, NULL, 4);
311 static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_fan_alarm, NULL, 5);
312 static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_fan_alarm, NULL, 6);
313 static SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO, show_fan_alarm, NULL, 7);
314
315 static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_fan_fault, NULL, 0);
316 static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_fan_fault, NULL, 1);
317 static SENSOR_DEVICE_ATTR(fan3_fault, S_IRUGO, show_fan_fault, NULL, 2);
318 static SENSOR_DEVICE_ATTR(fan4_fault, S_IRUGO, show_fan_fault, NULL, 3);
319 static SENSOR_DEVICE_ATTR(fan5_fault, S_IRUGO, show_fan_fault, NULL, 4);
320 static SENSOR_DEVICE_ATTR(fan6_fault, S_IRUGO, show_fan_fault, NULL, 5);
321 static SENSOR_DEVICE_ATTR(fan7_fault, S_IRUGO, show_fan_fault, NULL, 6);
322 static SENSOR_DEVICE_ATTR(fan8_fault, S_IRUGO, show_fan_fault, NULL, 7);
323
324 static struct attribute *pc87427_attributes_fan[8][5] = {
325         {
326                 &sensor_dev_attr_fan1_input.dev_attr.attr,
327                 &sensor_dev_attr_fan1_min.dev_attr.attr,
328                 &sensor_dev_attr_fan1_alarm.dev_attr.attr,
329                 &sensor_dev_attr_fan1_fault.dev_attr.attr,
330                 NULL
331         }, {
332                 &sensor_dev_attr_fan2_input.dev_attr.attr,
333                 &sensor_dev_attr_fan2_min.dev_attr.attr,
334                 &sensor_dev_attr_fan2_alarm.dev_attr.attr,
335                 &sensor_dev_attr_fan2_fault.dev_attr.attr,
336                 NULL
337         }, {
338                 &sensor_dev_attr_fan3_input.dev_attr.attr,
339                 &sensor_dev_attr_fan3_min.dev_attr.attr,
340                 &sensor_dev_attr_fan3_alarm.dev_attr.attr,
341                 &sensor_dev_attr_fan3_fault.dev_attr.attr,
342                 NULL
343         }, {
344                 &sensor_dev_attr_fan4_input.dev_attr.attr,
345                 &sensor_dev_attr_fan4_min.dev_attr.attr,
346                 &sensor_dev_attr_fan4_alarm.dev_attr.attr,
347                 &sensor_dev_attr_fan4_fault.dev_attr.attr,
348                 NULL
349         }, {
350                 &sensor_dev_attr_fan5_input.dev_attr.attr,
351                 &sensor_dev_attr_fan5_min.dev_attr.attr,
352                 &sensor_dev_attr_fan5_alarm.dev_attr.attr,
353                 &sensor_dev_attr_fan5_fault.dev_attr.attr,
354                 NULL
355         }, {
356                 &sensor_dev_attr_fan6_input.dev_attr.attr,
357                 &sensor_dev_attr_fan6_min.dev_attr.attr,
358                 &sensor_dev_attr_fan6_alarm.dev_attr.attr,
359                 &sensor_dev_attr_fan6_fault.dev_attr.attr,
360                 NULL
361         }, {
362                 &sensor_dev_attr_fan7_input.dev_attr.attr,
363                 &sensor_dev_attr_fan7_min.dev_attr.attr,
364                 &sensor_dev_attr_fan7_alarm.dev_attr.attr,
365                 &sensor_dev_attr_fan7_fault.dev_attr.attr,
366                 NULL
367         }, {
368                 &sensor_dev_attr_fan8_input.dev_attr.attr,
369                 &sensor_dev_attr_fan8_min.dev_attr.attr,
370                 &sensor_dev_attr_fan8_alarm.dev_attr.attr,
371                 &sensor_dev_attr_fan8_fault.dev_attr.attr,
372                 NULL
373         }
374 };
375
376 static const struct attribute_group pc87427_group_fan[8] = {
377         { .attrs = pc87427_attributes_fan[0] },
378         { .attrs = pc87427_attributes_fan[1] },
379         { .attrs = pc87427_attributes_fan[2] },
380         { .attrs = pc87427_attributes_fan[3] },
381         { .attrs = pc87427_attributes_fan[4] },
382         { .attrs = pc87427_attributes_fan[5] },
383         { .attrs = pc87427_attributes_fan[6] },
384         { .attrs = pc87427_attributes_fan[7] },
385 };
386
387 static ssize_t show_name(struct device *dev, struct device_attribute
388                          *devattr, char *buf)
389 {
390         struct pc87427_data *data = dev_get_drvdata(dev);
391
392         return sprintf(buf, "%s\n", data->name);
393 }
394 static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
395
396
397 /*
398  * Device detection, attach and detach
399  */
400
401 static void __devinit pc87427_init_device(struct device *dev)
402 {
403         struct pc87427_sio_data *sio_data = dev->platform_data;
404         struct pc87427_data *data = dev_get_drvdata(dev);
405         int i;
406         u8 reg;
407
408         /* The FMC module should be ready */
409         reg = pc87427_read8(data, LD_FAN, PC87427_REG_BANK);
410         if (!(reg & 0x80))
411                 dev_warn(dev, "FMC module not ready!\n");
412
413         /* Check which fans are enabled */
414         for (i = 0; i < 8; i++) {
415                 if (!(sio_data->has_fanin & (1 << i)))  /* Not wired */
416                         continue;
417                 reg = pc87427_read8_bank(data, LD_FAN, BANK_FM(i),
418                                          PC87427_REG_FAN_STATUS);
419                 if (reg & FAN_STATUS_MONEN)
420                         data->fan_enabled |= (1 << i);
421         }
422
423         if (!data->fan_enabled) {
424                 dev_dbg(dev, "Enabling monitoring of all fans\n");
425                 for (i = 0; i < 8; i++) {
426                         if (!(sio_data->has_fanin & (1 << i)))  /* Not wired */
427                                 continue;
428                         pc87427_write8_bank(data, LD_FAN, BANK_FM(i),
429                                             PC87427_REG_FAN_STATUS,
430                                             FAN_STATUS_MONEN);
431                 }
432                 data->fan_enabled = sio_data->has_fanin;
433         }
434 }
435
436 static int __devinit pc87427_probe(struct platform_device *pdev)
437 {
438         struct pc87427_data *data;
439         struct resource *res;
440         int i, err;
441
442         data = kzalloc(sizeof(struct pc87427_data), GFP_KERNEL);
443         if (!data) {
444                 err = -ENOMEM;
445                 printk(KERN_ERR DRVNAME ": Out of memory\n");
446                 goto exit;
447         }
448
449         /* This will need to be revisited when we add support for
450            temperature and voltage monitoring. */
451         res = platform_get_resource(pdev, IORESOURCE_IO, 0);
452         if (!request_region(res->start, resource_size(res), DRVNAME)) {
453                 err = -EBUSY;
454                 dev_err(&pdev->dev, "Failed to request region 0x%lx-0x%lx\n",
455                         (unsigned long)res->start, (unsigned long)res->end);
456                 goto exit_kfree;
457         }
458         data->address[0] = res->start;
459
460         mutex_init(&data->lock);
461         data->name = "pc87427";
462         platform_set_drvdata(pdev, data);
463         pc87427_init_device(&pdev->dev);
464
465         /* Register sysfs hooks */
466         err = device_create_file(&pdev->dev, &dev_attr_name);
467         if (err)
468                 goto exit_release_region;
469         for (i = 0; i < 8; i++) {
470                 if (!(data->fan_enabled & (1 << i)))
471                         continue;
472                 err = sysfs_create_group(&pdev->dev.kobj,
473                                          &pc87427_group_fan[i]);
474                 if (err)
475                         goto exit_remove_files;
476         }
477
478         data->hwmon_dev = hwmon_device_register(&pdev->dev);
479         if (IS_ERR(data->hwmon_dev)) {
480                 err = PTR_ERR(data->hwmon_dev);
481                 dev_err(&pdev->dev, "Class registration failed (%d)\n", err);
482                 goto exit_remove_files;
483         }
484
485         return 0;
486
487 exit_remove_files:
488         for (i = 0; i < 8; i++) {
489                 if (!(data->fan_enabled & (1 << i)))
490                         continue;
491                 sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]);
492         }
493 exit_release_region:
494         release_region(res->start, resource_size(res));
495 exit_kfree:
496         platform_set_drvdata(pdev, NULL);
497         kfree(data);
498 exit:
499         return err;
500 }
501
502 static int __devexit pc87427_remove(struct platform_device *pdev)
503 {
504         struct pc87427_data *data = platform_get_drvdata(pdev);
505         struct resource *res;
506         int i;
507
508         hwmon_device_unregister(data->hwmon_dev);
509         device_remove_file(&pdev->dev, &dev_attr_name);
510         for (i = 0; i < 8; i++) {
511                 if (!(data->fan_enabled & (1 << i)))
512                         continue;
513                 sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]);
514         }
515         platform_set_drvdata(pdev, NULL);
516         kfree(data);
517
518         res = platform_get_resource(pdev, IORESOURCE_IO, 0);
519         release_region(res->start, resource_size(res));
520
521         return 0;
522 }
523
524
525 static struct platform_driver pc87427_driver = {
526         .driver = {
527                 .owner  = THIS_MODULE,
528                 .name   = DRVNAME,
529         },
530         .probe          = pc87427_probe,
531         .remove         = __devexit_p(pc87427_remove),
532 };
533
534 static int __init pc87427_device_add(unsigned short address,
535                                      const struct pc87427_sio_data *sio_data)
536 {
537         struct resource res = {
538                 .start  = address,
539                 .end    = address + REGION_LENGTH - 1,
540                 .name   = logdev_str[0],
541                 .flags  = IORESOURCE_IO,
542         };
543         int err;
544
545         err = acpi_check_resource_conflict(&res);
546         if (err)
547                 goto exit;
548
549         pdev = platform_device_alloc(DRVNAME, address);
550         if (!pdev) {
551                 err = -ENOMEM;
552                 printk(KERN_ERR DRVNAME ": Device allocation failed\n");
553                 goto exit;
554         }
555
556         err = platform_device_add_resources(pdev, &res, 1);
557         if (err) {
558                 printk(KERN_ERR DRVNAME ": Device resource addition failed "
559                        "(%d)\n", err);
560                 goto exit_device_put;
561         }
562
563         err = platform_device_add_data(pdev, sio_data,
564                                        sizeof(struct pc87427_sio_data));
565         if (err) {
566                 printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
567                 goto exit_device_put;
568         }
569
570         err = platform_device_add(pdev);
571         if (err) {
572                 printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
573                        err);
574                 goto exit_device_put;
575         }
576
577         return 0;
578
579 exit_device_put:
580         platform_device_put(pdev);
581 exit:
582         return err;
583 }
584
585 static int __init pc87427_find(int sioaddr, unsigned short *address,
586                                struct pc87427_sio_data *sio_data)
587 {
588         u16 val;
589         u8 cfg, cfg_b;
590         int i, err = 0;
591
592         /* Identify device */
593         val = force_id ? force_id : superio_inb(sioaddr, SIOREG_DEVID);
594         if (val != 0xf2) {      /* PC87427 */
595                 err = -ENODEV;
596                 goto exit;
597         }
598
599         for (i = 0; i < 2; i++) {
600                 address[i] = 0;
601                 /* Select logical device */
602                 superio_outb(sioaddr, SIOREG_LDSEL, logdev[i]);
603
604                 val = superio_inb(sioaddr, SIOREG_ACT);
605                 if (!(val & 0x01)) {
606                         printk(KERN_INFO DRVNAME ": Logical device 0x%02x "
607                                "not activated\n", logdev[i]);
608                         continue;
609                 }
610
611                 val = superio_inb(sioaddr, SIOREG_MAP);
612                 if (val & 0x01) {
613                         printk(KERN_WARNING DRVNAME ": Logical device 0x%02x "
614                                "is memory-mapped, can't use\n", logdev[i]);
615                         continue;
616                 }
617
618                 val = (superio_inb(sioaddr, SIOREG_IOBASE) << 8)
619                     | superio_inb(sioaddr, SIOREG_IOBASE + 1);
620                 if (!val) {
621                         printk(KERN_INFO DRVNAME ": I/O base address not set "
622                                "for logical device 0x%02x\n", logdev[i]);
623                         continue;
624                 }
625                 address[i] = val;
626         }
627
628         /* Check which fan inputs are wired */
629         sio_data->has_fanin = (1 << 2) | (1 << 3);      /* FANIN2, FANIN3 */
630
631         cfg = superio_inb(sioaddr, SIOREG_CF2);
632         if (!(cfg & (1 << 3)))
633                 sio_data->has_fanin |= (1 << 0);        /* FANIN0 */
634         if (!(cfg & (1 << 2)))
635                 sio_data->has_fanin |= (1 << 4);        /* FANIN4 */
636
637         cfg = superio_inb(sioaddr, SIOREG_CFD);
638         if (!(cfg & (1 << 0)))
639                 sio_data->has_fanin |= (1 << 1);        /* FANIN1 */
640
641         cfg = superio_inb(sioaddr, SIOREG_CF4);
642         if (!(cfg & (1 << 0)))
643                 sio_data->has_fanin |= (1 << 7);        /* FANIN7 */
644         cfg_b = superio_inb(sioaddr, SIOREG_CFB);
645         if (!(cfg & (1 << 1)) && (cfg_b & (1 << 3)))
646                 sio_data->has_fanin |= (1 << 5);        /* FANIN5 */
647         cfg = superio_inb(sioaddr, SIOREG_CF3);
648         if ((cfg & (1 << 3)) && !(cfg_b & (1 << 5)))
649                 sio_data->has_fanin |= (1 << 6);        /* FANIN6 */
650
651 exit:
652         superio_exit(sioaddr);
653         return err;
654 }
655
656 static int __init pc87427_init(void)
657 {
658         int err;
659         unsigned short address[2];
660         struct pc87427_sio_data sio_data;
661
662         if (pc87427_find(0x2e, address, &sio_data)
663          && pc87427_find(0x4e, address, &sio_data))
664                 return -ENODEV;
665
666         /* For now the driver only handles fans so we only care about the
667            first address. */
668         if (!address[0])
669                 return -ENODEV;
670
671         err = platform_driver_register(&pc87427_driver);
672         if (err)
673                 goto exit;
674
675         /* Sets global pdev as a side effect */
676         err = pc87427_device_add(address[0], &sio_data);
677         if (err)
678                 goto exit_driver;
679
680         return 0;
681
682 exit_driver:
683         platform_driver_unregister(&pc87427_driver);
684 exit:
685         return err;
686 }
687
688 static void __exit pc87427_exit(void)
689 {
690         platform_device_unregister(pdev);
691         platform_driver_unregister(&pc87427_driver);
692 }
693
694 MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
695 MODULE_DESCRIPTION("PC87427 hardware monitoring driver");
696 MODULE_LICENSE("GPL");
697
698 module_init(pc87427_init);
699 module_exit(pc87427_exit);