aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2009-12-09 14:36:07 -0500
committerJean Delvare <khali@linux-fr.org>2009-12-09 14:36:07 -0500
commitebfaf1fbb6010204e973e329034d0004d6521503 (patch)
tree1048d124e52a5074994400556bc10b08d3bc2a00 /drivers/hwmon
parentd07ca4ad2f67ebb1bf48a2308a7a0cd81ef8f70a (diff)
hwmon: (adt7475) Voltage attenuators can be bypassed
It is possible to bypass the voltage attenuators on the +2.5V, Vccp, +5V and +12V voltage monitoring inputs. This is useful to connect other voltage channels than the ones the monitoring chip was originally designed for. When this feature is enabled, we must not include the scaling factors in our computations. 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/hwmon')
-rw-r--r--drivers/hwmon/adt7475.c42
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
236static inline int reg2volt(int channel, u16 reg) 243static 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
243static inline u16 volt2reg(int channel, long volt) 252static 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