From: r.marek@sh.cvut.cz (Rudolf Marek)
To: lm-sensors@vger.kernel.org
Subject: [lm-sensors] w83627ehf fan controll?
Date: Sat, 21 Jan 2006 19:23:30 +0000 [thread overview]
Message-ID: <43D28A32.5050602@sh.cvut.cz> (raw)
In-Reply-To: <20051230143805.GA21201@Apollo>
Hi all,
Sorry for late response. I did some quick review of this code. Maybe Yuan can find it useful.
1) max and min regs are switched
2) code does not use sensor_dev_attr and uses old macro system
3) it contains some tweaks to force PWM (seems from Aurelian attempts to get his PWM working :)
I have a question now:
1) does anyone else has something to show?
2) does anyone has userspace voltage support?
I cant work much on this next moth (feb) busy with final exams. Well maybe I will - as brain relax subroutine :)
Yuan have you this on your own schedule?
Thanks,
Regards
Rudolf
> --- /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 };
> +
Min and max are switched.
> 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]);
Maybe one tab missing?
> + }
> +
> /* 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); \
I think I have seen some patch that is changing this semaphore to mutexes.
> + 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);
Why this way?
What about this:
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),
and
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),
/* following are the sysfs callback functions */
static ssize_t show_in(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
int nr = sensor_attr->index;
struct w83792d_data *data = w83792d_update_device(dev);
return sprintf(buf,"%ld\n", IN_FROM_REG(nr,(in_count_from_reg(nr, data))));
}
I think you get it :)
> +
> +#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);
It seems this are your own tweaks. This needs to be removed.
> }
>
> 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;
>
>
>
> ------------------------------------------------------------------------
>
> _______________________________________________
> lm-sensors mailing list
> lm-sensors at lm-sensors.org
> http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
next prev parent reply other threads:[~2006-01-21 19:23 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
2006-01-21 19:23 ` Rudolf Marek [this message]
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=43D28A32.5050602@sh.cvut.cz \
--to=r.marek@sh.cvut.cz \
--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.