gl518sm chip driver for 2.6 kernel

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Jean,

> I've updated libsensors and sensors to support the 2.6 gl518sm driver.
> Could you please checkout lm_sensors CVS and give it a try?
I have tested it out, and there are 2 issues:

* libsensors is reading from 'in0' instead of 'in_input0'
  - I have edited chips.c and attached the patch

* libsensors is reading from 'temp_input1' but gl518sm provides 'temp_input'
  - I have edited the driver to use 'temp_*' instead.
  - however, it might be confusing to read from 'temp_input1', but
    specifying it as 'temp_{max,hyst}' in the config files.  It might
    be better to append '1' for all 'temp*'

> Also, I'd like you to make sure that the 2.4 driver still works with the
> new libsensors and sensors.
I don't think I will be able to test the 2.4 drivers for a few weeks.  I
will be going overseas for 3 weeks and being a server, it takes a bit of
effort to bring it down for a kernel change.  I am happy to do it when I
get back though.  I am still able to work on the driver but using the
current kernel.

The above was tested on fedora development's kernel-2.6.1-1.57, while the
previous tests were on 2.6.3-rc2.

I have also updated gl518sm.c:
- I have found a bug due to me misreading the old code.  It affects only
  fan_div*.
- I am thinking of replacing '(val >> 4) & 0x0f' with '(val & 0xf0) >> $)'
  as it allows easy checking with the chip specifications (the mask in
  particular).  I have changed a few, and if there are no objections,
  I will be changing the rest.
- I have added fan_auto1 that switches fan1 between [true] always on and
  [false] auto on(30C)/off(25C).  This was removed from the port as it
  did not a standard item, and I didn't know what to do with it.
- I have a question regarding the init of the driver.  Is there a need
  to init the chip?  The BIOS should have initialised the chip, and we
  only need to make sure it is enabled.  Initialising the chip resets
  the config such as the min/max which the BIOS should have set, as well
  as other hardware dependent options such as 'fan2off' in the old driver.
  My understanding is that we should not be able to write 'fan2off' as it
  depends on the hardware implementation.  So I am inclined not to reset
  the chip on init of the driver.
The patch is attached and based on linux-2.6.2-rc2-i2c-gl518sm-rc2.diff.


I hope to hear your comments.

Cheers,
Hong-Gunn
-------------- next part --------------
diff -ruN lm_sensors2-CVS/lib/chips.c lm_sensors2-CVS-hg1/lib/chips.c
--- lm_sensors2-CVS/lib/chips.c	2004-01-31 07:27:38.000000000 +1030
+++ lm_sensors2-CVS-hg1/lib/chips.c	2004-01-31 18:09:30.000000000 +1030
@@ -419,7 +419,7 @@
 static sensors_chip_feature gl518_features[] =
   {
     { SENSORS_GL518_VDD, "vdd", NOMAP,NOMAP,
-                            R, GL518_SYSCTL_VDD, VALUE(3), 2, "in0", 3 },
+                            R, GL518_SYSCTL_VDD, VALUE(3), 2, "in_input0", 3 },
     { SENSORS_GL518_VIN1, "vin1", NOMAP,NOMAP,
                              R, GL518_SYSCTL_VIN1, VALUE(3), 
                              2 },
-------------- next part --------------
--- gl518sm.c.rc2	2004-01-30 10:48:40.000000000 +1030
+++ gl518sm.c	2004-01-31 18:26:09.000000000 +1030
@@ -1,10 +1,10 @@
 /*
  * gl518sm.c - Part of lm_sensors, Linux kernel modules for hardware
  *             monitoring
- * Copyright (C) 1998, 1999	Frodo Looijaard	<frodol at dds.nl>,
- * 				Kyosti Malkki	<kmalkki at cc.hut.fi>
+ * Copyright (C) 1998, 1999     Frodo Looijaard <frodol at dds.nl>,
+ *                              Kyosti Malkki   <kmalkki at cc.hut.fi>
  * port to 2.6 Kernel
- * Copyright (C) 2004		Hong-Gunn Chew	<hglinux at gunnet.org>
+ * Copyright (C) 2004           Hong-Gunn Chew  <hglinux at gunnet.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -22,11 +22,8 @@
  */
 
 /*
- * v2.0 (2004-01-24, Hong-Gunn Chew)
- *	- ported to 2.6 kernel
- * v2.1 (2004-01-28, Hong-Gunn Chew)
- *	- Updated sysfs output according to standard data format
- *	  (temp, in)
+ * v2.0 (2004-01-30, Hong-Gunn Chew)
+ *      - ported to 2.6 kernel
  */
 
 #include <linux/config.h>
