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