From: aurelien@aurel32.net (Aurelien Jarno)
To: lm-sensors@vger.kernel.org
Subject: [lm-sensors] w83627ehf fan controll?
Date: Mon, 09 Jan 2006 10:20:20 +0000 [thread overview]
Message-ID: <20060109102020.GA6279@farad.aurel32.net> (raw)
In-Reply-To: <20051230143805.GA21201@Apollo>
On Sat, Dec 31, 2005 at 08:12:16PM +0100, Jean Delvare wrote:
> Hi Yuan & all,
Hi!
> > I have add some entries to test the chip (in my local CVS), But I have
> > not finished the test. Did anyone do the same work on this driver?
>
> A number of persons are supposedly working on improving this driver.
> Cadu said he would improve the driver back in July but we didn't hear
> back since. I think Rudolf has a W83627EHF chip and may be willing to
> help too. And I also seem to remember that Aurelien has such a chip and
> wanted to help with the driver some times ago.
>
> It's rare to have that many persons working on the same driver, so it's
> quite sad that nothing has been merged into the driver yet :(
>
> If you have a patch to contribute, please do! :)
>
Yes I have started to work on it, but I have then stopped due to lack of
time. Please find attached a patch between the current version in the
kernel and my local version. It adds support for voltage inputs and it
factorizes some code.
> > Actually I'm quiet confusing about the naming rule of device file, it
> > did not cover all the PWM/SmartFan functions.
>
> Same old story. We tried to standardize the PWM interface, but in the
> end nobody seems to be happy with that standard. I'm a bit tired of all
> this, so just implement any interface you like as long as it makes
> sense. All I am asking for is that fan stopped is PWM=0 and fan at full
> speed is PWM%5.
>
I have also started to work on pwm, until I understood the Asus guys
have wired the fans directly to +12V. That's why I finally used a
hardware solution instead of a software one :(
Bye,
Aurelien
--
.''`. Aurelien Jarno | GPG: 1024D/F1BCDB73
: :' : Debian developer | Electrical Engineer
`. `' aurel32 at debian.org | aurelien at aurel32.net
`- people.debian.org/~aurel32 | www.aurel32.net
-------------- next part --------------
--- /usr/src/linux-2.6.14/drivers/hwmon/w83627ehf.c 2005-10-28 02:02:08.000000000 +0200
+++ w83627ehf.c 2006-01-09 11:14:20.000000000 +0100
@@ -30,7 +30,7 @@
Supports the following chips:
Chip #vin #fan #pwm #temp chip_id man_id
- w83627ehf - 5 - 3 0x88 0x5ca3
+ w83627ehf 10 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.
@@ -114,6 +114,10 @@
#define W83627EHF_REG_CHIP_ID 0x49
#define W83627EHF_REG_MAN_ID 0x4F
+static const u16 W83627EHF_REG_IN[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x550, 0x551, 0x552 };
+static const u16 W83627EHF_REG_IN_MIN[] = { 0x2B, 0x2D, 0x2F, 0x31, 0x33, 0x35, 0x37, 0x554, 0x556, 0x558 };
+static const u16 W83627EHF_REG_IN_MAX[] = { 0x2C, 0x2E, 0x30, 0x32, 0x34, 0x36, 0x38, 0x555, 0x557, 0x559 };
+
static const u16 W83627EHF_REG_FAN[] = { 0x28, 0x29, 0x2a, 0x3f, 0x553 };
static const u16 W83627EHF_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d, 0x3e, 0x55c };
@@ -137,6 +141,22 @@
*/
static inline unsigned int
+in_from_reg(u8 reg)
+{
+ return reg * 8;
+}
+
+static inline u8
+reg_from_in(int val)
+{
+ if (val < 0)
+ return 0;
+ if (val > 2040)
+ return 255;
+ return (val + 4) / 8;
+}
+
+static inline unsigned int
fan_from_reg(u8 reg, unsigned int div)
{
if (reg = 0 || reg = 255)
@@ -182,6 +202,9 @@
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];
@@ -324,6 +347,16 @@
if (time_after(jiffies, data->last_updated + HZ)
|| !data->valid) {
+ /* 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]);
+ }
+
/* Fan clock dividers */
i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV1);
data->fan_div[0] = (i >> 4) & 0x03;
@@ -402,6 +435,81 @@
/*
* Sysfs callback functions
*/
+#define show_in_reg(reg) \
+static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
+{ \
+ struct w83627ehf_data *data = w83627ehf_update_device(dev); \
+ return sprintf(buf,"%d\n", in_from_reg(data->reg[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, const char *buf, size_t count, int nr) \
+{ \
+ struct i2c_client *client = to_i2c_client(dev); \
+ struct w83627ehf_data *data = i2c_get_clientdata(client); \
+ u32 val; \
+ \
+ val = simple_strtoul(buf, NULL, 10); \
+ \
+ down(&data->update_lock); \
+ data->in_##reg[nr] = reg_from_in(val); \
+ w83627ehf_write_value(client, W83627EHF_REG_IN_##REG[nr], \
+ data->in_##reg[nr]); \
+ \
+ up(&data->update_lock); \
+ return count; \
+}
+store_in_reg(MIN, min)
+store_in_reg(MAX, max)
+
+#define sysfs_in_offset(offset) \
+static ssize_t \
+show_regs_in_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
+{ \
+ return show_in(dev, buf, offset); \
+} \
+static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_regs_in_##offset, NULL);
+
+#define sysfs_in_reg_offset(reg, offset) \
+static ssize_t show_regs_in_##reg##offset (struct device *dev, struct device_attribute *attr, char *buf) \
+{ \
+ return show_in_##reg (dev, buf, offset); \
+} \
+static ssize_t \
+store_regs_in_##reg##offset (struct device *dev, struct device_attribute *attr, \
+ const char *buf, size_t count) \
+{ \
+ return store_in_##reg (dev, buf, count, offset); \
+} \
+static DEVICE_ATTR(in##offset##_##reg, S_IRUGO | S_IWUSR, \
+ show_regs_in_##reg##offset, store_regs_in_##reg##offset);
+
+#define sysfs_in_offsets(offset) \
+sysfs_in_offset(offset) \
+sysfs_in_reg_offset(min, offset) \
+sysfs_in_reg_offset(max, offset)
+
+sysfs_in_offsets(0);
+sysfs_in_offsets(1);
+sysfs_in_offsets(2);
+sysfs_in_offsets(3);
+sysfs_in_offsets(4);
+sysfs_in_offsets(5);
+sysfs_in_offsets(6);
+sysfs_in_offsets(7);
+sysfs_in_offsets(8);
+sysfs_in_offsets(9);
+
+#define device_create_file_in(client, offset) \
+do { \
+ device_create_file(&client->dev, &dev_attr_in##offset##_input); \
+ device_create_file(&client->dev, &dev_attr_in##offset##_max); \
+ device_create_file(&client->dev, &dev_attr_in##offset##_min); \
+} while (0)
#define show_fan_reg(reg) \
static ssize_t \
@@ -522,21 +630,23 @@
static DEVICE_ATTR(fan##offset##_div, S_IRUGO, \
show_reg_fan##offset##_div, NULL);
-sysfs_fan_offset(1);
-sysfs_fan_min_offset(1);
-sysfs_fan_div_offset(1);
-sysfs_fan_offset(2);
-sysfs_fan_min_offset(2);
-sysfs_fan_div_offset(2);
-sysfs_fan_offset(3);
-sysfs_fan_min_offset(3);
-sysfs_fan_div_offset(3);
-sysfs_fan_offset(4);
-sysfs_fan_min_offset(4);
-sysfs_fan_div_offset(4);
-sysfs_fan_offset(5);
-sysfs_fan_min_offset(5);
-sysfs_fan_div_offset(5);
+#define sysfs_fan_offsets(offset) \
+sysfs_fan_offset(offset) \
+sysfs_fan_min_offset(offset) \
+sysfs_fan_div_offset(offset)
+
+sysfs_fan_offsets(1);
+sysfs_fan_offsets(2);
+sysfs_fan_offsets(3);
+sysfs_fan_offsets(4);
+sysfs_fan_offsets(5);
+
+#define device_create_file_fan(client, offset) \
+do { \
+ device_create_file(&client->dev, &dev_attr_fan##offset##_input); \
+ device_create_file(&client->dev, &dev_attr_fan##offset##_min); \
+ device_create_file(&client->dev, &dev_attr_fan##offset##_div); \
+} while (0)
#define show_temp1_reg(reg) \
static ssize_t \
@@ -639,6 +749,13 @@
sysfs_temp_reg_offset(max, 3);
sysfs_temp_reg_offset(max_hyst, 3);
+#define device_create_file_temp(client, offset) \
+do { \
+ device_create_file(&client->dev, &dev_attr_temp##offset##_input); \
+ device_create_file(&client->dev, &dev_attr_temp##offset##_max); \
+ device_create_file(&client->dev, &dev_attr_temp##offset##_max_hyst); \
+} while (0)
+
/*
* Driver and client management
*/
@@ -665,6 +782,13 @@
W83627EHF_REG_TEMP_CONFIG[i],
tmp & 0xfe);
}
+ w83627ehf_write_value(client, 0x00, 0x04);
+ w83627ehf_write_value(client, 0x02, 0x04);
+ w83627ehf_write_value(client, 0x04, 0x00);
+ w83627ehf_write_value(client, 0x10, 0x04);
+ w83627ehf_write_value(client, 0x12, 0x00);
+ w83627ehf_write_value(client, 0x60, 0x04);
+ w83627ehf_write_value(client, 0x62, 0x00);
}
static int w83627ehf_detect(struct i2c_adapter *adapter)
@@ -724,36 +848,31 @@
goto exit_detach;
}
- device_create_file(&client->dev, &dev_attr_fan1_input);
- device_create_file(&client->dev, &dev_attr_fan1_min);
- device_create_file(&client->dev, &dev_attr_fan1_div);
- device_create_file(&client->dev, &dev_attr_fan2_input);
- device_create_file(&client->dev, &dev_attr_fan2_min);
- device_create_file(&client->dev, &dev_attr_fan2_div);
- device_create_file(&client->dev, &dev_attr_fan3_input);
- device_create_file(&client->dev, &dev_attr_fan3_min);
- device_create_file(&client->dev, &dev_attr_fan3_div);
+ device_create_file_in(client, 0);
+ device_create_file_in(client, 1);
+ device_create_file_in(client, 2);
+ device_create_file_in(client, 3);
+ device_create_file_in(client, 4);
+ device_create_file_in(client, 5);
+ device_create_file_in(client, 6);
+ device_create_file_in(client, 7);
+ device_create_file_in(client, 8);
+ device_create_file_in(client, 9);
+
+ device_create_file_fan(client, 1);
+ device_create_file_fan(client, 2);
+ device_create_file_fan(client, 3);
if (data->has_fan & (1 << 3)) {
- device_create_file(&client->dev, &dev_attr_fan4_input);
- device_create_file(&client->dev, &dev_attr_fan4_min);
- device_create_file(&client->dev, &dev_attr_fan4_div);
+ device_create_file_fan(client, 4);
}
if (data->has_fan & (1 << 4)) {
- device_create_file(&client->dev, &dev_attr_fan5_input);
- device_create_file(&client->dev, &dev_attr_fan5_min);
- device_create_file(&client->dev, &dev_attr_fan5_div);
+ device_create_file_fan(client, 5);
}
-
- device_create_file(&client->dev, &dev_attr_temp1_input);
- device_create_file(&client->dev, &dev_attr_temp1_max);
- device_create_file(&client->dev, &dev_attr_temp1_max_hyst);
- device_create_file(&client->dev, &dev_attr_temp2_input);
- device_create_file(&client->dev, &dev_attr_temp2_max);
- device_create_file(&client->dev, &dev_attr_temp2_max_hyst);
- device_create_file(&client->dev, &dev_attr_temp3_input);
- device_create_file(&client->dev, &dev_attr_temp3_max);
- device_create_file(&client->dev, &dev_attr_temp3_max_hyst);
+
+ device_create_file_temp(client, 1);
+ device_create_file_temp(client, 2);
+ device_create_file_temp(client, 3);
return 0;
next prev parent reply other threads:[~2006-01-09 10:20 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-12-30 14:38 [lm-sensors] w83627ehf fan controll? Sebastian Band
2005-12-30 14:53 ` Rudolf Marek
2005-12-31 9:18 ` Ymu
2005-12-31 19:12 ` Jean Delvare
2006-01-09 10:20 ` Aurelien Jarno [this message]
2006-01-21 19:23 ` Rudolf Marek
2006-01-23 2:14 ` Ymu
2006-01-24 6:05 ` Ymu
2006-01-29 21:31 ` Jean Delvare
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20060109102020.GA6279@farad.aurel32.net \
--to=aurelien@aurel32.net \
--cc=lm-sensors@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.