@@ -82,6 +79,11 @@
  * Fixing this is just not worth it.
  */
 
+#define RAW_FROM_REG(val)	val
+
+#define BOOL_FROM_REG(val)	((val)?0:1)
+#define BOOL_TO_REG(val)	((val)?0:1)
+
 #define TEMP_TO_REG(val)	(SENSORS_LIMIT(((((val)<0? \
 				(val)-500:(val)+500)/1000)+119),0,255))
 #define TEMP_FROM_REG(val)	(((val) - 119) * 1000)
@@ -106,13 +108,8 @@
 #define DIV_TO_REG(val)		((val)==8?3:(val)==4?2:(val)==1?0:1)
 #define DIV_FROM_REG(val)	(1 << (val))
 
-#define ALARMS_FROM_REG(val)	val
-
-#define BEEP_ENABLE_TO_REG(val)		((val)?0:1)
-#define BEEP_ENABLE_FROM_REG(val)	((val)?0:1)
-
-#define BEEP_MASK_TO_REG(val)		((val) & 0x7f & data->alarm_mask)
-#define BEEP_MASK_FROM_REG(val)		((val) & 0x7f)
+#define BEEP_MASK_TO_REG(val)	((val) & 0x7f & data->alarm_mask)
+#define BEEP_MASK_FROM_REG(val)	((val) & 0x7f)
 
 /* Each client has this additional data */
 struct gl518_data {
@@ -129,6 +126,7 @@
 	u8 fan_in[2];
 	u8 fan_min[2];
 	u8 fan_div[2];		/* Register encoding, shifted right */
+	u8 fan_auto1;		/* Boolean */
 	u8 temp_in;		/* Register values */
 	u8 temp_max;		/* Register values */
 	u8 temp_hyst;		/* Register values */
@@ -185,9 +183,10 @@
 		DIV_FROM_REG(data->fan_div[index])));			\
 }
 
-show(TEMP, temp_input, temp_in);
-show(TEMP, temp_max, temp_max);
-show(TEMP, temp_hyst, temp_hyst);
+show(TEMP, temp_input1, temp_in);
+show(TEMP, temp_max1, temp_max);
+show(TEMP, temp_hyst1, temp_hyst);
+show(BOOL, fan_auto1, fan_auto1);
 show_fan(fan_input1, fan_in, 0);
 show_fan(fan_input2, fan_in, 1);
 show_fan(fan_min1, fan_min, 0);
@@ -206,8 +205,8 @@
 show(IN, in_max1, voltage_max[1]);
 show(IN, in_max2, voltage_max[2]);
 show(IN, in_max3, voltage_max[3]);
-show(ALARMS, alarms, alarms);
-show(BEEP_ENABLE, beep_enable, beep_enable);
+show(RAW, alarms, alarms);
+show(BOOL, beep_enable, beep_enable);
 show(BEEP_MASK, beep_mask, beep_mask);
 
 #define set(type, suffix, value, reg)					\
@@ -229,20 +228,21 @@
 	struct gl518_data *data = i2c_get_clientdata(client);		\
 	int regvalue = gl518_read_value(client, reg);			\
 	data->value = type##_TO_REG(simple_strtoul(buf, NULL, 10));	\
