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.17-rc6 700 lines 21 kB view raw
1/* 2 * fscher.c - Part of lm_sensors, Linux kernel modules for hardware 3 * monitoring 4 * Copyright (C) 2003, 2004 Reinhard Nissl <rnissl@gmx.de> 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 as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 */ 20 21/* 22 * fujitsu siemens hermes chip, 23 * module based on fscpos.c 24 * Copyright (C) 2000 Hermann Jung <hej@odn.de> 25 * Copyright (C) 1998, 1999 Frodo Looijaard <frodol@dds.nl> 26 * and Philip Edelbrock <phil@netroedge.com> 27 */ 28 29#include <linux/module.h> 30#include <linux/init.h> 31#include <linux/slab.h> 32#include <linux/jiffies.h> 33#include <linux/i2c.h> 34#include <linux/hwmon.h> 35#include <linux/err.h> 36#include <linux/mutex.h> 37 38/* 39 * Addresses to scan 40 */ 41 42static unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END }; 43 44/* 45 * Insmod parameters 46 */ 47 48I2C_CLIENT_INSMOD_1(fscher); 49 50/* 51 * The FSCHER registers 52 */ 53 54/* chip identification */ 55#define FSCHER_REG_IDENT_0 0x00 56#define FSCHER_REG_IDENT_1 0x01 57#define FSCHER_REG_IDENT_2 0x02 58#define FSCHER_REG_REVISION 0x03 59 60/* global control and status */ 61#define FSCHER_REG_EVENT_STATE 0x04 62#define FSCHER_REG_CONTROL 0x05 63 64/* watchdog */ 65#define FSCHER_REG_WDOG_PRESET 0x28 66#define FSCHER_REG_WDOG_STATE 0x23 67#define FSCHER_REG_WDOG_CONTROL 0x21 68 69/* fan 0 */ 70#define FSCHER_REG_FAN0_MIN 0x55 71#define FSCHER_REG_FAN0_ACT 0x0e 72#define FSCHER_REG_FAN0_STATE 0x0d 73#define FSCHER_REG_FAN0_RIPPLE 0x0f 74 75/* fan 1 */ 76#define FSCHER_REG_FAN1_MIN 0x65 77#define FSCHER_REG_FAN1_ACT 0x6b 78#define FSCHER_REG_FAN1_STATE 0x62 79#define FSCHER_REG_FAN1_RIPPLE 0x6f 80 81/* fan 2 */ 82#define FSCHER_REG_FAN2_MIN 0xb5 83#define FSCHER_REG_FAN2_ACT 0xbb 84#define FSCHER_REG_FAN2_STATE 0xb2 85#define FSCHER_REG_FAN2_RIPPLE 0xbf 86 87/* voltage supervision */ 88#define FSCHER_REG_VOLT_12 0x45 89#define FSCHER_REG_VOLT_5 0x42 90#define FSCHER_REG_VOLT_BATT 0x48 91 92/* temperature 0 */ 93#define FSCHER_REG_TEMP0_ACT 0x64 94#define FSCHER_REG_TEMP0_STATE 0x71 95 96/* temperature 1 */ 97#define FSCHER_REG_TEMP1_ACT 0x32 98#define FSCHER_REG_TEMP1_STATE 0x81 99 100/* temperature 2 */ 101#define FSCHER_REG_TEMP2_ACT 0x35 102#define FSCHER_REG_TEMP2_STATE 0x91 103 104/* 105 * Functions declaration 106 */ 107 108static int fscher_attach_adapter(struct i2c_adapter *adapter); 109static int fscher_detect(struct i2c_adapter *adapter, int address, int kind); 110static int fscher_detach_client(struct i2c_client *client); 111static struct fscher_data *fscher_update_device(struct device *dev); 112static void fscher_init_client(struct i2c_client *client); 113 114static int fscher_read_value(struct i2c_client *client, u8 reg); 115static int fscher_write_value(struct i2c_client *client, u8 reg, u8 value); 116 117/* 118 * Driver data (common to all clients) 119 */ 120 121static struct i2c_driver fscher_driver = { 122 .driver = { 123 .name = "fscher", 124 }, 125 .id = I2C_DRIVERID_FSCHER, 126 .attach_adapter = fscher_attach_adapter, 127 .detach_client = fscher_detach_client, 128}; 129 130/* 131 * Client data (each client gets its own) 132 */ 133 134struct fscher_data { 135 struct i2c_client client; 136 struct class_device *class_dev; 137 struct mutex update_lock; 138 char valid; /* zero until following fields are valid */ 139 unsigned long last_updated; /* in jiffies */ 140 141 /* register values */ 142 u8 revision; /* revision of chip */ 143 u8 global_event; /* global event status */ 144 u8 global_control; /* global control register */ 145 u8 watchdog[3]; /* watchdog */ 146 u8 volt[3]; /* 12, 5, battery voltage */ 147 u8 temp_act[3]; /* temperature */ 148 u8 temp_status[3]; /* status of sensor */ 149 u8 fan_act[3]; /* fans revolutions per second */ 150 u8 fan_status[3]; /* fan status */ 151 u8 fan_min[3]; /* fan min value for rps */ 152 u8 fan_ripple[3]; /* divider for rps */ 153}; 154 155/* 156 * Sysfs stuff 157 */ 158 159#define sysfs_r(kind, sub, offset, reg) \ 160static ssize_t show_##kind##sub (struct fscher_data *, char *, int); \ 161static ssize_t show_##kind##offset##sub (struct device *, struct device_attribute *attr, char *); \ 162static ssize_t show_##kind##offset##sub (struct device *dev, struct device_attribute *attr, char *buf) \ 163{ \ 164 struct fscher_data *data = fscher_update_device(dev); \ 165 return show_##kind##sub(data, buf, (offset)); \ 166} 167 168#define sysfs_w(kind, sub, offset, reg) \ 169static ssize_t set_##kind##sub (struct i2c_client *, struct fscher_data *, const char *, size_t, int, int); \ 170static ssize_t set_##kind##offset##sub (struct device *, struct device_attribute *attr, const char *, size_t); \ 171static ssize_t set_##kind##offset##sub (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ 172{ \ 173 struct i2c_client *client = to_i2c_client(dev); \ 174 struct fscher_data *data = i2c_get_clientdata(client); \ 175 return set_##kind##sub(client, data, buf, count, (offset), reg); \ 176} 177 178#define sysfs_rw_n(kind, sub, offset, reg) \ 179sysfs_r(kind, sub, offset, reg) \ 180sysfs_w(kind, sub, offset, reg) \ 181static DEVICE_ATTR(kind##offset##sub, S_IRUGO | S_IWUSR, show_##kind##offset##sub, set_##kind##offset##sub); 182 183#define sysfs_rw(kind, sub, reg) \ 184sysfs_r(kind, sub, 0, reg) \ 185sysfs_w(kind, sub, 0, reg) \ 186static DEVICE_ATTR(kind##sub, S_IRUGO | S_IWUSR, show_##kind##0##sub, set_##kind##0##sub); 187 188#define sysfs_ro_n(kind, sub, offset, reg) \ 189sysfs_r(kind, sub, offset, reg) \ 190static DEVICE_ATTR(kind##offset##sub, S_IRUGO, show_##kind##offset##sub, NULL); 191 192#define sysfs_ro(kind, sub, reg) \ 193sysfs_r(kind, sub, 0, reg) \ 194static DEVICE_ATTR(kind, S_IRUGO, show_##kind##0##sub, NULL); 195 196#define sysfs_fan(offset, reg_status, reg_min, reg_ripple, reg_act) \ 197sysfs_rw_n(pwm, , offset, reg_min) \ 198sysfs_rw_n(fan, _status, offset, reg_status) \ 199sysfs_rw_n(fan, _div , offset, reg_ripple) \ 200sysfs_ro_n(fan, _input , offset, reg_act) 201 202#define sysfs_temp(offset, reg_status, reg_act) \ 203sysfs_rw_n(temp, _status, offset, reg_status) \ 204sysfs_ro_n(temp, _input , offset, reg_act) 205 206#define sysfs_in(offset, reg_act) \ 207sysfs_ro_n(in, _input, offset, reg_act) 208 209#define sysfs_revision(reg_revision) \ 210sysfs_ro(revision, , reg_revision) 211 212#define sysfs_alarms(reg_events) \ 213sysfs_ro(alarms, , reg_events) 214 215#define sysfs_control(reg_control) \ 216sysfs_rw(control, , reg_control) 217 218#define sysfs_watchdog(reg_control, reg_status, reg_preset) \ 219sysfs_rw(watchdog, _control, reg_control) \ 220sysfs_rw(watchdog, _status , reg_status) \ 221sysfs_rw(watchdog, _preset , reg_preset) 222 223sysfs_fan(1, FSCHER_REG_FAN0_STATE, FSCHER_REG_FAN0_MIN, 224 FSCHER_REG_FAN0_RIPPLE, FSCHER_REG_FAN0_ACT) 225sysfs_fan(2, FSCHER_REG_FAN1_STATE, FSCHER_REG_FAN1_MIN, 226 FSCHER_REG_FAN1_RIPPLE, FSCHER_REG_FAN1_ACT) 227sysfs_fan(3, FSCHER_REG_FAN2_STATE, FSCHER_REG_FAN2_MIN, 228 FSCHER_REG_FAN2_RIPPLE, FSCHER_REG_FAN2_ACT) 229 230sysfs_temp(1, FSCHER_REG_TEMP0_STATE, FSCHER_REG_TEMP0_ACT) 231sysfs_temp(2, FSCHER_REG_TEMP1_STATE, FSCHER_REG_TEMP1_ACT) 232sysfs_temp(3, FSCHER_REG_TEMP2_STATE, FSCHER_REG_TEMP2_ACT) 233 234sysfs_in(0, FSCHER_REG_VOLT_12) 235sysfs_in(1, FSCHER_REG_VOLT_5) 236sysfs_in(2, FSCHER_REG_VOLT_BATT) 237 238sysfs_revision(FSCHER_REG_REVISION) 239sysfs_alarms(FSCHER_REG_EVENTS) 240sysfs_control(FSCHER_REG_CONTROL) 241sysfs_watchdog(FSCHER_REG_WDOG_CONTROL, FSCHER_REG_WDOG_STATE, FSCHER_REG_WDOG_PRESET) 242 243#define device_create_file_fan(client, offset) \ 244do { \ 245 device_create_file(&client->dev, &dev_attr_fan##offset##_status); \ 246 device_create_file(&client->dev, &dev_attr_pwm##offset); \ 247 device_create_file(&client->dev, &dev_attr_fan##offset##_div); \ 248 device_create_file(&client->dev, &dev_attr_fan##offset##_input); \ 249} while (0) 250 251#define device_create_file_temp(client, offset) \ 252do { \ 253 device_create_file(&client->dev, &dev_attr_temp##offset##_status); \ 254 device_create_file(&client->dev, &dev_attr_temp##offset##_input); \ 255} while (0) 256 257#define device_create_file_in(client, offset) \ 258do { \ 259 device_create_file(&client->dev, &dev_attr_in##offset##_input); \ 260} while (0) 261 262#define device_create_file_revision(client) \ 263do { \ 264 device_create_file(&client->dev, &dev_attr_revision); \ 265} while (0) 266 267#define device_create_file_alarms(client) \ 268do { \ 269 device_create_file(&client->dev, &dev_attr_alarms); \ 270} while (0) 271 272#define device_create_file_control(client) \ 273do { \ 274 device_create_file(&client->dev, &dev_attr_control); \ 275} while (0) 276 277#define device_create_file_watchdog(client) \ 278do { \ 279 device_create_file(&client->dev, &dev_attr_watchdog_status); \ 280 device_create_file(&client->dev, &dev_attr_watchdog_control); \ 281 device_create_file(&client->dev, &dev_attr_watchdog_preset); \ 282} while (0) 283 284/* 285 * Real code 286 */ 287 288static int fscher_attach_adapter(struct i2c_adapter *adapter) 289{ 290 if (!(adapter->class & I2C_CLASS_HWMON)) 291 return 0; 292 return i2c_probe(adapter, &addr_data, fscher_detect); 293} 294 295static int fscher_detect(struct i2c_adapter *adapter, int address, int kind) 296{ 297 struct i2c_client *new_client; 298 struct fscher_data *data; 299 int err = 0; 300 301 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 302 goto exit; 303 304 /* OK. For now, we presume we have a valid client. We now create the 305 * client structure, even though we cannot fill it completely yet. 306 * But it allows us to access i2c_smbus_read_byte_data. */ 307 if (!(data = kzalloc(sizeof(struct fscher_data), GFP_KERNEL))) { 308 err = -ENOMEM; 309 goto exit; 310 } 311 312 /* The common I2C client data is placed right before the 313 * Hermes-specific data. */ 314 new_client = &data->client; 315 i2c_set_clientdata(new_client, data); 316 new_client->addr = address; 317 new_client->adapter = adapter; 318 new_client->driver = &fscher_driver; 319 new_client->flags = 0; 320 321 /* Do the remaining detection unless force or force_fscher parameter */ 322 if (kind < 0) { 323 if ((i2c_smbus_read_byte_data(new_client, 324 FSCHER_REG_IDENT_0) != 0x48) /* 'H' */ 325 || (i2c_smbus_read_byte_data(new_client, 326 FSCHER_REG_IDENT_1) != 0x45) /* 'E' */ 327 || (i2c_smbus_read_byte_data(new_client, 328 FSCHER_REG_IDENT_2) != 0x52)) /* 'R' */ 329 goto exit_free; 330 } 331 332 /* Fill in the remaining client fields and put it into the 333 * global list */ 334 strlcpy(new_client->name, "fscher", I2C_NAME_SIZE); 335 data->valid = 0; 336 mutex_init(&data->update_lock); 337 338 /* Tell the I2C layer a new client has arrived */ 339 if ((err = i2c_attach_client(new_client))) 340 goto exit_free; 341 342 fscher_init_client(new_client); 343 344 /* Register sysfs hooks */ 345 data->class_dev = hwmon_device_register(&new_client->dev); 346 if (IS_ERR(data->class_dev)) { 347 err = PTR_ERR(data->class_dev); 348 goto exit_detach; 349 } 350 351 device_create_file_revision(new_client); 352 device_create_file_alarms(new_client); 353 device_create_file_control(new_client); 354 device_create_file_watchdog(new_client); 355 356 device_create_file_in(new_client, 0); 357 device_create_file_in(new_client, 1); 358 device_create_file_in(new_client, 2); 359 360 device_create_file_fan(new_client, 1); 361 device_create_file_fan(new_client, 2); 362 device_create_file_fan(new_client, 3); 363 364 device_create_file_temp(new_client, 1); 365 device_create_file_temp(new_client, 2); 366 device_create_file_temp(new_client, 3); 367 368 return 0; 369 370exit_detach: 371 i2c_detach_client(new_client); 372exit_free: 373 kfree(data); 374exit: 375 return err; 376} 377 378static int fscher_detach_client(struct i2c_client *client) 379{ 380 struct fscher_data *data = i2c_get_clientdata(client); 381 int err; 382 383 hwmon_device_unregister(data->class_dev); 384 385 if ((err = i2c_detach_client(client))) 386 return err; 387 388 kfree(data); 389 return 0; 390} 391 392static int fscher_read_value(struct i2c_client *client, u8 reg) 393{ 394 dev_dbg(&client->dev, "read reg 0x%02x\n", reg); 395 396 return i2c_smbus_read_byte_data(client, reg); 397} 398 399static int fscher_write_value(struct i2c_client *client, u8 reg, u8 value) 400{ 401 dev_dbg(&client->dev, "write reg 0x%02x, val 0x%02x\n", 402 reg, value); 403 404 return i2c_smbus_write_byte_data(client, reg, value); 405} 406 407/* Called when we have found a new FSC Hermes. */ 408static void fscher_init_client(struct i2c_client *client) 409{ 410 struct fscher_data *data = i2c_get_clientdata(client); 411 412 /* Read revision from chip */ 413 data->revision = fscher_read_value(client, FSCHER_REG_REVISION); 414} 415 416static struct fscher_data *fscher_update_device(struct device *dev) 417{ 418 struct i2c_client *client = to_i2c_client(dev); 419 struct fscher_data *data = i2c_get_clientdata(client); 420 421 mutex_lock(&data->update_lock); 422 423 if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { 424 425 dev_dbg(&client->dev, "Starting fscher update\n"); 426 427 data->temp_act[0] = fscher_read_value(client, FSCHER_REG_TEMP0_ACT); 428 data->temp_act[1] = fscher_read_value(client, FSCHER_REG_TEMP1_ACT); 429 data->temp_act[2] = fscher_read_value(client, FSCHER_REG_TEMP2_ACT); 430 data->temp_status[0] = fscher_read_value(client, FSCHER_REG_TEMP0_STATE); 431 data->temp_status[1] = fscher_read_value(client, FSCHER_REG_TEMP1_STATE); 432 data->temp_status[2] = fscher_read_value(client, FSCHER_REG_TEMP2_STATE); 433 434 data->volt[0] = fscher_read_value(client, FSCHER_REG_VOLT_12); 435 data->volt[1] = fscher_read_value(client, FSCHER_REG_VOLT_5); 436 data->volt[2] = fscher_read_value(client, FSCHER_REG_VOLT_BATT); 437 438 data->fan_act[0] = fscher_read_value(client, FSCHER_REG_FAN0_ACT); 439 data->fan_act[1] = fscher_read_value(client, FSCHER_REG_FAN1_ACT); 440 data->fan_act[2] = fscher_read_value(client, FSCHER_REG_FAN2_ACT); 441 data->fan_status[0] = fscher_read_value(client, FSCHER_REG_FAN0_STATE); 442 data->fan_status[1] = fscher_read_value(client, FSCHER_REG_FAN1_STATE); 443 data->fan_status[2] = fscher_read_value(client, FSCHER_REG_FAN2_STATE); 444 data->fan_min[0] = fscher_read_value(client, FSCHER_REG_FAN0_MIN); 445 data->fan_min[1] = fscher_read_value(client, FSCHER_REG_FAN1_MIN); 446 data->fan_min[2] = fscher_read_value(client, FSCHER_REG_FAN2_MIN); 447 data->fan_ripple[0] = fscher_read_value(client, FSCHER_REG_FAN0_RIPPLE); 448 data->fan_ripple[1] = fscher_read_value(client, FSCHER_REG_FAN1_RIPPLE); 449 data->fan_ripple[2] = fscher_read_value(client, FSCHER_REG_FAN2_RIPPLE); 450 451 data->watchdog[0] = fscher_read_value(client, FSCHER_REG_WDOG_PRESET); 452 data->watchdog[1] = fscher_read_value(client, FSCHER_REG_WDOG_STATE); 453 data->watchdog[2] = fscher_read_value(client, FSCHER_REG_WDOG_CONTROL); 454 455 data->global_event = fscher_read_value(client, FSCHER_REG_EVENT_STATE); 456 457 data->last_updated = jiffies; 458 data->valid = 1; 459 } 460 461 mutex_unlock(&data->update_lock); 462 463 return data; 464} 465 466 467 468#define FAN_INDEX_FROM_NUM(nr) ((nr) - 1) 469 470static ssize_t set_fan_status(struct i2c_client *client, struct fscher_data *data, 471 const char *buf, size_t count, int nr, int reg) 472{ 473 /* bits 0..1, 3..7 reserved => mask with 0x04 */ 474 unsigned long v = simple_strtoul(buf, NULL, 10) & 0x04; 475 476 mutex_lock(&data->update_lock); 477 data->fan_status[FAN_INDEX_FROM_NUM(nr)] &= ~v; 478 fscher_write_value(client, reg, v); 479 mutex_unlock(&data->update_lock); 480 return count; 481} 482 483static ssize_t show_fan_status(struct fscher_data *data, char *buf, int nr) 484{ 485 /* bits 0..1, 3..7 reserved => mask with 0x04 */ 486 return sprintf(buf, "%u\n", data->fan_status[FAN_INDEX_FROM_NUM(nr)] & 0x04); 487} 488 489static ssize_t set_pwm(struct i2c_client *client, struct fscher_data *data, 490 const char *buf, size_t count, int nr, int reg) 491{ 492 unsigned long v = simple_strtoul(buf, NULL, 10); 493 494 mutex_lock(&data->update_lock); 495 data->fan_min[FAN_INDEX_FROM_NUM(nr)] = v > 0xff ? 0xff : v; 496 fscher_write_value(client, reg, data->fan_min[FAN_INDEX_FROM_NUM(nr)]); 497 mutex_unlock(&data->update_lock); 498 return count; 499} 500 501static ssize_t show_pwm(struct fscher_data *data, char *buf, int nr) 502{ 503 return sprintf(buf, "%u\n", data->fan_min[FAN_INDEX_FROM_NUM(nr)]); 504} 505 506static ssize_t set_fan_div(struct i2c_client *client, struct fscher_data *data, 507 const char *buf, size_t count, int nr, int reg) 508{ 509 /* supported values: 2, 4, 8 */ 510 unsigned long v = simple_strtoul(buf, NULL, 10); 511 512 switch (v) { 513 case 2: v = 1; break; 514 case 4: v = 2; break; 515 case 8: v = 3; break; 516 default: 517 dev_err(&client->dev, "fan_div value %ld not " 518 "supported. Choose one of 2, 4 or 8!\n", v); 519 return -EINVAL; 520 } 521 522 mutex_lock(&data->update_lock); 523 524 /* bits 2..7 reserved => mask with 0x03 */ 525 data->fan_ripple[FAN_INDEX_FROM_NUM(nr)] &= ~0x03; 526 data->fan_ripple[FAN_INDEX_FROM_NUM(nr)] |= v; 527 528 fscher_write_value(client, reg, data->fan_ripple[FAN_INDEX_FROM_NUM(nr)]); 529 mutex_unlock(&data->update_lock); 530 return count; 531} 532 533static ssize_t show_fan_div(struct fscher_data *data, char *buf, int nr) 534{ 535 /* bits 2..7 reserved => mask with 0x03 */ 536 return sprintf(buf, "%u\n", 1 << (data->fan_ripple[FAN_INDEX_FROM_NUM(nr)] & 0x03)); 537} 538 539#define RPM_FROM_REG(val) (val*60) 540 541static ssize_t show_fan_input (struct fscher_data *data, char *buf, int nr) 542{ 543 return sprintf(buf, "%u\n", RPM_FROM_REG(data->fan_act[FAN_INDEX_FROM_NUM(nr)])); 544} 545 546 547 548#define TEMP_INDEX_FROM_NUM(nr) ((nr) - 1) 549 550static ssize_t set_temp_status(struct i2c_client *client, struct fscher_data *data, 551 const char *buf, size_t count, int nr, int reg) 552{ 553 /* bits 2..7 reserved, 0 read only => mask with 0x02 */ 554 unsigned long v = simple_strtoul(buf, NULL, 10) & 0x02; 555 556 mutex_lock(&data->update_lock); 557 data->temp_status[TEMP_INDEX_FROM_NUM(nr)] &= ~v; 558 fscher_write_value(client, reg, v); 559 mutex_unlock(&data->update_lock); 560 return count; 561} 562 563static ssize_t show_temp_status(struct fscher_data *data, char *buf, int nr) 564{ 565 /* bits 2..7 reserved => mask with 0x03 */ 566 return sprintf(buf, "%u\n", data->temp_status[TEMP_INDEX_FROM_NUM(nr)] & 0x03); 567} 568 569#define TEMP_FROM_REG(val) (((val) - 128) * 1000) 570 571static ssize_t show_temp_input(struct fscher_data *data, char *buf, int nr) 572{ 573 return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_act[TEMP_INDEX_FROM_NUM(nr)])); 574} 575 576/* 577 * The final conversion is specified in sensors.conf, as it depends on 578 * mainboard specific values. We export the registers contents as 579 * pseudo-hundredths-of-Volts (range 0V - 2.55V). Not that it makes much 580 * sense per se, but it minimizes the conversions count and keeps the 581 * values within a usual range. 582 */ 583#define VOLT_FROM_REG(val) ((val) * 10) 584 585static ssize_t show_in_input(struct fscher_data *data, char *buf, int nr) 586{ 587 return sprintf(buf, "%u\n", VOLT_FROM_REG(data->volt[nr])); 588} 589 590 591 592static ssize_t show_revision(struct fscher_data *data, char *buf, int nr) 593{ 594 return sprintf(buf, "%u\n", data->revision); 595} 596 597 598 599static ssize_t show_alarms(struct fscher_data *data, char *buf, int nr) 600{ 601 /* bits 2, 5..6 reserved => mask with 0x9b */ 602 return sprintf(buf, "%u\n", data->global_event & 0x9b); 603} 604 605 606 607static ssize_t set_control(struct i2c_client *client, struct fscher_data *data, 608 const char *buf, size_t count, int nr, int reg) 609{ 610 /* bits 1..7 reserved => mask with 0x01 */ 611 unsigned long v = simple_strtoul(buf, NULL, 10) & 0x01; 612 613 mutex_lock(&data->update_lock); 614 data->global_control &= ~v; 615 fscher_write_value(client, reg, v); 616 mutex_unlock(&data->update_lock); 617 return count; 618} 619 620static ssize_t show_control(struct fscher_data *data, char *buf, int nr) 621{ 622 /* bits 1..7 reserved => mask with 0x01 */ 623 return sprintf(buf, "%u\n", data->global_control & 0x01); 624} 625 626 627 628static ssize_t set_watchdog_control(struct i2c_client *client, struct 629 fscher_data *data, const char *buf, size_t count, 630 int nr, int reg) 631{ 632 /* bits 0..3 reserved => mask with 0xf0 */ 633 unsigned long v = simple_strtoul(buf, NULL, 10) & 0xf0; 634 635 mutex_lock(&data->update_lock); 636 data->watchdog[2] &= ~0xf0; 637 data->watchdog[2] |= v; 638 fscher_write_value(client, reg, data->watchdog[2]); 639 mutex_unlock(&data->update_lock); 640 return count; 641} 642 643static ssize_t show_watchdog_control(struct fscher_data *data, char *buf, int nr) 644{ 645 /* bits 0..3 reserved, bit 5 write only => mask with 0xd0 */ 646 return sprintf(buf, "%u\n", data->watchdog[2] & 0xd0); 647} 648 649static ssize_t set_watchdog_status(struct i2c_client *client, struct fscher_data *data, 650 const char *buf, size_t count, int nr, int reg) 651{ 652 /* bits 0, 2..7 reserved => mask with 0x02 */ 653 unsigned long v = simple_strtoul(buf, NULL, 10) & 0x02; 654 655 mutex_lock(&data->update_lock); 656 data->watchdog[1] &= ~v; 657 fscher_write_value(client, reg, v); 658 mutex_unlock(&data->update_lock); 659 return count; 660} 661 662static ssize_t show_watchdog_status(struct fscher_data *data, char *buf, int nr) 663{ 664 /* bits 0, 2..7 reserved => mask with 0x02 */ 665 return sprintf(buf, "%u\n", data->watchdog[1] & 0x02); 666} 667 668static ssize_t set_watchdog_preset(struct i2c_client *client, struct fscher_data *data, 669 const char *buf, size_t count, int nr, int reg) 670{ 671 unsigned long v = simple_strtoul(buf, NULL, 10) & 0xff; 672 673 mutex_lock(&data->update_lock); 674 data->watchdog[0] = v; 675 fscher_write_value(client, reg, data->watchdog[0]); 676 mutex_unlock(&data->update_lock); 677 return count; 678} 679 680static ssize_t show_watchdog_preset(struct fscher_data *data, char *buf, int nr) 681{ 682 return sprintf(buf, "%u\n", data->watchdog[0]); 683} 684 685static int __init sensors_fscher_init(void) 686{ 687 return i2c_add_driver(&fscher_driver); 688} 689 690static void __exit sensors_fscher_exit(void) 691{ 692 i2c_del_driver(&fscher_driver); 693} 694 695MODULE_AUTHOR("Reinhard Nissl <rnissl@gmx.de>"); 696MODULE_DESCRIPTION("FSC Hermes driver"); 697MODULE_LICENSE("GPL"); 698 699module_init(sensors_fscher_init); 700module_exit(sensors_fscher_exit);