diff options
Diffstat (limited to 'drivers/hwmon/w83781d.c')
| -rw-r--r-- | drivers/hwmon/w83781d.c | 131 |
1 files changed, 53 insertions, 78 deletions
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index d27ed1bac002..7ab7967da0a0 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c | |||
| @@ -1054,11 +1054,11 @@ static int | |||
| 1054 | w83781d_detect(struct i2c_client *client, int kind, | 1054 | w83781d_detect(struct i2c_client *client, int kind, |
| 1055 | struct i2c_board_info *info) | 1055 | struct i2c_board_info *info) |
| 1056 | { | 1056 | { |
| 1057 | int val1 = 0, val2; | 1057 | int val1, val2; |
| 1058 | struct w83781d_data *isa = w83781d_data_if_isa(); | 1058 | struct w83781d_data *isa = w83781d_data_if_isa(); |
| 1059 | struct i2c_adapter *adapter = client->adapter; | 1059 | struct i2c_adapter *adapter = client->adapter; |
| 1060 | int address = client->addr; | 1060 | int address = client->addr; |
| 1061 | const char *client_name = ""; | 1061 | const char *client_name; |
| 1062 | enum vendor { winbond, asus } vendid; | 1062 | enum vendor { winbond, asus } vendid; |
| 1063 | 1063 | ||
| 1064 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 1064 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
| @@ -1070,98 +1070,73 @@ w83781d_detect(struct i2c_client *client, int kind, | |||
| 1070 | if (isa) | 1070 | if (isa) |
| 1071 | mutex_lock(&isa->update_lock); | 1071 | mutex_lock(&isa->update_lock); |
| 1072 | 1072 | ||
| 1073 | /* The w8378?d may be stuck in some other bank than bank 0. This may | 1073 | if (i2c_smbus_read_byte_data(client, W83781D_REG_CONFIG) & 0x80) { |
| 1074 | make reading other information impossible. Specify a force=... or | 1074 | dev_dbg(&adapter->dev, |
| 1075 | force_*=... parameter, and the Winbond will be reset to the right | 1075 | "Detection of w83781d chip failed at step 3\n"); |
| 1076 | bank. */ | 1076 | goto err_nodev; |
| 1077 | if (kind < 0) { | 1077 | } |
| 1078 | if (i2c_smbus_read_byte_data | 1078 | |
| 1079 | (client, W83781D_REG_CONFIG) & 0x80) { | 1079 | val1 = i2c_smbus_read_byte_data(client, W83781D_REG_BANK); |
| 1080 | dev_dbg(&adapter->dev, "Detection of w83781d chip " | 1080 | val2 = i2c_smbus_read_byte_data(client, W83781D_REG_CHIPMAN); |
| 1081 | "failed at step 3\n"); | 1081 | /* Check for Winbond or Asus ID if in bank 0 */ |
| 1082 | goto err_nodev; | 1082 | if (!(val1 & 0x07) && |
| 1083 | } | 1083 | ((!(val1 & 0x80) && val2 != 0xa3 && val2 != 0xc3) || |
| 1084 | val1 = i2c_smbus_read_byte_data(client, W83781D_REG_BANK); | 1084 | ( (val1 & 0x80) && val2 != 0x5c && val2 != 0x12))) { |
| 1085 | val2 = i2c_smbus_read_byte_data(client, W83781D_REG_CHIPMAN); | 1085 | dev_dbg(&adapter->dev, |
| 1086 | /* Check for Winbond or Asus ID if in bank 0 */ | 1086 | "Detection of w83781d chip failed at step 4\n"); |
| 1087 | if ((!(val1 & 0x07)) && | 1087 | goto err_nodev; |
| 1088 | (((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3)) | 1088 | } |
| 1089 | || ((val1 & 0x80) && (val2 != 0x5c) && (val2 != 0x12)))) { | 1089 | /* If Winbond SMBus, check address at 0x48. |
| 1090 | dev_dbg(&adapter->dev, "Detection of w83781d chip " | 1090 | Asus doesn't support, except for as99127f rev.2 */ |
| 1091 | "failed at step 4\n"); | 1091 | if ((!(val1 & 0x80) && val2 == 0xa3) || |
| 1092 | ( (val1 & 0x80) && val2 == 0x5c)) { | ||
| 1093 | if (i2c_smbus_read_byte_data(client, W83781D_REG_I2C_ADDR) | ||
| 1094 | != address) { | ||
| 1095 | dev_dbg(&adapter->dev, | ||
| 1096 | "Detection of w83781d chip failed at step 5\n"); | ||
| 1092 | goto err_nodev; | 1097 | goto err_nodev; |
| 1093 | } | 1098 | } |
| 1094 | /* If Winbond SMBus, check address at 0x48. | ||
| 1095 | Asus doesn't support, except for as99127f rev.2 */ | ||
| 1096 | if ((!(val1 & 0x80) && (val2 == 0xa3)) || | ||
| 1097 | ((val1 & 0x80) && (val2 == 0x5c))) { | ||
| 1098 | if (i2c_smbus_read_byte_data | ||
| 1099 | (client, W83781D_REG_I2C_ADDR) != address) { | ||
| 1100 | dev_dbg(&adapter->dev, "Detection of w83781d " | ||
| 1101 | "chip failed at step 5\n"); | ||
| 1102 | goto err_nodev; | ||
| 1103 | } | ||
| 1104 | } | ||
| 1105 | } | 1099 | } |
| 1106 | 1100 | ||
| 1107 | /* We have either had a force parameter, or we have already detected the | 1101 | /* Put it now into bank 0 and Vendor ID High Byte */ |
| 1108 | Winbond. Put it now into bank 0 and Vendor ID High Byte */ | ||
| 1109 | i2c_smbus_write_byte_data(client, W83781D_REG_BANK, | 1102 | i2c_smbus_write_byte_data(client, W83781D_REG_BANK, |
| 1110 | (i2c_smbus_read_byte_data(client, W83781D_REG_BANK) | 1103 | (i2c_smbus_read_byte_data(client, W83781D_REG_BANK) |
| 1111 | & 0x78) | 0x80); | 1104 | & 0x78) | 0x80); |
| 1112 | 1105 | ||
| 1113 | /* Determine the chip type. */ | 1106 | /* Get the vendor ID */ |
| 1114 | if (kind <= 0) { | 1107 | val2 = i2c_smbus_read_byte_data(client, W83781D_REG_CHIPMAN); |
| 1115 | /* get vendor ID */ | 1108 | if (val2 == 0x5c) |
| 1116 | val2 = i2c_smbus_read_byte_data(client, W83781D_REG_CHIPMAN); | 1109 | vendid = winbond; |
| 1117 | if (val2 == 0x5c) | 1110 | else if (val2 == 0x12) |
| 1118 | vendid = winbond; | 1111 | vendid = asus; |
| 1119 | else if (val2 == 0x12) | 1112 | else { |
| 1120 | vendid = asus; | 1113 | dev_dbg(&adapter->dev, |
| 1121 | else { | 1114 | "w83781d chip vendor is neither Winbond nor Asus\n"); |
| 1122 | dev_dbg(&adapter->dev, "w83781d chip vendor is " | 1115 | goto err_nodev; |
| 1123 | "neither Winbond nor Asus\n"); | ||
| 1124 | goto err_nodev; | ||
| 1125 | } | ||
| 1126 | |||
| 1127 | val1 = i2c_smbus_read_byte_data(client, W83781D_REG_WCHIPID); | ||
| 1128 | if ((val1 == 0x10 || val1 == 0x11) && vendid == winbond) | ||
| 1129 | kind = w83781d; | ||
| 1130 | else if (val1 == 0x30 && vendid == winbond) | ||
| 1131 | kind = w83782d; | ||
| 1132 | else if (val1 == 0x40 && vendid == winbond && address == 0x2d) | ||
| 1133 | kind = w83783s; | ||
| 1134 | else if (val1 == 0x31) | ||
| 1135 | kind = as99127f; | ||
| 1136 | else { | ||
| 1137 | if (kind == 0) | ||
| 1138 | dev_warn(&adapter->dev, "Ignoring 'force' " | ||
| 1139 | "parameter for unknown chip at " | ||
| 1140 | "address 0x%02x\n", address); | ||
| 1141 | goto err_nodev; | ||
| 1142 | } | ||
| 1143 | |||
| 1144 | if ((kind == w83781d || kind == w83782d) | ||
| 1145 | && w83781d_alias_detect(client, val1)) { | ||
| 1146 | dev_dbg(&adapter->dev, "Device at 0x%02x appears to " | ||
| 1147 | "be the same as ISA device\n", address); | ||
| 1148 | goto err_nodev; | ||
| 1149 | } | ||
| 1150 | } | 1116 | } |
| 1151 | 1117 | ||
| 1152 | if (isa) | 1118 | /* Determine the chip type. */ |
| 1153 | mutex_unlock(&isa->update_lock); | 1119 | val1 = i2c_smbus_read_byte_data(client, W83781D_REG_WCHIPID); |
| 1154 | 1120 | if ((val1 == 0x10 || val1 == 0x11) && vendid == winbond) | |
| 1155 | if (kind == w83781d) { | ||
| 1156 | client_name = "w83781d"; | 1121 | client_name = "w83781d"; |
| 1157 | } else if (kind == w83782d) { | 1122 | else if (val1 == 0x30 && vendid == winbond) |
| 1158 | client_name = "w83782d"; | 1123 | client_name = "w83782d"; |
| 1159 | } else if (kind == w83783s) { | 1124 | else if (val1 == 0x40 && vendid == winbond && address == 0x2d) |
| 1160 | client_name = "w83783s"; | 1125 | client_name = "w83783s"; |
| 1161 | } else if (kind == as99127f) { | 1126 | else if (val1 == 0x31) |
| 1162 | client_name = "as99127f"; | 1127 | client_name = "as99127f"; |
| 1128 | else | ||
| 1129 | goto err_nodev; | ||
| 1130 | |||
| 1131 | if (val1 <= 0x30 && w83781d_alias_detect(client, val1)) { | ||
| 1132 | dev_dbg(&adapter->dev, "Device at 0x%02x appears to " | ||
| 1133 | "be the same as ISA device\n", address); | ||
| 1134 | goto err_nodev; | ||
| 1163 | } | 1135 | } |
| 1164 | 1136 | ||
| 1137 | if (isa) | ||
| 1138 | mutex_unlock(&isa->update_lock); | ||
| 1139 | |||
| 1165 | strlcpy(info->type, client_name, I2C_NAME_SIZE); | 1140 | strlcpy(info->type, client_name, I2C_NAME_SIZE); |
| 1166 | 1141 | ||
| 1167 | return 0; | 1142 | return 0; |
