aboutsummaryrefslogtreecommitdiffstats
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
commitd8d2ee073274ab666282d1942d08f1bb454d715b (patch)
treec36ac0f8a63f3ff83a312c61a19d6dde1d5c34da
parentebfaf1fbb6010204e973e329034d0004d6521503 (diff)
hwmon: (adt7475) Add support for the ADT7476
Add support for the Analog Devices ADT7476 chip. This chip is largely compatible with the ADT7473 and ADT7475, with additional features. In particular, it has 5 voltage inputs instead of 2, and VID input pins. 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>
-rw-r--r--Documentation/hwmon/adt747520
-rw-r--r--drivers/hwmon/Kconfig5
-rw-r--r--drivers/hwmon/adt7475.c80
3 files changed, 80 insertions, 25 deletions
diff --git a/Documentation/hwmon/adt7475 b/Documentation/hwmon/adt7475
index f08f28715b84..03be1e6f69cf 100644
--- a/Documentation/hwmon/adt7475
+++ b/Documentation/hwmon/adt7475
@@ -10,6 +10,10 @@ Supported chips:
10 Prefix: 'adt7475' 10 Prefix: 'adt7475'
11 Addresses scanned: I2C 0x2E 11 Addresses scanned: I2C 0x2E
12 Datasheet: Publicly available at the On Semiconductors website 12 Datasheet: Publicly available at the On Semiconductors website
13 * Analog Devices ADT7476
14 Prefix: 'adt7476'
15 Addresses scanned: I2C 0x2C, 0x2D, 0x2E
16 Datasheet: Publicly available at the On Semiconductors website
13 * Analog Devices ADT7490 17 * Analog Devices ADT7490
14 Prefix: 'adt7490' 18 Prefix: 'adt7490'
15 Addresses scanned: I2C 0x2C, 0x2D, 0x2E 19 Addresses scanned: I2C 0x2C, 0x2D, 0x2E
@@ -25,11 +29,13 @@ Authors:
25Description 29Description
26----------- 30-----------
27 31
28This driver implements support for the Analog Devices ADT7473, ADT7475 and 32This driver implements support for the Analog Devices ADT7473, ADT7475,
29ADT7490 chip family. The ADT7473 and ADT7475 differ only in minor details. 33ADT7476 and ADT7490 chip family. The ADT7473 and ADT7475 differ only in
30The ADT7490 has additional features, including extra voltage measurement 34minor details. The ADT7476 has additional features, including extra voltage
31inputs and PECI support. All the supported chips will be collectively 35measurement inputs and VID support. The ADT7490 also has additional
32designed by the name "ADT747x" in the rest of this document. 36features, including extra voltage measurement inputs and PECI support. All
37the supported chips will be collectively designed by the name "ADT747x" in
38the rest of this document.
33 39
34The ADT747x uses the 2-wire interface compatible with the SMBus 2.0 40The ADT747x uses the 2-wire interface compatible with the SMBus 2.0
35specification. Using an analog to digital converter it measures three (3) 41specification. Using an analog to digital converter it measures three (3)
@@ -62,6 +68,10 @@ ADT7473:
62ADT7475: 68ADT7475:
63 * 2 voltage inputs 69 * 2 voltage inputs
64 70
71ADT7476:
72 * 5 voltage inputs
73 * VID support (not implemented)
74
65ADT7490: 75ADT7490:
66 * 6 voltage inputs 76 * 6 voltage inputs
67 * 1 Imon input (not implemented) 77 * 1 Imon input (not implemented)
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index f9f4365349b2..957171c62324 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -205,11 +205,12 @@ config SENSORS_ADT7473
205 will be called adt7473. 205 will be called adt7473.
206 206
207config SENSORS_ADT7475 207config SENSORS_ADT7475
208 tristate "Analog Devices ADT7473, ADT7475 and ADT7490" 208 tristate "Analog Devices ADT7473, ADT7475, ADT7476 and ADT7490"
209 depends on I2C && EXPERIMENTAL 209 depends on I2C && EXPERIMENTAL
210 help 210 help
211 If you say yes here you get support for the Analog Devices 211 If you say yes here you get support for the Analog Devices
212 ADT7473, ADT7475 and ADT7490 hardware monitoring chips. 212 ADT7473, ADT7475, ADT7476 and ADT7490 hardware monitoring
213 chips.
213 214
214 This driver can also be build as a module. If so, the module 215 This driver can also be build as a module. If so, the module
215 will be called adt7475. 216 will be called adt7475.
diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c
index eac24c1361bc..72c3b754e7b6 100644
--- a/drivers/hwmon/adt7475.c
+++ b/drivers/hwmon/adt7475.c
@@ -58,6 +58,8 @@
58#define REG_STATUS1 0x41 58#define REG_STATUS1 0x41
59#define REG_STATUS2 0x42 59#define REG_STATUS2 0x42
60 60
61#define REG_VID 0x43 /* ADT7476 only */
62
61#define REG_VOLTAGE_MIN_BASE 0x44 63#define REG_VOLTAGE_MIN_BASE 0x44
62#define REG_VOLTAGE_MAX_BASE 0x45 64#define REG_VOLTAGE_MAX_BASE 0x45
63 65
@@ -94,6 +96,8 @@
94#define REG_VTT_MIN 0x84 /* ADT7490 only */ 96#define REG_VTT_MIN 0x84 /* ADT7490 only */
95#define REG_VTT_MAX 0x86 /* ADT7490 only */ 97#define REG_VTT_MAX 0x86 /* ADT7490 only */
96 98
99#define VID_VIDSEL 0x80 /* ADT7476 only */
100
97#define CONFIG2_ATTN 0x20 101#define CONFIG2_ATTN 0x20
98 102
99#define CONFIG3_SMBALERT 0x01 103#define CONFIG3_SMBALERT 0x01
@@ -142,11 +146,12 @@
142 146
143static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; 147static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
144 148
145I2C_CLIENT_INSMOD_3(adt7473, adt7475, adt7490); 149I2C_CLIENT_INSMOD_4(adt7473, adt7475, adt7476, adt7490);
146 150
147static const struct i2c_device_id adt7475_id[] = { 151static const struct i2c_device_id adt7475_id[] = {
148 { "adt7473", adt7473 }, 152 { "adt7473", adt7473 },
149 { "adt7475", adt7475 }, 153 { "adt7475", adt7475 },
154 { "adt7476", adt7476 },
150 { "adt7490", adt7490 }, 155 { "adt7490", adt7490 },
151 { } 156 { }
152}; 157};
@@ -1082,7 +1087,6 @@ static struct attribute *pwm2_attrs[] = {
1082 NULL 1087 NULL
1083}; 1088};
1084 1089
1085/* Attributes specific to the ADT7490 */
1086static struct attribute *in0_attrs[] = { 1090static struct attribute *in0_attrs[] = {
1087 &sensor_dev_attr_in0_input.dev_attr.attr, 1091 &sensor_dev_attr_in0_input.dev_attr.attr,
1088 &sensor_dev_attr_in0_max.dev_attr.attr, 1092 &sensor_dev_attr_in0_max.dev_attr.attr,
@@ -1091,15 +1095,23 @@ static struct attribute *in0_attrs[] = {
1091 NULL 1095 NULL
1092}; 1096};
1093 1097
1094static struct attribute *adt7490_attrs[] = { 1098static struct attribute *in3_attrs[] = {
1095 &sensor_dev_attr_in3_input.dev_attr.attr, 1099 &sensor_dev_attr_in3_input.dev_attr.attr,
1096 &sensor_dev_attr_in3_max.dev_attr.attr, 1100 &sensor_dev_attr_in3_max.dev_attr.attr,
1097 &sensor_dev_attr_in3_min.dev_attr.attr, 1101 &sensor_dev_attr_in3_min.dev_attr.attr,
1098 &sensor_dev_attr_in3_alarm.dev_attr.attr, 1102 &sensor_dev_attr_in3_alarm.dev_attr.attr,
1103 NULL
1104};
1105
1106static struct attribute *in4_attrs[] = {
1099 &sensor_dev_attr_in4_input.dev_attr.attr, 1107 &sensor_dev_attr_in4_input.dev_attr.attr,
1100 &sensor_dev_attr_in4_max.dev_attr.attr, 1108 &sensor_dev_attr_in4_max.dev_attr.attr,
1101 &sensor_dev_attr_in4_min.dev_attr.attr, 1109 &sensor_dev_attr_in4_min.dev_attr.attr,
1102 &sensor_dev_attr_in4_alarm.dev_attr.attr, 1110 &sensor_dev_attr_in4_alarm.dev_attr.attr,
1111 NULL
1112};
1113
1114static struct attribute *in5_attrs[] = {
1103 &sensor_dev_attr_in5_input.dev_attr.attr, 1115 &sensor_dev_attr_in5_input.dev_attr.attr,
1104 &sensor_dev_attr_in5_max.dev_attr.attr, 1116 &sensor_dev_attr_in5_max.dev_attr.attr,
1105 &sensor_dev_attr_in5_min.dev_attr.attr, 1117 &sensor_dev_attr_in5_min.dev_attr.attr,
@@ -1111,7 +1123,9 @@ static struct attribute_group adt7475_attr_group = { .attrs = adt7475_attrs };
1111static struct attribute_group fan4_attr_group = { .attrs = fan4_attrs }; 1123static struct attribute_group fan4_attr_group = { .attrs = fan4_attrs };
1112static struct attribute_group pwm2_attr_group = { .attrs = pwm2_attrs }; 1124static struct attribute_group pwm2_attr_group = { .attrs = pwm2_attrs };
1113static struct attribute_group in0_attr_group = { .attrs = in0_attrs }; 1125static struct attribute_group in0_attr_group = { .attrs = in0_attrs };
1114static struct attribute_group adt7490_attr_group = { .attrs = adt7490_attrs }; 1126static struct attribute_group in3_attr_group = { .attrs = in3_attrs };
1127static struct attribute_group in4_attr_group = { .attrs = in4_attrs };
1128static struct attribute_group in5_attr_group = { .attrs = in5_attrs };
1115 1129
1116static int adt7475_detect(struct i2c_client *client, int kind, 1130static int adt7475_detect(struct i2c_client *client, int kind,
1117 struct i2c_board_info *info) 1131 struct i2c_board_info *info)
@@ -1134,11 +1148,13 @@ static int adt7475_detect(struct i2c_client *client, int kind,
1134 name = "adt7473"; 1148 name = "adt7473";
1135 else if (devid == 0x75 && client->addr == 0x2e) 1149 else if (devid == 0x75 && client->addr == 0x2e)
1136 name = "adt7475"; 1150 name = "adt7475";
1151 else if (devid == 0x76)
1152 name = "adt7476";
1137 else if ((devid2 & 0xfc) == 0x6c) 1153 else if ((devid2 & 0xfc) == 0x6c)
1138 name = "adt7490"; 1154 name = "adt7490";
1139 else { 1155 else {
1140 dev_dbg(&adapter->dev, 1156 dev_dbg(&adapter->dev,
1141 "Couldn't detect an ADT7473/75/90 part at " 1157 "Couldn't detect an ADT7473/75/76/90 part at "
1142 "0x%02x\n", (unsigned int)client->addr); 1158 "0x%02x\n", (unsigned int)client->addr);
1143 return -ENODEV; 1159 return -ENODEV;
1144 } 1160 }
@@ -1152,14 +1168,18 @@ static void adt7475_remove_files(struct i2c_client *client,
1152 struct adt7475_data *data) 1168 struct adt7475_data *data)
1153{ 1169{
1154 sysfs_remove_group(&client->dev.kobj, &adt7475_attr_group); 1170 sysfs_remove_group(&client->dev.kobj, &adt7475_attr_group);
1155 if (data->has_voltage & 0x39)
1156 sysfs_remove_group(&client->dev.kobj, &adt7490_attr_group);
1157 if (data->has_fan4) 1171 if (data->has_fan4)
1158 sysfs_remove_group(&client->dev.kobj, &fan4_attr_group); 1172 sysfs_remove_group(&client->dev.kobj, &fan4_attr_group);
1159 if (data->has_pwm2) 1173 if (data->has_pwm2)
1160 sysfs_remove_group(&client->dev.kobj, &pwm2_attr_group); 1174 sysfs_remove_group(&client->dev.kobj, &pwm2_attr_group);
1161 if (data->has_voltage & (1 << 0)) 1175 if (data->has_voltage & (1 << 0))
1162 sysfs_remove_group(&client->dev.kobj, &in0_attr_group); 1176 sysfs_remove_group(&client->dev.kobj, &in0_attr_group);
1177 if (data->has_voltage & (1 << 3))
1178 sysfs_remove_group(&client->dev.kobj, &in3_attr_group);
1179 if (data->has_voltage & (1 << 4))
1180 sysfs_remove_group(&client->dev.kobj, &in4_attr_group);
1181 if (data->has_voltage & (1 << 5))
1182 sysfs_remove_group(&client->dev.kobj, &in5_attr_group);
1163} 1183}
1164 1184
1165static int adt7475_probe(struct i2c_client *client, 1185static int adt7475_probe(struct i2c_client *client,
@@ -1168,6 +1188,7 @@ static int adt7475_probe(struct i2c_client *client,
1168 static const char *names[] = { 1188 static const char *names[] = {
1169 [adt7473] = "ADT7473", 1189 [adt7473] = "ADT7473",
1170 [adt7475] = "ADT7475", 1190 [adt7475] = "ADT7475",
1191 [adt7476] = "ADT7476",
1171 [adt7490] = "ADT7490", 1192 [adt7490] = "ADT7490",
1172 }; 1193 };
1173 1194
@@ -1184,6 +1205,10 @@ static int adt7475_probe(struct i2c_client *client,
1184 1205
1185 /* Initialize device-specific values */ 1206 /* Initialize device-specific values */
1186 switch (id->driver_data) { 1207 switch (id->driver_data) {
1208 case adt7476:
1209 data->has_voltage = 0x0e; /* in1 to in3 */
1210 revision = adt7475_read(REG_DEVID2) & 0x07;
1211 break;
1187 case adt7490: 1212 case adt7490:
1188 data->has_voltage = 0x3e; /* in1 to in5 */ 1213 data->has_voltage = 0x3e; /* in1 to in5 */
1189 revision = adt7475_read(REG_DEVID2) & 0x03; 1214 revision = adt7475_read(REG_DEVID2) & 0x03;
@@ -1208,17 +1233,27 @@ static int adt7475_probe(struct i2c_client *client,
1208 if ((data->config4 & CONFIG4_PINFUNC) == 0x0) 1233 if ((data->config4 & CONFIG4_PINFUNC) == 0x0)
1209 data->has_fan4 = 1; 1234 data->has_fan4 = 1;
1210 1235
1211 /* THERM configuration is more complex on the ADT7490, because 2 1236 /* THERM configuration is more complex on the ADT7476 and ADT7490,
1212 different pins (TACH4 and +2.5 Vin) can be used for this function */ 1237 because 2 different pins (TACH4 and +2.5 Vin) can be used for
1238 this function */
1213 if (id->driver_data == adt7490) { 1239 if (id->driver_data == adt7490) {
1214 if ((data->config4 & CONFIG4_PINFUNC) == 0x1 && 1240 if ((data->config4 & CONFIG4_PINFUNC) == 0x1 &&
1215 !(config3 & CONFIG3_THERM)) 1241 !(config3 & CONFIG3_THERM))
1216 data->has_fan4 = 1; 1242 data->has_fan4 = 1;
1243 }
1244 if (id->driver_data == adt7476 || id->driver_data == adt7490) {
1217 if (!(config3 & CONFIG3_THERM) || 1245 if (!(config3 & CONFIG3_THERM) ||
1218 (data->config4 & CONFIG4_PINFUNC) == 0x1) 1246 (data->config4 & CONFIG4_PINFUNC) == 0x1)
1219 data->has_voltage |= (1 << 0); /* in0 */ 1247 data->has_voltage |= (1 << 0); /* in0 */
1220 } 1248 }
1221 1249
1250 /* On the ADT7476, the +12V input pin may instead be used as VID5 */
1251 if (id->driver_data == adt7476) {
1252 u8 vid = adt7475_read(REG_VID);
1253 if (!(vid & VID_VIDSEL))
1254 data->has_voltage |= (1 << 4); /* in4 */
1255 }
1256
1222 /* Voltage attenuators can be bypassed, globally or individually */ 1257 /* Voltage attenuators can be bypassed, globally or individually */
1223 config2 = adt7475_read(REG_CONFIG2); 1258 config2 = adt7475_read(REG_CONFIG2);
1224 if (config2 & CONFIG2_ATTN) { 1259 if (config2 & CONFIG2_ATTN) {
@@ -1238,13 +1273,6 @@ static int adt7475_probe(struct i2c_client *client,
1238 if (ret) 1273 if (ret)
1239 goto efree; 1274 goto efree;
1240 1275
1241 if (id->driver_data == adt7490) {
1242 ret = sysfs_create_group(&client->dev.kobj,
1243 &adt7490_attr_group);
1244 if (ret)
1245 goto eremove;
1246 }
1247
1248 /* Features that can be disabled individually */ 1276 /* Features that can be disabled individually */
1249 if (data->has_fan4) { 1277 if (data->has_fan4) {
1250 ret = sysfs_create_group(&client->dev.kobj, &fan4_attr_group); 1278 ret = sysfs_create_group(&client->dev.kobj, &fan4_attr_group);
@@ -1261,6 +1289,21 @@ static int adt7475_probe(struct i2c_client *client,
1261 if (ret) 1289 if (ret)
1262 goto eremove; 1290 goto eremove;
1263 } 1291 }
1292 if (data->has_voltage & (1 << 3)) {
1293 ret = sysfs_create_group(&client->dev.kobj, &in3_attr_group);
1294 if (ret)
1295 goto eremove;
1296 }
1297 if (data->has_voltage & (1 << 4)) {
1298 ret = sysfs_create_group(&client->dev.kobj, &in4_attr_group);
1299 if (ret)
1300 goto eremove;
1301 }
1302 if (data->has_voltage & (1 << 5)) {
1303 ret = sysfs_create_group(&client->dev.kobj, &in5_attr_group);
1304 if (ret)
1305 goto eremove;
1306 }
1264 1307
1265 data->hwmon_dev = hwmon_device_register(&client->dev); 1308 data->hwmon_dev = hwmon_device_register(&client->dev);
1266 if (IS_ERR(data->hwmon_dev)) { 1309 if (IS_ERR(data->hwmon_dev)) {
@@ -1270,9 +1313,10 @@ static int adt7475_probe(struct i2c_client *client,
1270 1313
1271 dev_info(&client->dev, "%s device, revision %d\n", 1314 dev_info(&client->dev, "%s device, revision %d\n",
1272 names[id->driver_data], revision); 1315 names[id->driver_data], revision);
1273 if ((data->has_voltage & (1 << 0)) || data->has_fan4 || data->has_pwm2) 1316 if ((data->has_voltage & 0x11) || data->has_fan4 || data->has_pwm2)
1274 dev_info(&client->dev, "Optional features:%s%s%s\n", 1317 dev_info(&client->dev, "Optional features:%s%s%s%s\n",
1275 (data->has_voltage & (1 << 0)) ? " in0" : "", 1318 (data->has_voltage & (1 << 0)) ? " in0" : "",
1319 (data->has_voltage & (1 << 4)) ? " in4" : "",
1276 data->has_fan4 ? " fan4" : "", 1320 data->has_fan4 ? " fan4" : "",
1277 data->has_pwm2 ? " pwm2" : ""); 1321 data->has_pwm2 ? " pwm2" : "");
1278 if (data->bypass_attn) 1322 if (data->bypass_attn)