diff options
-rw-r--r-- | Documentation/hwmon/adt7475 | 20 | ||||
-rw-r--r-- | drivers/hwmon/Kconfig | 5 | ||||
-rw-r--r-- | drivers/hwmon/adt7475.c | 80 |
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: | |||
25 | Description | 29 | Description |
26 | ----------- | 30 | ----------- |
27 | 31 | ||
28 | This driver implements support for the Analog Devices ADT7473, ADT7475 and | 32 | This driver implements support for the Analog Devices ADT7473, ADT7475, |
29 | ADT7490 chip family. The ADT7473 and ADT7475 differ only in minor details. | 33 | ADT7476 and ADT7490 chip family. The ADT7473 and ADT7475 differ only in |
30 | The ADT7490 has additional features, including extra voltage measurement | 34 | minor details. The ADT7476 has additional features, including extra voltage |
31 | inputs and PECI support. All the supported chips will be collectively | 35 | measurement inputs and VID support. The ADT7490 also has additional |
32 | designed by the name "ADT747x" in the rest of this document. | 36 | features, including extra voltage measurement inputs and PECI support. All |
37 | the supported chips will be collectively designed by the name "ADT747x" in | ||
38 | the rest of this document. | ||
33 | 39 | ||
34 | The ADT747x uses the 2-wire interface compatible with the SMBus 2.0 | 40 | The ADT747x uses the 2-wire interface compatible with the SMBus 2.0 |
35 | specification. Using an analog to digital converter it measures three (3) | 41 | specification. Using an analog to digital converter it measures three (3) |
@@ -62,6 +68,10 @@ ADT7473: | |||
62 | ADT7475: | 68 | ADT7475: |
63 | * 2 voltage inputs | 69 | * 2 voltage inputs |
64 | 70 | ||
71 | ADT7476: | ||
72 | * 5 voltage inputs | ||
73 | * VID support (not implemented) | ||
74 | |||
65 | ADT7490: | 75 | ADT7490: |
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 | ||
207 | config SENSORS_ADT7475 | 207 | config 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 | ||
143 | static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; | 147 | static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; |
144 | 148 | ||
145 | I2C_CLIENT_INSMOD_3(adt7473, adt7475, adt7490); | 149 | I2C_CLIENT_INSMOD_4(adt7473, adt7475, adt7476, adt7490); |
146 | 150 | ||
147 | static const struct i2c_device_id adt7475_id[] = { | 151 | static 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 */ | ||
1086 | static struct attribute *in0_attrs[] = { | 1090 | static 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 | ||
1094 | static struct attribute *adt7490_attrs[] = { | 1098 | static 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 | |||
1106 | static 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 | |||
1114 | static 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 }; | |||
1111 | static struct attribute_group fan4_attr_group = { .attrs = fan4_attrs }; | 1123 | static struct attribute_group fan4_attr_group = { .attrs = fan4_attrs }; |
1112 | static struct attribute_group pwm2_attr_group = { .attrs = pwm2_attrs }; | 1124 | static struct attribute_group pwm2_attr_group = { .attrs = pwm2_attrs }; |
1113 | static struct attribute_group in0_attr_group = { .attrs = in0_attrs }; | 1125 | static struct attribute_group in0_attr_group = { .attrs = in0_attrs }; |
1114 | static struct attribute_group adt7490_attr_group = { .attrs = adt7490_attrs }; | 1126 | static struct attribute_group in3_attr_group = { .attrs = in3_attrs }; |
1127 | static struct attribute_group in4_attr_group = { .attrs = in4_attrs }; | ||
1128 | static struct attribute_group in5_attr_group = { .attrs = in5_attrs }; | ||
1115 | 1129 | ||
1116 | static int adt7475_detect(struct i2c_client *client, int kind, | 1130 | static 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 | ||
1165 | static int adt7475_probe(struct i2c_client *client, | 1185 | static 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) |