Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.30-rc1 654 lines 19 kB view raw
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);