aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/w83l786ng.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon/w83l786ng.c')
-rw-r--r--drivers/hwmon/w83l786ng.c190
1 files changed, 109 insertions, 81 deletions
diff --git a/drivers/hwmon/w83l786ng.c b/drivers/hwmon/w83l786ng.c
index 063bd9508d8a..5850b7706088 100644
--- a/drivers/hwmon/w83l786ng.c
+++ b/drivers/hwmon/w83l786ng.c
@@ -1,28 +1,28 @@
1/* 1/*
2 w83l786ng.c - Linux kernel driver for hardware monitoring 2 * w83l786ng.c - Linux kernel driver for hardware monitoring
3 Copyright (c) 2007 Kevin Lo <kevlo@kevlo.org> 3 * Copyright (c) 2007 Kevin Lo <kevlo@kevlo.org>
4 4 *
5 This program is free software; you can redistribute it and/or modify 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 6 * it under the terms of the GNU General Public License as published by
7 the Free Software Foundation - version 2. 7 * the Free Software Foundation - version 2.
8 8 *
9 This program is distributed in the hope that it will be useful, 9 * This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details. 12 * GNU General Public License for more details.
13 13 *
14 You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software 15 * along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 02110-1301 USA. 17 * 02110-1301 USA.
18*/ 18 */
19 19
20/* 20/*
21 Supports following chips: 21 * Supports following chips:
22 22 *
23 Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA 23 * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
24 w83l786ng 3 2 2 2 0x7b 0x5ca3 yes no 24 * w83l786ng 3 2 2 2 0x7b 0x5ca3 yes no
25*/ 25 */
26 26
27#include <linux/module.h> 27#include <linux/module.h>
28#include <linux/init.h> 28#include <linux/init.h>
@@ -52,7 +52,7 @@ MODULE_PARM_DESC(reset, "Set to 1 to reset chip, not recommended");
52 52
53#define W83L786NG_REG_CONFIG 0x40 53#define W83L786NG_REG_CONFIG 0x40
54#define W83L786NG_REG_ALARM1 0x41 54#define W83L786NG_REG_ALARM1 0x41
55#define W83L786NG_REG_ALARM2 0x42 55#define W83L786NG_REG_ALARM2 0x42
56#define W83L786NG_REG_GPIO_EN 0x47 56#define W83L786NG_REG_GPIO_EN 0x47
57#define W83L786NG_REG_MAN_ID2 0x4C 57#define W83L786NG_REG_MAN_ID2 0x4C
58#define W83L786NG_REG_MAN_ID1 0x4D 58#define W83L786NG_REG_MAN_ID1 0x4D
@@ -89,19 +89,23 @@ FAN_TO_REG(long rpm, int div)
89 return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254); 89 return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
90} 90}
91 91
92#define FAN_FROM_REG(val,div) ((val) == 0 ? -1 : \ 92#define FAN_FROM_REG(val, div) ((val) == 0 ? -1 : \
93 ((val) == 255 ? 0 : \ 93 ((val) == 255 ? 0 : \
94 1350000 / ((val) * (div)))) 94 1350000 / ((val) * (div))))
95 95
96/* for temp */ 96/* for temp */
97#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val) < 0 ? (val)+0x100*1000 \ 97#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val) < 0 ? \
98 : (val)) / 1000, 0, 0xff)) 98 (val) + 0x100 * 1000 \
99#define TEMP_FROM_REG(val) (((val) & 0x80 ? (val)-0x100 : (val)) * 1000) 99 : (val)) / 1000, 0, 0xff))
100 100#define TEMP_FROM_REG(val) (((val) & 0x80 ? \
101/* The analog voltage inputs have 8mV LSB. Since the sysfs output is 101 (val) - 0x100 : (val)) * 1000)
102 in mV as would be measured on the chip input pin, need to just 102
103 multiply/divide by 8 to translate from/to register values. */ 103/*
104#define IN_TO_REG(val) (SENSORS_LIMIT((((val) + 4) / 8), 0, 255)) 104 * The analog voltage inputs have 8mV LSB. Since the sysfs output is
105 * in mV as would be measured on the chip input pin, need to just
106 * multiply/divide by 8 to translate from/to register values.
107 */
108#define IN_TO_REG(val) (SENSORS_LIMIT((((val) + 4) / 8), 0, 255))
105#define IN_FROM_REG(val) ((val) * 8) 109#define IN_FROM_REG(val) ((val) * 8)
106 110
107#define DIV_FROM_REG(val) (1 << (val)) 111#define DIV_FROM_REG(val) (1 << (val))
@@ -116,7 +120,7 @@ DIV_TO_REG(long val)
116 break; 120 break;
117 val >>= 1; 121 val >>= 1;
118 } 122 }
119 return ((u8) i); 123 return (u8)i;
120} 124}
121 125
122struct w83l786ng_data { 126struct w83l786ng_data {
@@ -125,7 +129,7 @@ struct w83l786ng_data {
125 char valid; /* !=0 if following fields are valid */ 129 char valid; /* !=0 if following fields are valid */
126 unsigned long last_updated; /* In jiffies */ 130 unsigned long last_updated; /* In jiffies */
127 unsigned long last_nonvolatile; /* In jiffies, last time we update the 131 unsigned long last_nonvolatile; /* In jiffies, last time we update the
128 nonvolatile registers */ 132 * nonvolatile registers */
129 133
130 u8 in[3]; 134 u8 in[3];
131 u8 in_max[3]; 135 u8 in_max[3];
@@ -137,10 +141,10 @@ struct w83l786ng_data {
137 u8 temp[2][3]; 141 u8 temp[2][3];
138 u8 pwm[2]; 142 u8 pwm[2];
139 u8 pwm_mode[2]; /* 0->DC variable voltage 143 u8 pwm_mode[2]; /* 0->DC variable voltage
140 1->PWM variable duty cycle */ 144 * 1->PWM variable duty cycle */
141 145
142 u8 pwm_enable[2]; /* 1->manual 146 u8 pwm_enable[2]; /* 1->manual
143 2->thermal cruise (also called SmartFan I) */ 147 * 2->thermal cruise (also called SmartFan I) */
144 u8 tolerance[2]; 148 u8 tolerance[2];
145}; 149};
146 150
@@ -186,11 +190,11 @@ w83l786ng_write_value(struct i2c_client *client, u8 reg, u8 value)
186#define show_in_reg(reg) \ 190#define show_in_reg(reg) \
187static ssize_t \ 191static ssize_t \
188show_##reg(struct device *dev, struct device_attribute *attr, \ 192show_##reg(struct device *dev, struct device_attribute *attr, \
189 char *buf) \ 193 char *buf) \
190{ \ 194{ \
191 int nr = to_sensor_dev_attr(attr)->index; \ 195 int nr = to_sensor_dev_attr(attr)->index; \
192 struct w83l786ng_data *data = w83l786ng_update_device(dev); \ 196 struct w83l786ng_data *data = w83l786ng_update_device(dev); \
193 return sprintf(buf,"%d\n", IN_FROM_REG(data->reg[nr])); \ 197 return sprintf(buf, "%d\n", IN_FROM_REG(data->reg[nr])); \
194} 198}
195 199
196show_in_reg(in) 200show_in_reg(in)
@@ -199,13 +203,16 @@ show_in_reg(in_max)
199 203
200#define store_in_reg(REG, reg) \ 204#define store_in_reg(REG, reg) \
201static ssize_t \ 205static ssize_t \
202store_in_##reg (struct device *dev, struct device_attribute *attr, \ 206store_in_##reg(struct device *dev, struct device_attribute *attr, \
203 const char *buf, size_t count) \ 207 const char *buf, size_t count) \
204{ \ 208{ \
205 int nr = to_sensor_dev_attr(attr)->index; \ 209 int nr = to_sensor_dev_attr(attr)->index; \
206 struct i2c_client *client = to_i2c_client(dev); \ 210 struct i2c_client *client = to_i2c_client(dev); \
207 struct w83l786ng_data *data = i2c_get_clientdata(client); \ 211 struct w83l786ng_data *data = i2c_get_clientdata(client); \
208 unsigned long val = simple_strtoul(buf, NULL, 10); \ 212 unsigned long val; \
213 int err = kstrtoul(buf, 10, &val); \
214 if (err) \
215 return err; \
209 mutex_lock(&data->update_lock); \ 216 mutex_lock(&data->update_lock); \
210 data->in_##reg[nr] = IN_TO_REG(val); \ 217 data->in_##reg[nr] = IN_TO_REG(val); \
211 w83l786ng_write_value(client, W83L786NG_REG_IN_##REG(nr), \ 218 w83l786ng_write_value(client, W83L786NG_REG_IN_##REG(nr), \
@@ -241,8 +248,8 @@ static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
241{ \ 248{ \
242 int nr = to_sensor_dev_attr(attr)->index; \ 249 int nr = to_sensor_dev_attr(attr)->index; \
243 struct w83l786ng_data *data = w83l786ng_update_device(dev); \ 250 struct w83l786ng_data *data = w83l786ng_update_device(dev); \
244 return sprintf(buf,"%d\n", \ 251 return sprintf(buf, "%d\n", \
245 FAN_FROM_REG(data->fan[nr], DIV_FROM_REG(data->fan_div[nr]))); \ 252 FAN_FROM_REG(data->fan[nr], DIV_FROM_REG(data->fan_div[nr]))); \
246} 253}
247 254
248show_fan_reg(fan); 255show_fan_reg(fan);
@@ -255,9 +262,13 @@ store_fan_min(struct device *dev, struct device_attribute *attr,
255 int nr = to_sensor_dev_attr(attr)->index; 262 int nr = to_sensor_dev_attr(attr)->index;
256 struct i2c_client *client = to_i2c_client(dev); 263 struct i2c_client *client = to_i2c_client(dev);
257 struct w83l786ng_data *data = i2c_get_clientdata(client); 264 struct w83l786ng_data *data = i2c_get_clientdata(client);
258 u32 val; 265 unsigned long val;
266 int err;
267
268 err = kstrtoul(buf, 10, &val);
269 if (err)
270 return err;
259 271
260 val = simple_strtoul(buf, NULL, 10);
261 mutex_lock(&data->update_lock); 272 mutex_lock(&data->update_lock);
262 data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); 273 data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
263 w83l786ng_write_value(client, W83L786NG_REG_FAN_MIN(nr), 274 w83l786ng_write_value(client, W83L786NG_REG_FAN_MIN(nr),
@@ -276,10 +287,12 @@ show_fan_div(struct device *dev, struct device_attribute *attr,
276 return sprintf(buf, "%u\n", DIV_FROM_REG(data->fan_div[nr])); 287 return sprintf(buf, "%u\n", DIV_FROM_REG(data->fan_div[nr]));
277} 288}
278 289
279/* Note: we save and restore the fan minimum here, because its value is 290/*
280 determined in part by the fan divisor. This follows the principle of 291 * Note: we save and restore the fan minimum here, because its value is
281 least surprise; the user doesn't expect the fan minimum to change just 292 * determined in part by the fan divisor. This follows the principle of
282 because the divisor changed. */ 293 * least surprise; the user doesn't expect the fan minimum to change just
294 * because the divisor changed.
295 */
283static ssize_t 296static ssize_t
284store_fan_div(struct device *dev, struct device_attribute *attr, 297store_fan_div(struct device *dev, struct device_attribute *attr,
285 const char *buf, size_t count) 298 const char *buf, size_t count)
@@ -294,11 +307,18 @@ store_fan_div(struct device *dev, struct device_attribute *attr,
294 u8 keep_mask = 0; 307 u8 keep_mask = 0;
295 u8 new_shift = 0; 308 u8 new_shift = 0;
296 309
310 unsigned long val;
311 int err;
312
313 err = kstrtoul(buf, 10, &val);
314 if (err)
315 return err;
316
297 /* Save fan_min */ 317 /* Save fan_min */
298 mutex_lock(&data->update_lock); 318 mutex_lock(&data->update_lock);
299 min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); 319 min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr]));
300 320
301 data->fan_div[nr] = DIV_TO_REG(simple_strtoul(buf, NULL, 10)); 321 data->fan_div[nr] = DIV_TO_REG(val);
302 322
303 switch (nr) { 323 switch (nr) {
304 case 0: 324 case 0:
@@ -371,16 +391,20 @@ store_temp(struct device *dev, struct device_attribute *attr,
371 int index = sensor_attr->index; 391 int index = sensor_attr->index;
372 struct i2c_client *client = to_i2c_client(dev); 392 struct i2c_client *client = to_i2c_client(dev);
373 struct w83l786ng_data *data = i2c_get_clientdata(client); 393 struct w83l786ng_data *data = i2c_get_clientdata(client);
374 s32 val; 394 long val;
395 int err;
396
397 err = kstrtol(buf, 10, &val);
398 if (err)
399 return err;
375 400
376 val = simple_strtol(buf, NULL, 10);
377 mutex_lock(&data->update_lock); 401 mutex_lock(&data->update_lock);
378 data->temp[nr][index] = TEMP_TO_REG(val); 402 data->temp[nr][index] = TEMP_TO_REG(val);
379 w83l786ng_write_value(client, W83L786NG_REG_TEMP[nr][index], 403 w83l786ng_write_value(client, W83L786NG_REG_TEMP[nr][index],
380 data->temp[nr][index]); 404 data->temp[nr][index]);
381 mutex_unlock(&data->update_lock); 405 mutex_unlock(&data->update_lock);
382 406
383 return count; 407 return count;
384} 408}
385 409
386static struct sensor_device_attribute_2 sda_temp_input[] = { 410static struct sensor_device_attribute_2 sda_temp_input[] = {
@@ -403,8 +427,8 @@ static struct sensor_device_attribute_2 sda_temp_max_hyst[] = {
403}; 427};
404 428
405#define show_pwm_reg(reg) \ 429#define show_pwm_reg(reg) \
406static ssize_t show_##reg (struct device *dev, struct device_attribute *attr, \ 430static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
407 char *buf) \ 431 char *buf) \
408{ \ 432{ \
409 struct w83l786ng_data *data = w83l786ng_update_device(dev); \ 433 struct w83l786ng_data *data = w83l786ng_update_device(dev); \
410 int nr = to_sensor_dev_attr(attr)->index; \ 434 int nr = to_sensor_dev_attr(attr)->index; \
@@ -422,8 +446,13 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr,
422 int nr = to_sensor_dev_attr(attr)->index; 446 int nr = to_sensor_dev_attr(attr)->index;
423 struct i2c_client *client = to_i2c_client(dev); 447 struct i2c_client *client = to_i2c_client(dev);
424 struct w83l786ng_data *data = i2c_get_clientdata(client); 448 struct w83l786ng_data *data = i2c_get_clientdata(client);
425 u32 val = simple_strtoul(buf, NULL, 10);
426 u8 reg; 449 u8 reg;
450 unsigned long val;
451 int err;
452
453 err = kstrtoul(buf, 10, &val);
454 if (err)
455 return err;
427 456
428 if (val > 1) 457 if (val > 1)
429 return -EINVAL; 458 return -EINVAL;
@@ -445,7 +474,13 @@ store_pwm(struct device *dev, struct device_attribute *attr,
445 int nr = to_sensor_dev_attr(attr)->index; 474 int nr = to_sensor_dev_attr(attr)->index;
446 struct i2c_client *client = to_i2c_client(dev); 475 struct i2c_client *client = to_i2c_client(dev);
447 struct w83l786ng_data *data = i2c_get_clientdata(client); 476 struct w83l786ng_data *data = i2c_get_clientdata(client);
448 u32 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 0, 255); 477 unsigned long val;
478 int err;
479
480 err = kstrtoul(buf, 10, &val);
481 if (err)
482 return err;
483 val = SENSORS_LIMIT(val, 0, 255);
449 484
450 mutex_lock(&data->update_lock); 485 mutex_lock(&data->update_lock);
451 data->pwm[nr] = val; 486 data->pwm[nr] = val;
@@ -461,11 +496,15 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr,
461 int nr = to_sensor_dev_attr(attr)->index; 496 int nr = to_sensor_dev_attr(attr)->index;
462 struct i2c_client *client = to_i2c_client(dev); 497 struct i2c_client *client = to_i2c_client(dev);
463 struct w83l786ng_data *data = i2c_get_clientdata(client); 498 struct w83l786ng_data *data = i2c_get_clientdata(client);
464 u32 val = simple_strtoul(buf, NULL, 10);
465
466 u8 reg; 499 u8 reg;
500 unsigned long val;
501 int err;
467 502
468 if (!val || (val > 2)) /* only modes 1 and 2 are supported */ 503 err = kstrtoul(buf, 10, &val);
504 if (err)
505 return err;
506
507 if (!val || val > 2) /* only modes 1 and 2 are supported */
469 return -EINVAL; 508 return -EINVAL;
470 509
471 mutex_lock(&data->update_lock); 510 mutex_lock(&data->update_lock);
@@ -513,10 +552,13 @@ store_tolerance(struct device *dev, struct device_attribute *attr,
513 int nr = to_sensor_dev_attr(attr)->index; 552 int nr = to_sensor_dev_attr(attr)->index;
514 struct i2c_client *client = to_i2c_client(dev); 553 struct i2c_client *client = to_i2c_client(dev);
515 struct w83l786ng_data *data = i2c_get_clientdata(client); 554 struct w83l786ng_data *data = i2c_get_clientdata(client);
516 u32 val;
517 u8 tol_tmp, tol_mask; 555 u8 tol_tmp, tol_mask;
556 unsigned long val;
557 int err;
518 558
519 val = simple_strtoul(buf, NULL, 10); 559 err = kstrtoul(buf, 10, &val);
560 if (err)
561 return err;
520 562
521 mutex_lock(&data->update_lock); 563 mutex_lock(&data->update_lock);
522 tol_mask = w83l786ng_read_value(client, 564 tol_mask = w83l786ng_read_value(client,
@@ -524,9 +566,8 @@ store_tolerance(struct device *dev, struct device_attribute *attr,
524 tol_tmp = SENSORS_LIMIT(val, 0, 15); 566 tol_tmp = SENSORS_LIMIT(val, 0, 15);
525 tol_tmp &= 0x0f; 567 tol_tmp &= 0x0f;
526 data->tolerance[nr] = tol_tmp; 568 data->tolerance[nr] = tol_tmp;
527 if (nr == 1) { 569 if (nr == 1)
528 tol_tmp <<= 4; 570 tol_tmp <<= 4;
529 }
530 571
531 w83l786ng_write_value(client, W83L786NG_REG_TOLERANCE, 572 w83l786ng_write_value(client, W83L786NG_REG_TOLERANCE,
532 tol_mask | tol_tmp); 573 tol_mask | tol_tmp);
@@ -591,9 +632,8 @@ w83l786ng_detect(struct i2c_client *client, struct i2c_board_info *info)
591 u16 man_id; 632 u16 man_id;
592 u8 chip_id; 633 u8 chip_id;
593 634
594 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { 635 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
595 return -ENODEV; 636 return -ENODEV;
596 }
597 637
598 /* Detection */ 638 /* Detection */
599 if ((w83l786ng_read_value(client, W83L786NG_REG_CONFIG) & 0x80)) { 639 if ((w83l786ng_read_value(client, W83L786NG_REG_CONFIG) & 0x80)) {
@@ -652,7 +692,8 @@ w83l786ng_probe(struct i2c_client *client, const struct i2c_device_id *id)
652 data->fan_div[1] = (reg_tmp >> 4) & 0x07; 692 data->fan_div[1] = (reg_tmp >> 4) & 0x07;
653 693
654 /* Register sysfs hooks */ 694 /* Register sysfs hooks */
655 if ((err = sysfs_create_group(&client->dev.kobj, &w83l786ng_group))) 695 err = sysfs_create_group(&client->dev.kobj, &w83l786ng_group);
696 if (err)
656 goto exit_remove; 697 goto exit_remove;
657 698
658 data->hwmon_dev = hwmon_device_register(dev); 699 data->hwmon_dev = hwmon_device_register(dev);
@@ -769,21 +810,8 @@ static struct w83l786ng_data *w83l786ng_update_device(struct device *dev)
769 return data; 810 return data;
770} 811}
771 812
772static int __init 813module_i2c_driver(w83l786ng_driver);
773sensors_w83l786ng_init(void)
774{
775 return i2c_add_driver(&w83l786ng_driver);
776}
777
778static void __exit
779sensors_w83l786ng_exit(void)
780{
781 i2c_del_driver(&w83l786ng_driver);
782}
783 814
784MODULE_AUTHOR("Kevin Lo"); 815MODULE_AUTHOR("Kevin Lo");
785MODULE_DESCRIPTION("w83l786ng driver"); 816MODULE_DESCRIPTION("w83l786ng driver");
786MODULE_LICENSE("GPL"); 817MODULE_LICENSE("GPL");
787
788module_init(sensors_w83l786ng_init);
789module_exit(sensors_w83l786ng_exit);