Commit 2778fb13 authored by Dirk Eibach's avatar Dirk Eibach Committed by Guenter Roeck

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: default avatarDirk Eibach <eibach@gdsys.de>
Signed-off-by: default avatarGuenter Roeck <guenter.roeck@ericsson.com>
Cc: stable@kernel.org
parent 100b33c8
...@@ -98,6 +98,9 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END }; ...@@ -98,6 +98,9 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END };
* value, it uses signed 8-bit values with LSB = 1 degree Celsius. * value, it uses signed 8-bit values with LSB = 1 degree Celsius.
* For remote temperature, low and high limits, it uses signed 11-bit values * For remote temperature, low and high limits, it uses signed 11-bit values
* with LSB = 0.125 degree Celsius, left-justified in 16-bit registers. * with LSB = 0.125 degree Celsius, left-justified in 16-bit registers.
* For LM64 the actual remote diode temperature is 16 degree Celsius higher
* than the register reading. Remote temperature setpoints have to be
* adapted accordingly.
*/ */
#define FAN_FROM_REG(reg) ((reg) == 0xFFFC || (reg) == 0 ? 0 : \ #define FAN_FROM_REG(reg) ((reg) == 0xFFFC || (reg) == 0 ? 0 : \
...@@ -165,6 +168,8 @@ struct lm63_data { ...@@ -165,6 +168,8 @@ struct lm63_data {
struct mutex update_lock; struct mutex update_lock;
char valid; /* zero until following fields are valid */ char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */ unsigned long last_updated; /* in jiffies */
int kind;
int temp2_offset;
/* registers values */ /* registers values */
u8 config, config_fan; u8 config, config_fan;
...@@ -247,16 +252,34 @@ static ssize_t show_pwm1_enable(struct device *dev, struct device_attribute *dum ...@@ -247,16 +252,34 @@ static ssize_t show_pwm1_enable(struct device *dev, struct device_attribute *dum
return sprintf(buf, "%d\n", data->config_fan & 0x20 ? 1 : 2); return sprintf(buf, "%d\n", data->config_fan & 0x20 ? 1 : 2);
} }
static ssize_t show_temp8(struct device *dev, struct device_attribute *devattr, /*
char *buf) * There are 8bit registers for both local(temp1) and remote(temp2) sensor.
* For remote sensor registers temp2_offset has to be considered,
* for local sensor it must not.
* So we need separate 8bit accessors for local and remote sensor.
*/
static ssize_t show_local_temp8(struct device *dev,
struct device_attribute *devattr,
char *buf)
{ {
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct lm63_data *data = lm63_update_device(dev); struct lm63_data *data = lm63_update_device(dev);
return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->temp8[attr->index])); return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->temp8[attr->index]));
} }
static ssize_t set_temp8(struct device *dev, struct device_attribute *dummy, static ssize_t show_remote_temp8(struct device *dev,
const char *buf, size_t count) struct device_attribute *devattr,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct lm63_data *data = lm63_update_device(dev);
return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->temp8[attr->index])
+ data->temp2_offset);
}
static ssize_t set_local_temp8(struct device *dev,
struct device_attribute *dummy,
const char *buf, size_t count)
{ {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct lm63_data *data = i2c_get_clientdata(client); struct lm63_data *data = i2c_get_clientdata(client);
...@@ -274,7 +297,8 @@ static ssize_t show_temp11(struct device *dev, struct device_attribute *devattr, ...@@ -274,7 +297,8 @@ static ssize_t show_temp11(struct device *dev, struct device_attribute *devattr,
{ {
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct lm63_data *data = lm63_update_device(dev); struct lm63_data *data = lm63_update_device(dev);
return sprintf(buf, "%d\n", TEMP11_FROM_REG(data->temp11[attr->index])); return sprintf(buf, "%d\n", TEMP11_FROM_REG(data->temp11[attr->index])
+ data->temp2_offset);
} }
static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr, static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr,
...@@ -294,7 +318,7 @@ static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr, ...@@ -294,7 +318,7 @@ static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr,
int nr = attr->index; int nr = attr->index;
mutex_lock(&data->update_lock); mutex_lock(&data->update_lock);
data->temp11[nr] = TEMP11_TO_REG(val); data->temp11[nr] = TEMP11_TO_REG(val - data->temp2_offset);
i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2], i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2],
data->temp11[nr] >> 8); data->temp11[nr] >> 8);
i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1], i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1],
...@@ -310,6 +334,7 @@ static ssize_t show_temp2_crit_hyst(struct device *dev, struct device_attribute ...@@ -310,6 +334,7 @@ static ssize_t show_temp2_crit_hyst(struct device *dev, struct device_attribute
{ {
struct lm63_data *data = lm63_update_device(dev); struct lm63_data *data = lm63_update_device(dev);
return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->temp8[2]) return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->temp8[2])
+ data->temp2_offset
- TEMP8_FROM_REG(data->temp2_crit_hyst)); - TEMP8_FROM_REG(data->temp2_crit_hyst));
} }
...@@ -324,7 +349,7 @@ static ssize_t set_temp2_crit_hyst(struct device *dev, struct device_attribute * ...@@ -324,7 +349,7 @@ static ssize_t set_temp2_crit_hyst(struct device *dev, struct device_attribute *
long hyst; long hyst;
mutex_lock(&data->update_lock); mutex_lock(&data->update_lock);
hyst = TEMP8_FROM_REG(data->temp8[2]) - val; hyst = TEMP8_FROM_REG(data->temp8[2]) + data->temp2_offset - val;
i2c_smbus_write_byte_data(client, LM63_REG_REMOTE_TCRIT_HYST, i2c_smbus_write_byte_data(client, LM63_REG_REMOTE_TCRIT_HYST,
HYST_TO_REG(hyst)); HYST_TO_REG(hyst));
mutex_unlock(&data->update_lock); mutex_unlock(&data->update_lock);
...@@ -355,16 +380,21 @@ static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan, ...@@ -355,16 +380,21 @@ static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan,
static DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm1, set_pwm1); static DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm1, set_pwm1);
static DEVICE_ATTR(pwm1_enable, S_IRUGO, show_pwm1_enable, NULL); static DEVICE_ATTR(pwm1_enable, S_IRUGO, show_pwm1_enable, NULL);
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp8, NULL, 0); static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_local_temp8, NULL, 0);
static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp8, static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_local_temp8,
set_temp8, 1); set_local_temp8, 1);
static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp11, NULL, 0); static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp11, NULL, 0);
static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp11, static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp11,
set_temp11, 1); set_temp11, 1);
static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp11, static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp11,
set_temp11, 2); set_temp11, 2);
static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp8, NULL, 2); /*
* On LM63, temp2_crit can be set only once, which should be job
* of the bootloader.
*/
static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_remote_temp8,
NULL, 2);
static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp2_crit_hyst, static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp2_crit_hyst,
set_temp2_crit_hyst); set_temp2_crit_hyst);
...@@ -479,7 +509,12 @@ static int lm63_probe(struct i2c_client *new_client, ...@@ -479,7 +509,12 @@ static int lm63_probe(struct i2c_client *new_client,
data->valid = 0; data->valid = 0;
mutex_init(&data->update_lock); mutex_init(&data->update_lock);
/* Initialize the LM63 chip */ /* Set the device type */
data->kind = id->driver_data;
if (data->kind == lm64)
data->temp2_offset = 16000;
/* Initialize chip */
lm63_init_client(new_client); lm63_init_client(new_client);
/* Register sysfs hooks */ /* Register sysfs hooks */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment