diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-11-15 17:05:44 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-11-15 17:05:44 -0500 |
commit | 477d4e4fbedafb1cc636124f2de06defceb399b0 (patch) | |
tree | b855e5b1488f224c08ab2576d0c15e187842cba7 | |
parent | fe9d1159b299642f9e1a9b56bbf67a24c31bb418 (diff) | |
parent | 52d159eecced3e4ead901e2a14347f5c11ea4bab (diff) |
Merge branch 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging
* 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging:
hwmon: (w83795) Check for BEEP pin availability
hwmon: (w83795) Clear intrusion alarm immediately
hwmon: (w83795) Read the intrusion state properly
hwmon: (w83795) Print the actual temperature channels as sources
hwmon: (w83795) List all usable temperature sources
hwmon: (w83795) Expose fan control method
hwmon: (w83795) Fix fan control mode attributes
hwmon: (lm95241) Check validity of input values
hwmon: Change mail address of Hans J. Koch
-rw-r--r-- | drivers/hwmon/amc6821.c | 2 | ||||
-rw-r--r-- | drivers/hwmon/lm93.c | 4 | ||||
-rw-r--r-- | drivers/hwmon/lm95241.c | 19 | ||||
-rw-r--r-- | drivers/hwmon/max6650.c | 2 | ||||
-rw-r--r-- | drivers/hwmon/w83795.c | 207 |
5 files changed, 192 insertions, 42 deletions
diff --git a/drivers/hwmon/amc6821.c b/drivers/hwmon/amc6821.c index fa9708c2d723..4033974d1bb3 100644 --- a/drivers/hwmon/amc6821.c +++ b/drivers/hwmon/amc6821.c | |||
@@ -4,7 +4,7 @@ | |||
4 | Copyright (C) 2009 T. Mertelj <tomaz.mertelj@guest.arnes.si> | 4 | Copyright (C) 2009 T. Mertelj <tomaz.mertelj@guest.arnes.si> |
5 | 5 | ||
6 | Based on max6650.c: | 6 | Based on max6650.c: |
7 | Copyright (C) 2007 Hans J. Koch <hjk@linutronix.de> | 7 | Copyright (C) 2007 Hans J. Koch <hjk@hansjkoch.de> |
8 | 8 | ||
9 | This program is free software; you can redistribute it and/or modify | 9 | This program is free software; you can redistribute it and/or modify |
10 | it under the terms of the GNU General Public License as published by | 10 | it under the terms of the GNU General Public License as published by |
diff --git a/drivers/hwmon/lm93.c b/drivers/hwmon/lm93.c index 6669255aadcf..c9ed14eba5a6 100644 --- a/drivers/hwmon/lm93.c +++ b/drivers/hwmon/lm93.c | |||
@@ -20,7 +20,7 @@ | |||
20 | Adapted to 2.6.20 by Carsten Emde <cbe@osadl.org> | 20 | Adapted to 2.6.20 by Carsten Emde <cbe@osadl.org> |
21 | Copyright (c) 2006 Carsten Emde, Open Source Automation Development Lab | 21 | Copyright (c) 2006 Carsten Emde, Open Source Automation Development Lab |
22 | 22 | ||
23 | Modified for mainline integration by Hans J. Koch <hjk@linutronix.de> | 23 | Modified for mainline integration by Hans J. Koch <hjk@hansjkoch.de> |
24 | Copyright (c) 2007 Hans J. Koch, Linutronix GmbH | 24 | Copyright (c) 2007 Hans J. Koch, Linutronix GmbH |
25 | 25 | ||
26 | This program is free software; you can redistribute it and/or modify | 26 | This program is free software; you can redistribute it and/or modify |
@@ -2629,7 +2629,7 @@ static void __exit lm93_exit(void) | |||
2629 | } | 2629 | } |
2630 | 2630 | ||
2631 | MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>, " | 2631 | MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>, " |
2632 | "Hans J. Koch <hjk@linutronix.de"); | 2632 | "Hans J. Koch <hjk@hansjkoch.de>"); |
2633 | MODULE_DESCRIPTION("LM93 driver"); | 2633 | MODULE_DESCRIPTION("LM93 driver"); |
2634 | MODULE_LICENSE("GPL"); | 2634 | MODULE_LICENSE("GPL"); |
2635 | 2635 | ||
diff --git a/drivers/hwmon/lm95241.c b/drivers/hwmon/lm95241.c index 464340f25496..4546d82f024a 100644 --- a/drivers/hwmon/lm95241.c +++ b/drivers/hwmon/lm95241.c | |||
@@ -128,9 +128,12 @@ static ssize_t set_interval(struct device *dev, struct device_attribute *attr, | |||
128 | { | 128 | { |
129 | struct i2c_client *client = to_i2c_client(dev); | 129 | struct i2c_client *client = to_i2c_client(dev); |
130 | struct lm95241_data *data = i2c_get_clientdata(client); | 130 | struct lm95241_data *data = i2c_get_clientdata(client); |
131 | unsigned long val; | ||
131 | 132 | ||
132 | strict_strtol(buf, 10, &data->interval); | 133 | if (strict_strtoul(buf, 10, &val) < 0) |
133 | data->interval = data->interval * HZ / 1000; | 134 | return -EINVAL; |
135 | |||
136 | data->interval = val * HZ / 1000; | ||
134 | 137 | ||
135 | return count; | 138 | return count; |
136 | } | 139 | } |
@@ -188,7 +191,9 @@ static ssize_t set_type##flag(struct device *dev, \ | |||
188 | struct lm95241_data *data = i2c_get_clientdata(client); \ | 191 | struct lm95241_data *data = i2c_get_clientdata(client); \ |
189 | \ | 192 | \ |
190 | long val; \ | 193 | long val; \ |
191 | strict_strtol(buf, 10, &val); \ | 194 | \ |
195 | if (strict_strtol(buf, 10, &val) < 0) \ | ||
196 | return -EINVAL; \ | ||
192 | \ | 197 | \ |
193 | if ((val == 1) || (val == 2)) { \ | 198 | if ((val == 1) || (val == 2)) { \ |
194 | \ | 199 | \ |
@@ -227,7 +232,9 @@ static ssize_t set_min##flag(struct device *dev, \ | |||
227 | struct lm95241_data *data = i2c_get_clientdata(client); \ | 232 | struct lm95241_data *data = i2c_get_clientdata(client); \ |
228 | \ | 233 | \ |
229 | long val; \ | 234 | long val; \ |
230 | strict_strtol(buf, 10, &val); \ | 235 | \ |
236 | if (strict_strtol(buf, 10, &val) < 0) \ | ||
237 | return -EINVAL;\ | ||
231 | \ | 238 | \ |
232 | mutex_lock(&data->update_lock); \ | 239 | mutex_lock(&data->update_lock); \ |
233 | \ | 240 | \ |
@@ -256,7 +263,9 @@ static ssize_t set_max##flag(struct device *dev, \ | |||
256 | struct lm95241_data *data = i2c_get_clientdata(client); \ | 263 | struct lm95241_data *data = i2c_get_clientdata(client); \ |
257 | \ | 264 | \ |
258 | long val; \ | 265 | long val; \ |
259 | strict_strtol(buf, 10, &val); \ | 266 | \ |
267 | if (strict_strtol(buf, 10, &val) < 0) \ | ||
268 | return -EINVAL; \ | ||
260 | \ | 269 | \ |
261 | mutex_lock(&data->update_lock); \ | 270 | mutex_lock(&data->update_lock); \ |
262 | \ | 271 | \ |
diff --git a/drivers/hwmon/max6650.c b/drivers/hwmon/max6650.c index a0160ee5caef..9a11532ecae8 100644 --- a/drivers/hwmon/max6650.c +++ b/drivers/hwmon/max6650.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * max6650.c - Part of lm_sensors, Linux kernel modules for hardware | 2 | * max6650.c - Part of lm_sensors, Linux kernel modules for hardware |
3 | * monitoring. | 3 | * monitoring. |
4 | * | 4 | * |
5 | * (C) 2007 by Hans J. Koch <hjk@linutronix.de> | 5 | * (C) 2007 by Hans J. Koch <hjk@hansjkoch.de> |
6 | * | 6 | * |
7 | * based on code written by John Morris <john.morris@spirentcom.com> | 7 | * based on code written by John Morris <john.morris@spirentcom.com> |
8 | * Copyright (c) 2003 Spirent Communications | 8 | * Copyright (c) 2003 Spirent Communications |
diff --git a/drivers/hwmon/w83795.c b/drivers/hwmon/w83795.c index 1d840aa83782..cdbc7448491e 100644 --- a/drivers/hwmon/w83795.c +++ b/drivers/hwmon/w83795.c | |||
@@ -165,10 +165,14 @@ static const u8 IN_LSB_SHIFT_IDX[][2] = { | |||
165 | 165 | ||
166 | #define W83795_REG_VID_CTRL 0x6A | 166 | #define W83795_REG_VID_CTRL 0x6A |
167 | 167 | ||
168 | #define W83795_REG_ALARM_CTRL 0x40 | ||
169 | #define ALARM_CTRL_RTSACS (1 << 7) | ||
168 | #define W83795_REG_ALARM(index) (0x41 + (index)) | 170 | #define W83795_REG_ALARM(index) (0x41 + (index)) |
171 | #define W83795_REG_CLR_CHASSIS 0x4D | ||
169 | #define W83795_REG_BEEP(index) (0x50 + (index)) | 172 | #define W83795_REG_BEEP(index) (0x50 + (index)) |
170 | 173 | ||
171 | #define W83795_REG_CLR_CHASSIS 0x4D | 174 | #define W83795_REG_OVT_CFG 0x58 |
175 | #define OVT_CFG_SEL (1 << 7) | ||
172 | 176 | ||
173 | 177 | ||
174 | #define W83795_REG_FCMS1 0x201 | 178 | #define W83795_REG_FCMS1 0x201 |
@@ -178,6 +182,14 @@ static const u8 IN_LSB_SHIFT_IDX[][2] = { | |||
178 | 182 | ||
179 | #define W83795_REG_TSS(index) (0x209 + (index)) | 183 | #define W83795_REG_TSS(index) (0x209 + (index)) |
180 | 184 | ||
185 | #define TSS_MAP_RESERVED 0xff | ||
186 | static const u8 tss_map[4][6] = { | ||
187 | { 0, 1, 2, 3, 4, 5}, | ||
188 | { 6, 7, 8, 9, 0, 1}, | ||
189 | {10, 11, 12, 13, 2, 3}, | ||
190 | { 4, 5, 4, 5, TSS_MAP_RESERVED, TSS_MAP_RESERVED}, | ||
191 | }; | ||
192 | |||
181 | #define PWM_OUTPUT 0 | 193 | #define PWM_OUTPUT 0 |
182 | #define PWM_FREQ 1 | 194 | #define PWM_FREQ 1 |
183 | #define PWM_START 2 | 195 | #define PWM_START 2 |
@@ -369,6 +381,7 @@ struct w83795_data { | |||
369 | u8 setup_pwm[3]; /* Register value */ | 381 | u8 setup_pwm[3]; /* Register value */ |
370 | 382 | ||
371 | u8 alarms[6]; /* Register value */ | 383 | u8 alarms[6]; /* Register value */ |
384 | u8 enable_beep; | ||
372 | u8 beeps[6]; /* Register value */ | 385 | u8 beeps[6]; /* Register value */ |
373 | 386 | ||
374 | char valid; | 387 | char valid; |
@@ -499,8 +512,11 @@ static void w83795_update_limits(struct i2c_client *client) | |||
499 | } | 512 | } |
500 | 513 | ||
501 | /* Read beep settings */ | 514 | /* Read beep settings */ |
502 | for (i = 0; i < ARRAY_SIZE(data->beeps); i++) | 515 | if (data->enable_beep) { |
503 | data->beeps[i] = w83795_read(client, W83795_REG_BEEP(i)); | 516 | for (i = 0; i < ARRAY_SIZE(data->beeps); i++) |
517 | data->beeps[i] = | ||
518 | w83795_read(client, W83795_REG_BEEP(i)); | ||
519 | } | ||
504 | 520 | ||
505 | data->valid_limits = 1; | 521 | data->valid_limits = 1; |
506 | } | 522 | } |
@@ -577,6 +593,7 @@ static struct w83795_data *w83795_update_device(struct device *dev) | |||
577 | struct i2c_client *client = to_i2c_client(dev); | 593 | struct i2c_client *client = to_i2c_client(dev); |
578 | struct w83795_data *data = i2c_get_clientdata(client); | 594 | struct w83795_data *data = i2c_get_clientdata(client); |
579 | u16 tmp; | 595 | u16 tmp; |
596 | u8 intrusion; | ||
580 | int i; | 597 | int i; |
581 | 598 | ||
582 | mutex_lock(&data->update_lock); | 599 | mutex_lock(&data->update_lock); |
@@ -648,9 +665,24 @@ static struct w83795_data *w83795_update_device(struct device *dev) | |||
648 | w83795_read(client, W83795_REG_PWM(i, PWM_OUTPUT)); | 665 | w83795_read(client, W83795_REG_PWM(i, PWM_OUTPUT)); |
649 | } | 666 | } |
650 | 667 | ||
651 | /* update alarm */ | 668 | /* Update intrusion and alarms |
669 | * It is important to read intrusion first, because reading from | ||
670 | * register SMI STS6 clears the interrupt status temporarily. */ | ||
671 | tmp = w83795_read(client, W83795_REG_ALARM_CTRL); | ||
672 | /* Switch to interrupt status for intrusion if needed */ | ||
673 | if (tmp & ALARM_CTRL_RTSACS) | ||
674 | w83795_write(client, W83795_REG_ALARM_CTRL, | ||
675 | tmp & ~ALARM_CTRL_RTSACS); | ||
676 | intrusion = w83795_read(client, W83795_REG_ALARM(5)) & (1 << 6); | ||
677 | /* Switch to real-time alarms */ | ||
678 | w83795_write(client, W83795_REG_ALARM_CTRL, tmp | ALARM_CTRL_RTSACS); | ||
652 | for (i = 0; i < ARRAY_SIZE(data->alarms); i++) | 679 | for (i = 0; i < ARRAY_SIZE(data->alarms); i++) |
653 | data->alarms[i] = w83795_read(client, W83795_REG_ALARM(i)); | 680 | data->alarms[i] = w83795_read(client, W83795_REG_ALARM(i)); |
681 | data->alarms[5] |= intrusion; | ||
682 | /* Restore original configuration if needed */ | ||
683 | if (!(tmp & ALARM_CTRL_RTSACS)) | ||
684 | w83795_write(client, W83795_REG_ALARM_CTRL, | ||
685 | tmp & ~ALARM_CTRL_RTSACS); | ||
654 | 686 | ||
655 | data->last_updated = jiffies; | 687 | data->last_updated = jiffies; |
656 | data->valid = 1; | 688 | data->valid = 1; |
@@ -730,6 +762,10 @@ store_chassis_clear(struct device *dev, | |||
730 | val = w83795_read(client, W83795_REG_CLR_CHASSIS); | 762 | val = w83795_read(client, W83795_REG_CLR_CHASSIS); |
731 | val |= 0x80; | 763 | val |= 0x80; |
732 | w83795_write(client, W83795_REG_CLR_CHASSIS, val); | 764 | w83795_write(client, W83795_REG_CLR_CHASSIS, val); |
765 | |||
766 | /* Clear status and force cache refresh */ | ||
767 | w83795_read(client, W83795_REG_ALARM(5)); | ||
768 | data->valid = 0; | ||
733 | mutex_unlock(&data->update_lock); | 769 | mutex_unlock(&data->update_lock); |
734 | return count; | 770 | return count; |
735 | } | 771 | } |
@@ -857,20 +893,20 @@ show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf) | |||
857 | int index = sensor_attr->index; | 893 | int index = sensor_attr->index; |
858 | u8 tmp; | 894 | u8 tmp; |
859 | 895 | ||
860 | if (1 == (data->pwm_fcms[0] & (1 << index))) { | 896 | /* Speed cruise mode */ |
897 | if (data->pwm_fcms[0] & (1 << index)) { | ||
861 | tmp = 2; | 898 | tmp = 2; |
862 | goto out; | 899 | goto out; |
863 | } | 900 | } |
901 | /* Thermal cruise or SmartFan IV mode */ | ||
864 | for (tmp = 0; tmp < 6; tmp++) { | 902 | for (tmp = 0; tmp < 6; tmp++) { |
865 | if (data->pwm_tfmr[tmp] & (1 << index)) { | 903 | if (data->pwm_tfmr[tmp] & (1 << index)) { |
866 | tmp = 3; | 904 | tmp = 3; |
867 | goto out; | 905 | goto out; |
868 | } | 906 | } |
869 | } | 907 | } |
870 | if (data->pwm_fomc & (1 << index)) | 908 | /* Manual mode */ |
871 | tmp = 0; | 909 | tmp = 1; |
872 | else | ||
873 | tmp = 1; | ||
874 | 910 | ||
875 | out: | 911 | out: |
876 | return sprintf(buf, "%u\n", tmp); | 912 | return sprintf(buf, "%u\n", tmp); |
@@ -890,23 +926,21 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr, | |||
890 | 926 | ||
891 | if (strict_strtoul(buf, 10, &val) < 0) | 927 | if (strict_strtoul(buf, 10, &val) < 0) |
892 | return -EINVAL; | 928 | return -EINVAL; |
893 | if (val > 2) | 929 | if (val < 1 || val > 2) |
894 | return -EINVAL; | 930 | return -EINVAL; |
895 | 931 | ||
896 | mutex_lock(&data->update_lock); | 932 | mutex_lock(&data->update_lock); |
897 | switch (val) { | 933 | switch (val) { |
898 | case 0: | ||
899 | case 1: | 934 | case 1: |
935 | /* Clear speed cruise mode bits */ | ||
900 | data->pwm_fcms[0] &= ~(1 << index); | 936 | data->pwm_fcms[0] &= ~(1 << index); |
901 | w83795_write(client, W83795_REG_FCMS1, data->pwm_fcms[0]); | 937 | w83795_write(client, W83795_REG_FCMS1, data->pwm_fcms[0]); |
938 | /* Clear thermal cruise mode bits */ | ||
902 | for (i = 0; i < 6; i++) { | 939 | for (i = 0; i < 6; i++) { |
903 | data->pwm_tfmr[i] &= ~(1 << index); | 940 | data->pwm_tfmr[i] &= ~(1 << index); |
904 | w83795_write(client, W83795_REG_TFMR(i), | 941 | w83795_write(client, W83795_REG_TFMR(i), |
905 | data->pwm_tfmr[i]); | 942 | data->pwm_tfmr[i]); |
906 | } | 943 | } |
907 | data->pwm_fomc |= 1 << index; | ||
908 | data->pwm_fomc ^= val << index; | ||
909 | w83795_write(client, W83795_REG_FOMC, data->pwm_fomc); | ||
910 | break; | 944 | break; |
911 | case 2: | 945 | case 2: |
912 | data->pwm_fcms[0] |= (1 << index); | 946 | data->pwm_fcms[0] |= (1 << index); |
@@ -918,23 +952,60 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr, | |||
918 | } | 952 | } |
919 | 953 | ||
920 | static ssize_t | 954 | static ssize_t |
955 | show_pwm_mode(struct device *dev, struct device_attribute *attr, char *buf) | ||
956 | { | ||
957 | struct w83795_data *data = w83795_update_pwm_config(dev); | ||
958 | int index = to_sensor_dev_attr_2(attr)->index; | ||
959 | unsigned int mode; | ||
960 | |||
961 | if (data->pwm_fomc & (1 << index)) | ||
962 | mode = 0; /* DC */ | ||
963 | else | ||
964 | mode = 1; /* PWM */ | ||
965 | |||
966 | return sprintf(buf, "%u\n", mode); | ||
967 | } | ||
968 | |||
969 | /* | ||
970 | * Check whether a given temperature source can ever be useful. | ||
971 | * Returns the number of selectable temperature channels which are | ||
972 | * enabled. | ||
973 | */ | ||
974 | static int w83795_tss_useful(const struct w83795_data *data, int tsrc) | ||
975 | { | ||
976 | int useful = 0, i; | ||
977 | |||
978 | for (i = 0; i < 4; i++) { | ||
979 | if (tss_map[i][tsrc] == TSS_MAP_RESERVED) | ||
980 | continue; | ||
981 | if (tss_map[i][tsrc] < 6) /* Analog */ | ||
982 | useful += (data->has_temp >> tss_map[i][tsrc]) & 1; | ||
983 | else /* Digital */ | ||
984 | useful += (data->has_dts >> (tss_map[i][tsrc] - 6)) & 1; | ||
985 | } | ||
986 | |||
987 | return useful; | ||
988 | } | ||
989 | |||
990 | static ssize_t | ||
921 | show_temp_src(struct device *dev, struct device_attribute *attr, char *buf) | 991 | show_temp_src(struct device *dev, struct device_attribute *attr, char *buf) |
922 | { | 992 | { |
923 | struct sensor_device_attribute_2 *sensor_attr = | 993 | struct sensor_device_attribute_2 *sensor_attr = |
924 | to_sensor_dev_attr_2(attr); | 994 | to_sensor_dev_attr_2(attr); |
925 | struct w83795_data *data = w83795_update_pwm_config(dev); | 995 | struct w83795_data *data = w83795_update_pwm_config(dev); |
926 | int index = sensor_attr->index; | 996 | int index = sensor_attr->index; |
927 | u8 val = index / 2; | 997 | u8 tmp = data->temp_src[index / 2]; |
928 | u8 tmp = data->temp_src[val]; | ||
929 | 998 | ||
930 | if (index & 1) | 999 | if (index & 1) |
931 | val = 4; | 1000 | tmp >>= 4; /* Pick high nibble */ |
932 | else | 1001 | else |
933 | val = 0; | 1002 | tmp &= 0x0f; /* Pick low nibble */ |
934 | tmp >>= val; | ||
935 | tmp &= 0x0f; | ||
936 | 1003 | ||
937 | return sprintf(buf, "%u\n", tmp); | 1004 | /* Look-up the actual temperature channel number */ |
1005 | if (tmp >= 4 || tss_map[tmp][index] == TSS_MAP_RESERVED) | ||
1006 | return -EINVAL; /* Shouldn't happen */ | ||
1007 | |||
1008 | return sprintf(buf, "%u\n", (unsigned int)tss_map[tmp][index] + 1); | ||
938 | } | 1009 | } |
939 | 1010 | ||
940 | static ssize_t | 1011 | static ssize_t |
@@ -946,12 +1017,21 @@ store_temp_src(struct device *dev, struct device_attribute *attr, | |||
946 | struct sensor_device_attribute_2 *sensor_attr = | 1017 | struct sensor_device_attribute_2 *sensor_attr = |
947 | to_sensor_dev_attr_2(attr); | 1018 | to_sensor_dev_attr_2(attr); |
948 | int index = sensor_attr->index; | 1019 | int index = sensor_attr->index; |
949 | unsigned long tmp; | 1020 | int tmp; |
1021 | unsigned long channel; | ||
950 | u8 val = index / 2; | 1022 | u8 val = index / 2; |
951 | 1023 | ||
952 | if (strict_strtoul(buf, 10, &tmp) < 0) | 1024 | if (strict_strtoul(buf, 10, &channel) < 0 || |
1025 | channel < 1 || channel > 14) | ||
1026 | return -EINVAL; | ||
1027 | |||
1028 | /* Check if request can be fulfilled */ | ||
1029 | for (tmp = 0; tmp < 4; tmp++) { | ||
1030 | if (tss_map[tmp][index] == channel - 1) | ||
1031 | break; | ||
1032 | } | ||
1033 | if (tmp == 4) /* No match */ | ||
953 | return -EINVAL; | 1034 | return -EINVAL; |
954 | tmp = SENSORS_LIMIT(tmp, 0, 15); | ||
955 | 1035 | ||
956 | mutex_lock(&data->update_lock); | 1036 | mutex_lock(&data->update_lock); |
957 | if (index & 1) { | 1037 | if (index & 1) { |
@@ -1515,7 +1595,7 @@ store_sf_setup(struct device *dev, struct device_attribute *attr, | |||
1515 | 1595 | ||
1516 | #define NOT_USED -1 | 1596 | #define NOT_USED -1 |
1517 | 1597 | ||
1518 | /* Don't change the attribute order, _max and _min are accessed by index | 1598 | /* Don't change the attribute order, _max, _min and _beep are accessed by index |
1519 | * somewhere else in the code */ | 1599 | * somewhere else in the code */ |
1520 | #define SENSOR_ATTR_IN(index) { \ | 1600 | #define SENSOR_ATTR_IN(index) { \ |
1521 | SENSOR_ATTR_2(in##index##_input, S_IRUGO, show_in, NULL, \ | 1601 | SENSOR_ATTR_2(in##index##_input, S_IRUGO, show_in, NULL, \ |
@@ -1530,6 +1610,8 @@ store_sf_setup(struct device *dev, struct device_attribute *attr, | |||
1530 | show_alarm_beep, store_beep, BEEP_ENABLE, \ | 1610 | show_alarm_beep, store_beep, BEEP_ENABLE, \ |
1531 | index + ((index > 14) ? 1 : 0)) } | 1611 | index + ((index > 14) ? 1 : 0)) } |
1532 | 1612 | ||
1613 | /* Don't change the attribute order, _beep is accessed by index | ||
1614 | * somewhere else in the code */ | ||
1533 | #define SENSOR_ATTR_FAN(index) { \ | 1615 | #define SENSOR_ATTR_FAN(index) { \ |
1534 | SENSOR_ATTR_2(fan##index##_input, S_IRUGO, show_fan, \ | 1616 | SENSOR_ATTR_2(fan##index##_input, S_IRUGO, show_fan, \ |
1535 | NULL, FAN_INPUT, index - 1), \ | 1617 | NULL, FAN_INPUT, index - 1), \ |
@@ -1553,9 +1635,13 @@ store_sf_setup(struct device *dev, struct device_attribute *attr, | |||
1553 | show_pwm, store_pwm, PWM_FREQ, index - 1), \ | 1635 | show_pwm, store_pwm, PWM_FREQ, index - 1), \ |
1554 | SENSOR_ATTR_2(pwm##index##_enable, S_IWUSR | S_IRUGO, \ | 1636 | SENSOR_ATTR_2(pwm##index##_enable, S_IWUSR | S_IRUGO, \ |
1555 | show_pwm_enable, store_pwm_enable, NOT_USED, index - 1), \ | 1637 | show_pwm_enable, store_pwm_enable, NOT_USED, index - 1), \ |
1638 | SENSOR_ATTR_2(pwm##index##_mode, S_IRUGO, \ | ||
1639 | show_pwm_mode, NULL, NOT_USED, index - 1), \ | ||
1556 | SENSOR_ATTR_2(fan##index##_target, S_IWUSR | S_IRUGO, \ | 1640 | SENSOR_ATTR_2(fan##index##_target, S_IWUSR | S_IRUGO, \ |
1557 | show_fanin, store_fanin, FANIN_TARGET, index - 1) } | 1641 | show_fanin, store_fanin, FANIN_TARGET, index - 1) } |
1558 | 1642 | ||
1643 | /* Don't change the attribute order, _beep is accessed by index | ||
1644 | * somewhere else in the code */ | ||
1559 | #define SENSOR_ATTR_DTS(index) { \ | 1645 | #define SENSOR_ATTR_DTS(index) { \ |
1560 | SENSOR_ATTR_2(temp##index##_type, S_IRUGO , \ | 1646 | SENSOR_ATTR_2(temp##index##_type, S_IRUGO , \ |
1561 | show_dts_mode, NULL, NOT_USED, index - 7), \ | 1647 | show_dts_mode, NULL, NOT_USED, index - 7), \ |
@@ -1574,6 +1660,8 @@ store_sf_setup(struct device *dev, struct device_attribute *attr, | |||
1574 | SENSOR_ATTR_2(temp##index##_beep, S_IWUSR | S_IRUGO, \ | 1660 | SENSOR_ATTR_2(temp##index##_beep, S_IWUSR | S_IRUGO, \ |
1575 | show_alarm_beep, store_beep, BEEP_ENABLE, index + 17) } | 1661 | show_alarm_beep, store_beep, BEEP_ENABLE, index + 17) } |
1576 | 1662 | ||
1663 | /* Don't change the attribute order, _beep is accessed by index | ||
1664 | * somewhere else in the code */ | ||
1577 | #define SENSOR_ATTR_TEMP(index) { \ | 1665 | #define SENSOR_ATTR_TEMP(index) { \ |
1578 | SENSOR_ATTR_2(temp##index##_type, S_IRUGO | (index < 4 ? S_IWUSR : 0), \ | 1666 | SENSOR_ATTR_2(temp##index##_type, S_IRUGO | (index < 4 ? S_IWUSR : 0), \ |
1579 | show_temp_mode, store_temp_mode, NOT_USED, index - 1), \ | 1667 | show_temp_mode, store_temp_mode, NOT_USED, index - 1), \ |
@@ -1593,8 +1681,6 @@ store_sf_setup(struct device *dev, struct device_attribute *attr, | |||
1593 | SENSOR_ATTR_2(temp##index##_beep, S_IWUSR | S_IRUGO, \ | 1681 | SENSOR_ATTR_2(temp##index##_beep, S_IWUSR | S_IRUGO, \ |
1594 | show_alarm_beep, store_beep, BEEP_ENABLE, \ | 1682 | show_alarm_beep, store_beep, BEEP_ENABLE, \ |
1595 | index + (index > 4 ? 11 : 17)), \ | 1683 | index + (index > 4 ? 11 : 17)), \ |
1596 | SENSOR_ATTR_2(temp##index##_source_sel, S_IWUSR | S_IRUGO, \ | ||
1597 | show_temp_src, store_temp_src, NOT_USED, index - 1), \ | ||
1598 | SENSOR_ATTR_2(temp##index##_pwm_enable, S_IWUSR | S_IRUGO, \ | 1684 | SENSOR_ATTR_2(temp##index##_pwm_enable, S_IWUSR | S_IRUGO, \ |
1599 | show_temp_pwm_enable, store_temp_pwm_enable, \ | 1685 | show_temp_pwm_enable, store_temp_pwm_enable, \ |
1600 | TEMP_PWM_ENABLE, index - 1), \ | 1686 | TEMP_PWM_ENABLE, index - 1), \ |
@@ -1680,7 +1766,7 @@ static const struct sensor_device_attribute_2 w83795_fan[][4] = { | |||
1680 | SENSOR_ATTR_FAN(14), | 1766 | SENSOR_ATTR_FAN(14), |
1681 | }; | 1767 | }; |
1682 | 1768 | ||
1683 | static const struct sensor_device_attribute_2 w83795_temp[][29] = { | 1769 | static const struct sensor_device_attribute_2 w83795_temp[][28] = { |
1684 | SENSOR_ATTR_TEMP(1), | 1770 | SENSOR_ATTR_TEMP(1), |
1685 | SENSOR_ATTR_TEMP(2), | 1771 | SENSOR_ATTR_TEMP(2), |
1686 | SENSOR_ATTR_TEMP(3), | 1772 | SENSOR_ATTR_TEMP(3), |
@@ -1700,7 +1786,7 @@ static const struct sensor_device_attribute_2 w83795_dts[][8] = { | |||
1700 | SENSOR_ATTR_DTS(14), | 1786 | SENSOR_ATTR_DTS(14), |
1701 | }; | 1787 | }; |
1702 | 1788 | ||
1703 | static const struct sensor_device_attribute_2 w83795_pwm[][7] = { | 1789 | static const struct sensor_device_attribute_2 w83795_pwm[][8] = { |
1704 | SENSOR_ATTR_PWM(1), | 1790 | SENSOR_ATTR_PWM(1), |
1705 | SENSOR_ATTR_PWM(2), | 1791 | SENSOR_ATTR_PWM(2), |
1706 | SENSOR_ATTR_PWM(3), | 1792 | SENSOR_ATTR_PWM(3), |
@@ -1711,13 +1797,24 @@ static const struct sensor_device_attribute_2 w83795_pwm[][7] = { | |||
1711 | SENSOR_ATTR_PWM(8), | 1797 | SENSOR_ATTR_PWM(8), |
1712 | }; | 1798 | }; |
1713 | 1799 | ||
1800 | static const struct sensor_device_attribute_2 w83795_tss[6] = { | ||
1801 | SENSOR_ATTR_2(temp1_source_sel, S_IWUSR | S_IRUGO, | ||
1802 | show_temp_src, store_temp_src, NOT_USED, 0), | ||
1803 | SENSOR_ATTR_2(temp2_source_sel, S_IWUSR | S_IRUGO, | ||
1804 | show_temp_src, store_temp_src, NOT_USED, 1), | ||
1805 | SENSOR_ATTR_2(temp3_source_sel, S_IWUSR | S_IRUGO, | ||
1806 | show_temp_src, store_temp_src, NOT_USED, 2), | ||
1807 | SENSOR_ATTR_2(temp4_source_sel, S_IWUSR | S_IRUGO, | ||
1808 | show_temp_src, store_temp_src, NOT_USED, 3), | ||
1809 | SENSOR_ATTR_2(temp5_source_sel, S_IWUSR | S_IRUGO, | ||
1810 | show_temp_src, store_temp_src, NOT_USED, 4), | ||
1811 | SENSOR_ATTR_2(temp6_source_sel, S_IWUSR | S_IRUGO, | ||
1812 | show_temp_src, store_temp_src, NOT_USED, 5), | ||
1813 | }; | ||
1814 | |||
1714 | static const struct sensor_device_attribute_2 sda_single_files[] = { | 1815 | static const struct sensor_device_attribute_2 sda_single_files[] = { |
1715 | SENSOR_ATTR_2(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm_beep, | 1816 | SENSOR_ATTR_2(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm_beep, |
1716 | store_chassis_clear, ALARM_STATUS, 46), | 1817 | store_chassis_clear, ALARM_STATUS, 46), |
1717 | SENSOR_ATTR_2(intrusion0_beep, S_IWUSR | S_IRUGO, show_alarm_beep, | ||
1718 | store_beep, BEEP_ENABLE, 46), | ||
1719 | SENSOR_ATTR_2(beep_enable, S_IWUSR | S_IRUGO, show_alarm_beep, | ||
1720 | store_beep, BEEP_ENABLE, 47), | ||
1721 | #ifdef CONFIG_SENSORS_W83795_FANCTRL | 1818 | #ifdef CONFIG_SENSORS_W83795_FANCTRL |
1722 | SENSOR_ATTR_2(speed_cruise_tolerance, S_IWUSR | S_IRUGO, show_fanin, | 1819 | SENSOR_ATTR_2(speed_cruise_tolerance, S_IWUSR | S_IRUGO, show_fanin, |
1723 | store_fanin, FANIN_TOL, NOT_USED), | 1820 | store_fanin, FANIN_TOL, NOT_USED), |
@@ -1730,6 +1827,13 @@ static const struct sensor_device_attribute_2 sda_single_files[] = { | |||
1730 | #endif | 1827 | #endif |
1731 | }; | 1828 | }; |
1732 | 1829 | ||
1830 | static const struct sensor_device_attribute_2 sda_beep_files[] = { | ||
1831 | SENSOR_ATTR_2(intrusion0_beep, S_IWUSR | S_IRUGO, show_alarm_beep, | ||
1832 | store_beep, BEEP_ENABLE, 46), | ||
1833 | SENSOR_ATTR_2(beep_enable, S_IWUSR | S_IRUGO, show_alarm_beep, | ||
1834 | store_beep, BEEP_ENABLE, 47), | ||
1835 | }; | ||
1836 | |||
1733 | /* | 1837 | /* |
1734 | * Driver interface | 1838 | * Driver interface |
1735 | */ | 1839 | */ |
@@ -1859,6 +1963,8 @@ static int w83795_handle_files(struct device *dev, int (*fn)(struct device *, | |||
1859 | if (!(data->has_in & (1 << i))) | 1963 | if (!(data->has_in & (1 << i))) |
1860 | continue; | 1964 | continue; |
1861 | for (j = 0; j < ARRAY_SIZE(w83795_in[0]); j++) { | 1965 | for (j = 0; j < ARRAY_SIZE(w83795_in[0]); j++) { |
1966 | if (j == 4 && !data->enable_beep) | ||
1967 | continue; | ||
1862 | err = fn(dev, &w83795_in[i][j].dev_attr); | 1968 | err = fn(dev, &w83795_in[i][j].dev_attr); |
1863 | if (err) | 1969 | if (err) |
1864 | return err; | 1970 | return err; |
@@ -1869,18 +1975,37 @@ static int w83795_handle_files(struct device *dev, int (*fn)(struct device *, | |||
1869 | if (!(data->has_fan & (1 << i))) | 1975 | if (!(data->has_fan & (1 << i))) |
1870 | continue; | 1976 | continue; |
1871 | for (j = 0; j < ARRAY_SIZE(w83795_fan[0]); j++) { | 1977 | for (j = 0; j < ARRAY_SIZE(w83795_fan[0]); j++) { |
1978 | if (j == 3 && !data->enable_beep) | ||
1979 | continue; | ||
1872 | err = fn(dev, &w83795_fan[i][j].dev_attr); | 1980 | err = fn(dev, &w83795_fan[i][j].dev_attr); |
1873 | if (err) | 1981 | if (err) |
1874 | return err; | 1982 | return err; |
1875 | } | 1983 | } |
1876 | } | 1984 | } |
1877 | 1985 | ||
1986 | for (i = 0; i < ARRAY_SIZE(w83795_tss); i++) { | ||
1987 | j = w83795_tss_useful(data, i); | ||
1988 | if (!j) | ||
1989 | continue; | ||
1990 | err = fn(dev, &w83795_tss[i].dev_attr); | ||
1991 | if (err) | ||
1992 | return err; | ||
1993 | } | ||
1994 | |||
1878 | for (i = 0; i < ARRAY_SIZE(sda_single_files); i++) { | 1995 | for (i = 0; i < ARRAY_SIZE(sda_single_files); i++) { |
1879 | err = fn(dev, &sda_single_files[i].dev_attr); | 1996 | err = fn(dev, &sda_single_files[i].dev_attr); |
1880 | if (err) | 1997 | if (err) |
1881 | return err; | 1998 | return err; |
1882 | } | 1999 | } |
1883 | 2000 | ||
2001 | if (data->enable_beep) { | ||
2002 | for (i = 0; i < ARRAY_SIZE(sda_beep_files); i++) { | ||
2003 | err = fn(dev, &sda_beep_files[i].dev_attr); | ||
2004 | if (err) | ||
2005 | return err; | ||
2006 | } | ||
2007 | } | ||
2008 | |||
1884 | #ifdef CONFIG_SENSORS_W83795_FANCTRL | 2009 | #ifdef CONFIG_SENSORS_W83795_FANCTRL |
1885 | for (i = 0; i < data->has_pwm; i++) { | 2010 | for (i = 0; i < data->has_pwm; i++) { |
1886 | for (j = 0; j < ARRAY_SIZE(w83795_pwm[0]); j++) { | 2011 | for (j = 0; j < ARRAY_SIZE(w83795_pwm[0]); j++) { |
@@ -1899,6 +2024,8 @@ static int w83795_handle_files(struct device *dev, int (*fn)(struct device *, | |||
1899 | #else | 2024 | #else |
1900 | for (j = 0; j < 8; j++) { | 2025 | for (j = 0; j < 8; j++) { |
1901 | #endif | 2026 | #endif |
2027 | if (j == 7 && !data->enable_beep) | ||
2028 | continue; | ||
1902 | err = fn(dev, &w83795_temp[i][j].dev_attr); | 2029 | err = fn(dev, &w83795_temp[i][j].dev_attr); |
1903 | if (err) | 2030 | if (err) |
1904 | return err; | 2031 | return err; |
@@ -1910,6 +2037,8 @@ static int w83795_handle_files(struct device *dev, int (*fn)(struct device *, | |||
1910 | if (!(data->has_dts & (1 << i))) | 2037 | if (!(data->has_dts & (1 << i))) |
1911 | continue; | 2038 | continue; |
1912 | for (j = 0; j < ARRAY_SIZE(w83795_dts[0]); j++) { | 2039 | for (j = 0; j < ARRAY_SIZE(w83795_dts[0]); j++) { |
2040 | if (j == 7 && !data->enable_beep) | ||
2041 | continue; | ||
1913 | err = fn(dev, &w83795_dts[i][j].dev_attr); | 2042 | err = fn(dev, &w83795_dts[i][j].dev_attr); |
1914 | if (err) | 2043 | if (err) |
1915 | return err; | 2044 | return err; |
@@ -2049,6 +2178,18 @@ static int w83795_probe(struct i2c_client *client, | |||
2049 | else | 2178 | else |
2050 | data->has_pwm = 2; | 2179 | data->has_pwm = 2; |
2051 | 2180 | ||
2181 | /* Check if BEEP pin is available */ | ||
2182 | if (data->chip_type == w83795g) { | ||
2183 | /* The W83795G has a dedicated BEEP pin */ | ||
2184 | data->enable_beep = 1; | ||
2185 | } else { | ||
2186 | /* The W83795ADG has a shared pin for OVT# and BEEP, so you | ||
2187 | * can't have both */ | ||
2188 | tmp = w83795_read(client, W83795_REG_OVT_CFG); | ||
2189 | if ((tmp & OVT_CFG_SEL) == 0) | ||
2190 | data->enable_beep = 1; | ||
2191 | } | ||
2192 | |||
2052 | err = w83795_handle_files(dev, device_create_file); | 2193 | err = w83795_handle_files(dev, device_create_file); |
2053 | if (err) | 2194 | if (err) |
2054 | goto exit_remove; | 2195 | goto exit_remove; |