All of lore.kernel.org
 help / color / mirror / Atom feed
* [lm-sensors] [PATCH 5/5] hwmon: (lm63) Add support for
@ 2012-01-10  3:42 Guenter Roeck
  2012-01-11 21:57 ` [lm-sensors] [PATCH 5/5] hwmon: (lm63) Add support for update_interval sysfs attribute Jean Delvare
  2012-01-11 22:51 ` Guenter Roeck
  0 siblings, 2 replies; 3+ messages in thread
From: Guenter Roeck @ 2012-01-10  3:42 UTC (permalink / raw)
  To: lm-sensors

The update interval is configurable on LM63 and compatibles. Add support for it.

Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 drivers/hwmon/lm63.c |   95 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 94 insertions(+), 1 deletions(-)

diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c
index 6370e28..368db01 100644
--- a/drivers/hwmon/lm63.c
+++ b/drivers/hwmon/lm63.c
@@ -61,6 +61,7 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END };
  */
 
 #define LM63_REG_CONFIG1		0x03
+#define LM63_REG_CONVRATE		0x04
 #define LM63_REG_CONFIG2		0xBF
 #define LM63_REG_CONFIG_FAN		0x4A
 
@@ -96,6 +97,11 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END };
 #define LM96163_REG_REMOTE_TEMP_U_LSB	0x32
 #define LM96163_REG_CONFIG_ENHANCED	0x45
 
+#define LM63_MAX_CONVRATE		9
+
+#define LM63_MAX_CONVRATE_HZ		32
+#define LM96163_MAX_CONVRATE_HZ		26
+
 /*
  * Conversions and various macros
  * For tachometer counts, the LM63 uses 16-bit values.
@@ -132,6 +138,10 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END };
 				 (val) >= 127000 ? 127 : \
 				 ((val) + 500) / 1000)
 
+#define UPDATE_INTERVAL(max, rate) \
+	DIV_ROUND_CLOSEST(10000000, \
+			  ((max) * 10000) >> (LM63_MAX_CONVRATE - (rate)))
+
 /*
  * Functions declaration
  */
