diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/hwmon/emc2103.c | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'drivers/hwmon/emc2103.c')
-rw-r--r-- | drivers/hwmon/emc2103.c | 99 |
1 files changed, 52 insertions, 47 deletions
diff --git a/drivers/hwmon/emc2103.c b/drivers/hwmon/emc2103.c index 77f434c5823..af914ad93ec 100644 --- a/drivers/hwmon/emc2103.c +++ b/drivers/hwmon/emc2103.c | |||
@@ -1,21 +1,21 @@ | |||
1 | /* | 1 | /* |
2 | * emc2103.c - Support for SMSC EMC2103 | 2 | emc2103.c - Support for SMSC EMC2103 |
3 | * Copyright (c) 2010 SMSC | 3 | Copyright (c) 2010 SMSC |
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; either version 2 of the License, or | 7 | the Free Software Foundation; either version 2 of the License, or |
8 | * (at your option) any later version. | 8 | (at your option) any later version. |
9 | * | 9 | |
10 | * This program is distributed in the hope that it will be useful, | 10 | This program is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | * GNU General Public License for more details. | 13 | GNU General Public License for more details. |
14 | * | 14 | |
15 | * You should have received a copy of the GNU General Public License | 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 | 16 | along with this program; if not, write to the Free Software |
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
@@ -48,16 +48,14 @@ static const u8 REG_TEMP_MAX[4] = { 0x34, 0x30, 0x31, 0x32 }; | |||
48 | /* equation 4 from datasheet: rpm = (3932160 * multipler) / count */ | 48 | /* equation 4 from datasheet: rpm = (3932160 * multipler) / count */ |
49 | #define FAN_RPM_FACTOR 3932160 | 49 | #define FAN_RPM_FACTOR 3932160 |
50 | 50 | ||
51 | /* | 51 | /* 2103-2 and 2103-4's 3rd temperature sensor can be connected to two diodes |
52 | * 2103-2 and 2103-4's 3rd temperature sensor can be connected to two diodes | ||
53 | * in anti-parallel mode, and in this configuration both can be read | 52 | * in anti-parallel mode, and in this configuration both can be read |
54 | * independently (so we have 4 temperature inputs). The device can't | 53 | * independently (so we have 4 temperature inputs). The device can't |
55 | * detect if it's connected in this mode, so we have to manually enable | 54 | * detect if it's connected in this mode, so we have to manually enable |
56 | * it. Default is to leave the device in the state it's already in (-1). | 55 | * it. Default is to leave the device in the state it's already in (-1). |
57 | * This parameter allows APD mode to be optionally forced on or off | 56 | * This parameter allows APD mode to be optionally forced on or off */ |
58 | */ | ||
59 | static int apd = -1; | 57 | static int apd = -1; |
60 | module_param(apd, bint, 0); | 58 | module_param(apd, bool, 0); |
61 | MODULE_PARM_DESC(init, "Set to zero to disable anti-parallel diode mode"); | 59 | MODULE_PARM_DESC(init, "Set to zero to disable anti-parallel diode mode"); |
62 | 60 | ||
63 | struct temperature { | 61 | struct temperature { |
@@ -246,7 +244,7 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *da, | |||
246 | struct emc2103_data *data = i2c_get_clientdata(client); | 244 | struct emc2103_data *data = i2c_get_clientdata(client); |
247 | long val; | 245 | long val; |
248 | 246 | ||
249 | int result = kstrtol(buf, 10, &val); | 247 | int result = strict_strtol(buf, 10, &val); |
250 | if (result < 0) | 248 | if (result < 0) |
251 | return -EINVAL; | 249 | return -EINVAL; |
252 | 250 | ||
@@ -270,7 +268,7 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *da, | |||
270 | struct emc2103_data *data = i2c_get_clientdata(client); | 268 | struct emc2103_data *data = i2c_get_clientdata(client); |
271 | long val; | 269 | long val; |
272 | 270 | ||
273 | int result = kstrtol(buf, 10, &val); | 271 | int result = strict_strtol(buf, 10, &val); |
274 | if (result < 0) | 272 | if (result < 0) |
275 | return -EINVAL; | 273 | return -EINVAL; |
276 | 274 | ||
@@ -304,12 +302,10 @@ show_fan_div(struct device *dev, struct device_attribute *da, char *buf) | |||
304 | return sprintf(buf, "%d\n", fan_div); | 302 | return sprintf(buf, "%d\n", fan_div); |
305 | } | 303 | } |
306 | 304 | ||
307 | /* | 305 | /* Note: we also update the fan target here, because its value is |
308 | * Note: we also update the fan target here, because its value is | 306 | determined in part by the fan clock divider. This follows the principle |
309 | * determined in part by the fan clock divider. This follows the principle | 307 | of least surprise; the user doesn't expect the fan target to change just |
310 | * of least surprise; the user doesn't expect the fan target to change just | 308 | because the divider changed. */ |
311 | * because the divider changed. | ||
312 | */ | ||
313 | static ssize_t set_fan_div(struct device *dev, struct device_attribute *da, | 309 | static ssize_t set_fan_div(struct device *dev, struct device_attribute *da, |
314 | const char *buf, size_t count) | 310 | const char *buf, size_t count) |
315 | { | 311 | { |
@@ -318,7 +314,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *da, | |||
318 | int new_range_bits, old_div = 8 / data->fan_multiplier; | 314 | int new_range_bits, old_div = 8 / data->fan_multiplier; |
319 | long new_div; | 315 | long new_div; |
320 | 316 | ||
321 | int status = kstrtol(buf, 10, &new_div); | 317 | int status = strict_strtol(buf, 10, &new_div); |
322 | if (status < 0) | 318 | if (status < 0) |
323 | return -EINVAL; | 319 | return -EINVAL; |
324 | 320 | ||
@@ -392,7 +388,7 @@ static ssize_t set_fan_target(struct device *dev, struct device_attribute *da, | |||
392 | struct i2c_client *client = to_i2c_client(dev); | 388 | struct i2c_client *client = to_i2c_client(dev); |
393 | long rpm_target; | 389 | long rpm_target; |
394 | 390 | ||
395 | int result = kstrtol(buf, 10, &rpm_target); | 391 | int result = strict_strtol(buf, 10, &rpm_target); |
396 | if (result < 0) | 392 | if (result < 0) |
397 | return -EINVAL; | 393 | return -EINVAL; |
398 | 394 | ||
@@ -438,7 +434,7 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *da, | |||
438 | long new_value; | 434 | long new_value; |
439 | u8 conf_reg; | 435 | u8 conf_reg; |
440 | 436 | ||
441 | int result = kstrtol(buf, 10, &new_value); | 437 | int result = strict_strtol(buf, 10, &new_value); |
442 | if (result < 0) | 438 | if (result < 0) |
443 | return -EINVAL; | 439 | return -EINVAL; |
444 | 440 | ||
@@ -451,15 +447,11 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *da, | |||
451 | data->fan_rpm_control = true; | 447 | data->fan_rpm_control = true; |
452 | break; | 448 | break; |
453 | default: | 449 | default: |
454 | count = -EINVAL; | 450 | mutex_unlock(&data->update_lock); |
455 | goto err; | 451 | return -EINVAL; |
456 | } | 452 | } |
457 | 453 | ||
458 | result = read_u8_from_i2c(client, REG_FAN_CONF1, &conf_reg); | 454 | read_u8_from_i2c(client, REG_FAN_CONF1, &conf_reg); |
459 | if (result) { | ||
460 | count = result; | ||
461 | goto err; | ||
462 | } | ||
463 | 455 | ||
464 | if (data->fan_rpm_control) | 456 | if (data->fan_rpm_control) |
465 | conf_reg |= 0x80; | 457 | conf_reg |= 0x80; |
@@ -467,7 +459,7 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *da, | |||
467 | conf_reg &= ~0x80; | 459 | conf_reg &= ~0x80; |
468 | 460 | ||
469 | i2c_smbus_write_byte_data(client, REG_FAN_CONF1, conf_reg); | 461 | i2c_smbus_write_byte_data(client, REG_FAN_CONF1, conf_reg); |
470 | err: | 462 | |
471 | mutex_unlock(&data->update_lock); | 463 | mutex_unlock(&data->update_lock); |
472 | return count; | 464 | return count; |
473 | } | 465 | } |
@@ -590,8 +582,7 @@ emc2103_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
590 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 582 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
591 | return -EIO; | 583 | return -EIO; |
592 | 584 | ||
593 | data = devm_kzalloc(&client->dev, sizeof(struct emc2103_data), | 585 | data = kzalloc(sizeof(struct emc2103_data), GFP_KERNEL); |
594 | GFP_KERNEL); | ||
595 | if (!data) | 586 | if (!data) |
596 | return -ENOMEM; | 587 | return -ENOMEM; |
597 | 588 | ||
@@ -609,7 +600,7 @@ emc2103_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
609 | if (status < 0) { | 600 | if (status < 0) { |
610 | dev_dbg(&client->dev, "reg 0x%02x, err %d\n", REG_CONF1, | 601 | dev_dbg(&client->dev, "reg 0x%02x, err %d\n", REG_CONF1, |
611 | status); | 602 | status); |
612 | return status; | 603 | goto exit_free; |
613 | } | 604 | } |
614 | 605 | ||
615 | /* detect current state of hardware */ | 606 | /* detect current state of hardware */ |
@@ -632,7 +623,7 @@ emc2103_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
632 | /* Register sysfs hooks */ | 623 | /* Register sysfs hooks */ |
633 | status = sysfs_create_group(&client->dev.kobj, &emc2103_group); | 624 | status = sysfs_create_group(&client->dev.kobj, &emc2103_group); |
634 | if (status) | 625 | if (status) |
635 | return status; | 626 | goto exit_free; |
636 | 627 | ||
637 | if (data->temp_count >= 3) { | 628 | if (data->temp_count >= 3) { |
638 | status = sysfs_create_group(&client->dev.kobj, | 629 | status = sysfs_create_group(&client->dev.kobj, |
@@ -667,6 +658,8 @@ exit_remove_temp3: | |||
667 | sysfs_remove_group(&client->dev.kobj, &emc2103_temp3_group); | 658 | sysfs_remove_group(&client->dev.kobj, &emc2103_temp3_group); |
668 | exit_remove: | 659 | exit_remove: |
669 | sysfs_remove_group(&client->dev.kobj, &emc2103_group); | 660 | sysfs_remove_group(&client->dev.kobj, &emc2103_group); |
661 | exit_free: | ||
662 | kfree(data); | ||
670 | return status; | 663 | return status; |
671 | } | 664 | } |
672 | 665 | ||
@@ -684,6 +677,7 @@ static int emc2103_remove(struct i2c_client *client) | |||
684 | 677 | ||
685 | sysfs_remove_group(&client->dev.kobj, &emc2103_group); | 678 | sysfs_remove_group(&client->dev.kobj, &emc2103_group); |
686 | 679 | ||
680 | kfree(data); | ||
687 | return 0; | 681 | return 0; |
688 | } | 682 | } |
689 | 683 | ||
@@ -728,8 +722,19 @@ static struct i2c_driver emc2103_driver = { | |||
728 | .address_list = normal_i2c, | 722 | .address_list = normal_i2c, |
729 | }; | 723 | }; |
730 | 724 | ||
731 | module_i2c_driver(emc2103_driver); | 725 | static int __init sensors_emc2103_init(void) |
726 | { | ||
727 | return i2c_add_driver(&emc2103_driver); | ||
728 | } | ||
732 | 729 | ||
733 | MODULE_AUTHOR("Steve Glendinning <steve.glendinning@shawell.net>"); | 730 | static void __exit sensors_emc2103_exit(void) |
731 | { | ||
732 | i2c_del_driver(&emc2103_driver); | ||
733 | } | ||
734 | |||
735 | MODULE_AUTHOR("Steve Glendinning <steve.glendinning@smsc.com>"); | ||
734 | MODULE_DESCRIPTION("SMSC EMC2103 hwmon driver"); | 736 | MODULE_DESCRIPTION("SMSC EMC2103 hwmon driver"); |
735 | MODULE_LICENSE("GPL"); | 737 | MODULE_LICENSE("GPL"); |
738 | |||
739 | module_init(sensors_emc2103_init); | ||
740 | module_exit(sensors_emc2103_exit); | ||