diff options
Diffstat (limited to 'drivers/hwmon/adt7475.c')
-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 | ||