Commit e872c91e authored by Guenter Roeck's avatar Guenter Roeck Committed by Jean Delvare

hwmon: (lm63) Add support for unsigned upper temperature limits

LM96163 supports unsigned upper limits for the external temperature sensor.
Add support for it.
Signed-off-by: default avatarGuenter Roeck <linux@roeck-us.net>
Signed-off-by: default avatarJean Delvare <khali@linux-fr.org>
parent 210961c4
...@@ -92,6 +92,8 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END }; ...@@ -92,6 +92,8 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END };
#define LM63_REG_MAN_ID 0xFE #define LM63_REG_MAN_ID 0xFE
#define LM63_REG_CHIP_ID 0xFF #define LM63_REG_CHIP_ID 0xFF
#define LM96163_REG_REMOTE_TEMP_U_MSB 0x31
#define LM96163_REG_REMOTE_TEMP_U_LSB 0x32
#define LM96163_REG_CONFIG_ENHANCED 0x45 #define LM96163_REG_CONFIG_ENHANCED 0x45
/* /*
...@@ -120,6 +122,9 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END }; ...@@ -120,6 +122,9 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END };
(val) >= 127875 ? 0x7FE0 : \ (val) >= 127875 ? 0x7FE0 : \
(val) < 0 ? ((val) - 62) / 125 * 32 : \ (val) < 0 ? ((val) - 62) / 125 * 32 : \
((val) + 62) / 125 * 32) ((val) + 62) / 125 * 32)
#define TEMP11U_TO_REG(val) ((val) <= 0 ? 0 : \
(val) >= 255875 ? 0xFFE0 : \
((val) + 62) / 125 * 32)
#define HYST_TO_REG(val) ((val) <= 0 ? 0 : \ #define HYST_TO_REG(val) ((val) <= 0 ? 0 : \
(val) >= 127000 ? 127 : \ (val) >= 127000 ? 127 : \
((val) + 500) / 1000) ((val) + 500) / 1000)
...@@ -188,11 +193,20 @@ struct lm63_data { ...@@ -188,11 +193,20 @@ struct lm63_data {
1: remote low limit 1: remote low limit
2: remote high limit 2: remote high limit
3: remote offset */ 3: remote offset */
u16 temp11u; /* remote input (unsigned) */
u8 temp2_crit_hyst; u8 temp2_crit_hyst;
u8 alarms; u8 alarms;
bool pwm_highres; bool pwm_highres;
bool remote_unsigned; /* true if unsigned remote upper limits */
}; };
static inline int temp8_from_reg(struct lm63_data *data, int nr)
{
if (data->remote_unsigned)
return TEMP8_FROM_REG((u8)data->temp8[nr]);
return TEMP8_FROM_REG(data->temp8[nr]);
}
/* /*
* Sysfs callback functions and files * Sysfs callback functions and files
*/ */
...@@ -295,7 +309,7 @@ static ssize_t show_remote_temp8(struct device *dev, ...@@ -295,7 +309,7 @@ static ssize_t show_remote_temp8(struct device *dev,
{ {
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, attr->index)
+ data->temp2_offset); + data->temp2_offset);
} }
...@@ -324,8 +338,25 @@ static ssize_t show_temp11(struct device *dev, struct device_attribute *devattr, ...@@ -324,8 +338,25 @@ 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]) int nr = attr->index;
+ data->temp2_offset); int temp;
if (!nr) {
/*
* Use unsigned temperature unless its value is zero.
* If it is zero, use signed temperature.
*/
if (data->temp11u)
temp = TEMP11_FROM_REG(data->temp11u);
else
temp = TEMP11_FROM_REG(data->temp11[nr]);
} else {
if (data->remote_unsigned && nr == 2)
temp = TEMP11_FROM_REG((u16)data->temp11[nr]);
else
temp = TEMP11_FROM_REG(data->temp11[nr]);
}
return sprintf(buf, "%d\n", temp + 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,
...@@ -352,7 +383,11 @@ static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr, ...@@ -352,7 +383,11 @@ static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr,
return err; return err;
mutex_lock(&data->update_lock); mutex_lock(&data->update_lock);
data->temp11[nr] = TEMP11_TO_REG(val - data->temp2_offset); if (data->remote_unsigned && nr == 2)
data->temp11[nr] = TEMP11U_TO_REG(val - data->temp2_offset);
else
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],
...@@ -369,7 +404,7 @@ static ssize_t show_temp2_crit_hyst(struct device *dev, ...@@ -369,7 +404,7 @@ static ssize_t show_temp2_crit_hyst(struct device *dev,
struct device_attribute *dummy, char *buf) struct device_attribute *dummy, char *buf)
{ {
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, 2)
+ data->temp2_offset + data->temp2_offset
- TEMP8_FROM_REG(data->temp2_crit_hyst)); - TEMP8_FROM_REG(data->temp2_crit_hyst));
} }
...@@ -393,7 +428,7 @@ static ssize_t set_temp2_crit_hyst(struct device *dev, ...@@ -393,7 +428,7 @@ static ssize_t set_temp2_crit_hyst(struct device *dev,
return err; return err;
mutex_lock(&data->update_lock); mutex_lock(&data->update_lock);
hyst = TEMP8_FROM_REG(data->temp8[2]) + data->temp2_offset - val; hyst = temp8_from_reg(data, 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);
...@@ -620,9 +655,8 @@ static void lm63_init_client(struct i2c_client *client) ...@@ -620,9 +655,8 @@ static void lm63_init_client(struct i2c_client *client)
data->pwm1_freq = 1; data->pwm1_freq = 1;
/* /*
* For LM96163, check if high resolution PWM is enabled. * For LM96163, check if high resolution PWM
* Also, check if unsigned temperature format is enabled * and unsigned temperature format is enabled.
* and display a warning message if it is.
*/ */
if (data->kind == lm96163) { if (data->kind == lm96163) {
u8 config_enhanced u8 config_enhanced
...@@ -632,8 +666,7 @@ static void lm63_init_client(struct i2c_client *client) ...@@ -632,8 +666,7 @@ static void lm63_init_client(struct i2c_client *client)
&& !(data->config_fan & 0x08) && data->pwm1_freq == 8) && !(data->config_fan & 0x08) && data->pwm1_freq == 8)
data->pwm_highres = true; data->pwm_highres = true;
if (config_enhanced & 0x08) if (config_enhanced & 0x08)
dev_warn(&client->dev, data->remote_unsigned = true;
"Unsigned format for High and Crit setpoints enabled but not supported by driver\n");
} }
/* Show some debug info about the LM63 configuration */ /* Show some debug info about the LM63 configuration */
...@@ -709,6 +742,13 @@ static struct lm63_data *lm63_update_device(struct device *dev) ...@@ -709,6 +742,13 @@ static struct lm63_data *lm63_update_device(struct device *dev)
LM63_REG_REMOTE_OFFSET_MSB) << 8) LM63_REG_REMOTE_OFFSET_MSB) << 8)
| i2c_smbus_read_byte_data(client, | i2c_smbus_read_byte_data(client,
LM63_REG_REMOTE_OFFSET_LSB); LM63_REG_REMOTE_OFFSET_LSB);
if (data->kind == lm96163)
data->temp11u = (i2c_smbus_read_byte_data(client,
LM96163_REG_REMOTE_TEMP_U_MSB) << 8)
| i2c_smbus_read_byte_data(client,
LM96163_REG_REMOTE_TEMP_U_LSB);
data->temp8[2] = i2c_smbus_read_byte_data(client, data->temp8[2] = i2c_smbus_read_byte_data(client,
LM63_REG_REMOTE_TCRIT); LM63_REG_REMOTE_TCRIT);
data->temp2_crit_hyst = i2c_smbus_read_byte_data(client, data->temp2_crit_hyst = i2c_smbus_read_byte_data(client,
......
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