Commit 2778fb13ba0fed1b3e4a040e71f7881d399610a3
Committed by
Guenter Roeck
1 parent
100b33c8bd
Exists in
master
and in
39 other branches
hwmon: (lm63) Consider LM64 temperature offset
LM64 has 16 degrees Celsius temperature offset on all remote sensor registers. This was not considered When LM64 support was added to lm63.c. Signed-off-by: Dirk Eibach <eibach@gdsys.de> Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com> Cc: stable@kernel.org
Showing 1 changed file with 47 additions and 12 deletions Side-by-side Diff
drivers/hwmon/lm63.c
... | ... | @@ -98,6 +98,9 @@ |
98 | 98 | * value, it uses signed 8-bit values with LSB = 1 degree Celsius. |
99 | 99 | * For remote temperature, low and high limits, it uses signed 11-bit values |
100 | 100 | * with LSB = 0.125 degree Celsius, left-justified in 16-bit registers. |
101 | + * For LM64 the actual remote diode temperature is 16 degree Celsius higher | |
102 | + * than the register reading. Remote temperature setpoints have to be | |
103 | + * adapted accordingly. | |
101 | 104 | */ |
102 | 105 | |
103 | 106 | #define FAN_FROM_REG(reg) ((reg) == 0xFFFC || (reg) == 0 ? 0 : \ |
... | ... | @@ -165,6 +168,8 @@ |
165 | 168 | struct mutex update_lock; |
166 | 169 | char valid; /* zero until following fields are valid */ |
167 | 170 | unsigned long last_updated; /* in jiffies */ |
171 | + int kind; | |
172 | + int temp2_offset; | |
168 | 173 | |
169 | 174 | /* registers values */ |
170 | 175 | u8 config, config_fan; |
171 | 176 | |
172 | 177 | |
... | ... | @@ -247,17 +252,35 @@ |
247 | 252 | return sprintf(buf, "%d\n", data->config_fan & 0x20 ? 1 : 2); |
248 | 253 | } |
249 | 254 | |
250 | -static ssize_t show_temp8(struct device *dev, struct device_attribute *devattr, | |
251 | - char *buf) | |
255 | +/* | |
256 | + * There are 8bit registers for both local(temp1) and remote(temp2) sensor. | |
257 | + * For remote sensor registers temp2_offset has to be considered, | |
258 | + * for local sensor it must not. | |
259 | + * So we need separate 8bit accessors for local and remote sensor. | |
260 | + */ | |
261 | +static ssize_t show_local_temp8(struct device *dev, | |
262 | + struct device_attribute *devattr, | |
263 | + char *buf) | |
252 | 264 | { |
253 | 265 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
254 | 266 | struct lm63_data *data = lm63_update_device(dev); |
255 | 267 | return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->temp8[attr->index])); |
256 | 268 | } |
257 | 269 | |
258 | -static ssize_t set_temp8(struct device *dev, struct device_attribute *dummy, | |
259 | - const char *buf, size_t count) | |
270 | +static ssize_t show_remote_temp8(struct device *dev, | |
271 | + struct device_attribute *devattr, | |
272 | + char *buf) | |
260 | 273 | { |
274 | + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | |
275 | + struct lm63_data *data = lm63_update_device(dev); | |
276 | + return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->temp8[attr->index]) | |
277 | + + data->temp2_offset); | |
278 | +} | |
279 | + | |
280 | +static ssize_t set_local_temp8(struct device *dev, | |
281 | + struct device_attribute *dummy, | |
282 | + const char *buf, size_t count) | |
283 | +{ | |
261 | 284 | struct i2c_client *client = to_i2c_client(dev); |
262 | 285 | struct lm63_data *data = i2c_get_clientdata(client); |
263 | 286 | long val = simple_strtol(buf, NULL, 10); |
... | ... | @@ -274,7 +297,8 @@ |
274 | 297 | { |
275 | 298 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
276 | 299 | struct lm63_data *data = lm63_update_device(dev); |
277 | - return sprintf(buf, "%d\n", TEMP11_FROM_REG(data->temp11[attr->index])); | |
300 | + return sprintf(buf, "%d\n", TEMP11_FROM_REG(data->temp11[attr->index]) | |
301 | + + data->temp2_offset); | |
278 | 302 | } |
279 | 303 | |
280 | 304 | static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr, |
... | ... | @@ -294,7 +318,7 @@ |
294 | 318 | int nr = attr->index; |
295 | 319 | |
296 | 320 | mutex_lock(&data->update_lock); |
297 | - data->temp11[nr] = TEMP11_TO_REG(val); | |
321 | + data->temp11[nr] = TEMP11_TO_REG(val - data->temp2_offset); | |
298 | 322 | i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2], |
299 | 323 | data->temp11[nr] >> 8); |
300 | 324 | i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1], |
... | ... | @@ -310,6 +334,7 @@ |
310 | 334 | { |
311 | 335 | struct lm63_data *data = lm63_update_device(dev); |
312 | 336 | return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->temp8[2]) |
337 | + + data->temp2_offset | |
313 | 338 | - TEMP8_FROM_REG(data->temp2_crit_hyst)); |
314 | 339 | } |
315 | 340 | |
... | ... | @@ -324,7 +349,7 @@ |
324 | 349 | long hyst; |
325 | 350 | |
326 | 351 | mutex_lock(&data->update_lock); |
327 | - hyst = TEMP8_FROM_REG(data->temp8[2]) - val; | |
352 | + hyst = TEMP8_FROM_REG(data->temp8[2]) + data->temp2_offset - val; | |
328 | 353 | i2c_smbus_write_byte_data(client, LM63_REG_REMOTE_TCRIT_HYST, |
329 | 354 | HYST_TO_REG(hyst)); |
330 | 355 | mutex_unlock(&data->update_lock); |
331 | 356 | |
... | ... | @@ -355,16 +380,21 @@ |
355 | 380 | static DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm1, set_pwm1); |
356 | 381 | static DEVICE_ATTR(pwm1_enable, S_IRUGO, show_pwm1_enable, NULL); |
357 | 382 | |
358 | -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp8, NULL, 0); | |
359 | -static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp8, | |
360 | - set_temp8, 1); | |
383 | +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_local_temp8, NULL, 0); | |
384 | +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_local_temp8, | |
385 | + set_local_temp8, 1); | |
361 | 386 | |
362 | 387 | static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp11, NULL, 0); |
363 | 388 | static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp11, |
364 | 389 | set_temp11, 1); |
365 | 390 | static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp11, |
366 | 391 | set_temp11, 2); |
367 | -static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp8, NULL, 2); | |
392 | +/* | |
393 | + * On LM63, temp2_crit can be set only once, which should be job | |
394 | + * of the bootloader. | |
395 | + */ | |
396 | +static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_remote_temp8, | |
397 | + NULL, 2); | |
368 | 398 | static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp2_crit_hyst, |
369 | 399 | set_temp2_crit_hyst); |
370 | 400 | |
... | ... | @@ -479,7 +509,12 @@ |
479 | 509 | data->valid = 0; |
480 | 510 | mutex_init(&data->update_lock); |
481 | 511 | |
482 | - /* Initialize the LM63 chip */ | |
512 | + /* Set the device type */ | |
513 | + data->kind = id->driver_data; | |
514 | + if (data->kind == lm64) | |
515 | + data->temp2_offset = 16000; | |
516 | + | |
517 | + /* Initialize chip */ | |
483 | 518 | lm63_init_client(new_client); |
484 | 519 | |
485 | 520 | /* Register sysfs hooks */ |