linux/drivers/hwmon/fscpos.c
<<
>>
Prefs
   1/*
   2        fscpos.c - Kernel module for hardware monitoring with FSC Poseidon chips
   3        Copyright (C) 2004, 2005 Stefan Ott <stefan@desire.ch>
   4
   5        This program is free software; you can redistribute it and/or modify
   6        it under the terms of the GNU General Public License as published by
   7        the Free Software Foundation; either version 2 of the License, or
   8        (at your option) any later version.
   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        You should have received a copy of the GNU General Public License
  16        along with this program; if not, write to the Free Software
  17        Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18*/
  19
  20/*
  21        fujitsu siemens poseidon chip,
  22        module based on the old fscpos module by Hermann Jung <hej@odn.de> and
  23        the fscher module by Reinhard Nissl <rnissl@gmx.de>
  24
  25        original module based on lm80.c
  26        Copyright (C) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
  27        and Philip Edelbrock <phil@netroedge.com>
  28
  29        Thanks to Jean Delvare for reviewing my code and suggesting a lot of
  30        improvements.
  31*/
  32
  33#include <linux/module.h>
  34#include <linux/slab.h>
  35#include <linux/jiffies.h>
  36#include <linux/i2c.h>
  37#include <linux/init.h>
  38#include <linux/hwmon.h>
  39#include <linux/err.h>
  40#include <linux/mutex.h>
  41#include <linux/sysfs.h>
  42
  43/*
  44 * Addresses to scan
  45 */
  46static const unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END };
  47
  48/*
  49 * Insmod parameters
  50 */
  51I2C_CLIENT_INSMOD_1(fscpos);
  52
  53/*
  54 * The FSCPOS registers
  55 */
  56
  57/* chip identification */
  58#define FSCPOS_REG_IDENT_0              0x00
  59#define FSCPOS_REG_IDENT_1              0x01
  60#define FSCPOS_REG_IDENT_2              0x02
  61#define FSCPOS_REG_REVISION             0x03
  62
  63/* global control and status */
  64#define FSCPOS_REG_EVENT_STATE          0x04
  65#define FSCPOS_REG_CONTROL              0x05
  66
  67/* watchdog */
  68#define FSCPOS_REG_WDOG_PRESET          0x28
  69#define FSCPOS_REG_WDOG_STATE           0x23
  70#define FSCPOS_REG_WDOG_CONTROL         0x21
  71
  72/* voltages */
  73#define FSCPOS_REG_VOLT_12              0x45
  74#define FSCPOS_REG_VOLT_5               0x42
  75#define FSCPOS_REG_VOLT_BATT            0x48
  76
  77/* fans - the chip does not support minimum speed for fan2 */
  78static u8 FSCPOS_REG_PWM[] = { 0x55, 0x65 };
  79static u8 FSCPOS_REG_FAN_ACT[] = { 0x0e, 0x6b, 0xab };
  80static u8 FSCPOS_REG_FAN_STATE[] = { 0x0d, 0x62, 0xa2 };
  81static u8 FSCPOS_REG_FAN_RIPPLE[] = { 0x0f, 0x6f, 0xaf };
  82
  83/* temperatures */
  84static u8 FSCPOS_REG_TEMP_ACT[] = { 0x64, 0x32, 0x35 };
  85static u8 FSCPOS_REG_TEMP_STATE[] = { 0x71, 0x81, 0x91 };
  86
  87/*
  88 * Functions declaration
  89 */
  90static int fscpos_probe(struct i2c_client *client,
  91                        const struct i2c_device_id *id);
  92static int fscpos_detect(struct i2c_client *client, int kind,
  93                         struct i2c_board_info *info);
  94static int fscpos_remove(struct i2c_client *client);
  95
  96static int fscpos_read_value(struct i2c_client *client, u8 reg);
  97static int fscpos_write_value(struct i2c_client *client, u8 reg, u8 value);
  98static struct fscpos_data *fscpos_update_device(struct device *dev);
  99static void fscpos_init_client(struct i2c_client *client);
 100
 101static void reset_fan_alarm(struct i2c_client *client, int nr);
 102
 103/*
 104 * Driver data (common to all clients)
 105 */
 106static const struct i2c_device_id fscpos_id[] = {
 107        { "fscpos", fscpos },
 108        { }
 109};
 110
 111static struct i2c_driver fscpos_driver = {
 112        .class          = I2C_CLASS_HWMON,
 113        .driver = {
 114                .name   = "fscpos",
 115        },
 116        .probe          = fscpos_probe,
 117        .remove         = fscpos_remove,
 118        .id_table       = fscpos_id,
 119        .detect         = fscpos_detect,
 120        .address_data   = &addr_data,
 121};
 122
 123/*
 124 * Client data (each client gets its own)
 125 */
 126struct fscpos_data {
 127        struct device *hwmon_dev;
 128        struct mutex update_lock;
 129        char valid;             /* 0 until following fields are valid */
 130        unsigned long last_updated;     /* In jiffies */
 131
 132        /* register values */
 133        u8 revision;            /* revision of chip */
 134        u8 global_event;        /* global event status */
 135        u8 global_control;      /* global control register */
 136        u8 wdog_control;        /* watchdog control */
 137        u8 wdog_state;          /* watchdog status */
 138        u8 wdog_preset;         /* watchdog preset */
 139        u8 volt[3];             /* 12, 5, battery current */
 140        u8 temp_act[3];         /* temperature */
 141        u8 temp_status[3];      /* status of sensor */
 142        u8 fan_act[3];          /* fans revolutions per second */
 143        u8 fan_status[3];       /* fan status */
 144        u8 pwm[2];              /* fan min value for rps */
 145        u8 fan_ripple[3];       /* divider for rps */
 146};
 147
 148/* Temperature */
 149#define TEMP_FROM_REG(val)      (((val) - 128) * 1000)
 150
 151static ssize_t show_temp_input(struct fscpos_data *data, char *buf, int nr)
 152{
 153        return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_act[nr - 1]));
 154}
 155
 156static ssize_t show_temp_status(struct fscpos_data *data, char *buf, int nr)
 157{
 158        /* bits 2..7 reserved => mask with 0x03 */
 159        return sprintf(buf, "%u\n", data->temp_status[nr - 1] & 0x03);
 160}
 161
 162static ssize_t show_temp_reset(struct fscpos_data *data, char *buf, int nr)
 163{
 164        return sprintf(buf, "1\n");
 165}
 166
 167static ssize_t set_temp_reset(struct i2c_client *client, struct fscpos_data
 168                        *data, const char *buf, size_t count, int nr, int reg)
 169{
 170        unsigned long v = simple_strtoul(buf, NULL, 10);
 171        if (v != 1) {
 172                dev_err(&client->dev, "temp_reset value %ld not supported. "
 173                                        "Use 1 to reset the alarm!\n", v);
 174                return -EINVAL;
 175        }
 176
 177        dev_info(&client->dev, "You used the temp_reset feature which has not "
 178                                "been proplerly tested. Please report your "
 179                                "experience to the module author.\n");
 180
 181        /* Supported value: 2 (clears the status) */
 182        fscpos_write_value(client, FSCPOS_REG_TEMP_STATE[nr - 1], 2);
 183        return count;
 184}
 185
 186/* Fans */
 187#define RPM_FROM_REG(val)       ((val) * 60)
 188
 189static ssize_t show_fan_status(struct fscpos_data *data, char *buf, int nr)
 190{
 191        /* bits 0..1, 3..7 reserved => mask with 0x04 */
 192        return sprintf(buf, "%u\n", data->fan_status[nr - 1] & 0x04);
 193}
 194
 195static ssize_t show_fan_input(struct fscpos_data *data, char *buf, int nr)
 196{
 197        return sprintf(buf, "%u\n", RPM_FROM_REG(data->fan_act[nr - 1]));
 198}
 199
 200static ssize_t show_fan_ripple(struct fscpos_data *data, char *buf, int nr)
 201{
 202        /* bits 2..7 reserved => mask with 0x03 */
 203        return sprintf(buf, "%u\n", data->fan_ripple[nr - 1] & 0x03);
 204}
 205
 206static ssize_t set_fan_ripple(struct i2c_client *client, struct fscpos_data
 207                        *data, const char *buf, size_t count, int nr, int reg)
 208{
 209        /* supported values: 2, 4, 8 */
 210        unsigned long v = simple_strtoul(buf, NULL, 10);
 211
 212        switch (v) {
 213                case 2: v = 1; break;
 214                case 4: v = 2; break;
 215                case 8: v = 3; break;
 216        default:
 217                dev_err(&client->dev, "fan_ripple value %ld not supported. "
 218                                        "Must be one of 2, 4 or 8!\n", v);
 219                return -EINVAL;
 220        }
 221        
 222        mutex_lock(&data->update_lock);
 223        /* bits 2..7 reserved => mask with 0x03 */
 224        data->fan_ripple[nr - 1] &= ~0x03;
 225        data->fan_ripple[nr - 1] |= v;
 226        
 227        fscpos_write_value(client, reg, data->fan_ripple[nr - 1]);
 228        mutex_unlock(&data->update_lock);
 229        return count;
 230}
 231
 232static ssize_t show_pwm(struct fscpos_data *data, char *buf, int nr)
 233{
 234        return sprintf(buf, "%u\n", data->pwm[nr - 1]);
 235}
 236
 237static ssize_t set_pwm(struct i2c_client *client, struct fscpos_data *data,
 238                                const char *buf, size_t count, int nr, int reg)
 239{
 240        unsigned long v = simple_strtoul(buf, NULL, 10);
 241
 242        /* Range: 0..255 */
 243        if (v < 0) v = 0;
 244        if (v > 255) v = 255;
 245
 246        mutex_lock(&data->update_lock);
 247        data->pwm[nr - 1] = v;
 248        fscpos_write_value(client, reg, data->pwm[nr - 1]);
 249        mutex_unlock(&data->update_lock);
 250        return count;
 251}
 252
 253static void reset_fan_alarm(struct i2c_client *client, int nr)
 254{
 255        fscpos_write_value(client, FSCPOS_REG_FAN_STATE[nr], 4);
 256}
 257
 258/* Volts */
 259#define VOLT_FROM_REG(val, mult)        ((val) * (mult) / 255)
 260
 261static ssize_t show_volt_12(struct device *dev, struct device_attribute *attr, char *buf)
 262{
 263        struct fscpos_data *data = fscpos_update_device(dev);
 264        return sprintf(buf, "%u\n", VOLT_FROM_REG(data->volt[0], 14200));
 265}
 266
 267static ssize_t show_volt_5(struct device *dev, struct device_attribute *attr, char *buf)
 268{
 269        struct fscpos_data *data = fscpos_update_device(dev);
 270        return sprintf(buf, "%u\n", VOLT_FROM_REG(data->volt[1], 6600));
 271}
 272
 273static ssize_t show_volt_batt(struct device *dev, struct device_attribute *attr, char *buf)
 274{
 275        struct fscpos_data *data = fscpos_update_device(dev);
 276        return sprintf(buf, "%u\n", VOLT_FROM_REG(data->volt[2], 3300));
 277}
 278
 279/* Watchdog */
 280static ssize_t show_wdog_control(struct fscpos_data *data, char *buf)
 281{
 282        /* bits 0..3 reserved, bit 6 write only => mask with 0xb0 */
 283        return sprintf(buf, "%u\n", data->wdog_control & 0xb0);
 284}
 285
 286static ssize_t set_wdog_control(struct i2c_client *client, struct fscpos_data
 287                                *data, const char *buf, size_t count, int reg)
 288{
 289        /* bits 0..3 reserved => mask with 0xf0 */
 290        unsigned long v = simple_strtoul(buf, NULL, 10) & 0xf0;
 291
 292        mutex_lock(&data->update_lock);
 293        data->wdog_control &= ~0xf0;
 294        data->wdog_control |= v;
 295        fscpos_write_value(client, reg, data->wdog_control);
 296        mutex_unlock(&data->update_lock);
 297        return count;
 298}
 299
 300static ssize_t show_wdog_state(struct fscpos_data *data, char *buf)
 301{
 302        /* bits 0, 2..7 reserved => mask with 0x02 */
 303        return sprintf(buf, "%u\n", data->wdog_state & 0x02);
 304}
 305
 306static ssize_t set_wdog_state(struct i2c_client *client, struct fscpos_data
 307                                *data, const char *buf, size_t count, int reg)
 308{
 309        unsigned long v = simple_strtoul(buf, NULL, 10) & 0x02;
 310
 311        /* Valid values: 2 (clear) */
 312        if (v != 2) {
 313                dev_err(&client->dev, "wdog_state value %ld not supported. "
 314                                        "Must be 2 to clear the state!\n", v);
 315                return -EINVAL;
 316        }
 317
 318        mutex_lock(&data->update_lock);
 319        data->wdog_state &= ~v;
 320        fscpos_write_value(client, reg, v);
 321        mutex_unlock(&data->update_lock);
 322        return count;
 323}
 324
 325static ssize_t show_wdog_preset(struct fscpos_data *data, char *buf)
 326{
 327        return sprintf(buf, "%u\n", data->wdog_preset);
 328}
 329
 330static ssize_t set_wdog_preset(struct i2c_client *client, struct fscpos_data
 331                                *data, const char *buf, size_t count, int reg)
 332{
 333        unsigned long v = simple_strtoul(buf, NULL, 10) & 0xff;
 334
 335        mutex_lock(&data->update_lock);
 336        data->wdog_preset = v;
 337        fscpos_write_value(client, reg, data->wdog_preset);
 338        mutex_unlock(&data->update_lock);
 339        return count;
 340}
 341
 342/* Event */
 343static ssize_t show_event(struct device *dev, struct device_attribute *attr, char *buf)
 344{
 345        /* bits 5..7 reserved => mask with 0x1f */
 346        struct fscpos_data *data = fscpos_update_device(dev);
 347        return sprintf(buf, "%u\n", data->global_event & 0x9b);
 348}
 349
 350/*
 351 * Sysfs stuff
 352 */
 353#define create_getter(kind, sub) \
 354        static ssize_t sysfs_show_##kind##sub(struct device *dev, struct device_attribute *attr, char *buf) \
 355        { \
 356                struct fscpos_data *data = fscpos_update_device(dev); \
 357                return show_##kind##sub(data, buf); \
 358        }
 359
 360#define create_getter_n(kind, offset, sub) \
 361        static ssize_t sysfs_show_##kind##offset##sub(struct device *dev, struct device_attribute *attr, char\
 362                                                                        *buf) \
 363        { \
 364                struct fscpos_data *data = fscpos_update_device(dev); \
 365                return show_##kind##sub(data, buf, offset); \
 366        }
 367
 368#define create_setter(kind, sub, reg) \
 369        static ssize_t sysfs_set_##kind##sub (struct device *dev, struct device_attribute *attr, const char \
 370                                                        *buf, size_t count) \
 371        { \
 372                struct i2c_client *client = to_i2c_client(dev); \
 373                struct fscpos_data *data = i2c_get_clientdata(client); \
 374                return set_##kind##sub(client, data, buf, count, reg); \
 375        }
 376
 377#define create_setter_n(kind, offset, sub, reg) \
 378        static ssize_t sysfs_set_##kind##offset##sub (struct device *dev, struct device_attribute *attr, \
 379                                        const char *buf, size_t count) \
 380        { \
 381                struct i2c_client *client = to_i2c_client(dev); \
 382                struct fscpos_data *data = i2c_get_clientdata(client); \
 383                return set_##kind##sub(client, data, buf, count, offset, reg);\
 384        }
 385
 386#define create_sysfs_device_ro(kind, sub, offset) \
 387        static DEVICE_ATTR(kind##offset##sub, S_IRUGO, \
 388                                        sysfs_show_##kind##offset##sub, NULL);
 389
 390#define create_sysfs_device_rw(kind, sub, offset) \
 391        static DEVICE_ATTR(kind##offset##sub, S_IRUGO | S_IWUSR, \
 392                sysfs_show_##kind##offset##sub, sysfs_set_##kind##offset##sub);
 393
 394#define sysfs_ro_n(kind, sub, offset) \
 395        create_getter_n(kind, offset, sub); \
 396        create_sysfs_device_ro(kind, sub, offset);
 397
 398#define sysfs_rw_n(kind, sub, offset, reg) \
 399        create_getter_n(kind, offset, sub); \
 400        create_setter_n(kind, offset, sub, reg); \
 401        create_sysfs_device_rw(kind, sub, offset);
 402
 403#define sysfs_rw(kind, sub, reg) \
 404        create_getter(kind, sub); \
 405        create_setter(kind, sub, reg); \
 406        create_sysfs_device_rw(kind, sub,);
 407
 408#define sysfs_fan_with_min(offset, reg_status, reg_ripple, reg_min) \
 409        sysfs_fan(offset, reg_status, reg_ripple); \
 410        sysfs_rw_n(pwm,, offset, reg_min);
 411
 412#define sysfs_fan(offset, reg_status, reg_ripple) \
 413        sysfs_ro_n(fan, _input, offset); \
 414        sysfs_ro_n(fan, _status, offset); \
 415        sysfs_rw_n(fan, _ripple, offset, reg_ripple);
 416
 417#define sysfs_temp(offset, reg_status) \
 418        sysfs_ro_n(temp, _input, offset); \
 419        sysfs_ro_n(temp, _status, offset); \
 420        sysfs_rw_n(temp, _reset, offset, reg_status);
 421
 422#define sysfs_watchdog(reg_wdog_preset, reg_wdog_state, reg_wdog_control) \
 423        sysfs_rw(wdog, _control, reg_wdog_control); \
 424        sysfs_rw(wdog, _preset, reg_wdog_preset); \
 425        sysfs_rw(wdog, _state, reg_wdog_state);
 426
 427sysfs_fan_with_min(1, FSCPOS_REG_FAN_STATE[0], FSCPOS_REG_FAN_RIPPLE[0],
 428                                                        FSCPOS_REG_PWM[0]);
 429sysfs_fan_with_min(2, FSCPOS_REG_FAN_STATE[1], FSCPOS_REG_FAN_RIPPLE[1],
 430                                                        FSCPOS_REG_PWM[1]);
 431sysfs_fan(3, FSCPOS_REG_FAN_STATE[2], FSCPOS_REG_FAN_RIPPLE[2]);
 432
 433sysfs_temp(1, FSCPOS_REG_TEMP_STATE[0]);
 434sysfs_temp(2, FSCPOS_REG_TEMP_STATE[1]);
 435sysfs_temp(3, FSCPOS_REG_TEMP_STATE[2]);
 436
 437sysfs_watchdog(FSCPOS_REG_WDOG_PRESET, FSCPOS_REG_WDOG_STATE,
 438                                                FSCPOS_REG_WDOG_CONTROL);
 439
 440static DEVICE_ATTR(event, S_IRUGO, show_event, NULL);
 441static DEVICE_ATTR(in0_input, S_IRUGO, show_volt_12, NULL);
 442static DEVICE_ATTR(in1_input, S_IRUGO, show_volt_5, NULL);
 443static DEVICE_ATTR(in2_input, S_IRUGO, show_volt_batt, NULL);
 444
 445static struct attribute *fscpos_attributes[] = {
 446        &dev_attr_event.attr,
 447        &dev_attr_in0_input.attr,
 448        &dev_attr_in1_input.attr,
 449        &dev_attr_in2_input.attr,
 450
 451        &dev_attr_wdog_control.attr,
 452        &dev_attr_wdog_preset.attr,
 453        &dev_attr_wdog_state.attr,
 454
 455        &dev_attr_temp1_input.attr,
 456        &dev_attr_temp1_status.attr,
 457        &dev_attr_temp1_reset.attr,
 458        &dev_attr_temp2_input.attr,
 459        &dev_attr_temp2_status.attr,
 460        &dev_attr_temp2_reset.attr,
 461        &dev_attr_temp3_input.attr,
 462        &dev_attr_temp3_status.attr,
 463        &dev_attr_temp3_reset.attr,
 464
 465        &dev_attr_fan1_input.attr,
 466        &dev_attr_fan1_status.attr,
 467        &dev_attr_fan1_ripple.attr,
 468        &dev_attr_pwm1.attr,
 469        &dev_attr_fan2_input.attr,
 470        &dev_attr_fan2_status.attr,
 471        &dev_attr_fan2_ripple.attr,
 472        &dev_attr_pwm2.attr,
 473        &dev_attr_fan3_input.attr,
 474        &dev_attr_fan3_status.attr,
 475        &dev_attr_fan3_ripple.attr,
 476        NULL
 477};
 478
 479static const struct attribute_group fscpos_group = {
 480        .attrs = fscpos_attributes,
 481};
 482
 483/* Return 0 if detection is successful, -ENODEV otherwise */
 484static int fscpos_detect(struct i2c_client *new_client, int kind,
 485                         struct i2c_board_info *info)
 486{
 487        struct i2c_adapter *adapter = new_client->adapter;
 488
 489        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 490                return -ENODEV;
 491
 492        /* Do the remaining detection unless force or force_fscpos parameter */
 493        if (kind < 0) {
 494                if ((fscpos_read_value(new_client, FSCPOS_REG_IDENT_0)
 495                        != 0x50) /* 'P' */
 496                || (fscpos_read_value(new_client, FSCPOS_REG_IDENT_1)
 497                        != 0x45) /* 'E' */
 498                || (fscpos_read_value(new_client, FSCPOS_REG_IDENT_2)
 499                        != 0x47))/* 'G' */
 500                        return -ENODEV;
 501        }
 502
 503        strlcpy(info->type, "fscpos", I2C_NAME_SIZE);
 504
 505        return 0;
 506}
 507
 508static int fscpos_probe(struct i2c_client *new_client,
 509                        const struct i2c_device_id *id)
 510{
 511        struct fscpos_data *data;
 512        int err;
 513
 514        data = kzalloc(sizeof(struct fscpos_data), GFP_KERNEL);
 515        if (!data) {
 516                err = -ENOMEM;
 517                goto exit;
 518        }
 519
 520        i2c_set_clientdata(new_client, data);
 521        data->valid = 0;
 522        mutex_init(&data->update_lock);
 523
 524        /* Inizialize the fscpos chip */
 525        fscpos_init_client(new_client);
 526
 527        /* Announce that the chip was found */
 528        dev_info(&new_client->dev, "Found fscpos chip, rev %u\n", data->revision);
 529
 530        /* Register sysfs hooks */
 531        if ((err = sysfs_create_group(&new_client->dev.kobj, &fscpos_group)))
 532                goto exit_free;
 533
 534        data->hwmon_dev = hwmon_device_register(&new_client->dev);
 535        if (IS_ERR(data->hwmon_dev)) {
 536                err = PTR_ERR(data->hwmon_dev);
 537                goto exit_remove_files;
 538        }
 539
 540        return 0;
 541
 542exit_remove_files:
 543        sysfs_remove_group(&new_client->dev.kobj, &fscpos_group);
 544exit_free:
 545        kfree(data);
 546exit:
 547        return err;
 548}
 549
 550static int fscpos_remove(struct i2c_client *client)
 551{
 552        struct fscpos_data *data = i2c_get_clientdata(client);
 553
 554        hwmon_device_unregister(data->hwmon_dev);
 555        sysfs_remove_group(&client->dev.kobj, &fscpos_group);
 556
 557        kfree(data);
 558        return 0;
 559}
 560
 561static int fscpos_read_value(struct i2c_client *client, u8 reg)
 562{
 563        dev_dbg(&client->dev, "Read reg 0x%02x\n", reg);
 564        return i2c_smbus_read_byte_data(client, reg);
 565}
 566
 567static int fscpos_write_value(struct i2c_client *client, u8 reg, u8 value)
 568{
 569        dev_dbg(&client->dev, "Write reg 0x%02x, val 0x%02x\n", reg, value);
 570        return i2c_smbus_write_byte_data(client, reg, value);
 571}
 572
 573/* Called when we have found a new FSCPOS chip */
 574static void fscpos_init_client(struct i2c_client *client)
 575{
 576        struct fscpos_data *data = i2c_get_clientdata(client);
 577
 578        /* read revision from chip */
 579        data->revision = fscpos_read_value(client, FSCPOS_REG_REVISION);
 580}
 581
 582static struct fscpos_data *fscpos_update_device(struct device *dev)
 583{
 584        struct i2c_client *client = to_i2c_client(dev);
 585        struct fscpos_data *data = i2c_get_clientdata(client);
 586
 587        mutex_lock(&data->update_lock);
 588
 589        if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) {
 590                int i;
 591
 592                dev_dbg(&client->dev, "Starting fscpos update\n");
 593
 594                for (i = 0; i < 3; i++) {
 595                        data->temp_act[i] = fscpos_read_value(client,
 596                                                FSCPOS_REG_TEMP_ACT[i]);
 597                        data->temp_status[i] = fscpos_read_value(client,
 598                                                FSCPOS_REG_TEMP_STATE[i]);
 599                        data->fan_act[i] = fscpos_read_value(client,
 600                                                FSCPOS_REG_FAN_ACT[i]);
 601                        data->fan_status[i] = fscpos_read_value(client,
 602                                                FSCPOS_REG_FAN_STATE[i]);
 603                        data->fan_ripple[i] = fscpos_read_value(client,
 604                                                FSCPOS_REG_FAN_RIPPLE[i]);
 605                        if (i < 2) {
 606                                /* fan2_min is not supported by the chip */
 607                                data->pwm[i] = fscpos_read_value(client,
 608                                                        FSCPOS_REG_PWM[i]);
 609                        }
 610                        /* reset fan status if speed is back to > 0 */
 611                        if (data->fan_status[i] != 0 && data->fan_act[i] > 0) {
 612                                reset_fan_alarm(client, i);
 613                        }
 614                }
 615
 616                data->volt[0] = fscpos_read_value(client, FSCPOS_REG_VOLT_12);
 617                data->volt[1] = fscpos_read_value(client, FSCPOS_REG_VOLT_5);
 618                data->volt[2] = fscpos_read_value(client, FSCPOS_REG_VOLT_BATT);
 619
 620                data->wdog_preset = fscpos_read_value(client,
 621                                                        FSCPOS_REG_WDOG_PRESET);
 622                data->wdog_state = fscpos_read_value(client,
 623                                                        FSCPOS_REG_WDOG_STATE);
 624                data->wdog_control = fscpos_read_value(client,
 625                                                FSCPOS_REG_WDOG_CONTROL);
 626
 627                data->global_event = fscpos_read_value(client,
 628                                                FSCPOS_REG_EVENT_STATE);
 629
 630                data->last_updated = jiffies;
 631                data->valid = 1;
 632        }
 633        mutex_unlock(&data->update_lock);
 634        return data;
 635}
 636
 637static int __init sm_fscpos_init(void)
 638{
 639        return i2c_add_driver(&fscpos_driver);
 640}
 641
 642static void __exit sm_fscpos_exit(void)
 643{
 644        i2c_del_driver(&fscpos_driver);
 645}
 646
 647MODULE_AUTHOR("Stefan Ott <stefan@desire.ch> based on work from Hermann Jung "
 648                                "<hej@odn.de>, Frodo Looijaard <frodol@dds.nl>"
 649                                " and Philip Edelbrock <phil@netroedge.com>");
 650MODULE_DESCRIPTION("fujitsu siemens poseidon chip driver");
 651MODULE_LICENSE("GPL");
 652
 653module_init(sm_fscpos_init);
 654module_exit(sm_fscpos_exit);
 655