@@ -183,6 +193,9 @@ struct lm63_data {
 	int kind;
 	int temp2_offset;
 
+	int update_interval;	/* in milliseconds */
+	int max_convrate_hz;
+
 	/* registers values */
 	u8 config, config_fan;
 	u16 fan[2];	/* 0: input
@@ -463,6 +476,59 @@ static ssize_t set_temp2_crit_hyst(struct device *dev,
 	return count;
 }
 
+/*
+ * Set conversion rate.
+ * client->update_lock must be held when calling this function (unless we are
+ * in detection or initialization steps).
+ */
+static void lm63_set_convrate(struct i2c_client *client, struct lm63_data *data,
+			      unsigned int interval)
+{
+	int i;
+	unsigned int update_interval;
+
+	/* Shift calculations to avoid rounding errors */
+	interval <<= 6;
+
+	/* find the nearest update rate */
+	update_interval = (1 << (LM63_MAX_CONVRATE + 6)) * 1000
+	  / data->max_convrate_hz;
+	for (i = 0; i < LM63_MAX_CONVRATE; i++, update_interval >>= 1)
+		if (interval >= update_interval * 3 / 4)
+			break;
+
+	i2c_smbus_write_byte_data(client, LM63_REG_CONVRATE, i);
+	data->update_interval = UPDATE_INTERVAL(data->max_convrate_hz, i);
+}
+
+static ssize_t show_update_interval(struct device *dev,
+				    struct device_attribute *attr, char *buf)
+{
+	struct lm63_data *data = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%u\n", data->update_interval);
+}
+
+static ssize_t set_update_interval(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm63_data *data = i2c_get_clientdata(client);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+
+	mutex_lock(&data->update_lock);
+	lm63_set_convrate(client, data, val);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
 static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy,
 			   char *buf)
 {
@@ -513,6 +579,9 @@ static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6);
 /* Raw alarm file for compatibility */
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
+static DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR, show_update_interval,
+		   set_update_interval);
+
 static struct attribute *lm63_attributes[] = {
 	&dev_attr_pwm1.attr,
 	&dev_attr_pwm1_enable.attr,
@@ -531,6 +600,7 @@ static struct attribute *lm63_attributes[] = {
 	&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
 	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
 	&dev_attr_alarms.attr,
+	&dev_attr_update_interval.attr,
 	NULL
 };
 
@@ -683,6 +753,7 @@ exit:
 static void lm63_init_client(struct i2c_client *client)
 {
 	struct lm63_data *data = i2c_get_clientdata(client);
+	u8 convrate;
 
 	data->config = i2c_smbus_read_byte_data(client, LM63_REG_CONFIG1);
 	data->config_fan = i2c_smbus_read_byte_data(client,
@@ -701,6 +772,24 @@ static void lm63_init_client(struct i2c_client *client)
 	if (data->pwm1_freq = 0)
 		data->pwm1_freq = 1;
 
+	switch (data->kind) {
+	case lm63:
+	case lm64:
+		data->max_convrate_hz = LM63_MAX_CONVRATE_HZ;
+		break;
+	case lm96163:
+		data->max_convrate_hz = LM96163_MAX_CONVRATE_HZ;
+		break;
+	default:
+		BUG();
+		break;
+	}
+	convrate = i2c_smbus_read_byte_data(client, LM63_REG_CONVRATE);
+	if (convrate > LM63_MAX_CONVRATE)
+		convrate = LM63_MAX_CONVRATE;
+	data->update_interval = UPDATE_INTERVAL(data->max_convrate_hz,
+						convrate);
+
 	/*
 	 * For LM96163, check if high resolution PWM
 	 * and unsigned temperature format is enabled.
@@ -744,10 +833,14 @@ static struct lm63_data *lm63_update_device(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm63_data *data = i2c_get_clientdata(client);
+	unsigned long next_update;
 
 	mutex_lock(&data->update_lock);
 
-	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
+	next_update = data->last_updated
+	  + msecs_to_jiffies(data->update_interval) + 1;
+
+	if (time_after(jiffies, next_update) || !data->valid) {
 		if (data->config & 0x04) { /* tachometer enabled  */
 			/* order matters for fan1_input */
 			data->fan[0] = i2c_smbus_read_byte_data(client,
-- 
1.7.5.4


_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [lm-sensors] [PATCH 5/5] hwmon: (lm63) Add support for update_interval sysfs attribute
  2012-01-10  3:42 [lm-sensors] [PATCH 5/5] hwmon: (lm63) Add support for Guenter Roeck
@ 2012-01-11 21:57 ` Jean Delvare
  2012-01-11 22:51 ` Guenter Roeck
  1 sibling, 0 replies; 3+ messages in thread
From: Jean Delvare @ 2012-01-11 21:57 UTC (permalink / raw)
  To: lm-sensors

Hi Guenter,

Sorry for the late review of this one, I wanted to spend some time to
ensure that the computing code was correct, as it is not trivial.

On Mon,  9 Jan 2012 19:42:03 -0800, Guenter Roeck wrote:
> The update interval is configurable on LM63 and compatibles. Add support for it.
> 
> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
> ---
>  drivers/hwmon/lm63.c |   95 +++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 files changed, 94 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c
> index 6370e28..368db01 100644
> --- a/drivers/hwmon/lm63.c
> +++ b/drivers/hwmon/lm63.c
> @@ -61,6 +61,7 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END };
>   */
>  
>  #define LM63_REG_CONFIG1		0x03
> +#define LM63_REG_CONVRATE		0x04
>  #define LM63_REG_CONFIG2		0xBF
>  #define LM63_REG_CONFIG_FAN		0x4A
>  
> @@ -96,6 +97,11 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END };
>  #define LM96163_REG_REMOTE_TEMP_U_LSB	0x32
>  #define LM96163_REG_CONFIG_ENHANCED	0x45
>  
> +#define LM63_MAX_CONVRATE		9
> +
> +#define LM63_MAX_CONVRATE_HZ		32
> +#define LM96163_MAX_CONVRATE_HZ		26

How smart from the manufacturer :/

> +
>  /*
>   * Conversions and various macros
>   * For tachometer counts, the LM63 uses 16-bit values.
> @@ -132,6 +138,10 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END };
>  				 (val) >= 127000 ? 127 : \
>  				 ((val) + 500) / 1000)
>  
> +#define UPDATE_INTERVAL(max, rate) \
> +	DIV_ROUND_CLOSEST(10000000, \
> +			  ((max) * 10000) >> (LM63_MAX_CONVRATE - (rate)))

I'd prefer an inline function. Macros are evil and this driver already
have plenty of these.

I don't quite get the rationale for the 10000, BTW. If you want to
avoid loss of precision, you'd rather use 2^LM63_MAX_CONVRATE i.e. 512
as your magic constant. But it would seem even smarter to do things the
other way around so you don't need such a constant:

#define UPDATE_INTERVAL(max, rate) \
	((1000 << (LM63_MAX_CONVRATE - (rate))) / (max))

This should be much faster, and also more accurate for slow frequencies.

> +
>  /*
>   * Functions declaration
>   */
> @@ -183,6 +193,9 @@ struct lm63_data {
>  	int kind;
>  	int temp2_offset;
>  
> +	int update_interval;	/* in milliseconds */
> +	int max_convrate_hz;
> +
>  	/* registers values */
>  	u8 config, config_fan;
>  	u16 fan[2];	/* 0: input
> @@ -463,6 +476,59 @@ static ssize_t set_temp2_crit_hyst(struct device *dev,
>  	return count;
>  }
>  
> +/*
> + * Set conversion rate.
> + * client->update_lock must be held when calling this function (unless we are
> + * in detection or initialization steps).

Nice copy-and-paste but "detection step" obviously doesn't apply here;
detection wouldn't reconfigure the device.

> + */
> +static void lm63_set_convrate(struct i2c_client *client, struct lm63_data *data,
> +			      unsigned int interval)
> +{
> +	int i;
> +	unsigned int update_interval;
> +
> +	/* Shift calculations to avoid rounding errors */
> +	interval <<= 6;

This could overflow, at least in theory. You should check for
	interval >= (1 << LM63_MAX_CONVRATE) * 1000 / data->max_convrate_hz
or even more simply and arbitrarily for
	interval >= 100000
and skip the loop in this case. Yes, the lm90 driver suffers from the
same problem.

> +
> +	/* find the nearest update rate */
> +	update_interval = (1 << (LM63_MAX_CONVRATE + 6)) * 1000
> +	  / data->max_convrate_hz;
> +	for (i = 0; i < LM63_MAX_CONVRATE; i++, update_interval >>= 1)
> +		if (interval >= update_interval * 3 / 4)
> +			break;
> +
> +	i2c_smbus_write_byte_data(client, LM63_REG_CONVRATE, i);
> +	data->update_interval = UPDATE_INTERVAL(data->max_convrate_hz, i);
> +}
> +
> +static ssize_t show_update_interval(struct device *dev,
> +				    struct device_attribute *attr, char *buf)
> +{
> +	struct lm63_data *data = dev_get_drvdata(dev);
> +
> +	return sprintf(buf, "%u\n", data->update_interval);
> +}
> +
> +static ssize_t set_update_interval(struct device *dev,
> +				   struct device_attribute *attr,
> +				   const char *buf, size_t count)
> +{
> +	struct i2c_client *client = to_i2c_client(dev);
> +	struct lm63_data *data = i2c_get_clientdata(client);
> +	unsigned long val;
> +	int err;
> +
> +	err = kstrtoul(buf, 10, &val);
> +	if (err)
> +		return err;
> +
> +	mutex_lock(&data->update_lock);
> +	lm63_set_convrate(client, data, val);
> +	mutex_unlock(&data->update_lock);
> +
> +	return count;
> +}
> +
>  static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy,
>  			   char *buf)
>  {
> @@ -513,6 +579,9 @@ static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6);
>  /* Raw alarm file for compatibility */
>  static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
>  
> +static DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR, show_update_interval,
> +		   set_update_interval);
> +
>  static struct attribute *lm63_attributes[] = {
>  	&dev_attr_pwm1.attr,
>  	&dev_attr_pwm1_enable.attr,
> @@ -531,6 +600,7 @@ static struct attribute *lm63_attributes[] = {
>  	&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
>  	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
>  	&dev_attr_alarms.attr,
> +	&dev_attr_update_interval.attr,
>  	NULL
>  };
>  
> @@ -683,6 +753,7 @@ exit:
>  static void lm63_init_client(struct i2c_client *client)
>  {
>  	struct lm63_data *data = i2c_get_clientdata(client);
> +	u8 convrate;
>  
>  	data->config = i2c_smbus_read_byte_data(client, LM63_REG_CONFIG1);
>  	data->config_fan = i2c_smbus_read_byte_data(client,
> @@ -701,6 +772,24 @@ static void lm63_init_client(struct i2c_client *client)
>  	if (data->pwm1_freq = 0)
>  		data->pwm1_freq = 1;
>  
> +	switch (data->kind) {
> +	case lm63:
> +	case lm64:
> +		data->max_convrate_hz = LM63_MAX_CONVRATE_HZ;
> +		break;
> +	case lm96163:
> +		data->max_convrate_hz = LM96163_MAX_CONVRATE_HZ;
> +		break;
> +	default:
> +		BUG();
> +		break;
> +	}

If you'd turn data->type into enum chips, you could remove the default
statement: gcc would kindly warn if a chip type is omitted.

Probably something to be done in all i2c-based hwmon drivers...

> +	convrate = i2c_smbus_read_byte_data(client, LM63_REG_CONVRATE);
> +	if (convrate > LM63_MAX_CONVRATE)

Might make sense to use unlikely() here, as this isn't supposed to
happen.

> +		convrate = LM63_MAX_CONVRATE;
> +	data->update_interval = UPDATE_INTERVAL(data->max_convrate_hz,
> +						convrate);
> +
>  	/*
>  	 * For LM96163, check if high resolution PWM
>  	 * and unsigned temperature format is enabled.
> @@ -744,10 +833,14 @@ static struct lm63_data *lm63_update_device(struct device *dev)
>  {
>  	struct i2c_client *client = to_i2c_client(dev);
>  	struct lm63_data *data = i2c_get_clientdata(client);
> +	unsigned long next_update;
>  
>  	mutex_lock(&data->update_lock);
>  
> -	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
> +	next_update = data->last_updated
> +	  + msecs_to_jiffies(data->update_interval) + 1;
> +
> +	if (time_after(jiffies, next_update) || !data->valid) {
>  		if (data->config & 0x04) { /* tachometer enabled  */
>  			/* order matters for fan1_input */
>  			data->fan[0] = i2c_smbus_read_byte_data(client,


-- 
Jean Delvare

_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [lm-sensors] [PATCH 5/5] hwmon: (lm63) Add support for update_interval sysfs attribute
  2012-01-10  3:42 [lm-sensors] [PATCH 5/5] hwmon: (lm63) Add support for Guenter Roeck
  2012-01-11 21:57 ` [lm-sensors] [PATCH 5/5] hwmon: (lm63) Add support for update_interval sysfs attribute Jean Delvare
@ 2012-01-11 22:51 ` Guenter Roeck
  1 sibling, 0 replies; 3+ messages in thread
From: Guenter Roeck @ 2012-01-11 22:51 UTC (permalink / raw)
  To: lm-sensors

Hi Jean,

On Wed, 2012-01-11 at 16:57 -0500, Jean Delvare wrote:
> Hi Guenter,
> 
> Sorry for the late review of this one, I wanted to spend some time to
> ensure that the computing code was correct, as it is not trivial.
> 
No problem. Take your time.

> On Mon,  9 Jan 2012 19:42:03 -0800, Guenter Roeck wrote:
> > The update interval is configurable on LM63 and compatibles. Add support for it.
> > 
> > Signed-off-by: Guenter Roeck <linux@roeck-us.net>
> > ---
> >  drivers/hwmon/lm63.c |   95 +++++++++++++++++++++++++++++++++++++++++++++++++-
> >  1 files changed, 94 insertions(+), 1 deletions(-)
> > 
> > diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c
> > index 6370e28..368db01 100644
> > --- a/drivers/hwmon/lm63.c
> > +++ b/drivers/hwmon/lm63.c
> > @@ -61,6 +61,7 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END };
> >   */
> >  
> >  #define LM63_REG_CONFIG1		0x03
> > +#define LM63_REG_CONVRATE		0x04
> >  #define LM63_REG_CONFIG2		0xBF
> >  #define LM63_REG_CONFIG_FAN		0x4A
> >  
> > @@ -96,6 +97,11 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END };
> >  #define LM96163_REG_REMOTE_TEMP_U_LSB	0x32
> >  #define LM96163_REG_CONFIG_ENHANCED	0x45
> >  
> > +#define LM63_MAX_CONVRATE		9
> > +
> > +#define LM63_MAX_CONVRATE_HZ		32
> > +#define LM96163_MAX_CONVRATE_HZ		26
> 
> How smart from the manufacturer :/
> 
> > +
> >  /*
> >   * Conversions and various macros
> >   * For tachometer counts, the LM63 uses 16-bit values.
> > @@ -132,6 +138,10 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END };
> >  				 (val) >= 127000 ? 127 : \
> >  				 ((val) + 500) / 1000)
> >  
> > +#define UPDATE_INTERVAL(max, rate) \
> > +	DIV_ROUND_CLOSEST(10000000, \
> > +			  ((max) * 10000) >> (LM63_MAX_CONVRATE - (rate)))
> 
> I'd prefer an inline function. Macros are evil and this driver already
> have plenty of these.
> 
> I don't quite get the rationale for the 10000, BTW. If you want to
> avoid loss of precision, you'd rather use 2^LM63_MAX_CONVRATE i.e. 512
> as your magic constant. But it would seem even smarter to do things the
> other way around so you don't need such a constant:
> 
> #define UPDATE_INTERVAL(max, rate) \
> 	((1000 << (LM63_MAX_CONVRATE - (rate))) / (max))
> 
> This should be much faster, and also more accurate for slow frequencies.
> 
I'll take your define.

> > +
> >  /*
> >   * Functions declaration
> >   */
> > @@ -183,6 +193,9 @@ struct lm63_data {
> >  	int kind;
> >  	int temp2_offset;
> >  
> > +	int update_interval;	/* in milliseconds */
> > +	int max_convrate_hz;
> > +
> >  	/* registers values */
> >  	u8 config, config_fan;
> >  	u16 fan[2];	/* 0: input
> > @@ -463,6 +476,59 @@ static ssize_t set_temp2_crit_hyst(struct device *dev,
> >  	return count;
> >  }
> >  
> > +/*
> > + * Set conversion rate.
> > + * client->update_lock must be held when calling this function (unless we are
> > + * in detection or initialization steps).
> 
> Nice copy-and-paste but "detection step" obviously doesn't apply here;
> detection wouldn't reconfigure the device.
> 
> > + */
> > +static void lm63_set_convrate(struct i2c_client *client, struct lm63_data *data,
> > +			      unsigned int interval)
> > +{
> > +	int i;
> > +	unsigned int update_interval;
> > +
> > +	/* Shift calculations to avoid rounding errors */
> > +	interval <<= 6;
> 
> This could overflow, at least in theory. You should check for
> 	interval >= (1 << LM63_MAX_CONVRATE) * 1000 / data->max_convrate_hz
> or even more simply and arbitrarily for
> 	interval >= 100000
> and skip the loop in this case. Yes, the lm90 driver suffers from the
> same problem.
> 
For simplicity, I'll bound it in the calling code with SENSORS_LIMIT.
And submit a matching patch for lm90.c.

> > +
> > +	/* find the nearest update rate */
> > +	update_interval = (1 << (LM63_MAX_CONVRATE + 6)) * 1000
> > +	  / data->max_convrate_hz;
> > +	for (i = 0; i < LM63_MAX_CONVRATE; i++, update_interval >>= 1)
> > +		if (interval >= update_interval * 3 / 4)
> > +			break;
> > +
> > +	i2c_smbus_write_byte_data(client, LM63_REG_CONVRATE, i);
> > +	data->update_interval = UPDATE_INTERVAL(data->max_convrate_hz, i);
> > +}
> > +
> > +static ssize_t show_update_interval(struct device *dev,
> > +				    struct device_attribute *attr, char *buf)
> > +{
> > +	struct lm63_data *data = dev_get_drvdata(dev);
> > +
> > +	return sprintf(buf, "%u\n", data->update_interval);
> > +}
> > +
> > +static ssize_t set_update_interval(struct device *dev,
> > +				   struct device_attribute *attr,
> > +				   const char *buf, size_t count)
> > +{
> > +	struct i2c_client *client = to_i2c_client(dev);
> > +	struct lm63_data *data = i2c_get_clientdata(client);
> > +	unsigned long val;
> > +	int err;
> > +
> > +	err = kstrtoul(buf, 10, &val);
> > +	if (err)
> > +		return err;
> > +
> > +	mutex_lock(&data->update_lock);
> > +	lm63_set_convrate(client, data, val);
> > +	mutex_unlock(&data->update_lock);
> > +
> > +	return count;
> > +}
> > +
> >  static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy,
> >  			   char *buf)
> >  {
> > @@ -513,6 +579,9 @@ static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6);
> >  /* Raw alarm file for compatibility */
> >  static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
> >  
> > +static DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR, show_update_interval,
> > +		   set_update_interval);
> > +
> >  static struct attribute *lm63_attributes[] = {
> >  	&dev_attr_pwm1.attr,
> >  	&dev_attr_pwm1_enable.attr,
> > @@ -531,6 +600,7 @@ static struct attribute *lm63_attributes[] = {
> >  	&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
> >  	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
> >  	&dev_attr_alarms.attr,
> > +	&dev_attr_update_interval.attr,
> >  	NULL
> >  };
> >  
> > @@ -683,6 +753,7 @@ exit:
> >  static void lm63_init_client(struct i2c_client *client)
> >  {
> >  	struct lm63_data *data = i2c_get_clientdata(client);
> > +	u8 convrate;
> >  
> >  	data->config = i2c_smbus_read_byte_data(client, LM63_REG_CONFIG1);
> >  	data->config_fan = i2c_smbus_read_byte_data(client,
> > @@ -701,6 +772,24 @@ static void lm63_init_client(struct i2c_client *client)
> >  	if (data->pwm1_freq = 0)
> >  		data->pwm1_freq = 1;
> >  
> > +	switch (data->kind) {
> > +	case lm63:
> > +	case lm64:
> > +		data->max_convrate_hz = LM63_MAX_CONVRATE_HZ;
> > +		break;
> > +	case lm96163:
> > +		data->max_convrate_hz = LM96163_MAX_CONVRATE_HZ;
> > +		break;
> > +	default:
> > +		BUG();
> > +		break;
> > +	}
> 
> If you'd turn data->type into enum chips, you could remove the default
> statement: gcc would kindly warn if a chip type is omitted.
> 
Done.

> Probably something to be done in all i2c-based hwmon drivers...
> 
Something for the to-do list.

> > +	convrate = i2c_smbus_read_byte_data(client, LM63_REG_CONVRATE);
> > +	if (convrate > LM63_MAX_CONVRATE)
> 
> Might make sense to use unlikely() here, as this isn't supposed to
> happen.
> 
Ok.

> > +		convrate = LM63_MAX_CONVRATE;
> > +	data->update_interval = UPDATE_INTERVAL(data->max_convrate_hz,
> > +						convrate);
> > +
> >  	/*
> >  	 * For LM96163, check if high resolution PWM
> >  	 * and unsigned temperature format is enabled.
> > @@ -744,10 +833,14 @@ static struct lm63_data *lm63_update_device(struct device *dev)
> >  {
> >  	struct i2c_client *client = to_i2c_client(dev);
> >  	struct lm63_data *data = i2c_get_clientdata(client);
> > +	unsigned long next_update;
> >  
> >  	mutex_lock(&data->update_lock);
> >  
> > -	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
> > +	next_update = data->last_updated
> > +	  + msecs_to_jiffies(data->update_interval) + 1;
> > +
> > +	if (time_after(jiffies, next_update) || !data->valid) {
> >  		if (data->config & 0x04) { /* tachometer enabled  */
> >  			/* order matters for fan1_input */
> >  			data->fan[0] = i2c_smbus_read_byte_data(client,
> 
> 
Thanks,
Guenter



_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2012-01-11 22:51 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-01-10  3:42 [lm-sensors] [PATCH 5/5] hwmon: (lm63) Add support for Guenter Roeck
2012-01-11 21:57 ` [lm-sensors] [PATCH 5/5] hwmon: (lm63) Add support for update_interval sysfs attribute Jean Delvare
2012-01-11 22:51 ` Guenter Roeck

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.