linux/drivers/hwmon/pc87427.c
<<
>>
Prefs
   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
  38static unsigned short force_id;
  39module_param(force_id, ushort, 0);
  40MODULE_PARM_DESC(force_id, "Override the detected device ID");
  41
  42static 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). */
  49struct 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
  72static const u8 logdev[2] = { 0x09, 0x14 };
  73static 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
  78static inline void superio_outb(int sioaddr, int reg, int val)
  79{
  80        outb(reg, sioaddr);
  81        outb(val, sioaddr + 1);
  82}
  83
  84static inline int superio_inb(int sioaddr, int reg)
  85{
  86        outb(reg, sioaddr);
  87        return inb(sioaddr + 1);
  88}
  89
  90static 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 */
 111static 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 */
 117static 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 */
 125static 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 */
 149static 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. */
 163static 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. */
 172static 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
 185static 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
 203done:
 204        mutex_unlock(&data->lock);
 205        return data;
 206}
 207
 208static 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
 218static 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
 228static 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
 239static 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
 250static 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
 273static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0);
 274static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1);
 275static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan_input, NULL, 2);
 276static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan_input, NULL, 3);
 277static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan_input, NULL, 4);
 278static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan_input, NULL, 5);
 279static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan_input, NULL, 6);
 280static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_fan_input, NULL, 7);
 281
 282static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO,
 283                          show_fan_min, set_fan_min, 0);
 284static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO,
 285                          show_fan_min, set_fan_min, 1);
 286static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO,
 287                          show_fan_min, set_fan_min, 2);
 288static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO,
 289                          show_fan_min, set_fan_min, 3);
 290static SENSOR_DEVICE_ATTR(fan5_min, S_IWUSR | S_IRUGO,
 291                          show_fan_min, set_fan_min, 4);
 292static SENSOR_DEVICE_ATTR(fan6_min, S_IWUSR | S_IRUGO,
 293                          show_fan_min, set_fan_min, 5);
 294static SENSOR_DEVICE_ATTR(fan7_min, S_IWUSR | S_IRUGO,
 295                          show_fan_min, set_fan_min, 6);
 296static SENSOR_DEVICE_ATTR(fan8_min, S_IWUSR | S_IRUGO,
 297                          show_fan_min, set_fan_min, 7);
 298
 299static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0);
 300static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 1);
 301static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 2);
 302static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 3);
 303static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_fan_alarm, NULL, 4);
 304static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_fan_alarm, NULL, 5);
 305static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_fan_alarm, NULL, 6);
 306static SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO, show_fan_alarm, NULL, 7);
 307
 308static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_fan_fault, NULL, 0);
 309static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_fan_fault, NULL, 1);
 310static SENSOR_DEVICE_ATTR(fan3_fault, S_IRUGO, show_fan_fault, NULL, 2);
 311static SENSOR_DEVICE_ATTR(fan4_fault, S_IRUGO, show_fan_fault, NULL, 3);
 312static SENSOR_DEVICE_ATTR(fan5_fault, S_IRUGO, show_fan_fault, NULL, 4);
 313static SENSOR_DEVICE_ATTR(fan6_fault, S_IRUGO, show_fan_fault, NULL, 5);
 314static SENSOR_DEVICE_ATTR(fan7_fault, S_IRUGO, show_fan_fault, NULL, 6);
 315static SENSOR_DEVICE_ATTR(fan8_fault, S_IRUGO, show_fan_fault, NULL, 7);
 316
 317static 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
 369static 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
 380static 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}
 387static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 388
 389
 390/*
 391 * Device detection, attach and detach
 392 */
 393
 394static 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
 423static 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
 471exit_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        }
 477exit_release_region:
 478        release_region(res->start, resource_size(res));
 479exit_kfree:
 480        platform_set_drvdata(pdev, NULL);
 481        kfree(data);
 482exit:
 483        return err;
 484}
 485
 486static 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
 509static 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
 518static 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
 555exit_device_put:
 556        platform_device_put(pdev);
 557exit:
 558        return err;
 559}
 560
 561static 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
 602exit:
 603        superio_exit(sioaddr);
 604        return err;
 605}
 606
 607static 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
 632exit_driver:
 633        platform_driver_unregister(&pc87427_driver);
 634exit:
 635        return err;
 636}
 637
 638static void __exit pc87427_exit(void)
 639{
 640        platform_device_unregister(pdev);
 641        platform_driver_unregister(&pc87427_driver);
 642}
 643
 644MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
 645MODULE_DESCRIPTION("PC87427 hardware monitoring driver");
 646MODULE_LICENSE("GPL");
 647
 648module_init(pc87427_init);
 649module_exit(pc87427_exit);
 650