[PATCH] I2C: lm63 uses new sysfs callbacks

I updated the lm63 hardware monitoring driver to take benefit of Yani
Ioannou's new sysfs callback capabilities.

Signed-off-by: Jean Delvare <khali@linux-fr.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Jean Delvare 2005-06-05 20:32:27 +02:00 committed by Greg Kroah-Hartman
parent 1a86c05121
commit bc51ae1159

View File

@ -1,7 +1,7 @@
/* /*
* lm63.c - driver for the National Semiconductor LM63 temperature sensor * lm63.c - driver for the National Semiconductor LM63 temperature sensor
* with integrated fan control * with integrated fan control
* Copyright (C) 2004 Jean Delvare <khali@linux-fr.org> * Copyright (C) 2004-2005 Jean Delvare <khali@linux-fr.org>
* Based on the lm90 driver. * Based on the lm90 driver.
* *
* The LM63 is a sensor chip made by National Semiconductor. It measures * The LM63 is a sensor chip made by National Semiconductor. It measures
@ -43,6 +43,7 @@
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-sensor.h> #include <linux/i2c-sensor.h>
#include <linux/i2c-sysfs.h>
/* /*
* Addresses to scan * Addresses to scan
@ -157,16 +158,16 @@ struct lm63_data {
/* registers values */ /* registers values */
u8 config, config_fan; u8 config, config_fan;
u16 fan1_input; u16 fan[2]; /* 0: input
u16 fan1_low; 1: low limit */
u8 pwm1_freq; u8 pwm1_freq;
u8 pwm1_value; u8 pwm1_value;
s8 temp1_input; s8 temp8[3]; /* 0: local input
s8 temp1_high; 1: local high limit
s16 temp2_input; 2: remote critical limit */
s16 temp2_high; s16 temp11[3]; /* 0: remote input
s16 temp2_low; 1: remote low limit
s8 temp2_crit; 2: remote high limit */
u8 temp2_crit_hyst; u8 temp2_crit_hyst;
u8 alarms; u8 alarms;
}; };
@ -175,33 +176,33 @@ struct lm63_data {
* Sysfs callback functions and files * Sysfs callback functions and files
*/ */
#define show_fan(value) \ static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \ char *buf)
{ \ {
struct lm63_data *data = lm63_update_device(dev); \ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
return sprintf(buf, "%d\n", FAN_FROM_REG(data->value)); \ struct lm63_data *data = lm63_update_device(dev);
return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[attr->index]));
} }
show_fan(fan1_input);
show_fan(fan1_low);
static ssize_t set_fan1_low(struct device *dev, struct device_attribute *attr, const char *buf, static ssize_t set_fan(struct device *dev, struct device_attribute *dummy,
size_t count) const char *buf, size_t count)
{ {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct lm63_data *data = i2c_get_clientdata(client); struct lm63_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10); unsigned long val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock); down(&data->update_lock);
data->fan1_low = FAN_TO_REG(val); data->fan[1] = FAN_TO_REG(val);
i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_LSB, i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_LSB,
data->fan1_low & 0xFF); data->fan[1] & 0xFF);
i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_MSB, i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_MSB,
data->fan1_low >> 8); data->fan[1] >> 8);
up(&data->update_lock); up(&data->update_lock);
return count; return count;
} }
static ssize_t show_pwm1(struct device *dev, struct device_attribute *attr, char *buf) static ssize_t show_pwm1(struct device *dev, struct device_attribute *dummy,
char *buf)
{ {
struct lm63_data *data = lm63_update_device(dev); struct lm63_data *data = lm63_update_device(dev);
return sprintf(buf, "%d\n", data->pwm1_value >= 2 * data->pwm1_freq ? return sprintf(buf, "%d\n", data->pwm1_value >= 2 * data->pwm1_freq ?
@ -209,7 +210,8 @@ static ssize_t show_pwm1(struct device *dev, struct device_attribute *attr, char
(2 * data->pwm1_freq)); (2 * data->pwm1_freq));
} }
static ssize_t set_pwm1(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) static ssize_t set_pwm1(struct device *dev, struct device_attribute *dummy,
const char *buf, size_t count)
{ {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct lm63_data *data = i2c_get_clientdata(client); struct lm63_data *data = i2c_get_clientdata(client);
@ -228,77 +230,83 @@ static ssize_t set_pwm1(struct device *dev, struct device_attribute *attr, const
return count; return count;
} }
static ssize_t show_pwm1_enable(struct device *dev, struct device_attribute *attr, char *buf) static ssize_t show_pwm1_enable(struct device *dev, struct device_attribute *dummy,
char *buf)
{ {
struct lm63_data *data = lm63_update_device(dev); struct lm63_data *data = lm63_update_device(dev);
return sprintf(buf, "%d\n", data->config_fan & 0x20 ? 1 : 2); return sprintf(buf, "%d\n", data->config_fan & 0x20 ? 1 : 2);
} }
#define show_temp8(value) \ static ssize_t show_temp8(struct device *dev, struct device_attribute *devattr,
static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \ char *buf)
{ \ {
struct lm63_data *data = lm63_update_device(dev); \ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->value)); \ struct lm63_data *data = lm63_update_device(dev);
return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->temp8[attr->index]));
} }
#define show_temp11(value) \
static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct lm63_data *data = lm63_update_device(dev); \
return sprintf(buf, "%d\n", TEMP11_FROM_REG(data->value)); \
}
show_temp8(temp1_input);
show_temp8(temp1_high);
show_temp11(temp2_input);
show_temp11(temp2_high);
show_temp11(temp2_low);
show_temp8(temp2_crit);
#define set_temp8(value, reg) \ static ssize_t set_temp8(struct device *dev, struct device_attribute *dummy,
static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, \ const char *buf, size_t count)
size_t count) \ {
{ \ struct i2c_client *client = to_i2c_client(dev);
struct i2c_client *client = to_i2c_client(dev); \ struct lm63_data *data = i2c_get_clientdata(client);
struct lm63_data *data = i2c_get_clientdata(client); \ long val = simple_strtol(buf, NULL, 10);
long val = simple_strtol(buf, NULL, 10); \
\ down(&data->update_lock);
down(&data->update_lock); \ data->temp8[1] = TEMP8_TO_REG(val);
data->value = TEMP8_TO_REG(val); \ i2c_smbus_write_byte_data(client, LM63_REG_LOCAL_HIGH, data->temp8[1]);
i2c_smbus_write_byte_data(client, reg, data->value); \ up(&data->update_lock);
up(&data->update_lock); \ return count;
return count; \
} }
#define set_temp11(value, reg_msb, reg_lsb) \
static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, \ static ssize_t show_temp11(struct device *dev, struct device_attribute *devattr,
size_t count) \ char *buf)
{ \ {
struct i2c_client *client = to_i2c_client(dev); \ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct lm63_data *data = i2c_get_clientdata(client); \ struct lm63_data *data = lm63_update_device(dev);
long val = simple_strtol(buf, NULL, 10); \ return sprintf(buf, "%d\n", TEMP11_FROM_REG(data->temp11[attr->index]));
\ }
down(&data->update_lock); \
data->value = TEMP11_TO_REG(val); \ static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr,
i2c_smbus_write_byte_data(client, reg_msb, data->value >> 8); \ const char *buf, size_t count)
i2c_smbus_write_byte_data(client, reg_lsb, data->value & 0xff); \ {
up(&data->update_lock); \ static const u8 reg[4] = {
return count; \ LM63_REG_REMOTE_LOW_MSB,
LM63_REG_REMOTE_LOW_LSB,
LM63_REG_REMOTE_HIGH_MSB,
LM63_REG_REMOTE_HIGH_LSB,
};
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev);
struct lm63_data *data = i2c_get_clientdata(client);
long val = simple_strtol(buf, NULL, 10);
int nr = attr->index;
down(&data->update_lock);
data->temp11[nr] = TEMP11_TO_REG(val);
i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2],
data->temp11[nr] >> 8);
i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1],
data->temp11[nr] & 0xff);
up(&data->update_lock);
return count;
} }
set_temp8(temp1_high, LM63_REG_LOCAL_HIGH);
set_temp11(temp2_high, LM63_REG_REMOTE_HIGH_MSB, LM63_REG_REMOTE_HIGH_LSB);
set_temp11(temp2_low, LM63_REG_REMOTE_LOW_MSB, LM63_REG_REMOTE_LOW_LSB);
/* Hysteresis register holds a relative value, while we want to present /* Hysteresis register holds a relative value, while we want to present
an absolute to user-space */ an absolute to user-space */
static ssize_t show_temp2_crit_hyst(struct device *dev, struct device_attribute *attr, char *buf) static ssize_t show_temp2_crit_hyst(struct device *dev, struct device_attribute *dummy,
char *buf)
{ {
struct lm63_data *data = lm63_update_device(dev); struct lm63_data *data = lm63_update_device(dev);
return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->temp2_crit) return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->temp8[2])
- TEMP8_FROM_REG(data->temp2_crit_hyst)); - TEMP8_FROM_REG(data->temp2_crit_hyst));
} }
/* And now the other way around, user-space provides an absolute /* And now the other way around, user-space provides an absolute
hysteresis value and we have to store a relative one */ hysteresis value and we have to store a relative one */
static ssize_t set_temp2_crit_hyst(struct device *dev, struct device_attribute *attr, const char *buf, static ssize_t set_temp2_crit_hyst(struct device *dev, struct device_attribute *dummy,
size_t count) const char *buf, size_t count)
{ {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct lm63_data *data = i2c_get_clientdata(client); struct lm63_data *data = i2c_get_clientdata(client);
@ -306,36 +314,37 @@ static ssize_t set_temp2_crit_hyst(struct device *dev, struct device_attribute *
long hyst; long hyst;
down(&data->update_lock); down(&data->update_lock);
hyst = TEMP8_FROM_REG(data->temp2_crit) - val; hyst = TEMP8_FROM_REG(data->temp8[2]) - val;
i2c_smbus_write_byte_data(client, LM63_REG_REMOTE_TCRIT_HYST, i2c_smbus_write_byte_data(client, LM63_REG_REMOTE_TCRIT_HYST,
HYST_TO_REG(hyst)); HYST_TO_REG(hyst));
up(&data->update_lock); up(&data->update_lock);
return count; return count;
} }
static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf) static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy,
char *buf)
{ {
struct lm63_data *data = lm63_update_device(dev); struct lm63_data *data = lm63_update_device(dev);
return sprintf(buf, "%u\n", data->alarms); return sprintf(buf, "%u\n", data->alarms);
} }
static DEVICE_ATTR(fan1_input, S_IRUGO, show_fan1_input, NULL); static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
static DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan1_low, static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan,
set_fan1_low); set_fan, 1);
static DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm1, set_pwm1); static DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm1, set_pwm1);
static DEVICE_ATTR(pwm1_enable, S_IRUGO, show_pwm1_enable, NULL); static DEVICE_ATTR(pwm1_enable, S_IRUGO, show_pwm1_enable, NULL);
static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1_input, NULL); static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp8, NULL, 0);
static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp1_high, static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp8,
set_temp1_high); set_temp8, 1);
static DEVICE_ATTR(temp2_input, S_IRUGO, show_temp2_input, NULL); static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp11, NULL, 0);
static DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp2_low, static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp11,
set_temp2_low); set_temp11, 1);
static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp2_high, static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp11,
set_temp2_high); set_temp11, 2);
static DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp2_crit, NULL); static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp8, NULL, 2);
static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp2_crit_hyst, static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp2_crit_hyst,
set_temp2_crit_hyst); set_temp2_crit_hyst);
@ -429,17 +438,25 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind)
/* Register sysfs hooks */ /* Register sysfs hooks */
if (data->config & 0x04) { /* tachometer enabled */ if (data->config & 0x04) { /* tachometer enabled */
device_create_file(&new_client->dev, &dev_attr_fan1_input); device_create_file(&new_client->dev,
device_create_file(&new_client->dev, &dev_attr_fan1_min); &sensor_dev_attr_fan1_input.dev_attr);
device_create_file(&new_client->dev,
&sensor_dev_attr_fan1_min.dev_attr);
} }
device_create_file(&new_client->dev, &dev_attr_pwm1); device_create_file(&new_client->dev, &dev_attr_pwm1);
device_create_file(&new_client->dev, &dev_attr_pwm1_enable); device_create_file(&new_client->dev, &dev_attr_pwm1_enable);
device_create_file(&new_client->dev, &dev_attr_temp1_input); device_create_file(&new_client->dev,
device_create_file(&new_client->dev, &dev_attr_temp2_input); &sensor_dev_attr_temp1_input.dev_attr);
device_create_file(&new_client->dev, &dev_attr_temp2_min); device_create_file(&new_client->dev,
device_create_file(&new_client->dev, &dev_attr_temp1_max); &sensor_dev_attr_temp2_input.dev_attr);
device_create_file(&new_client->dev, &dev_attr_temp2_max); device_create_file(&new_client->dev,
device_create_file(&new_client->dev, &dev_attr_temp2_crit); &sensor_dev_attr_temp2_min.dev_attr);
device_create_file(&new_client->dev,
&sensor_dev_attr_temp1_max.dev_attr);
device_create_file(&new_client->dev,
&sensor_dev_attr_temp2_max.dev_attr);
device_create_file(&new_client->dev,
&sensor_dev_attr_temp2_crit.dev_attr);
device_create_file(&new_client->dev, &dev_attr_temp2_crit_hyst); device_create_file(&new_client->dev, &dev_attr_temp2_crit_hyst);
device_create_file(&new_client->dev, &dev_attr_alarms); device_create_file(&new_client->dev, &dev_attr_alarms);
@ -510,14 +527,14 @@ static struct lm63_data *lm63_update_device(struct device *dev)
if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
if (data->config & 0x04) { /* tachometer enabled */ if (data->config & 0x04) { /* tachometer enabled */
/* order matters for fan1_input */ /* order matters for fan1_input */
data->fan1_input = i2c_smbus_read_byte_data(client, data->fan[0] = i2c_smbus_read_byte_data(client,
LM63_REG_TACH_COUNT_LSB) & 0xFC; LM63_REG_TACH_COUNT_LSB) & 0xFC;
data->fan1_input |= i2c_smbus_read_byte_data(client, data->fan[0] |= i2c_smbus_read_byte_data(client,
LM63_REG_TACH_COUNT_MSB) << 8; LM63_REG_TACH_COUNT_MSB) << 8;
data->fan1_low = (i2c_smbus_read_byte_data(client, data->fan[1] = (i2c_smbus_read_byte_data(client,
LM63_REG_TACH_LIMIT_LSB) & 0xFC) LM63_REG_TACH_LIMIT_LSB) & 0xFC)
| (i2c_smbus_read_byte_data(client, | (i2c_smbus_read_byte_data(client,
LM63_REG_TACH_LIMIT_MSB) << 8); LM63_REG_TACH_LIMIT_MSB) << 8);
} }
data->pwm1_freq = i2c_smbus_read_byte_data(client, data->pwm1_freq = i2c_smbus_read_byte_data(client,
@ -527,26 +544,26 @@ static struct lm63_data *lm63_update_device(struct device *dev)
data->pwm1_value = i2c_smbus_read_byte_data(client, data->pwm1_value = i2c_smbus_read_byte_data(client,
LM63_REG_PWM_VALUE); LM63_REG_PWM_VALUE);
data->temp1_input = i2c_smbus_read_byte_data(client, data->temp8[0] = i2c_smbus_read_byte_data(client,
LM63_REG_LOCAL_TEMP); LM63_REG_LOCAL_TEMP);
data->temp1_high = i2c_smbus_read_byte_data(client, data->temp8[1] = i2c_smbus_read_byte_data(client,
LM63_REG_LOCAL_HIGH); LM63_REG_LOCAL_HIGH);
/* order matters for temp2_input */ /* order matters for temp2_input */
data->temp2_input = i2c_smbus_read_byte_data(client, data->temp11[0] = i2c_smbus_read_byte_data(client,
LM63_REG_REMOTE_TEMP_MSB) << 8; LM63_REG_REMOTE_TEMP_MSB) << 8;
data->temp2_input |= i2c_smbus_read_byte_data(client, data->temp11[0] |= i2c_smbus_read_byte_data(client,
LM63_REG_REMOTE_TEMP_LSB); LM63_REG_REMOTE_TEMP_LSB);
data->temp2_high = (i2c_smbus_read_byte_data(client, data->temp11[1] = (i2c_smbus_read_byte_data(client,
LM63_REG_REMOTE_HIGH_MSB) << 8)
| i2c_smbus_read_byte_data(client,
LM63_REG_REMOTE_HIGH_LSB);
data->temp2_low = (i2c_smbus_read_byte_data(client,
LM63_REG_REMOTE_LOW_MSB) << 8) LM63_REG_REMOTE_LOW_MSB) << 8)
| i2c_smbus_read_byte_data(client, | i2c_smbus_read_byte_data(client,
LM63_REG_REMOTE_LOW_LSB); LM63_REG_REMOTE_LOW_LSB);
data->temp2_crit = i2c_smbus_read_byte_data(client, data->temp11[2] = (i2c_smbus_read_byte_data(client,
LM63_REG_REMOTE_TCRIT); LM63_REG_REMOTE_HIGH_MSB) << 8)
| i2c_smbus_read_byte_data(client,
LM63_REG_REMOTE_HIGH_LSB);
data->temp8[2] = i2c_smbus_read_byte_data(client,
LM63_REG_REMOTE_TCRIT);
data->temp2_crit_hyst = i2c_smbus_read_byte_data(client, data->temp2_crit_hyst = i2c_smbus_read_byte_data(client,
LM63_REG_REMOTE_TCRIT_HYST); LM63_REG_REMOTE_TCRIT_HYST);