diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/hwmon/adt7475.c | 42 |
1 files changed, 36 insertions, 6 deletions
diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c index 688b0a1af5a8..eac24c1361bc 100644 --- a/drivers/hwmon/adt7475.c +++ b/drivers/hwmon/adt7475.c | |||
| @@ -80,6 +80,8 @@ | |||
| 80 | 80 | ||
| 81 | #define REG_TEMP_OFFSET_BASE 0x70 | 81 | #define REG_TEMP_OFFSET_BASE 0x70 |
| 82 | 82 | ||
| 83 | #define REG_CONFIG2 0x73 | ||
| 84 | |||
| 83 | #define REG_EXTEND1 0x76 | 85 | #define REG_EXTEND1 0x76 |
| 84 | #define REG_EXTEND2 0x77 | 86 | #define REG_EXTEND2 0x77 |
| 85 | 87 | ||
| @@ -92,11 +94,15 @@ | |||
| 92 | #define REG_VTT_MIN 0x84 /* ADT7490 only */ | 94 | #define REG_VTT_MIN 0x84 /* ADT7490 only */ |
| 93 | #define REG_VTT_MAX 0x86 /* ADT7490 only */ | 95 | #define REG_VTT_MAX 0x86 /* ADT7490 only */ |
| 94 | 96 | ||
| 97 | #define CONFIG2_ATTN 0x20 | ||
| 98 | |||
| 95 | #define CONFIG3_SMBALERT 0x01 | 99 | #define CONFIG3_SMBALERT 0x01 |
| 96 | #define CONFIG3_THERM 0x02 | 100 | #define CONFIG3_THERM 0x02 |
| 97 | 101 | ||
| 98 | #define CONFIG4_PINFUNC 0x03 | 102 | #define CONFIG4_PINFUNC 0x03 |
| 99 | #define CONFIG4_MAXDUTY 0x08 | 103 | #define CONFIG4_MAXDUTY 0x08 |
| 104 | #define CONFIG4_ATTN_IN10 0x30 | ||
| 105 | #define CONFIG4_ATTN_IN43 0xC0 | ||
| 100 | 106 | ||
| 101 | #define CONFIG5_TWOSCOMP 0x01 | 107 | #define CONFIG5_TWOSCOMP 0x01 |
| 102 | #define CONFIG5_TEMPOFFSET 0x02 | 108 | #define CONFIG5_TEMPOFFSET 0x02 |
| @@ -157,6 +163,7 @@ struct adt7475_data { | |||
| 157 | u8 config4; | 163 | u8 config4; |
| 158 | u8 config5; | 164 | u8 config5; |
| 159 | u8 has_voltage; | 165 | u8 has_voltage; |
| 166 | u8 bypass_attn; /* Bypass voltage attenuator */ | ||
| 160 | u8 has_pwm2:1; | 167 | u8 has_pwm2:1; |
| 161 | u8 has_fan4:1; | 168 | u8 has_fan4:1; |
| 162 | u32 alarms; | 169 | u32 alarms; |
| @@ -233,19 +240,24 @@ static const int adt7473_in_scaling[ADT7475_VOLTAGE_COUNT + 1][2] = { | |||
| 233 | { 45, 45 }, /* Vtt */ | 240 | { 45, 45 }, /* Vtt */ |
| 234 | }; | 241 | }; |
| 235 | 242 | ||
| 236 | static inline int reg2volt(int channel, u16 reg) | 243 | static inline int reg2volt(int channel, u16 reg, u8 bypass_attn) |
| 237 | { | 244 | { |
| 238 | const int *r = adt7473_in_scaling[channel]; | 245 | const int *r = adt7473_in_scaling[channel]; |
| 239 | 246 | ||
| 247 | if (bypass_attn & (1 << channel)) | ||
| 248 | return DIV_ROUND_CLOSEST(reg * 2250, 1024); | ||
| 240 | return DIV_ROUND_CLOSEST(reg * (r[0] + r[1]) * 2250, r[1] * 1024); | 249 | return DIV_ROUND_CLOSEST(reg * (r[0] + r[1]) * 2250, r[1] * 1024); |
| 241 | } | 250 | } |
| 242 | 251 | ||
| 243 | static inline u16 volt2reg(int channel, long volt) | 252 | static inline u16 volt2reg(int channel, long volt, u8 bypass_attn) |
| 244 | { | 253 | { |
| 245 | const int *r = adt7473_in_scaling[channel]; | 254 | const int *r = adt7473_in_scaling[channel]; |
| 246 | long reg; | 255 | long reg; |
| 247 | 256 | ||
| 248 | reg = (volt * r[1] * 1024) / ((r[0] + r[1]) * 2250); | 257 | if (bypass_attn & (1 << channel)) |
| 258 | reg = (volt * 1024) / 2250; | ||
| 259 | else | ||
| 260 | reg = (volt * r[1] * 1024) / ((r[0] + r[1]) * 2250); | ||
| 249 | return SENSORS_LIMIT(reg, 0, 1023) & (0xff << 2); | 261 | return SENSORS_LIMIT(reg, 0, 1023) & (0xff << 2); |
| 250 | } | 262 | } |
| 251 | 263 | ||
| @@ -305,7 +317,8 @@ static ssize_t show_voltage(struct device *dev, struct device_attribute *attr, | |||
| 305 | (data->alarms >> sattr->index) & 1); | 317 | (data->alarms >> sattr->index) & 1); |
| 306 | default: | 318 | default: |
| 307 | val = data->voltage[sattr->nr][sattr->index]; | 319 | val = data->voltage[sattr->nr][sattr->index]; |
| 308 | return sprintf(buf, "%d\n", reg2volt(sattr->index, val)); | 320 | return sprintf(buf, "%d\n", |
| 321 | reg2volt(sattr->index, val, data->bypass_attn)); | ||
| 309 | } | 322 | } |
| 310 | } | 323 | } |
| 311 | 324 | ||
| @@ -324,7 +337,8 @@ static ssize_t set_voltage(struct device *dev, struct device_attribute *attr, | |||
| 324 | 337 | ||
| 325 | mutex_lock(&data->lock); | 338 | mutex_lock(&data->lock); |
| 326 | 339 | ||
| 327 | data->voltage[sattr->nr][sattr->index] = volt2reg(sattr->index, val); | 340 | data->voltage[sattr->nr][sattr->index] = |
| 341 | volt2reg(sattr->index, val, data->bypass_attn); | ||
| 328 | 342 | ||
| 329 | if (sattr->index < ADT7475_VOLTAGE_COUNT) { | 343 | if (sattr->index < ADT7475_VOLTAGE_COUNT) { |
| 330 | if (sattr->nr == MIN) | 344 | if (sattr->nr == MIN) |
| @@ -1159,7 +1173,7 @@ static int adt7475_probe(struct i2c_client *client, | |||
| 1159 | 1173 | ||
| 1160 | struct adt7475_data *data; | 1174 | struct adt7475_data *data; |
| 1161 | int i, ret = 0, revision; | 1175 | int i, ret = 0, revision; |
| 1162 | u8 config3; | 1176 | u8 config2, config3; |
| 1163 | 1177 | ||
| 1164 | data = kzalloc(sizeof(*data), GFP_KERNEL); | 1178 | data = kzalloc(sizeof(*data), GFP_KERNEL); |
| 1165 | if (data == NULL) | 1179 | if (data == NULL) |
| @@ -1205,6 +1219,16 @@ static int adt7475_probe(struct i2c_client *client, | |||
| 1205 | data->has_voltage |= (1 << 0); /* in0 */ | 1219 | data->has_voltage |= (1 << 0); /* in0 */ |
| 1206 | } | 1220 | } |
| 1207 | 1221 | ||
| 1222 | /* Voltage attenuators can be bypassed, globally or individually */ | ||
| 1223 | config2 = adt7475_read(REG_CONFIG2); | ||
| 1224 | if (config2 & CONFIG2_ATTN) { | ||
| 1225 | data->bypass_attn = (0x3 << 3) | 0x3; | ||
| 1226 | } else { | ||
| 1227 | data->bypass_attn = ((data->config4 & CONFIG4_ATTN_IN10) >> 4) | | ||
| 1228 | ((data->config4 & CONFIG4_ATTN_IN43) >> 3); | ||
| 1229 | } | ||
| 1230 | data->bypass_attn &= data->has_voltage; | ||
| 1231 | |||
| 1208 | /* Call adt7475_read_pwm for all pwm's as this will reprogram any | 1232 | /* Call adt7475_read_pwm for all pwm's as this will reprogram any |
| 1209 | pwm's which are disabled to manual mode with 0% duty cycle */ | 1233 | pwm's which are disabled to manual mode with 0% duty cycle */ |
| 1210 | for (i = 0; i < ADT7475_PWM_COUNT; i++) | 1234 | for (i = 0; i < ADT7475_PWM_COUNT; i++) |
| @@ -1251,6 +1275,12 @@ static int adt7475_probe(struct i2c_client *client, | |||
| 1251 | (data->has_voltage & (1 << 0)) ? " in0" : "", | 1275 | (data->has_voltage & (1 << 0)) ? " in0" : "", |
| 1252 | data->has_fan4 ? " fan4" : "", | 1276 | data->has_fan4 ? " fan4" : "", |
| 1253 | data->has_pwm2 ? " pwm2" : ""); | 1277 | data->has_pwm2 ? " pwm2" : ""); |
| 1278 | if (data->bypass_attn) | ||
| 1279 | dev_info(&client->dev, "Bypassing attenuators on:%s%s%s%s\n", | ||
| 1280 | (data->bypass_attn & (1 << 0)) ? " in0" : "", | ||
| 1281 | (data->bypass_attn & (1 << 1)) ? " in1" : "", | ||
| 1282 | (data->bypass_attn & (1 << 3)) ? " in3" : "", | ||
| 1283 | (data->bypass_attn & (1 << 4)) ? " in4" : ""); | ||
| 1254 | 1284 | ||
| 1255 | return 0; | 1285 | return 0; |
| 1256 | 1286 | ||
