aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon
diff options
context:
space:
mode:
authorGuenter Roeck <guenter.roeck@ericsson.com>2012-01-16 16:51:45 -0500
committerJean Delvare <khali@endymion.delvare>2012-01-16 16:51:45 -0500
commit210961c436d5c552a816ae9c6b38cbc8b993395a (patch)
tree234ab06ad1a1a3acc69082d4964e5b955dd337a6 /drivers/hwmon
parent786375f7298dcc78a7cf44be9e15fb79bddc6f25 (diff)
hwmon: (lm63) Add support for LM96163
LM96163 is an enhanced version of LM63 with improved PWM resolution. Add chip detection code as well as support for improved PWM resolution if the chip is configured to use it. Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com> Tested-by: Thierry Reding <thierry.reding@avionic-design.de> Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r--drivers/hwmon/Kconfig4
-rw-r--r--drivers/hwmon/lm63.c41
2 files changed, 38 insertions, 7 deletions
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index cb351d358387..f468bbb6357a 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -515,11 +515,11 @@ config SENSORS_LINEAGE
515 will be called lineage-pem. 515 will be called lineage-pem.
516 516
517config SENSORS_LM63 517config SENSORS_LM63
518 tristate "National Semiconductor LM63 and LM64" 518 tristate "National Semiconductor LM63 and compatibles"
519 depends on I2C 519 depends on I2C
520 help 520 help
521 If you say yes here you get support for the National 521 If you say yes here you get support for the National
522 Semiconductor LM63 and LM64 remote diode digital temperature 522 Semiconductor LM63, LM64, and LM96163 remote diode digital temperature
523 sensors with integrated fan control. Such chips are found 523 sensors with integrated fan control. Such chips are found
524 on the Tyan S4882 (Thunder K8QS Pro) motherboard, among 524 on the Tyan S4882 (Thunder K8QS Pro) motherboard, among
525 others. 525 others.
diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c
index 313aee18be1d..3d882c93b46d 100644
--- a/drivers/hwmon/lm63.c
+++ b/drivers/hwmon/lm63.c
@@ -47,6 +47,7 @@
47#include <linux/err.h> 47#include <linux/err.h>
48#include <linux/mutex.h> 48#include <linux/mutex.h>
49#include <linux/sysfs.h> 49#include <linux/sysfs.h>
50#include <linux/types.h>
50 51
51/* 52/*
52 * Addresses to scan 53 * Addresses to scan
@@ -91,6 +92,8 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END };
91#define LM63_REG_MAN_ID 0xFE 92#define LM63_REG_MAN_ID 0xFE
92#define LM63_REG_CHIP_ID 0xFF 93#define LM63_REG_CHIP_ID 0xFF
93 94
95#define LM96163_REG_CONFIG_ENHANCED 0x45
96
94/* 97/*
95 * Conversions and various macros 98 * Conversions and various macros
96 * For tachometer counts, the LM63 uses 16-bit values. 99 * For tachometer counts, the LM63 uses 16-bit values.
@@ -134,7 +137,7 @@ static struct lm63_data *lm63_update_device(struct device *dev);
134static int lm63_detect(struct i2c_client *client, struct i2c_board_info *info); 137static int lm63_detect(struct i2c_client *client, struct i2c_board_info *info);
135static void lm63_init_client(struct i2c_client *client); 138static void lm63_init_client(struct i2c_client *client);
136 139
137enum chips { lm63, lm64 }; 140enum chips { lm63, lm64, lm96163 };
138 141
139/* 142/*
140 * Driver data (common to all clients) 143 * Driver data (common to all clients)
@@ -143,6 +146,7 @@ enum chips { lm63, lm64 };
143static const struct i2c_device_id lm63_id[] = { 146static const struct i2c_device_id lm63_id[] = {
144 { "lm63", lm63 }, 147 { "lm63", lm63 },
145 { "lm64", lm64 }, 148 { "lm64", lm64 },
149 { "lm96163", lm96163 },
146 { } 150 { }
147}; 151};
148MODULE_DEVICE_TABLE(i2c, lm63_id); 152MODULE_DEVICE_TABLE(i2c, lm63_id);
@@ -186,6 +190,7 @@ struct lm63_data {
186 3: remote offset */ 190 3: remote offset */
187 u8 temp2_crit_hyst; 191 u8 temp2_crit_hyst;
188 u8 alarms; 192 u8 alarms;
193 bool pwm_highres;
189}; 194};
190 195
191/* 196/*
@@ -226,9 +231,16 @@ static ssize_t show_pwm1(struct device *dev, struct device_attribute *dummy,
226 char *buf) 231 char *buf)
227{ 232{
228 struct lm63_data *data = lm63_update_device(dev); 233 struct lm63_data *data = lm63_update_device(dev);
229 return sprintf(buf, "%d\n", data->pwm1_value >= 2 * data->pwm1_freq ? 234 int pwm;
235
236 if (data->pwm_highres)
237 pwm = data->pwm1_value;
238 else
239 pwm = data->pwm1_value >= 2 * data->pwm1_freq ?
230 255 : (data->pwm1_value * 255 + data->pwm1_freq) / 240 255 : (data->pwm1_value * 255 + data->pwm1_freq) /
231 (2 * data->pwm1_freq)); 241 (2 * data->pwm1_freq);
242
243 return sprintf(buf, "%d\n", pwm);
232} 244}
233 245
234static ssize_t set_pwm1(struct device *dev, struct device_attribute *dummy, 246static ssize_t set_pwm1(struct device *dev, struct device_attribute *dummy,
@@ -246,9 +258,9 @@ static ssize_t set_pwm1(struct device *dev, struct device_attribute *dummy,
246 if (err) 258 if (err)
247 return err; 259 return err;
248 260
261 val = SENSORS_LIMIT(val, 0, 255);
249 mutex_lock(&data->update_lock); 262 mutex_lock(&data->update_lock);
250 data->pwm1_value = val <= 0 ? 0 : 263 data->pwm1_value = data->pwm_highres ? val :
251 val >= 255 ? 2 * data->pwm1_freq :
252 (val * data->pwm1_freq * 2 + 127) / 255; 264 (val * data->pwm1_freq * 2 + 127) / 255;
253 i2c_smbus_write_byte_data(client, LM63_REG_PWM_VALUE, data->pwm1_value); 265 i2c_smbus_write_byte_data(client, LM63_REG_PWM_VALUE, data->pwm1_value);
254 mutex_unlock(&data->update_lock); 266 mutex_unlock(&data->update_lock);
@@ -522,6 +534,8 @@ static int lm63_detect(struct i2c_client *new_client,
522 strlcpy(info->type, "lm63", I2C_NAME_SIZE); 534 strlcpy(info->type, "lm63", I2C_NAME_SIZE);
523 else if (chip_id == 0x51 && (address == 0x18 || address == 0x4e)) 535 else if (chip_id == 0x51 && (address == 0x18 || address == 0x4e))
524 strlcpy(info->type, "lm64", I2C_NAME_SIZE); 536 strlcpy(info->type, "lm64", I2C_NAME_SIZE);
537 else if (chip_id == 0x49 && address == 0x4c)
538 strlcpy(info->type, "lm96163", I2C_NAME_SIZE);
525 else 539 else
526 return -ENODEV; 540 return -ENODEV;
527 541
@@ -605,6 +619,23 @@ static void lm63_init_client(struct i2c_client *client)
605 if (data->pwm1_freq == 0) 619 if (data->pwm1_freq == 0)
606 data->pwm1_freq = 1; 620 data->pwm1_freq = 1;
607 621
622 /*
623 * For LM96163, check if high resolution PWM is enabled.
624 * Also, check if unsigned temperature format is enabled
625 * and display a warning message if it is.
626 */
627 if (data->kind == lm96163) {
628 u8 config_enhanced
629 = i2c_smbus_read_byte_data(client,
630 LM96163_REG_CONFIG_ENHANCED);
631 if ((config_enhanced & 0x10)
632 && !(data->config_fan & 0x08) && data->pwm1_freq == 8)
633 data->pwm_highres = true;
634 if (config_enhanced & 0x08)
635 dev_warn(&client->dev,
636 "Unsigned format for High and Crit setpoints enabled but not supported by driver\n");
637 }
638
608 /* Show some debug info about the LM63 configuration */ 639 /* Show some debug info about the LM63 configuration */
609 dev_dbg(&client->dev, "Alert/tach pin configured for %s\n", 640 dev_dbg(&client->dev, "Alert/tach pin configured for %s\n",
610 (data->config & 0x04) ? "tachometer input" : 641 (data->config & 0x04) ? "tachometer input" :