aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2009-12-09 14:36:08 -0500
committerJean Delvare <khali@linux-fr.org>2009-12-09 14:36:08 -0500
commit54fe4671aa5853ca88da72d67e969a3d8de6dcf6 (patch)
treed92f5306dc6c2deedf8bb082f9a848f77110258d /drivers
parentb058b8596136d97b9469366f1f97fb35accf3d66 (diff)
hwmon: (adt7475) Add VID support for the ADT7476
The ADT7476 has 5 dedicated pins for VID input, and the +12V input can optionally be used as a 6th VID pin. Add support for VID input. Signed-off-by: Jean Delvare <khali@linux-fr.org> Cc: Hans de Goede <hdegoede@redhat.com> Cc: Jordan Crouse <jordan@cosmicpenguin.net> Cc: "Darrick J. Wong" <djwong@us.ibm.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/hwmon/Kconfig1
-rw-r--r--drivers/hwmon/adt7475.c66
2 files changed, 64 insertions, 3 deletions
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 957171c62324..9e640c62ebd9 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -207,6 +207,7 @@ config SENSORS_ADT7473
207config SENSORS_ADT7475 207config SENSORS_ADT7475
208 tristate "Analog Devices ADT7473, ADT7475, ADT7476 and ADT7490" 208 tristate "Analog Devices ADT7473, ADT7475, ADT7476 and ADT7490"
209 depends on I2C && EXPERIMENTAL 209 depends on I2C && EXPERIMENTAL
210 select HWMON_VID
210 help 211 help
211 If you say yes here you get support for the Analog Devices 212 If you say yes here you get support for the Analog Devices
212 ADT7473, ADT7475, ADT7476 and ADT7490 hardware monitoring 213 ADT7473, ADT7475, ADT7476 and ADT7490 hardware monitoring
diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c
index 72c3b754e7b6..99abfddedbc3 100644
--- a/drivers/hwmon/adt7475.c
+++ b/drivers/hwmon/adt7475.c
@@ -18,6 +18,7 @@
18#include <linux/i2c.h> 18#include <linux/i2c.h>
19#include <linux/hwmon.h> 19#include <linux/hwmon.h>
20#include <linux/hwmon-sysfs.h> 20#include <linux/hwmon-sysfs.h>
21#include <linux/hwmon-vid.h>
21#include <linux/err.h> 22#include <linux/err.h>
22 23
23/* Indexes for the sysfs hooks */ 24/* Indexes for the sysfs hooks */
@@ -110,6 +111,7 @@
110 111
111#define CONFIG5_TWOSCOMP 0x01 112#define CONFIG5_TWOSCOMP 0x01
112#define CONFIG5_TEMPOFFSET 0x02 113#define CONFIG5_TEMPOFFSET 0x02
114#define CONFIG5_VIDGPIO 0x10 /* ADT7476 only */
113 115
114/* ADT7475 Settings */ 116/* ADT7475 Settings */
115 117
@@ -171,6 +173,7 @@ struct adt7475_data {
171 u8 bypass_attn; /* Bypass voltage attenuator */ 173 u8 bypass_attn; /* Bypass voltage attenuator */
172 u8 has_pwm2:1; 174 u8 has_pwm2:1;
173 u8 has_fan4:1; 175 u8 has_fan4:1;
176 u8 has_vid:1;
174 u32 alarms; 177 u32 alarms;
175 u16 voltage[3][6]; 178 u16 voltage[3][6];
176 u16 temp[7][3]; 179 u16 temp[7][3];
@@ -179,6 +182,9 @@ struct adt7475_data {
179 u8 range[3]; 182 u8 range[3];
180 u8 pwmctl[3]; 183 u8 pwmctl[3];
181 u8 pwmchan[3]; 184 u8 pwmchan[3];
185
186 u8 vid;
187 u8 vrm;
182}; 188};
183 189
184static struct i2c_driver adt7475_driver; 190static struct i2c_driver adt7475_driver;
@@ -864,6 +870,35 @@ static ssize_t set_pwm_at_crit(struct device *dev,
864 return count; 870 return count;
865} 871}
866 872
873static ssize_t show_vrm(struct device *dev, struct device_attribute *devattr,
874 char *buf)
875{
876 struct adt7475_data *data = dev_get_drvdata(dev);
877 return sprintf(buf, "%d\n", (int)data->vrm);
878}
879
880static ssize_t set_vrm(struct device *dev, struct device_attribute *devattr,
881 const char *buf, size_t count)
882{
883 struct adt7475_data *data = dev_get_drvdata(dev);
884 long val;
885
886 if (strict_strtol(buf, 10, &val))
887 return -EINVAL;
888 if (val < 0 || val > 255)
889 return -EINVAL;
890 data->vrm = val;
891
892 return count;
893}
894
895static ssize_t show_vid(struct device *dev, struct device_attribute *devattr,
896 char *buf)
897{
898 struct adt7475_data *data = adt7475_update_device(dev);
899 return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
900}
901
867static SENSOR_DEVICE_ATTR_2(in0_input, S_IRUGO, show_voltage, NULL, INPUT, 0); 902static SENSOR_DEVICE_ATTR_2(in0_input, S_IRUGO, show_voltage, NULL, INPUT, 0);
868static SENSOR_DEVICE_ATTR_2(in0_max, S_IRUGO | S_IWUSR, show_voltage, 903static SENSOR_DEVICE_ATTR_2(in0_max, S_IRUGO | S_IWUSR, show_voltage,
869 set_voltage, MAX, 0); 904 set_voltage, MAX, 0);
@@ -1007,6 +1042,9 @@ static SENSOR_DEVICE_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO | S_IWUSR, show_pwm,
1007static DEVICE_ATTR(pwm_use_point2_pwm_at_crit, S_IWUSR | S_IRUGO, 1042static DEVICE_ATTR(pwm_use_point2_pwm_at_crit, S_IWUSR | S_IRUGO,
1008 show_pwm_at_crit, set_pwm_at_crit); 1043 show_pwm_at_crit, set_pwm_at_crit);
1009 1044
1045static DEVICE_ATTR(vrm, S_IWUSR | S_IRUGO, show_vrm, set_vrm);
1046static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
1047
1010static struct attribute *adt7475_attrs[] = { 1048static struct attribute *adt7475_attrs[] = {
1011 &sensor_dev_attr_in1_input.dev_attr.attr, 1049 &sensor_dev_attr_in1_input.dev_attr.attr,
1012 &sensor_dev_attr_in1_max.dev_attr.attr, 1050 &sensor_dev_attr_in1_max.dev_attr.attr,
@@ -1119,6 +1157,12 @@ static struct attribute *in5_attrs[] = {
1119 NULL 1157 NULL
1120}; 1158};
1121 1159
1160static struct attribute *vid_attrs[] = {
1161 &dev_attr_cpu0_vid.attr,
1162 &dev_attr_vrm.attr,
1163 NULL
1164};
1165
1122static struct attribute_group adt7475_attr_group = { .attrs = adt7475_attrs }; 1166static struct attribute_group adt7475_attr_group = { .attrs = adt7475_attrs };
1123static struct attribute_group fan4_attr_group = { .attrs = fan4_attrs }; 1167static struct attribute_group fan4_attr_group = { .attrs = fan4_attrs };
1124static struct attribute_group pwm2_attr_group = { .attrs = pwm2_attrs }; 1168static struct attribute_group pwm2_attr_group = { .attrs = pwm2_attrs };
@@ -1126,6 +1170,7 @@ static struct attribute_group in0_attr_group = { .attrs = in0_attrs };
1126static struct attribute_group in3_attr_group = { .attrs = in3_attrs }; 1170static struct attribute_group in3_attr_group = { .attrs = in3_attrs };
1127static struct attribute_group in4_attr_group = { .attrs = in4_attrs }; 1171static struct attribute_group in4_attr_group = { .attrs = in4_attrs };
1128static struct attribute_group in5_attr_group = { .attrs = in5_attrs }; 1172static struct attribute_group in5_attr_group = { .attrs = in5_attrs };
1173static struct attribute_group vid_attr_group = { .attrs = vid_attrs };
1129 1174
1130static int adt7475_detect(struct i2c_client *client, int kind, 1175static int adt7475_detect(struct i2c_client *client, int kind,
1131 struct i2c_board_info *info) 1176 struct i2c_board_info *info)
@@ -1180,6 +1225,8 @@ static void adt7475_remove_files(struct i2c_client *client,
1180 sysfs_remove_group(&client->dev.kobj, &in4_attr_group); 1225 sysfs_remove_group(&client->dev.kobj, &in4_attr_group);
1181 if (data->has_voltage & (1 << 5)) 1226 if (data->has_voltage & (1 << 5))
1182 sysfs_remove_group(&client->dev.kobj, &in5_attr_group); 1227 sysfs_remove_group(&client->dev.kobj, &in5_attr_group);
1228 if (data->has_vid)
1229 sysfs_remove_group(&client->dev.kobj, &vid_attr_group);
1183} 1230}
1184 1231
1185static int adt7475_probe(struct i2c_client *client, 1232static int adt7475_probe(struct i2c_client *client,
@@ -1247,11 +1294,14 @@ static int adt7475_probe(struct i2c_client *client,
1247 data->has_voltage |= (1 << 0); /* in0 */ 1294 data->has_voltage |= (1 << 0); /* in0 */
1248 } 1295 }
1249 1296
1250 /* On the ADT7476, the +12V input pin may instead be used as VID5 */ 1297 /* On the ADT7476, the +12V input pin may instead be used as VID5,
1298 and VID pins may alternatively be used as GPIO */
1251 if (id->driver_data == adt7476) { 1299 if (id->driver_data == adt7476) {
1252 u8 vid = adt7475_read(REG_VID); 1300 u8 vid = adt7475_read(REG_VID);
1253 if (!(vid & VID_VIDSEL)) 1301 if (!(vid & VID_VIDSEL))
1254 data->has_voltage |= (1 << 4); /* in4 */ 1302 data->has_voltage |= (1 << 4); /* in4 */
1303
1304 data->has_vid = !(adt7475_read(REG_CONFIG5) & CONFIG5_VIDGPIO);
1255 } 1305 }
1256 1306
1257 /* Voltage attenuators can be bypassed, globally or individually */ 1307 /* Voltage attenuators can be bypassed, globally or individually */
@@ -1304,6 +1354,12 @@ static int adt7475_probe(struct i2c_client *client,
1304 if (ret) 1354 if (ret)
1305 goto eremove; 1355 goto eremove;
1306 } 1356 }
1357 if (data->has_vid) {
1358 data->vrm = vid_which_vrm();
1359 ret = sysfs_create_group(&client->dev.kobj, &vid_attr_group);
1360 if (ret)
1361 goto eremove;
1362 }
1307 1363
1308 data->hwmon_dev = hwmon_device_register(&client->dev); 1364 data->hwmon_dev = hwmon_device_register(&client->dev);
1309 if (IS_ERR(data->hwmon_dev)) { 1365 if (IS_ERR(data->hwmon_dev)) {
@@ -1314,11 +1370,12 @@ static int adt7475_probe(struct i2c_client *client,
1314 dev_info(&client->dev, "%s device, revision %d\n", 1370 dev_info(&client->dev, "%s device, revision %d\n",
1315 names[id->driver_data], revision); 1371 names[id->driver_data], revision);
1316 if ((data->has_voltage & 0x11) || data->has_fan4 || data->has_pwm2) 1372 if ((data->has_voltage & 0x11) || data->has_fan4 || data->has_pwm2)
1317 dev_info(&client->dev, "Optional features:%s%s%s%s\n", 1373 dev_info(&client->dev, "Optional features:%s%s%s%s%s\n",
1318 (data->has_voltage & (1 << 0)) ? " in0" : "", 1374 (data->has_voltage & (1 << 0)) ? " in0" : "",
1319 (data->has_voltage & (1 << 4)) ? " in4" : "", 1375 (data->has_voltage & (1 << 4)) ? " in4" : "",
1320 data->has_fan4 ? " fan4" : "", 1376 data->has_fan4 ? " fan4" : "",
1321 data->has_pwm2 ? " pwm2" : ""); 1377 data->has_pwm2 ? " pwm2" : "",
1378 data->has_vid ? " vid" : "");
1322 if (data->bypass_attn) 1379 if (data->bypass_attn)
1323 dev_info(&client->dev, "Bypassing attenuators on:%s%s%s%s\n", 1380 dev_info(&client->dev, "Bypassing attenuators on:%s%s%s%s\n",
1324 (data->bypass_attn & (1 << 0)) ? " in0" : "", 1381 (data->bypass_attn & (1 << 0)) ? " in0" : "",
@@ -1472,6 +1529,9 @@ static struct adt7475_data *adt7475_update_device(struct device *dev)
1472 data->pwm[INPUT][i] = adt7475_read(PWM_REG(i)); 1529 data->pwm[INPUT][i] = adt7475_read(PWM_REG(i));
1473 } 1530 }
1474 1531
1532 if (data->has_vid)
1533 data->vid = adt7475_read(REG_VID) & 0x3f;
1534
1475 data->measure_updated = jiffies; 1535 data->measure_updated = jiffies;
1476 } 1536 }
1477 1537