aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/adt7475.c
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/hwmon/adt7475.c
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/hwmon/adt7475.c')
-rw-r--r--drivers/hwmon/adt7475.c66
1 files changed, 63 insertions, 3 deletions
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