aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/hwmon/lm633
-rw-r--r--drivers/hwmon/lm63.c148
2 files changed, 136 insertions, 15 deletions
diff --git a/Documentation/hwmon/lm63 b/Documentation/hwmon/lm63
index df3e1ae42f39..4d30d209881a 100644
--- a/Documentation/hwmon/lm63
+++ b/Documentation/hwmon/lm63
@@ -66,7 +66,8 @@ supported either.
66 66
67The lm63 driver will not update its values more frequently than configured with 67The lm63 driver will not update its values more frequently than configured with
68the update_interval sysfs attribute; reading them more often will do no harm, 68the update_interval sysfs attribute; reading them more often will do no harm,
69but will return 'old' values. 69but will return 'old' values. Values in the automatic fan control lookup table
70(attributes pwm1_auto_*) have their own independent lifetime of 5 seconds.
70 71
71The LM64 is effectively an LM63 with GPIO lines. The driver does not 72The LM64 is effectively an LM63 with GPIO lines. The driver does not
72support these GPIO lines at present. 73support these GPIO lines at present.
diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c
index a5e4ba82af17..1c06a333ba20 100644
--- a/drivers/hwmon/lm63.c
+++ b/drivers/hwmon/lm63.c
@@ -75,6 +75,9 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END };
75 75
76#define LM63_REG_PWM_VALUE 0x4C 76#define LM63_REG_PWM_VALUE 0x4C
77#define LM63_REG_PWM_FREQ 0x4D 77#define LM63_REG_PWM_FREQ 0x4D
78#define LM63_REG_LUT_TEMP_HYST 0x4F
79#define LM63_REG_LUT_TEMP(nr) (0x50 + 2 * (nr))
80#define LM63_REG_LUT_PWM(nr) (0x51 + 2 * (nr))
78 81
79#define LM63_REG_LOCAL_TEMP 0x00 82#define LM63_REG_LOCAL_TEMP 0x00
80#define LM63_REG_LOCAL_HIGH 0x05 83#define LM63_REG_LOCAL_HIGH 0x05
@@ -192,7 +195,9 @@ struct lm63_data {
192 struct device *hwmon_dev; 195 struct device *hwmon_dev;
193 struct mutex update_lock; 196 struct mutex update_lock;
194 char valid; /* zero until following fields are valid */ 197 char valid; /* zero until following fields are valid */
198 char lut_valid; /* zero until lut fields are valid */
195 unsigned long last_updated; /* in jiffies */ 199 unsigned long last_updated; /* in jiffies */
200 unsigned long lut_last_updated; /* in jiffies */
196 enum chips kind; 201 enum chips kind;
197 int temp2_offset; 202 int temp2_offset;
198 203
@@ -204,18 +209,22 @@ struct lm63_data {
204 u16 fan[2]; /* 0: input 209 u16 fan[2]; /* 0: input
205 1: low limit */ 210 1: low limit */
206 u8 pwm1_freq; 211 u8 pwm1_freq;
207 u8 pwm1_value; 212 u8 pwm1[9]; /* 0: current output
208 s8 temp8[3]; /* 0: local input 213 1-8: lookup table */
214 s8 temp8[11]; /* 0: local input
209 1: local high limit 215 1: local high limit
210 2: remote critical limit */ 216 2: remote critical limit
217 3-10: lookup table */
211 s16 temp11[4]; /* 0: remote input 218 s16 temp11[4]; /* 0: remote input
212 1: remote low limit 219 1: remote low limit
213 2: remote high limit 220 2: remote high limit
214 3: remote offset */ 221 3: remote offset */
215 u16 temp11u; /* remote input (unsigned) */ 222 u16 temp11u; /* remote input (unsigned) */
216 u8 temp2_crit_hyst; 223 u8 temp2_crit_hyst;
224 u8 lut_temp_hyst;
217 u8 alarms; 225 u8 alarms;
218 bool pwm_highres; 226 bool pwm_highres;
227 bool lut_temp_highres;
219 bool remote_unsigned; /* true if unsigned remote upper limits */ 228 bool remote_unsigned; /* true if unsigned remote upper limits */
220 bool trutherm; 229 bool trutherm;
221}; 230};
@@ -227,6 +236,11 @@ static inline int temp8_from_reg(struct lm63_data *data, int nr)
227 return TEMP8_FROM_REG(data->temp8[nr]); 236 return TEMP8_FROM_REG(data->temp8[nr]);
228} 237}
229 238
239static inline int lut_temp_from_reg(struct lm63_data *data, int nr)
240{
241 return data->temp8[nr] * (data->lut_temp_highres ? 500 : 1000);
242}
243
230/* 244/*
231 * Sysfs callback functions and files 245 * Sysfs callback functions and files
232 */ 246 */
@@ -261,17 +275,19 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *dummy,
261 return count; 275 return count;
262} 276}
263 277
264static ssize_t show_pwm1(struct device *dev, struct device_attribute *dummy, 278static ssize_t show_pwm1(struct device *dev, struct device_attribute *devattr,
265 char *buf) 279 char *buf)
266{ 280{
281 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
267 struct lm63_data *data = lm63_update_device(dev); 282 struct lm63_data *data = lm63_update_device(dev);
283 int nr = attr->index;
268 int pwm; 284 int pwm;
269 285
270 if (data->pwm_highres) 286 if (data->pwm_highres)
271 pwm = data->pwm1_value; 287 pwm = data->pwm1[nr];
272 else 288 else
273 pwm = data->pwm1_value >= 2 * data->pwm1_freq ? 289 pwm = data->pwm1[nr] >= 2 * data->pwm1_freq ?
274 255 : (data->pwm1_value * 255 + data->pwm1_freq) / 290 255 : (data->pwm1[nr] * 255 + data->pwm1_freq) /
275 (2 * data->pwm1_freq); 291 (2 * data->pwm1_freq);
276 292
277 return sprintf(buf, "%d\n", pwm); 293 return sprintf(buf, "%d\n", pwm);
@@ -294,9 +310,9 @@ static ssize_t set_pwm1(struct device *dev, struct device_attribute *dummy,
294 310
295 val = SENSORS_LIMIT(val, 0, 255); 311 val = SENSORS_LIMIT(val, 0, 255);
296 mutex_lock(&data->update_lock); 312 mutex_lock(&data->update_lock);
297 data->pwm1_value = data->pwm_highres ? val : 313 data->pwm1[0] = data->pwm_highres ? val :
298 (val * data->pwm1_freq * 2 + 127) / 255; 314 (val * data->pwm1_freq * 2 + 127) / 255;
299 i2c_smbus_write_byte_data(client, LM63_REG_PWM_VALUE, data->pwm1_value); 315 i2c_smbus_write_byte_data(client, LM63_REG_PWM_VALUE, data->pwm1[0]);
300 mutex_unlock(&data->update_lock); 316 mutex_unlock(&data->update_lock);
301 return count; 317 return count;
302} 318}
@@ -333,6 +349,16 @@ static ssize_t show_remote_temp8(struct device *dev,
333 + data->temp2_offset); 349 + data->temp2_offset);
334} 350}
335 351
352static ssize_t show_lut_temp(struct device *dev,
353 struct device_attribute *devattr,
354 char *buf)
355{
356 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
357 struct lm63_data *data = lm63_update_device(dev);
358 return sprintf(buf, "%d\n", lut_temp_from_reg(data, attr->index)
359 + data->temp2_offset);
360}
361
336static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr, 362static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr,
337 const char *buf, size_t count) 363 const char *buf, size_t count)
338{ 364{
@@ -440,6 +466,17 @@ static ssize_t show_temp2_crit_hyst(struct device *dev,
440 - TEMP8_FROM_REG(data->temp2_crit_hyst)); 466 - TEMP8_FROM_REG(data->temp2_crit_hyst));
441} 467}
442 468
469static ssize_t show_lut_temp_hyst(struct device *dev,
470 struct device_attribute *devattr, char *buf)
471{
472 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
473 struct lm63_data *data = lm63_update_device(dev);
474
475 return sprintf(buf, "%d\n", lut_temp_from_reg(data, attr->index)
476 + data->temp2_offset
477 - TEMP8_FROM_REG(data->lut_temp_hyst));
478}
479
443/* 480/*
444 * And now the other way around, user-space provides an absolute 481 * And now the other way around, user-space provides an absolute
445 * hysteresis value and we have to store a relative one 482 * hysteresis value and we have to store a relative one
@@ -574,8 +611,48 @@ static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
574static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan, 611static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan,
575 set_fan, 1); 612 set_fan, 1);
576 613
577static DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm1, set_pwm1); 614static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm1, set_pwm1, 0);
578static DEVICE_ATTR(pwm1_enable, S_IRUGO, show_pwm1_enable, NULL); 615static DEVICE_ATTR(pwm1_enable, S_IRUGO, show_pwm1_enable, NULL);
616static SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IRUGO, show_pwm1, NULL, 1);
617static SENSOR_DEVICE_ATTR(pwm1_auto_point1_temp, S_IRUGO,
618 show_lut_temp, NULL, 3);
619static SENSOR_DEVICE_ATTR(pwm1_auto_point1_temp_hyst, S_IRUGO,
620 show_lut_temp_hyst, NULL, 3);
621static SENSOR_DEVICE_ATTR(pwm1_auto_point2_pwm, S_IRUGO, show_pwm1, NULL, 2);
622static SENSOR_DEVICE_ATTR(pwm1_auto_point2_temp, S_IRUGO,
623 show_lut_temp, NULL, 4);
624static SENSOR_DEVICE_ATTR(pwm1_auto_point2_temp_hyst, S_IRUGO,
625 show_lut_temp_hyst, NULL, 4);
626static SENSOR_DEVICE_ATTR(pwm1_auto_point3_pwm, S_IRUGO, show_pwm1, NULL, 3);
627static SENSOR_DEVICE_ATTR(pwm1_auto_point3_temp, S_IRUGO,
628 show_lut_temp, NULL, 5);
629static SENSOR_DEVICE_ATTR(pwm1_auto_point3_temp_hyst, S_IRUGO,
630 show_lut_temp_hyst, NULL, 5);
631static SENSOR_DEVICE_ATTR(pwm1_auto_point4_pwm, S_IRUGO, show_pwm1, NULL, 4);
632static SENSOR_DEVICE_ATTR(pwm1_auto_point4_temp, S_IRUGO,
633 show_lut_temp, NULL, 6);
634static SENSOR_DEVICE_ATTR(pwm1_auto_point4_temp_hyst, S_IRUGO,
635 show_lut_temp_hyst, NULL, 6);
636static SENSOR_DEVICE_ATTR(pwm1_auto_point5_pwm, S_IRUGO, show_pwm1, NULL, 5);
637static SENSOR_DEVICE_ATTR(pwm1_auto_point5_temp, S_IRUGO,
638 show_lut_temp, NULL, 7);
639static SENSOR_DEVICE_ATTR(pwm1_auto_point5_temp_hyst, S_IRUGO,
640 show_lut_temp_hyst, NULL, 7);
641static SENSOR_DEVICE_ATTR(pwm1_auto_point6_pwm, S_IRUGO, show_pwm1, NULL, 6);
642static SENSOR_DEVICE_ATTR(pwm1_auto_point6_temp, S_IRUGO,
643 show_lut_temp, NULL, 8);
644static SENSOR_DEVICE_ATTR(pwm1_auto_point6_temp_hyst, S_IRUGO,
645 show_lut_temp_hyst, NULL, 8);
646static SENSOR_DEVICE_ATTR(pwm1_auto_point7_pwm, S_IRUGO, show_pwm1, NULL, 7);
647static SENSOR_DEVICE_ATTR(pwm1_auto_point7_temp, S_IRUGO,
648 show_lut_temp, NULL, 9);
649static SENSOR_DEVICE_ATTR(pwm1_auto_point7_temp_hyst, S_IRUGO,
650 show_lut_temp_hyst, NULL, 9);
651static SENSOR_DEVICE_ATTR(pwm1_auto_point8_pwm, S_IRUGO, show_pwm1, NULL, 8);
652static SENSOR_DEVICE_ATTR(pwm1_auto_point8_temp, S_IRUGO,
653 show_lut_temp, NULL, 10);
654static SENSOR_DEVICE_ATTR(pwm1_auto_point8_temp_hyst, S_IRUGO,
655 show_lut_temp_hyst, NULL, 10);
579 656
580static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_local_temp8, NULL, 0); 657static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_local_temp8, NULL, 0);
581static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_local_temp8, 658static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_local_temp8,
@@ -609,8 +686,33 @@ static DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR, show_update_interval,
609 set_update_interval); 686 set_update_interval);
610 687
611static struct attribute *lm63_attributes[] = { 688static struct attribute *lm63_attributes[] = {
612 &dev_attr_pwm1.attr, 689 &sensor_dev_attr_pwm1.dev_attr.attr,
613 &dev_attr_pwm1_enable.attr, 690 &dev_attr_pwm1_enable.attr,
691 &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr,
692 &sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr,
693 &sensor_dev_attr_pwm1_auto_point1_temp_hyst.dev_attr.attr,
694 &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr,
695 &sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr,
696 &sensor_dev_attr_pwm1_auto_point2_temp_hyst.dev_attr.attr,
697 &sensor_dev_attr_pwm1_auto_point3_pwm.dev_attr.attr,
698 &sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr,
699 &sensor_dev_attr_pwm1_auto_point3_temp_hyst.dev_attr.attr,
700 &sensor_dev_attr_pwm1_auto_point4_pwm.dev_attr.attr,
701 &sensor_dev_attr_pwm1_auto_point4_temp.dev_attr.attr,
702 &sensor_dev_attr_pwm1_auto_point4_temp_hyst.dev_attr.attr,
703 &sensor_dev_attr_pwm1_auto_point5_pwm.dev_attr.attr,
704 &sensor_dev_attr_pwm1_auto_point5_temp.dev_attr.attr,
705 &sensor_dev_attr_pwm1_auto_point5_temp_hyst.dev_attr.attr,
706 &sensor_dev_attr_pwm1_auto_point6_pwm.dev_attr.attr,
707 &sensor_dev_attr_pwm1_auto_point6_temp.dev_attr.attr,
708 &sensor_dev_attr_pwm1_auto_point6_temp_hyst.dev_attr.attr,
709 &sensor_dev_attr_pwm1_auto_point7_pwm.dev_attr.attr,
710 &sensor_dev_attr_pwm1_auto_point7_temp.dev_attr.attr,
711 &sensor_dev_attr_pwm1_auto_point7_temp_hyst.dev_attr.attr,
712 &sensor_dev_attr_pwm1_auto_point8_pwm.dev_attr.attr,
713 &sensor_dev_attr_pwm1_auto_point8_temp.dev_attr.attr,
714 &sensor_dev_attr_pwm1_auto_point8_temp_hyst.dev_attr.attr,
715
614 &sensor_dev_attr_temp1_input.dev_attr.attr, 716 &sensor_dev_attr_temp1_input.dev_attr.attr,
615 &sensor_dev_attr_temp2_input.dev_attr.attr, 717 &sensor_dev_attr_temp2_input.dev_attr.attr,
616 &sensor_dev_attr_temp2_min.dev_attr.attr, 718 &sensor_dev_attr_temp2_min.dev_attr.attr,
@@ -834,6 +936,8 @@ static void lm63_init_client(struct i2c_client *client)
834 u8 config_enhanced 936 u8 config_enhanced
835 = i2c_smbus_read_byte_data(client, 937 = i2c_smbus_read_byte_data(client,
836 LM96163_REG_CONFIG_ENHANCED); 938 LM96163_REG_CONFIG_ENHANCED);
939 if (config_enhanced & 0x20)
940 data->lut_temp_highres = true;
837 if ((config_enhanced & 0x10) 941 if ((config_enhanced & 0x10)
838 && !(data->config_fan & 0x08) && data->pwm1_freq == 8) 942 && !(data->config_fan & 0x08) && data->pwm1_freq == 8)
839 data->pwm_highres = true; 943 data->pwm_highres = true;
@@ -872,6 +976,7 @@ static struct lm63_data *lm63_update_device(struct device *dev)
872 struct i2c_client *client = to_i2c_client(dev); 976 struct i2c_client *client = to_i2c_client(dev);
873 struct lm63_data *data = i2c_get_clientdata(client); 977 struct lm63_data *data = i2c_get_clientdata(client);
874 unsigned long next_update; 978 unsigned long next_update;
979 int i;
875 980
876 mutex_lock(&data->update_lock); 981 mutex_lock(&data->update_lock);
877 982
@@ -895,8 +1000,8 @@ static struct lm63_data *lm63_update_device(struct device *dev)
895 LM63_REG_PWM_FREQ); 1000 LM63_REG_PWM_FREQ);
896 if (data->pwm1_freq == 0) 1001 if (data->pwm1_freq == 0)
897 data->pwm1_freq = 1; 1002 data->pwm1_freq = 1;
898 data->pwm1_value = i2c_smbus_read_byte_data(client, 1003 data->pwm1[0] = i2c_smbus_read_byte_data(client,
899 LM63_REG_PWM_VALUE); 1004 LM63_REG_PWM_VALUE);
900 1005
901 data->temp8[0] = i2c_smbus_read_byte_data(client, 1006 data->temp8[0] = i2c_smbus_read_byte_data(client,
902 LM63_REG_LOCAL_TEMP); 1007 LM63_REG_LOCAL_TEMP);
@@ -939,6 +1044,21 @@ static struct lm63_data *lm63_update_device(struct device *dev)
939 data->valid = 1; 1044 data->valid = 1;
940 } 1045 }
941 1046
1047 if (time_after(jiffies, data->lut_last_updated + 5 * HZ) ||
1048 !data->lut_valid) {
1049 for (i = 0; i < 8; i++) {
1050 data->pwm1[1 + i] = i2c_smbus_read_byte_data(client,
1051 LM63_REG_LUT_PWM(i));
1052 data->temp8[3 + i] = i2c_smbus_read_byte_data(client,
1053 LM63_REG_LUT_TEMP(i));
1054 }
1055 data->lut_temp_hyst = i2c_smbus_read_byte_data(client,
1056 LM63_REG_LUT_TEMP_HYST);
1057
1058 data->lut_last_updated = jiffies;
1059 data->lut_valid = 1;
1060 }
1061
942 mutex_unlock(&data->update_lock); 1062 mutex_unlock(&data->update_lock);
943 1063
944 return data; 1064 return data;