-	regvalue = (regvalue & mask) | (data->value << shift);		\
+	regvalue = (regvalue & ~mask) | (data->value << shift);		\
 	gl518_write_value(client, reg, regvalue);			\
 	return count;							\
 }
 
 #define set_low(type, suffix, value, reg)				\
-	set_bits(type, suffix, value, reg, 0xff00, 0)
+	set_bits(type, suffix, value, reg, 0x00ff, 0)
 #define set_high(type, suffix, value, reg)				\
-	set_bits(type, suffix, value, reg, 0x00ff, 8)
+	set_bits(type, suffix, value, reg, 0xff00, 8)
 
-set(TEMP, temp_max, temp_max, GL518_REG_TEMP_MAX);
-set(TEMP, temp_hyst, temp_hyst, GL518_REG_TEMP_HYST);
-set_bits(DIV, fan_div1, fan_div[0], GL518_REG_MISC, 0x3f, 4);
-set_bits(DIV, fan_div2, fan_div[1], GL518_REG_MISC, 0xcf, 6);
+set(TEMP, temp_max1, temp_max, GL518_REG_TEMP_MAX);
+set(TEMP, temp_hyst1, temp_hyst, GL518_REG_TEMP_HYST);
+set_bits(BOOL, fan_auto1, fan_auto1, GL518_REG_MISC, 0x08, 3);
+set_bits(DIV, fan_div1, fan_div[0], GL518_REG_MISC, 0xc0, 6);
+set_bits(DIV, fan_div2, fan_div[1], GL518_REG_MISC, 0x30, 4);
 set_low(VDD, in_min0, voltage_min[0], GL518_REG_VDD_LIMIT);
 set_low(IN, in_min1, voltage_min[1], GL518_REG_VIN1_LIMIT);
 set_low(IN, in_min2, voltage_min[2], GL518_REG_VIN2_LIMIT);
@@ -251,7 +251,7 @@
 set_high(IN, in_max1, voltage_max[1], GL518_REG_VIN1_LIMIT);
 set_high(IN, in_max2, voltage_max[2], GL518_REG_VIN2_LIMIT);
 set_high(IN, in_max3, voltage_max[3], GL518_REG_VIN3_LIMIT);
-set_bits(BEEP_ENABLE, beep_enable, beep_enable, GL518_REG_CONF, 0xfb, 2);
+set_bits(BOOL, beep_enable, beep_enable, GL518_REG_CONF, 0x04, 2);
 set(BEEP_MASK, beep_mask, beep_mask, GL518_REG_ALARM);
 
 static ssize_t set_fan_min1(struct device *dev, const char *buf, size_t count)
@@ -262,11 +262,11 @@
 
 	data->fan_min[0] = FAN_TO_REG(simple_strtoul(buf, NULL, 10),
 		DIV_FROM_REG(data->fan_div[0]));
-	regvalue = (regvalue & 0xff00) | data->fan_min[0];
+	regvalue = (regvalue & 0x00ff) | (data->fan_min[0] << 8);
 	if (data->fan_min[0] == 0)
-		data->alarm_mask &= ~0x0020;
+		data->alarm_mask &= ~0x20;
 	else
-		data->alarm_mask |= 0x0020;
+		data->alarm_mask |= 0x20;
 	gl518_write_value(client, GL518_REG_FAN_LIMIT, regvalue);
 
 	return count;
@@ -280,19 +280,21 @@
 
 	data->fan_min[1] = FAN_TO_REG(simple_strtoul(buf, NULL, 10),
 		DIV_FROM_REG(data->fan_div[0]));
-	regvalue = (regvalue & 0x00ff) | (data->fan_min[1] << 8);
+	regvalue = (regvalue & 0xff00) | data->fan_min[1];
 	if (data->fan_min[1] == 0)
-		data->alarm_mask &= ~0x0040;
+		data->alarm_mask &= ~0x40;
 	else
-		data->alarm_mask |= 0x0040;
+		data->alarm_mask |= 0x40;
 	gl518_write_value(client, GL518_REG_FAN_LIMIT, regvalue);
 
 	return count;
 }
 
