aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2009-12-09 14:36:06 -0500
committerJean Delvare <khali@linux-fr.org>2009-12-09 14:36:06 -0500
commit378933c99402f26587ad80e97bff405265116f9e (patch)
treec96aea59308a4426ece06e47adf3caf1c8277e79 /drivers
parent0f14480b62235ef4fce1cd4755e1cde4c9be5f78 (diff)
hwmon: (adt7475) Handle alternative pin functions
The TACH4 pin can be used for other functions, so fan4 may not always be available. Likewise, the PWM2 pin can be used for ALERT output, in which case pwm2 is not available For the ADT7490, the +2.5 Vin pin may also be used for other functions, in which case in0 is not available. 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/adt7475.c114
1 files changed, 99 insertions, 15 deletions
diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c
index 716dae9ff0f7..d20130723d68 100644
--- a/drivers/hwmon/adt7475.c
+++ b/drivers/hwmon/adt7475.c
@@ -80,6 +80,8 @@
80 80
81#define REG_EXTEND1 0x76 81#define REG_EXTEND1 0x76
82#define REG_EXTEND2 0x77 82#define REG_EXTEND2 0x77
83
84#define REG_CONFIG3 0x78
83#define REG_CONFIG5 0x7C 85#define REG_CONFIG5 0x7C
84#define REG_CONFIG4 0x7D 86#define REG_CONFIG4 0x7D
85 87
@@ -88,6 +90,10 @@
88#define REG_VTT_MIN 0x84 /* ADT7490 only */ 90#define REG_VTT_MIN 0x84 /* ADT7490 only */
89#define REG_VTT_MAX 0x86 /* ADT7490 only */ 91#define REG_VTT_MAX 0x86 /* ADT7490 only */
90 92
93#define CONFIG3_SMBALERT 0x01
94#define CONFIG3_THERM 0x02
95
96#define CONFIG4_PINFUNC 0x03
91#define CONFIG4_MAXDUTY 0x08 97#define CONFIG4_MAXDUTY 0x08
92 98
93#define CONFIG5_TWOSCOMP 0x01 99#define CONFIG5_TWOSCOMP 0x01
@@ -149,6 +155,8 @@ struct adt7475_data {
149 u8 config4; 155 u8 config4;
150 u8 config5; 156 u8 config5;
151 u8 has_voltage; 157 u8 has_voltage;
158 u8 has_pwm2:1;
159 u8 has_fan4:1;
152 u32 alarms; 160 u32 alarms;
153 u16 voltage[3][6]; 161 u16 voltage[3][6];
154 u16 temp[7][3]; 162 u16 temp[7][3];
@@ -1025,21 +1033,12 @@ static struct attribute *adt7475_attrs[] = {
1025 &sensor_dev_attr_fan3_input.dev_attr.attr, 1033 &sensor_dev_attr_fan3_input.dev_attr.attr,
1026 &sensor_dev_attr_fan3_min.dev_attr.attr, 1034 &sensor_dev_attr_fan3_min.dev_attr.attr,
1027 &sensor_dev_attr_fan3_alarm.dev_attr.attr, 1035 &sensor_dev_attr_fan3_alarm.dev_attr.attr,
1028 &sensor_dev_attr_fan4_input.dev_attr.attr,
1029 &sensor_dev_attr_fan4_min.dev_attr.attr,
1030 &sensor_dev_attr_fan4_alarm.dev_attr.attr,
1031 &sensor_dev_attr_pwm1.dev_attr.attr, 1036 &sensor_dev_attr_pwm1.dev_attr.attr,
1032 &sensor_dev_attr_pwm1_freq.dev_attr.attr, 1037 &sensor_dev_attr_pwm1_freq.dev_attr.attr,
1033 &sensor_dev_attr_pwm1_enable.dev_attr.attr, 1038 &sensor_dev_attr_pwm1_enable.dev_attr.attr,
1034 &sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr, 1039 &sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr,
1035 &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, 1040 &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr,
1036 &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr, 1041 &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr,
1037 &sensor_dev_attr_pwm2.dev_attr.attr,
1038 &sensor_dev_attr_pwm2_freq.dev_attr.attr,
1039 &sensor_dev_attr_pwm2_enable.dev_attr.attr,
1040 &sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr,
1041 &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr,
1042 &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr,
1043 &sensor_dev_attr_pwm3.dev_attr.attr, 1042 &sensor_dev_attr_pwm3.dev_attr.attr,
1044 &sensor_dev_attr_pwm3_freq.dev_attr.attr, 1043 &sensor_dev_attr_pwm3_freq.dev_attr.attr,
1045 &sensor_dev_attr_pwm3_enable.dev_attr.attr, 1044 &sensor_dev_attr_pwm3_enable.dev_attr.attr,
@@ -1050,12 +1049,33 @@ static struct attribute *adt7475_attrs[] = {
1050 NULL, 1049 NULL,
1051}; 1050};
1052 1051
1052static struct attribute *fan4_attrs[] = {
1053 &sensor_dev_attr_fan4_input.dev_attr.attr,
1054 &sensor_dev_attr_fan4_min.dev_attr.attr,
1055 &sensor_dev_attr_fan4_alarm.dev_attr.attr,
1056 NULL
1057};
1058
1059static struct attribute *pwm2_attrs[] = {
1060 &sensor_dev_attr_pwm2.dev_attr.attr,
1061 &sensor_dev_attr_pwm2_freq.dev_attr.attr,
1062 &sensor_dev_attr_pwm2_enable.dev_attr.attr,
1063 &sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr,
1064 &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr,
1065 &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr,
1066 NULL
1067};
1068
1053/* Attributes specific to the ADT7490 */ 1069/* Attributes specific to the ADT7490 */
1054static struct attribute *adt7490_attrs[] = { 1070static struct attribute *in0_attrs[] = {
1055 &sensor_dev_attr_in0_input.dev_attr.attr, 1071 &sensor_dev_attr_in0_input.dev_attr.attr,
1056 &sensor_dev_attr_in0_max.dev_attr.attr, 1072 &sensor_dev_attr_in0_max.dev_attr.attr,
1057 &sensor_dev_attr_in0_min.dev_attr.attr, 1073 &sensor_dev_attr_in0_min.dev_attr.attr,
1058 &sensor_dev_attr_in0_alarm.dev_attr.attr, 1074 &sensor_dev_attr_in0_alarm.dev_attr.attr,
1075 NULL
1076};
1077
1078static struct attribute *adt7490_attrs[] = {
1059 &sensor_dev_attr_in3_input.dev_attr.attr, 1079 &sensor_dev_attr_in3_input.dev_attr.attr,
1060 &sensor_dev_attr_in3_max.dev_attr.attr, 1080 &sensor_dev_attr_in3_max.dev_attr.attr,
1061 &sensor_dev_attr_in3_min.dev_attr.attr, 1081 &sensor_dev_attr_in3_min.dev_attr.attr,
@@ -1072,6 +1092,9 @@ static struct attribute *adt7490_attrs[] = {
1072}; 1092};
1073 1093
1074static struct attribute_group adt7475_attr_group = { .attrs = adt7475_attrs }; 1094static struct attribute_group adt7475_attr_group = { .attrs = adt7475_attrs };
1095static struct attribute_group fan4_attr_group = { .attrs = fan4_attrs };
1096static struct attribute_group pwm2_attr_group = { .attrs = pwm2_attrs };
1097static struct attribute_group in0_attr_group = { .attrs = in0_attrs };
1075static struct attribute_group adt7490_attr_group = { .attrs = adt7490_attrs }; 1098static struct attribute_group adt7490_attr_group = { .attrs = adt7490_attrs };
1076 1099
1077static int adt7475_detect(struct i2c_client *client, int kind, 1100static int adt7475_detect(struct i2c_client *client, int kind,
@@ -1115,13 +1138,20 @@ static void adt7475_remove_files(struct i2c_client *client,
1115 sysfs_remove_group(&client->dev.kobj, &adt7475_attr_group); 1138 sysfs_remove_group(&client->dev.kobj, &adt7475_attr_group);
1116 if (data->has_voltage & 0x39) 1139 if (data->has_voltage & 0x39)
1117 sysfs_remove_group(&client->dev.kobj, &adt7490_attr_group); 1140 sysfs_remove_group(&client->dev.kobj, &adt7490_attr_group);
1141 if (data->has_fan4)
1142 sysfs_remove_group(&client->dev.kobj, &fan4_attr_group);
1143 if (data->has_pwm2)
1144 sysfs_remove_group(&client->dev.kobj, &pwm2_attr_group);
1145 if (data->has_voltage & (1 << 0))
1146 sysfs_remove_group(&client->dev.kobj, &in0_attr_group);
1118} 1147}
1119 1148
1120static int adt7475_probe(struct i2c_client *client, 1149static int adt7475_probe(struct i2c_client *client,
1121 const struct i2c_device_id *id) 1150 const struct i2c_device_id *id)
1122{ 1151{
1123 struct adt7475_data *data; 1152 struct adt7475_data *data;
1124 int i, ret = 0; 1153 int i, ret = 0, revision;
1154 u8 config3;
1125 1155
1126 data = kzalloc(sizeof(*data), GFP_KERNEL); 1156 data = kzalloc(sizeof(*data), GFP_KERNEL);
1127 if (data == NULL) 1157 if (data == NULL)
@@ -1133,10 +1163,36 @@ static int adt7475_probe(struct i2c_client *client,
1133 /* Initialize device-specific values */ 1163 /* Initialize device-specific values */
1134 switch (id->driver_data) { 1164 switch (id->driver_data) {
1135 case adt7490: 1165 case adt7490:
1136 data->has_voltage = 0x3f; /* in0 to in5 */ 1166 data->has_voltage = 0x3e; /* in1 to in5 */
1167 revision = adt7475_read(REG_DEVID2) & 0x03;
1137 break; 1168 break;
1138 default: 1169 default:
1139 data->has_voltage = 0x06; /* in1, in2 */ 1170 data->has_voltage = 0x06; /* in1, in2 */
1171 revision = adt7475_read(REG_DEVID2) & 0x07;
1172 }
1173
1174 config3 = adt7475_read(REG_CONFIG3);
1175 /* Pin PWM2 may alternatively be used for ALERT output */
1176 if (!(config3 & CONFIG3_SMBALERT))
1177 data->has_pwm2 = 1;
1178 /* Meaning of this bit is inverted for the ADT7473-1 */
1179 if (id->driver_data == adt7473 && revision >= 1)
1180 data->has_pwm2 = !data->has_pwm2;
1181
1182 data->config4 = adt7475_read(REG_CONFIG4);
1183 /* Pin TACH4 may alternatively be used for THERM */
1184 if ((data->config4 & CONFIG4_PINFUNC) == 0x0)
1185 data->has_fan4 = 1;
1186
1187 /* THERM configuration is more complex on the ADT7490, because 2
1188 different pins (TACH4 and +2.5 Vin) can be used for this function */
1189 if (id->driver_data == adt7490) {
1190 if ((data->config4 & CONFIG4_PINFUNC) == 0x1 &&
1191 !(config3 & CONFIG3_THERM))
1192 data->has_fan4 = 1;
1193 if (!(config3 & CONFIG3_THERM) ||
1194 (data->config4 & CONFIG4_PINFUNC) == 0x1)
1195 data->has_voltage |= (1 << 0); /* in0 */
1140 } 1196 }
1141 1197
1142 /* Call adt7475_read_pwm for all pwm's as this will reprogram any 1198 /* Call adt7475_read_pwm for all pwm's as this will reprogram any
@@ -1155,6 +1211,23 @@ static int adt7475_probe(struct i2c_client *client,
1155 goto eremove; 1211 goto eremove;
1156 } 1212 }
1157 1213
1214 /* Features that can be disabled individually */
1215 if (data->has_fan4) {
1216 ret = sysfs_create_group(&client->dev.kobj, &fan4_attr_group);
1217 if (ret)
1218 goto eremove;
1219 }
1220 if (data->has_pwm2) {
1221 ret = sysfs_create_group(&client->dev.kobj, &pwm2_attr_group);
1222 if (ret)
1223 goto eremove;
1224 }
1225 if (data->has_voltage & (1 << 0)) {
1226 ret = sysfs_create_group(&client->dev.kobj, &in0_attr_group);
1227 if (ret)
1228 goto eremove;
1229 }
1230
1158 data->hwmon_dev = hwmon_device_register(&client->dev); 1231 data->hwmon_dev = hwmon_device_register(&client->dev);
1159 if (IS_ERR(data->hwmon_dev)) { 1232 if (IS_ERR(data->hwmon_dev)) {
1160 ret = PTR_ERR(data->hwmon_dev); 1233 ret = PTR_ERR(data->hwmon_dev);
@@ -1293,13 +1366,19 @@ static struct adt7475_data *adt7475_update_device(struct device *dev)
1293 ((ext >> 4) & 3); 1366 ((ext >> 4) & 3);
1294 } 1367 }
1295 1368
1296 for (i = 0; i < ADT7475_TACH_COUNT; i++) 1369 for (i = 0; i < ADT7475_TACH_COUNT; i++) {
1370 if (i == 3 && !data->has_fan4)
1371 continue;
1297 data->tach[INPUT][i] = 1372 data->tach[INPUT][i] =
1298 adt7475_read_word(client, TACH_REG(i)); 1373 adt7475_read_word(client, TACH_REG(i));
1374 }
1299 1375
1300 /* Updated by hw when in auto mode */ 1376 /* Updated by hw when in auto mode */
1301 for (i = 0; i < ADT7475_PWM_COUNT; i++) 1377 for (i = 0; i < ADT7475_PWM_COUNT; i++) {
1378 if (i == 1 && !data->has_pwm2)
1379 continue;
1302 data->pwm[INPUT][i] = adt7475_read(PWM_REG(i)); 1380 data->pwm[INPUT][i] = adt7475_read(PWM_REG(i));
1381 }
1303 1382
1304 data->measure_updated = jiffies; 1383 data->measure_updated = jiffies;
1305 } 1384 }
@@ -1340,11 +1419,16 @@ static struct adt7475_data *adt7475_update_device(struct device *dev)
1340 } 1419 }
1341 adt7475_read_hystersis(client); 1420 adt7475_read_hystersis(client);
1342 1421
1343 for (i = 0; i < ADT7475_TACH_COUNT; i++) 1422 for (i = 0; i < ADT7475_TACH_COUNT; i++) {
1423 if (i == 3 && !data->has_fan4)
1424 continue;
1344 data->tach[MIN][i] = 1425 data->tach[MIN][i] =
1345 adt7475_read_word(client, TACH_MIN_REG(i)); 1426 adt7475_read_word(client, TACH_MIN_REG(i));
1427 }
1346 1428
1347 for (i = 0; i < ADT7475_PWM_COUNT; i++) { 1429 for (i = 0; i < ADT7475_PWM_COUNT; i++) {
1430 if (i == 1 && !data->has_pwm2)
1431 continue;
1348 data->pwm[MAX][i] = adt7475_read(PWM_MAX_REG(i)); 1432 data->pwm[MAX][i] = adt7475_read(PWM_MAX_REG(i));
1349 data->pwm[MIN][i] = adt7475_read(PWM_MIN_REG(i)); 1433 data->pwm[MIN][i] = adt7475_read(PWM_MIN_REG(i));
1350 /* Set the channel and control information */ 1434 /* Set the channel and control information */