diff options
Diffstat (limited to 'drivers/hwmon/w83l786ng.c')
-rw-r--r-- | drivers/hwmon/w83l786ng.c | 190 |
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 | ||
122 | struct w83l786ng_data { | 126 | struct 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) \ |
187 | static ssize_t \ | 191 | static ssize_t \ |
188 | show_##reg(struct device *dev, struct device_attribute *attr, \ | 192 | show_##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 | ||
196 | show_in_reg(in) | 200 | show_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) \ |
201 | static ssize_t \ | 205 | static ssize_t \ |
202 | store_in_##reg (struct device *dev, struct device_attribute *attr, \ | 206 | store_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 | ||
248 | show_fan_reg(fan); | 255 | show_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 | */ | ||
283 | static ssize_t | 296 | static ssize_t |
284 | store_fan_div(struct device *dev, struct device_attribute *attr, | 297 | store_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 | ||
386 | static struct sensor_device_attribute_2 sda_temp_input[] = { | 410 | static 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) \ |
406 | static ssize_t show_##reg (struct device *dev, struct device_attribute *attr, \ | 430 | static 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 | ||
772 | static int __init | 813 | module_i2c_driver(w83l786ng_driver); |
773 | sensors_w83l786ng_init(void) | ||
774 | { | ||
775 | return i2c_add_driver(&w83l786ng_driver); | ||
776 | } | ||
777 | |||
778 | static void __exit | ||
779 | sensors_w83l786ng_exit(void) | ||
780 | { | ||
781 | i2c_del_driver(&w83l786ng_driver); | ||
782 | } | ||
783 | 814 | ||
784 | MODULE_AUTHOR("Kevin Lo"); | 815 | MODULE_AUTHOR("Kevin Lo"); |
785 | MODULE_DESCRIPTION("w83l786ng driver"); | 816 | MODULE_DESCRIPTION("w83l786ng driver"); |
786 | MODULE_LICENSE("GPL"); | 817 | MODULE_LICENSE("GPL"); |
787 | |||
788 | module_init(sensors_w83l786ng_init); | ||
789 | module_exit(sensors_w83l786ng_exit); | ||