-static DEVICE_ATTR(temp_input, S_IRUGO, show_temp_input, NULL);
-static DEVICE_ATTR(temp_max, S_IWUSR|S_IRUGO, show_temp_max, set_temp_max);
-static DEVICE_ATTR(temp_hyst, S_IWUSR|S_IRUGO, show_temp_hyst, set_temp_hyst);
+static DEVICE_ATTR(temp_input1, S_IRUGO, show_temp_input1, NULL);
+static DEVICE_ATTR(temp_max1, S_IWUSR|S_IRUGO, show_temp_max1, set_temp_max1);
+static DEVICE_ATTR(temp_hyst1, S_IWUSR|S_IRUGO,
+	show_temp_hyst1, set_temp_hyst1);
+static DEVICE_ATTR(fan_auto1, S_IWUSR|S_IRUGO, show_fan_auto1, set_fan_auto1);
 static DEVICE_ATTR(fan_input1, S_IRUGO, show_fan_input1, NULL);
 static DEVICE_ATTR(fan_input2, S_IRUGO, show_fan_input2, NULL);
 static DEVICE_ATTR(fan_min1, S_IWUSR|S_IRUGO, show_fan_min1, set_fan_min1);
@@ -417,15 +419,16 @@
 	device_create_file(&new_client->dev, &dev_attr_in_max1);
 	device_create_file(&new_client->dev, &dev_attr_in_max2);
 	device_create_file(&new_client->dev, &dev_attr_in_max3);
+	device_create_file(&new_client->dev, &dev_attr_fan_auto1);
 	device_create_file(&new_client->dev, &dev_attr_fan_input1);
 	device_create_file(&new_client->dev, &dev_attr_fan_input2);
 	device_create_file(&new_client->dev, &dev_attr_fan_min1);
 	device_create_file(&new_client->dev, &dev_attr_fan_min2);
 	device_create_file(&new_client->dev, &dev_attr_fan_div1);
 	device_create_file(&new_client->dev, &dev_attr_fan_div2);
-	device_create_file(&new_client->dev, &dev_attr_temp_input);
-	device_create_file(&new_client->dev, &dev_attr_temp_max);
-	device_create_file(&new_client->dev, &dev_attr_temp_hyst);
+	device_create_file(&new_client->dev, &dev_attr_temp_input1);
+	device_create_file(&new_client->dev, &dev_attr_temp_max1);
+	device_create_file(&new_client->dev, &dev_attr_temp_hyst1);
 	device_create_file(&new_client->dev, &dev_attr_alarms);
 	device_create_file(&new_client->dev, &dev_attr_beep_enable);
 	device_create_file(&new_client->dev, &dev_attr_beep_mask);
@@ -545,19 +548,17 @@
 		    gl518_read_value(client, GL518_REG_TEMP_HYST);
 
 		val = gl518_read_value(client, GL518_REG_MISC);
-		data->fan_div[0] = (val >> 6) & 0x03;
-		data->fan_div[1] = (val >> 4) & 0x03;
+		data->fan_div[0] = (val & 0xc0) >> 6;
+		data->fan_div[1] = (val & 0x30) >> 4;
+		data->fan_auto1  = (val & 0x08) >> 3;
 
 		data->alarms &= data->alarm_mask;
 
 		val = gl518_read_value(client, GL518_REG_CONF);
-		data->beep_enable = (val >> 2) & 1;
+		data->beep_enable = (val & 0x04) >> 2;
+		data->fan_auto1  |= (val & 0x10) >> 3;
 
-		if (data->type == gl518sm_r00) {
-			data->voltage_in[0] = 0;
-			data->voltage_in[1] = 0;
-			data->voltage_in[2] = 0;
-		} else {
+		if (data->type != gl518sm_r00) {
 			data->voltage_in[0] =
 			    gl518_read_value(client, GL518_REG_VDD);
 			data->voltage_in[1] =


[Index of Archives]     [Linux Kernel]     [Linux Hardware Monitoring]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux