All of lore.kernel.org
 help / color / mirror / Atom feed
* [lm-sensors] [PATCH 2/44] [PATCH] w83627ehf: Add voltage inputs
@ 2006-06-22 18:27 Greg KH
  0 siblings, 0 replies; only message in thread
From: Greg KH @ 2006-06-22 18:27 UTC (permalink / raw)
  To: lm-sensors

From: Rudolf Marek <r.marek at sh.cvut.cz>

Add the voltage measuring support to W83627EHF. The code is based
on the patch provided by Yuan Mu from Winbond.

Signed-off-by: Yuan Mu <Ymu at winbond.com.tw>
Signed-off-by: Rudolf Marek <r.marek at sh.cvut.cz>
Signed-off-by: Jean Delvare <khali at linux-fr.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
---
 drivers/hwmon/w83627ehf.c |  124 ++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 120 insertions(+), 4 deletions(-)

diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index b6bd568..08bbeaf 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -30,10 +30,7 @@
     Supports the following chips:
 
     Chip        #vin    #fan    #pwm    #temp   chip_id man_id
-    w83627ehf   -       5       -       3       0x88    0x5ca3
-
-    This is a preliminary version of the driver, only supporting the
-    fan and temperature inputs. The chip does much more than that.
+    w83627ehf   10      5       -       3       0x88    0x5ca3
 */
 
 #include <linux/module.h>
@@ -121,6 +118,14 @@ #define W83627EHF_REG_MAN_ID		0x4F
 static const u16 W83627EHF_REG_FAN[] = { 0x28, 0x29, 0x2a, 0x3f, 0x553 };
 static const u16 W83627EHF_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d, 0x3e, 0x55c };
 
+/* The W83627EHF registers for nr=7,8,9 are in bank 5 */
+#define W83627EHF_REG_IN_MAX(nr)	((nr < 7) ? (0x2b + (nr) * 2) : \
+					 (0x554 + (((nr) - 7) * 2)))
+#define W83627EHF_REG_IN_MIN(nr)	((nr < 7) ? (0x2c + (nr) * 2) : \
+					 (0x555 + (((nr) - 7) * 2)))
+#define W83627EHF_REG_IN(nr)		((nr < 7) ? (0x20 + (nr)) : \
+					 (0x550 + (nr) - 7))
+
 #define W83627EHF_REG_TEMP1		0x27
 #define W83627EHF_REG_TEMP1_HYST	0x3a
 #define W83627EHF_REG_TEMP1_OVER	0x39
@@ -172,6 +177,20 @@ temp1_to_reg(int temp)
 	return (temp + 500) / 1000;
 }
 
+/* Some of analog inputs have internal scaling (2x), 8mV is ADC LSB */
+
+static u8 scale_in[10] = { 8, 8, 16, 16, 8, 8, 8, 16, 16, 8 };
+
+static inline long in_from_reg(u8 reg, u8 nr)
+{
+	return reg * scale_in[nr];
+}
+
+static inline u8 in_to_reg(u32 val, u8 nr)
+{
+	return SENSORS_LIMIT(((val + (scale_in[nr] / 2)) / scale_in[nr]), 0, 255);
+}
+
 /*
  * Data structures and manipulation thereof
  */
@@ -186,6 +205,9 @@ struct w83627ehf_data {
 	unsigned long last_updated;	/* In jiffies */
 
 	/* Register values */
+	u8 in[10];		/* Register value */
+	u8 in_max[10];		/* Register value */
+	u8 in_min[10];		/* Register value */
 	u8 fan[5];
 	u8 fan_min[5];
 	u8 fan_div[5];
@@ -349,6 +371,16 @@ static struct w83627ehf_data *w83627ehf_
 			data->fan_div[3] |= (i >> 5) & 0x04;
 		}
 
+		/* Measured voltages and limits */
+		for (i = 0; i < 10; i++) {
+			data->in[i] = w83627ehf_read_value(client,
+				      W83627EHF_REG_IN(i));
+			data->in_min[i] = w83627ehf_read_value(client,
+					  W83627EHF_REG_IN_MIN(i));
+			data->in_max[i] = w83627ehf_read_value(client,
+					  W83627EHF_REG_IN_MAX(i));
+		}
+
 		/* Measured fan speeds and limits */
 		for (i = 0; i < 5; i++) {
 			if (!(data->has_fan & (1 << i)))
@@ -406,6 +438,87 @@ static struct w83627ehf_data *w83627ehf_
 /*
  * Sysfs callback functions
  */
+#define show_in_reg(reg) \
+static ssize_t \
+show_##reg(struct device *dev, struct device_attribute *attr, \
+	   char *buf) \
+{ \
+	struct w83627ehf_data *data = w83627ehf_update_device(dev); \
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	int nr = sensor_attr->index; \
+	return sprintf(buf, "%ld\n", in_from_reg(data->reg[nr], nr)); \
+}
+show_in_reg(in)
+show_in_reg(in_min)
+show_in_reg(in_max)
+
+#define store_in_reg(REG, reg) \
+static ssize_t \
+store_in_##reg (struct device *dev, struct device_attribute *attr, \
+			const char *buf, size_t count) \
+{ \
+	struct i2c_client *client = to_i2c_client(dev); \
+	struct w83627ehf_data *data = i2c_get_clientdata(client); \
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	int nr = sensor_attr->index; \
+	u32 val = simple_strtoul(buf, NULL, 10); \
+ \
+	mutex_lock(&data->update_lock); \
+	data->in_##reg[nr] = in_to_reg(val, nr); \
+	w83627ehf_write_value(client, W83627EHF_REG_IN_##REG(nr), \
+			      data->in_##reg[nr]); \
+	mutex_unlock(&data->update_lock); \
+	return count; \
+}
+
+store_in_reg(MIN, min)
+store_in_reg(MAX, max)
+
+static struct sensor_device_attribute sda_in_input[] = {
+	SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0),
+	SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1),
+	SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2),
+	SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3),
+	SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4),
+	SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5),
+	SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6),
+	SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7),
+	SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8),
+	SENSOR_ATTR(in9_input, S_IRUGO, show_in, NULL, 9),
+};
+
+static struct sensor_device_attribute sda_in_min[] = {
+       SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0),
+       SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1),
+       SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2),
+       SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3),
+       SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4),
+       SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5),
+       SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6),
+       SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7),
+       SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8),
+       SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 9),
+};
+
+static struct sensor_device_attribute sda_in_max[] = {
+       SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0),
+       SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1),
+       SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2),
+       SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3),
+       SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4),
+       SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5),
+       SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6),
+       SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7),
+       SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8),
+       SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9),
+};
+
+static void device_create_file_in(struct device *dev, int i)
+{
+	device_create_file(dev, &sda_in_input[i].dev_attr);
+	device_create_file(dev, &sda_in_min[i].dev_attr);
+	device_create_file(dev, &sda_in_max[i].dev_attr);
+}
 
 #define show_fan_reg(reg) \
 static ssize_t \
@@ -705,6 +818,9 @@ static int w83627ehf_detect(struct i2c_a
 		goto exit_detach;
 	}
 
+	for (i = 0; i < 10; i++)
+		device_create_file_in(dev, i);
+
 	for (i = 0; i < 5; i++) {
 		if (data->has_fan & (1 << i))
 			device_create_file_fan(dev, i);
-- 
1.4.0



^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2006-06-22 18:27 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-06-22 18:27 [lm-sensors] [PATCH 2/44] [PATCH] w83627ehf: Add voltage inputs Greg KH

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.