From c83c41e4e623aa6504d30c858a05eac771048029 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Thu, 19 Jul 2007 08:00:17 +0200 Subject: hwmon: adm1021 clean ups This patch provides some coding standard cleanups and general code improvements (more debug info, signed values for temperatures, changed names of ADM1023 regs, removed read/write_value functions). Signed-off-by: Krzysztof Helt Acked-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/adm1021.c | 226 ++++++++++++++++++++++++++---------------------- 1 file changed, 122 insertions(+), 104 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c index c466329b2ef..5418a675bb6 100644 --- a/drivers/hwmon/adm1021.c +++ b/drivers/hwmon/adm1021.c @@ -1,6 +1,6 @@ /* adm1021.c - Part of lm_sensors, Linux kernel modules for hardware - monitoring + monitoring Copyright (c) 1998, 1999 Frodo Looijaard and Philip Edelbrock @@ -32,11 +32,12 @@ /* Addresses to scan */ static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, - 0x4c, 0x4d, 0x4e, + 0x4c, 0x4d, 0x4e, I2C_CLIENT_END }; /* Insmod parameters */ -I2C_CLIENT_INSMOD_8(adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm, mc1066); +I2C_CLIENT_INSMOD_8(adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm, + mc1066); /* adm1021 constants specified below */ @@ -45,20 +46,21 @@ I2C_CLIENT_INSMOD_8(adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm, #define ADM1021_REG_TEMP 0x00 #define ADM1021_REG_REMOTE_TEMP 0x01 #define ADM1021_REG_STATUS 0x02 -#define ADM1021_REG_MAN_ID 0x0FE /* 0x41 = AMD, 0x49 = TI, 0x4D = Maxim, 0x23 = Genesys , 0x54 = Onsemi*/ -#define ADM1021_REG_DEV_ID 0x0FF /* ADM1021 = 0x0X, ADM1023 = 0x3X */ -#define ADM1021_REG_DIE_CODE 0x0FF /* MAX1617A */ +/* 0x41 = AD, 0x49 = TI, 0x4D = Maxim, 0x23 = Genesys , 0x54 = Onsemi */ +#define ADM1021_REG_MAN_ID 0xFE +/* ADM1021 = 0x0X, ADM1023 = 0x3X */ +#define ADM1021_REG_DEV_ID 0xFF /* These use different addresses for reading/writing */ #define ADM1021_REG_CONFIG_R 0x03 #define ADM1021_REG_CONFIG_W 0x09 #define ADM1021_REG_CONV_RATE_R 0x04 #define ADM1021_REG_CONV_RATE_W 0x0A /* These are for the ADM1023's additional precision on the remote temp sensor */ -#define ADM1021_REG_REM_TEMP_PREC 0x010 -#define ADM1021_REG_REM_OFFSET 0x011 -#define ADM1021_REG_REM_OFFSET_PREC 0x012 -#define ADM1021_REG_REM_TOS_PREC 0x013 -#define ADM1021_REG_REM_THYST_PREC 0x014 +#define ADM1023_REG_REM_TEMP_PREC 0x10 +#define ADM1023_REG_REM_OFFSET 0x11 +#define ADM1023_REG_REM_OFFSET_PREC 0x12 +#define ADM1023_REG_REM_TOS_PREC 0x13 +#define ADM1023_REG_REM_THYST_PREC 0x14 /* limits */ #define ADM1021_REG_TOS_R 0x05 #define ADM1021_REG_TOS_W 0x0B @@ -77,14 +79,13 @@ I2C_CLIENT_INSMOD_8(adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm, these macros are called: arguments may be evaluated more than once. Fixing this is just not worth it. */ /* Conversions note: 1021 uses normal integer signed-byte format*/ -#define TEMP_FROM_REG(val) (val > 127 ? (val-256)*1000 : val*1000) -#define TEMP_TO_REG(val) (SENSORS_LIMIT((val < 0 ? (val/1000)+256 : val/1000),0,255)) +#define TEMP_TO_REG(val) SENSORS_LIMIT((val) / 1000, -128, 127) /* Initial values */ -/* Note: Even though I left the low and high limits named os and hyst, -they don't quite work like a thermostat the way the LM75 does. I.e., -a lower temp than THYST actually triggers an alarm instead of +/* Note: Even though I left the low and high limits named os and hyst, +they don't quite work like a thermostat the way the LM75 does. I.e., +a lower temp than THYST actually triggers an alarm instead of clearing it. Weird, ey? --Phil */ /* Each client has this additional data */ @@ -97,12 +98,12 @@ struct adm1021_data { char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ - u8 temp_max; /* Register values */ - u8 temp_hyst; - u8 temp_input; - u8 remote_temp_max; - u8 remote_temp_hyst; - u8 remote_temp_input; + s8 temp_max; /* Register values */ + s8 temp_hyst; + s8 temp_input; + s8 remote_temp_max; + s8 remote_temp_hyst; + s8 remote_temp_input; u8 alarms; /* Special values for ADM1023 only */ u8 remote_temp_prec; @@ -116,9 +117,6 @@ static int adm1021_attach_adapter(struct i2c_adapter *adapter); static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind); static void adm1021_init_client(struct i2c_client *client); static int adm1021_detach_client(struct i2c_client *client); -static int adm1021_read_value(struct i2c_client *client, u8 reg); -static int adm1021_write_value(struct i2c_client *client, u8 reg, - u16 value); static struct adm1021_data *adm1021_update_device(struct device *dev); /* (amalysh) read only mode, otherwise any limit's writing confuse BIOS */ @@ -135,11 +133,12 @@ static struct i2c_driver adm1021_driver = { .detach_client = adm1021_detach_client, }; -#define show(value) \ -static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \ +#define show(value) \ +static ssize_t show_##value(struct device *dev, \ + struct device_attribute *attr, char *buf) \ { \ struct adm1021_data *data = adm1021_update_device(dev); \ - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->value)); \ + return sprintf(buf, "%d\n", 1000 * data->value); \ } show(temp_max); show(temp_hyst); @@ -148,26 +147,29 @@ show(remote_temp_max); show(remote_temp_hyst); show(remote_temp_input); -#define show2(value) \ -static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - struct adm1021_data *data = adm1021_update_device(dev); \ - return sprintf(buf, "%d\n", data->value); \ +static ssize_t show_alarms(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct adm1021_data *data = adm1021_update_device(dev); + return sprintf(buf, "%u\n", data->alarms); } -show2(alarms); - -#define set(value, reg) \ -static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ -{ \ - struct i2c_client *client = to_i2c_client(dev); \ - struct adm1021_data *data = i2c_get_clientdata(client); \ - int temp = simple_strtoul(buf, NULL, 10); \ - \ - mutex_lock(&data->update_lock); \ - data->value = TEMP_TO_REG(temp); \ - adm1021_write_value(client, reg, data->value); \ - mutex_unlock(&data->update_lock); \ - return count; \ + +#define set(value, reg) \ +static ssize_t set_##value(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, size_t count) \ +{ \ + struct i2c_client *client = to_i2c_client(dev); \ + struct adm1021_data *data = i2c_get_clientdata(client); \ + int temp = simple_strtoul(buf, NULL, 10); \ + \ + mutex_lock(&data->update_lock); \ + data->value = TEMP_TO_REG(temp); \ + if (!read_only) \ + i2c_smbus_write_byte_data(client, reg, data->value); \ + mutex_unlock(&data->update_lock); \ + return count; \ } set(temp_max, ADM1021_REG_TOS_W); set(temp_hyst, ADM1021_REG_THYST_W); @@ -208,35 +210,44 @@ static const struct attribute_group adm1021_group = { static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind) { int i; - struct i2c_client *new_client; + struct i2c_client *client; struct adm1021_data *data; int err = 0; const char *type_name = ""; + int conv_rate, status, config; - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + pr_debug("adm1021: detect failed, " + "smbus byte data not supported!\n"); goto error0; + } /* OK. For now, we presume we have a valid client. We now create the client structure, even though we cannot fill it completely yet. - But it allows us to access adm1021_{read,write}_value. */ + But it allows us to access adm1021 register values. */ if (!(data = kzalloc(sizeof(struct adm1021_data), GFP_KERNEL))) { + pr_debug("adm1021: detect failed, kzalloc failed!\n"); err = -ENOMEM; goto error0; } - new_client = &data->client; - i2c_set_clientdata(new_client, data); - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &adm1021_driver; - new_client->flags = 0; + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &adm1021_driver; + status = i2c_smbus_read_byte_data(client, ADM1021_REG_STATUS); + conv_rate = i2c_smbus_read_byte_data(client, + ADM1021_REG_CONV_RATE_R); + config = i2c_smbus_read_byte_data(client, ADM1021_REG_CONFIG_R); /* Now, we do the remaining detection. */ if (kind < 0) { - if ((adm1021_read_value(new_client, ADM1021_REG_STATUS) & 0x03) != 0x00 - || (adm1021_read_value(new_client, ADM1021_REG_CONFIG_R) & 0x3F) != 0x00 - || (adm1021_read_value(new_client, ADM1021_REG_CONV_RATE_R) & 0xF8) != 0x00) { + if ((status & 0x03) != 0x00 || (config & 0x3F) != 0x00 + || (conv_rate & 0xF8) != 0x00) { + pr_debug("adm1021: detect failed, " + "chip not detected!\n"); err = -ENODEV; goto error1; } @@ -244,9 +255,10 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind) /* Determine the chip type. */ if (kind <= 0) { - i = adm1021_read_value(new_client, ADM1021_REG_MAN_ID); + i = i2c_smbus_read_byte_data(client, ADM1021_REG_MAN_ID); if (i == 0x41) - if ((adm1021_read_value(new_client, ADM1021_REG_DEV_ID) & 0x0F0) == 0x030) + if ((i2c_smbus_read_byte_data(client, + ADM1021_REG_DEV_ID) & 0xF0) == 0x30) kind = adm1023; else kind = adm1021; @@ -255,15 +267,16 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind) else if (i == 0x23) kind = gl523sm; else if ((i == 0x4d) && - (adm1021_read_value(new_client, ADM1021_REG_DEV_ID) == 0x01)) + (i2c_smbus_read_byte_data(client, + ADM1021_REG_DEV_ID) == 0x01)) kind = max1617a; else if (i == 0x54) kind = mc1066; /* LM84 Mfr ID in a different place, and it has more unused bits */ - else if (adm1021_read_value(new_client, ADM1021_REG_CONV_RATE_R) == 0x00 - && (kind == 0 /* skip extra detection */ - || ((adm1021_read_value(new_client, ADM1021_REG_CONFIG_R) & 0x7F) == 0x00 - && (adm1021_read_value(new_client, ADM1021_REG_STATUS) & 0xAB) == 0x00))) + else if (conv_rate == 0x00 + && (kind == 0 /* skip extra detection */ + || ((config & 0x7F) == 0x00 + && (status & 0xAB) == 0x00))) kind = lm84; else kind = max1617; @@ -286,26 +299,27 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind) } else if (kind == mc1066) { type_name = "mc1066"; } + pr_debug("adm1021: Detected chip %s at adapter %d, address 0x%02x.\n", + type_name, i2c_adapter_id(adapter), address); - /* Fill in the remaining client fields and put it into the global list */ - strlcpy(new_client->name, type_name, I2C_NAME_SIZE); + /* Fill in the remaining client fields */ + strlcpy(client->name, type_name, I2C_NAME_SIZE); data->type = kind; - data->valid = 0; mutex_init(&data->update_lock); /* Tell the I2C layer a new client has arrived */ - if ((err = i2c_attach_client(new_client))) + if ((err = i2c_attach_client(client))) goto error1; /* Initialize the ADM1021 chip */ - if (kind != lm84) - adm1021_init_client(new_client); + if (kind != lm84 && !read_only) + adm1021_init_client(client); /* Register sysfs hooks */ - if ((err = sysfs_create_group(&new_client->dev.kobj, &adm1021_group))) + if ((err = sysfs_create_group(&client->dev.kobj, &adm1021_group))) goto error2; - data->class_dev = hwmon_device_register(&new_client->dev); + data->class_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->class_dev)) { err = PTR_ERR(data->class_dev); goto error3; @@ -314,9 +328,9 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind) return 0; error3: - sysfs_remove_group(&new_client->dev.kobj, &adm1021_group); + sysfs_remove_group(&client->dev.kobj, &adm1021_group); error2: - i2c_detach_client(new_client); + i2c_detach_client(client); error1: kfree(data); error0: @@ -326,10 +340,10 @@ error0: static void adm1021_init_client(struct i2c_client *client) { /* Enable ADC and disable suspend mode */ - adm1021_write_value(client, ADM1021_REG_CONFIG_W, - adm1021_read_value(client, ADM1021_REG_CONFIG_R) & 0xBF); + i2c_smbus_write_byte_data(client, ADM1021_REG_CONFIG_W, + i2c_smbus_read_byte_data(client, ADM1021_REG_CONFIG_R) & 0xBF); /* Set Conversion rate to 1/sec (this can be tinkered with) */ - adm1021_write_value(client, ADM1021_REG_CONV_RATE_W, 0x04); + i2c_smbus_write_byte_data(client, ADM1021_REG_CONV_RATE_W, 0x04); } static int adm1021_detach_client(struct i2c_client *client) @@ -347,19 +361,6 @@ static int adm1021_detach_client(struct i2c_client *client) return 0; } -/* All registers are byte-sized */ -static int adm1021_read_value(struct i2c_client *client, u8 reg) -{ - return i2c_smbus_read_byte_data(client, reg); -} - -static int adm1021_write_value(struct i2c_client *client, u8 reg, u16 value) -{ - if (!read_only) - return i2c_smbus_write_byte_data(client, reg, value); - return 0; -} - static struct adm1021_data *adm1021_update_device(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); @@ -371,19 +372,36 @@ static struct adm1021_data *adm1021_update_device(struct device *dev) || !data->valid) { dev_dbg(&client->dev, "Starting adm1021 update\n"); - data->temp_input = adm1021_read_value(client, ADM1021_REG_TEMP); - data->temp_max = adm1021_read_value(client, ADM1021_REG_TOS_R); - data->temp_hyst = adm1021_read_value(client, ADM1021_REG_THYST_R); - data->remote_temp_input = adm1021_read_value(client, ADM1021_REG_REMOTE_TEMP); - data->remote_temp_max = adm1021_read_value(client, ADM1021_REG_REMOTE_TOS_R); - data->remote_temp_hyst = adm1021_read_value(client, ADM1021_REG_REMOTE_THYST_R); - data->alarms = adm1021_read_value(client, ADM1021_REG_STATUS) & 0x7c; + data->temp_input = i2c_smbus_read_byte_data(client, + ADM1021_REG_TEMP); + data->temp_max = i2c_smbus_read_byte_data(client, + ADM1021_REG_TOS_R); + data->temp_hyst = i2c_smbus_read_byte_data(client, + ADM1021_REG_THYST_R); + data->remote_temp_input = i2c_smbus_read_byte_data(client, + ADM1021_REG_REMOTE_TEMP); + data->remote_temp_max = i2c_smbus_read_byte_data(client, + ADM1021_REG_REMOTE_TOS_R); + data->remote_temp_hyst = i2c_smbus_read_byte_data(client, + ADM1021_REG_REMOTE_THYST_R); + data->alarms = i2c_smbus_read_byte_data(client, + ADM1021_REG_STATUS) & 0x7c; if (data->type == adm1023) { - data->remote_temp_prec = adm1021_read_value(client, ADM1021_REG_REM_TEMP_PREC); - data->remote_temp_os_prec = adm1021_read_value(client, ADM1021_REG_REM_TOS_PREC); - data->remote_temp_hyst_prec = adm1021_read_value(client, ADM1021_REG_REM_THYST_PREC); - data->remote_temp_offset = adm1021_read_value(client, ADM1021_REG_REM_OFFSET); - data->remote_temp_offset_prec = adm1021_read_value(client, ADM1021_REG_REM_OFFSET_PREC); + data->remote_temp_prec = + i2c_smbus_read_byte_data(client, + ADM1023_REG_REM_TEMP_PREC); + data->remote_temp_os_prec = + i2c_smbus_read_byte_data(client, + ADM1023_REG_REM_TOS_PREC); + data->remote_temp_hyst_prec = + i2c_smbus_read_byte_data(client, + ADM1023_REG_REM_THYST_PREC); + data->remote_temp_offset = + i2c_smbus_read_byte_data(client, + ADM1023_REG_REM_OFFSET); + data->remote_temp_offset_prec = + i2c_smbus_read_byte_data(client, + ADM1023_REG_REM_OFFSET_PREC); } data->last_updated = jiffies; data->valid = 1; -- cgit v1.2.3 From 43e61a2d7e2ce70a093df83871a436732bc48125 Mon Sep 17 00:00:00 2001 From: Gong Jun Date: Fri, 13 Jul 2007 18:45:54 +0200 Subject: hwmon: (w83792d) Add individual alarm files w83792d: add individual alarm files for the new libsensors. Signed-off-by: Gong Jun Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/w83792d.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c index b0fa296740d..f6dee380062 100644 --- a/drivers/hwmon/w83792d.c +++ b/drivers/hwmon/w83792d.c @@ -540,6 +540,15 @@ show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf) return sprintf(buf, "%d\n", data->alarms); } +static ssize_t show_alarm(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, "%d\n", (data->alarms >> nr) & 1); +} + static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, char *buf) @@ -1015,6 +1024,25 @@ static SENSOR_DEVICE_ATTR_2(temp2_max_hyst, S_IRUGO | S_IWUSR, static SENSOR_DEVICE_ATTR_2(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp23, store_temp23, 1, 4); static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); +static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0); +static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 2); +static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 3); +static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 4); +static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 5); +static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 6); +static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 7); +static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 8); +static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 9); +static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 10); +static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 11); +static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 12); +static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_alarm, NULL, 15); +static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 19); +static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 20); +static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 21); +static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 22); +static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_alarm, NULL, 23); static DEVICE_ATTR(chassis, S_IRUGO, show_regs_chassis, NULL); static DEVICE_ATTR(chassis_clear, S_IRUGO | S_IWUSR, show_chassis_clear, store_chassis_clear); @@ -1123,26 +1151,30 @@ static SENSOR_DEVICE_ATTR(fan6_div, S_IWUSR | S_IRUGO, static SENSOR_DEVICE_ATTR(fan7_div, S_IWUSR | S_IRUGO, show_fan_div, store_fan_div, 7); -static struct attribute *w83792d_attributes_fan[4][4] = { +static struct attribute *w83792d_attributes_fan[4][5] = { { &sensor_dev_attr_fan4_input.dev_attr.attr, &sensor_dev_attr_fan4_min.dev_attr.attr, &sensor_dev_attr_fan4_div.dev_attr.attr, + &sensor_dev_attr_fan4_alarm.dev_attr.attr, NULL }, { &sensor_dev_attr_fan5_input.dev_attr.attr, &sensor_dev_attr_fan5_min.dev_attr.attr, &sensor_dev_attr_fan5_div.dev_attr.attr, + &sensor_dev_attr_fan5_alarm.dev_attr.attr, NULL }, { &sensor_dev_attr_fan6_input.dev_attr.attr, &sensor_dev_attr_fan6_min.dev_attr.attr, &sensor_dev_attr_fan6_div.dev_attr.attr, + &sensor_dev_attr_fan6_alarm.dev_attr.attr, NULL }, { &sensor_dev_attr_fan7_input.dev_attr.attr, &sensor_dev_attr_fan7_min.dev_attr.attr, &sensor_dev_attr_fan7_div.dev_attr.attr, + &sensor_dev_attr_fan7_alarm.dev_attr.attr, NULL } }; @@ -1182,6 +1214,15 @@ static struct attribute *w83792d_attributes[] = { &sensor_dev_attr_in8_input.dev_attr.attr, &sensor_dev_attr_in8_max.dev_attr.attr, &sensor_dev_attr_in8_min.dev_attr.attr, + &sensor_dev_attr_in0_alarm.dev_attr.attr, + &sensor_dev_attr_in1_alarm.dev_attr.attr, + &sensor_dev_attr_in2_alarm.dev_attr.attr, + &sensor_dev_attr_in3_alarm.dev_attr.attr, + &sensor_dev_attr_in4_alarm.dev_attr.attr, + &sensor_dev_attr_in5_alarm.dev_attr.attr, + &sensor_dev_attr_in6_alarm.dev_attr.attr, + &sensor_dev_attr_in7_alarm.dev_attr.attr, + &sensor_dev_attr_in8_alarm.dev_attr.attr, &sensor_dev_attr_temp1_input.dev_attr.attr, &sensor_dev_attr_temp1_max.dev_attr.attr, &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, @@ -1191,6 +1232,9 @@ static struct attribute *w83792d_attributes[] = { &sensor_dev_attr_temp3_input.dev_attr.attr, &sensor_dev_attr_temp3_max.dev_attr.attr, &sensor_dev_attr_temp3_max_hyst.dev_attr.attr, + &sensor_dev_attr_temp1_alarm.dev_attr.attr, + &sensor_dev_attr_temp2_alarm.dev_attr.attr, + &sensor_dev_attr_temp3_alarm.dev_attr.attr, &sensor_dev_attr_pwm1.dev_attr.attr, &sensor_dev_attr_pwm1_mode.dev_attr.attr, &sensor_dev_attr_pwm1_enable.dev_attr.attr, @@ -1233,12 +1277,15 @@ static struct attribute *w83792d_attributes[] = { &sensor_dev_attr_fan1_input.dev_attr.attr, &sensor_dev_attr_fan1_min.dev_attr.attr, &sensor_dev_attr_fan1_div.dev_attr.attr, + &sensor_dev_attr_fan1_alarm.dev_attr.attr, &sensor_dev_attr_fan2_input.dev_attr.attr, &sensor_dev_attr_fan2_min.dev_attr.attr, &sensor_dev_attr_fan2_div.dev_attr.attr, + &sensor_dev_attr_fan2_alarm.dev_attr.attr, &sensor_dev_attr_fan3_input.dev_attr.attr, &sensor_dev_attr_fan3_min.dev_attr.attr, &sensor_dev_attr_fan3_div.dev_attr.attr, + &sensor_dev_attr_fan3_alarm.dev_attr.attr, NULL }; -- cgit v1.2.3 From 9cab0217f3f35bd618363842576867badb72ca4b Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 15 Jul 2007 10:36:06 +0200 Subject: hwmon: (f71805f) List the F71806F/FG as supported The Fintek F71806F/FG is compatible with the F71872F/FG, so it is already supported by the f71805f hardware monitoring driver. In fact, both chips have the same chip ID, so the driver can't even differentiate between them. Signed-off-by: Jean Delvare Acked-by: Hans de Goede Signed-off-by: Mark M. Hoffman --- drivers/hwmon/Kconfig | 6 +++--- drivers/hwmon/f71805f.c | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 192953b29b2..2aeec4787e5 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -206,12 +206,12 @@ config SENSORS_DS1621 will be called ds1621. config SENSORS_F71805F - tristate "Fintek F71805F/FG and F71872F/FG" + tristate "Fintek F71805F/FG, F71806F/FG and F71872F/FG" depends on EXPERIMENTAL help If you say yes here you get support for hardware monitoring - features of the Fintek F71805F/FG and F71872F/FG Super-I/O - chips. + features of the Fintek F71805F/FG, F71806F/FG and F71872F/FG + Super-I/O chips. This driver can also be built as a module. If so, the module will be called f71805f. diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c index 6f60715f34f..1cd71a5be0e 100644 --- a/drivers/hwmon/f71805f.c +++ b/drivers/hwmon/f71805f.c @@ -10,6 +10,9 @@ * The F71872F/FG is almost the same, with two more voltages monitored, * and 6 VID inputs. * + * The F71806F/FG is essentially the same as the F71872F/FG. It even has + * the same chip ID, so the driver can't differentiate between. + * * 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 * the Free Software Foundation; either version 2 of the License, or @@ -1485,7 +1488,7 @@ static int __init f71805f_find(int sioaddr, unsigned short *address, static const char *names[] = { "F71805F/FG", - "F71872F/FG", + "F71872F/FG or F71806F/FG", }; superio_enter(sioaddr); -- cgit v1.2.3 From 45fb366940d51c309581813ef35bb70a9e34b17d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 13 Jul 2007 14:34:19 +0200 Subject: hwmon: add support for Fintek F71882FG and F71883FG This is the second version of a new driver for the hardware monitoring features of the Fintek F71882FG and F71883FG Super-I/O chips. This version has several small fixes for flaws discovered during the review of the first version. This version of the driver does not support the pwm part of these chips (yet). I'll first design a sysfs api for this and post that for discussion, and then implement pwm support as an incremental patch over this one. This driver supports all sensors of this chip, except for the vid inputs. The vid inputs are somewhat documented in the datasheet, but I know nothing about vid/vrm stuff. Help with this would be much appreciated. Signed-off-by: Hans de Goede Acked-by: Darrick J. Wong Signed-off-by: Mark M. Hoffman --- drivers/hwmon/Kconfig | 10 + drivers/hwmon/Makefile | 1 + drivers/hwmon/f71882fg.c | 950 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 961 insertions(+) create mode 100644 drivers/hwmon/f71882fg.c (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 2aeec4787e5..73177933ae8 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -216,6 +216,16 @@ config SENSORS_F71805F This driver can also be built as a module. If so, the module will be called f71805f. +config SENSORS_F71882FG + tristate "Fintek F71882FG and F71883FG" + depends on EXPERIMENTAL + help + If you say yes here you get support for hardware monitoring + features of the Fintek F71882FG and F71883FG Super-I/O chips. + + This driver can also be built as a module. If so, the module + will be called f71882fg. + config SENSORS_FSCHER tristate "FSC Hermes" depends on I2C diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index d04f90031eb..6e9fdc29061 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o obj-$(CONFIG_SENSORS_DME1737) += dme1737.o obj-$(CONFIG_SENSORS_DS1621) += ds1621.o obj-$(CONFIG_SENSORS_F71805F) += f71805f.o +obj-$(CONFIG_SENSORS_F71882FG) += f71882fg.o obj-$(CONFIG_SENSORS_FSCHER) += fscher.o obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c new file mode 100644 index 00000000000..68f5102110b --- /dev/null +++ b/drivers/hwmon/f71882fg.c @@ -0,0 +1,950 @@ +/*************************************************************************** + * Copyright (C) 2006 by Hans Edgington * + * Copyright (C) 2007 by Hans de Goede * + * * + * 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 * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "f71882fg" + +#define SIO_F71882FG_LD_HWM 0x04 /* Hardware monitor logical device*/ +#define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */ +#define SIO_LOCK_KEY 0xAA /* Key to diasble Super-I/O */ + +#define SIO_REG_LDSEL 0x07 /* Logical device select */ +#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */ +#define SIO_REG_DEVREV 0x22 /* Device revision */ +#define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */ +#define SIO_REG_ENABLE 0x30 /* Logical device enable */ +#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ + +#define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */ +#define SIO_F71882_ID 0x0541 /* Chipset ID */ + +#define REGION_LENGTH 8 +#define ADDR_REG_OFFSET 5 +#define DATA_REG_OFFSET 6 + +#define F71882FG_REG_PECI 0x0A + +#define F71882FG_REG_IN_STATUS 0x12 +#define F71882FG_REG_IN_BEEP 0x13 +#define F71882FG_REG_IN(nr) (0x20 + (nr)) +#define F71882FG_REG_IN1_HIGH 0x32 + +#define F71882FG_REG_FAN(nr) (0xA0 + (16 * (nr))) +#define F71882FG_REG_FAN_STATUS 0x92 +#define F71882FG_REG_FAN_BEEP 0x93 + +#define F71882FG_REG_TEMP(nr) (0x72 + 2 * (nr)) +#define F71882FG_REG_TEMP_OVT(nr) (0x82 + 2 * (nr)) +#define F71882FG_REG_TEMP_HIGH(nr) (0x83 + 2 * (nr)) +#define F71882FG_REG_TEMP_STATUS 0x62 +#define F71882FG_REG_TEMP_BEEP 0x63 +#define F71882FG_REG_TEMP_HYST1 0x6C +#define F71882FG_REG_TEMP_HYST23 0x6D +#define F71882FG_REG_TEMP_TYPE 0x6B +#define F71882FG_REG_TEMP_DIODE_OPEN 0x6F + +#define F71882FG_REG_START 0x01 + +#define FAN_MIN_DETECT 366 /* Lowest detectable fanspeed */ + +static struct platform_device *f71882fg_pdev = NULL; + +/* Super-I/O Function prototypes */ +static inline int superio_inb(int base, int reg); +static inline int superio_inw(int base, int reg); +static inline void superio_enter(int base); +static inline void superio_select(int base, int ld); +static inline void superio_exit(int base); + +static inline u16 fan_from_reg ( u16 reg ); + +struct f71882fg_data { + unsigned short addr; + struct class_device *class_dev; + + struct mutex update_lock; + char valid; /* !=0 if following fields are valid */ + unsigned long last_updated; /* In jiffies */ + unsigned long last_limits; /* In jiffies */ + + /* Register Values */ + u8 in[9]; + u8 in1_max; + u8 in_status; + u8 in_beep; + u16 fan[4]; + u8 fan_status; + u8 fan_beep; + u8 temp[3]; + u8 temp_ovt[3]; + u8 temp_high[3]; + u8 temp_hyst[3]; + u8 temp_type[3]; + u8 temp_status; + u8 temp_beep; + u8 temp_diode_open; +}; + +static u8 f71882fg_read8(struct f71882fg_data *data, u8 reg); +static u16 f71882fg_read16(struct f71882fg_data *data, u8 reg); +static void f71882fg_write8(struct f71882fg_data *data, u8 reg, u8 val); + +/* Sysfs in*/ +static ssize_t show_in(struct device *dev, struct device_attribute *devattr, + char *buf); +static ssize_t show_in_max(struct device *dev, struct device_attribute + *devattr, char *buf); +static ssize_t store_in_max(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count); +static ssize_t show_in_beep(struct device *dev, struct device_attribute + *devattr, char *buf); +static ssize_t store_in_beep(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count); +static ssize_t show_in_alarm(struct device *dev, struct device_attribute + *devattr, char *buf); +/* Sysfs Fan */ +static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, + char *buf); +static ssize_t show_fan_beep(struct device *dev, struct device_attribute + *devattr, char *buf); +static ssize_t store_fan_beep(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count); +static ssize_t show_fan_alarm(struct device *dev, struct device_attribute + *devattr, char *buf); +/* Sysfs Temp */ +static ssize_t show_temp(struct device *dev, struct device_attribute + *devattr, char *buf); +static ssize_t show_temp_max(struct device *dev, struct device_attribute + *devattr, char *buf); +static ssize_t store_temp_max(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count); +static ssize_t show_temp_max_hyst(struct device *dev, struct device_attribute + *devattr, char *buf); +static ssize_t store_temp_max_hyst(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count); +static ssize_t show_temp_crit(struct device *dev, struct device_attribute + *devattr, char *buf); +static ssize_t store_temp_crit(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count); +static ssize_t show_temp_crit_hyst(struct device *dev, struct device_attribute + *devattr, char *buf); +static ssize_t show_temp_type(struct device *dev, struct device_attribute + *devattr, char *buf); +static ssize_t show_temp_beep(struct device *dev, struct device_attribute + *devattr, char *buf); +static ssize_t store_temp_beep(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count); +static ssize_t show_temp_alarm(struct device *dev, struct device_attribute + *devattr, char *buf); +static ssize_t show_temp_fault(struct device *dev, struct device_attribute + *devattr, char *buf); +/* Sysfs misc */ +static ssize_t show_name(struct device *dev, struct device_attribute *devattr, + char *buf); + +static int __devinit f71882fg_probe(struct platform_device * pdev); +static int __devexit f71882fg_remove(struct platform_device *pdev); +static int __init f71882fg_init(void); +static int __init f71882fg_find(int sioaddr, unsigned short *address); +static int __init f71882fg_device_add(unsigned short address); +static void __exit f71882fg_exit(void); + +static struct platform_driver f71882fg_driver = { + .driver = { + .owner = THIS_MODULE, + .name = DRVNAME, + }, + .probe = f71882fg_probe, + .remove = __devexit_p(f71882fg_remove), +}; + +static struct device_attribute f71882fg_dev_attr[] = +{ + __ATTR( name, S_IRUGO, show_name, NULL ), +}; + +static struct sensor_device_attribute f71882fg_in_temp_attr[] = +{ + SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0), + SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1), + SENSOR_ATTR(in1_max, S_IRUGO|S_IWUSR, show_in_max, store_in_max, 1), + SENSOR_ATTR(in1_beep, S_IRUGO|S_IWUSR, show_in_beep, store_in_beep, 1), + SENSOR_ATTR(in1_alarm, S_IRUGO, show_in_alarm, NULL, 1), + SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2), + SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3), + SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4), + SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5), + SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6), + SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7), + SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8), + SENSOR_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0), + SENSOR_ATTR(temp1_max, S_IRUGO|S_IWUSR, show_temp_max, + store_temp_max, 0), + SENSOR_ATTR(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst, + store_temp_max_hyst, 0), + SENSOR_ATTR(temp1_crit, S_IRUGO|S_IWUSR, show_temp_crit, + store_temp_crit, 0), + SENSOR_ATTR(temp1_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, 0), + SENSOR_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0), + SENSOR_ATTR(temp1_beep, S_IRUGO|S_IWUSR, show_temp_beep, + store_temp_beep, 0), + SENSOR_ATTR(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0), + SENSOR_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0), + SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1), + SENSOR_ATTR(temp2_max, S_IRUGO|S_IWUSR, show_temp_max, + store_temp_max, 1), + SENSOR_ATTR(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst, + store_temp_max_hyst, 1), + SENSOR_ATTR(temp2_crit, S_IRUGO|S_IWUSR, show_temp_crit, + store_temp_crit, 1), + SENSOR_ATTR(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, 1), + SENSOR_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1), + SENSOR_ATTR(temp2_beep, S_IRUGO|S_IWUSR, show_temp_beep, + store_temp_beep, 1), + SENSOR_ATTR(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 1), + SENSOR_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1), + SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2), + SENSOR_ATTR(temp3_max, S_IRUGO|S_IWUSR, show_temp_max, + store_temp_max, 2), + SENSOR_ATTR(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst, + store_temp_max_hyst, 2), + SENSOR_ATTR(temp3_crit, S_IRUGO|S_IWUSR, show_temp_crit, + store_temp_crit, 2), + SENSOR_ATTR(temp3_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, 2), + SENSOR_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2), + SENSOR_ATTR(temp3_beep, S_IRUGO|S_IWUSR, show_temp_beep, + store_temp_beep, 2), + SENSOR_ATTR(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 2), + SENSOR_ATTR(temp3_fault, S_IRUGO, show_temp_fault, NULL, 2) +}; + +static struct sensor_device_attribute f71882fg_fan_attr[] = +{ + SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0), + SENSOR_ATTR(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep, + store_fan_beep, 0), + SENSOR_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0), + SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1), + SENSOR_ATTR(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep, + store_fan_beep, 1), + SENSOR_ATTR(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 1), + SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2), + SENSOR_ATTR(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep, + store_fan_beep, 2), + SENSOR_ATTR(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 2), + SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3), + SENSOR_ATTR(fan4_beep, S_IRUGO|S_IWUSR, show_fan_beep, + store_fan_beep, 3), + SENSOR_ATTR(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 3) +}; + + +/* Super I/O functions */ +static inline int superio_inb(int base, int reg) +{ + outb(reg, base); + return inb(base + 1); +} + +static int superio_inw(int base, int reg) +{ + int val; + outb(reg++, base); + val = inb(base + 1) << 8; + outb(reg, base); + val |= inb(base + 1); + return val; +} + +static inline void superio_enter(int base) +{ + /* according to the datasheet the key must be send twice! */ + outb( SIO_UNLOCK_KEY, base); + outb( SIO_UNLOCK_KEY, base); +} + +static inline void superio_select( int base, int ld) +{ + outb(SIO_REG_LDSEL, base); + outb(ld, base + 1); +} + +static inline void superio_exit(int base) +{ + outb(SIO_LOCK_KEY, base); +} + +static inline u16 fan_from_reg(u16 reg) +{ + return reg ? (1500000 / reg) : 0; +} + +static u8 f71882fg_read8(struct f71882fg_data *data, u8 reg) +{ + u8 val; + + outb(reg, data->addr + ADDR_REG_OFFSET); + val = inb(data->addr + DATA_REG_OFFSET); + + return val; +} + +static u16 f71882fg_read16(struct f71882fg_data *data, u8 reg) +{ + u16 val; + + outb(reg++, data->addr + ADDR_REG_OFFSET); + val = inb(data->addr + DATA_REG_OFFSET) << 8; + outb(reg, data->addr + ADDR_REG_OFFSET); + val |= inb(data->addr + DATA_REG_OFFSET); + + return val; +} + +static void f71882fg_write8(struct f71882fg_data *data, u8 reg, u8 val) +{ + outb(reg, data->addr + ADDR_REG_OFFSET); + outb(val, data->addr + DATA_REG_OFFSET); +} + +static struct f71882fg_data *f71882fg_update_device(struct device * dev) +{ + struct f71882fg_data *data = dev_get_drvdata(dev); + int nr, reg, reg2; + + mutex_lock(&data->update_lock); + + /* Update once every 60 seconds */ + if ( time_after(jiffies, data->last_limits + 60 * HZ ) || + !data->valid) { + data->in1_max = f71882fg_read8(data, F71882FG_REG_IN1_HIGH); + data->in_beep = f71882fg_read8(data, F71882FG_REG_IN_BEEP); + + /* Get High & boundary temps*/ + for (nr = 0; nr < 3; nr++) { + data->temp_ovt[nr] = f71882fg_read8(data, + F71882FG_REG_TEMP_OVT(nr)); + data->temp_high[nr] = f71882fg_read8(data, + F71882FG_REG_TEMP_HIGH(nr)); + } + + /* Have to hardcode hyst*/ + data->temp_hyst[0] = f71882fg_read8(data, + F71882FG_REG_TEMP_HYST1) >> 4; + /* Hyst temps 2 & 3 stored in same register */ + reg = f71882fg_read8(data, F71882FG_REG_TEMP_HYST23); + data->temp_hyst[1] = reg & 0x0F; + data->temp_hyst[2] = reg >> 4; + + /* Have to hardcode type, because temp1 is special */ + reg = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE); + reg2 = f71882fg_read8(data, F71882FG_REG_PECI); + if ((reg2 & 0x03) == 0x01) + data->temp_type[0] = 6 /* PECI */; + else if ((reg2 & 0x03) == 0x02) + data->temp_type[0] = 5 /* AMDSI */; + else + data->temp_type[0] = (reg & 0x02) ? 2 : 4; + + data->temp_type[1] = (reg & 0x04) ? 2 : 4; + data->temp_type[2] = (reg & 0x08) ? 2 : 4; + + data->temp_beep = f71882fg_read8(data, F71882FG_REG_TEMP_BEEP); + + data->fan_beep = f71882fg_read8(data, F71882FG_REG_FAN_BEEP); + + data->last_limits = jiffies; + } + + /* Update every second */ + if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { + data->temp_status = f71882fg_read8(data, + F71882FG_REG_TEMP_STATUS); + data->temp_diode_open = f71882fg_read8(data, + F71882FG_REG_TEMP_DIODE_OPEN); + for (nr = 0; nr < 3; nr++) + data->temp[nr] = f71882fg_read8(data, + F71882FG_REG_TEMP(nr)); + + data->fan_status = f71882fg_read8(data, + F71882FG_REG_FAN_STATUS); + for (nr = 0; nr < 4; nr++) + data->fan[nr] = f71882fg_read16(data, + F71882FG_REG_FAN(nr)); + + data->in_status = f71882fg_read8(data, + F71882FG_REG_IN_STATUS); + for (nr = 0; nr < 9; nr++) + data->in[nr] = f71882fg_read8(data, + F71882FG_REG_IN(nr)); + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +/* Sysfs Interface */ +static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct f71882fg_data *data = f71882fg_update_device(dev); + int nr = to_sensor_dev_attr(devattr)->index; + int speed = fan_from_reg(data->fan[nr]); + + if (speed == FAN_MIN_DETECT) + speed = 0; + + return sprintf(buf, "%d\n", speed); +} + +static ssize_t show_fan_beep(struct device *dev, struct device_attribute + *devattr, char *buf) +{ + struct f71882fg_data *data = f71882fg_update_device(dev); + int nr = to_sensor_dev_attr(devattr)->index; + + if (data->fan_beep & (1 << nr)) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + +static ssize_t store_fan_beep(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count) +{ + struct f71882fg_data *data = dev_get_drvdata(dev); + int nr = to_sensor_dev_attr(devattr)->index; + int val = simple_strtoul(buf, NULL, 10); + + mutex_lock(&data->update_lock); + if (val) + data->fan_beep |= 1 << nr; + else + data->fan_beep &= ~(1 << nr); + + f71882fg_write8(data, F71882FG_REG_FAN_BEEP, data->fan_beep); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_fan_alarm(struct device *dev, struct device_attribute + *devattr, char *buf) +{ + struct f71882fg_data *data = f71882fg_update_device(dev); + int nr = to_sensor_dev_attr(devattr)->index; + + if (data->fan_status & (1 << nr)) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + +static ssize_t show_in(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct f71882fg_data *data = f71882fg_update_device(dev); + int nr = to_sensor_dev_attr(devattr)->index; + + return sprintf(buf, "%d\n", data->in[nr] * 8); +} + +static ssize_t show_in_max(struct device *dev, struct device_attribute + *devattr, char *buf) +{ + struct f71882fg_data *data = f71882fg_update_device(dev); + + return sprintf(buf, "%d\n", data->in1_max * 8); +} + +static ssize_t store_in_max(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count) +{ + struct f71882fg_data *data = dev_get_drvdata(dev); + int val = simple_strtoul(buf, NULL, 10) / 8; + + if (val > 255) + val = 255; + + mutex_lock(&data->update_lock); + f71882fg_write8(data, F71882FG_REG_IN1_HIGH, val); + data->in1_max = val; + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_in_beep(struct device *dev, struct device_attribute + *devattr, char *buf) +{ + struct f71882fg_data *data = f71882fg_update_device(dev); + int nr = to_sensor_dev_attr(devattr)->index; + + if (data->in_beep & (1 << nr)) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + +static ssize_t store_in_beep(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count) +{ + struct f71882fg_data *data = dev_get_drvdata(dev); + int nr = to_sensor_dev_attr(devattr)->index; + int val = simple_strtoul(buf, NULL, 10); + + mutex_lock(&data->update_lock); + if (val) + data->in_beep |= 1 << nr; + else + data->in_beep &= ~(1 << nr); + + f71882fg_write8(data, F71882FG_REG_IN_BEEP, data->in_beep); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_in_alarm(struct device *dev, struct device_attribute + *devattr, char *buf) +{ + struct f71882fg_data *data = f71882fg_update_device(dev); + int nr = to_sensor_dev_attr(devattr)->index; + + if (data->in_status & (1 << nr)) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + +static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct f71882fg_data *data = f71882fg_update_device(dev); + int nr = to_sensor_dev_attr(devattr)->index; + + return sprintf(buf, "%d\n", data->temp[nr] * 1000); +} + +static ssize_t show_temp_max(struct device *dev, struct device_attribute + *devattr, char *buf) +{ + struct f71882fg_data *data = f71882fg_update_device(dev); + int nr = to_sensor_dev_attr(devattr)->index; + + return sprintf(buf, "%d\n", data->temp_high[nr] * 1000); +} + +static ssize_t store_temp_max(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count) +{ + struct f71882fg_data *data = dev_get_drvdata(dev); + int nr = to_sensor_dev_attr(devattr)->index; + int val = simple_strtoul(buf, NULL, 10) / 1000; + + if (val > 255) + val = 255; + + mutex_lock(&data->update_lock); + f71882fg_write8(data, F71882FG_REG_TEMP_HIGH(nr), val); + data->temp_high[nr] = val; + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_temp_max_hyst(struct device *dev, struct device_attribute + *devattr, char *buf) +{ + struct f71882fg_data *data = f71882fg_update_device(dev); + int nr = to_sensor_dev_attr(devattr)->index; + + return sprintf(buf, "%d\n", + (data->temp_high[nr] - data->temp_hyst[nr]) * 1000); +} + +static ssize_t store_temp_max_hyst(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count) +{ + struct f71882fg_data *data = dev_get_drvdata(dev); + int nr = to_sensor_dev_attr(devattr)->index; + int val = simple_strtoul(buf, NULL, 10) / 1000; + ssize_t ret = count; + + mutex_lock(&data->update_lock); + + /* convert abs to relative and check */ + val = data->temp_high[nr] - val; + if (val < 0 || val > 15) { + ret = -EINVAL; + goto store_temp_max_hyst_exit; + } + + data->temp_hyst[nr] = val; + + /* convert value to register contents */ + switch(nr) { + case 0: + val = val << 4; + break; + case 1: + val = val | (data->temp_hyst[2] << 4); + break; + case 2: + val = data->temp_hyst[1] | (val << 4); + break; + } + + f71882fg_write8(data, nr ? F71882FG_REG_TEMP_HYST23 : + F71882FG_REG_TEMP_HYST1, val); + +store_temp_max_hyst_exit: + mutex_unlock(&data->update_lock); + return ret; +} + +static ssize_t show_temp_crit(struct device *dev, struct device_attribute + *devattr, char *buf) +{ + struct f71882fg_data *data = f71882fg_update_device(dev); + int nr = to_sensor_dev_attr(devattr)->index; + + return sprintf(buf, "%d\n", data->temp_ovt[nr] * 1000); +} + +static ssize_t store_temp_crit(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count) +{ + struct f71882fg_data *data = dev_get_drvdata(dev); + int nr = to_sensor_dev_attr(devattr)->index; + int val = simple_strtoul(buf, NULL, 10) / 1000; + + if (val > 255) + val = 255; + + mutex_lock(&data->update_lock); + f71882fg_write8(data, F71882FG_REG_TEMP_OVT(nr), val); + data->temp_ovt[nr] = val; + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_temp_crit_hyst(struct device *dev, struct device_attribute + *devattr, char *buf) +{ + struct f71882fg_data *data = f71882fg_update_device(dev); + int nr = to_sensor_dev_attr(devattr)->index; + + return sprintf(buf, "%d\n", + (data->temp_ovt[nr] - data->temp_hyst[nr]) * 1000); +} + +static ssize_t show_temp_type(struct device *dev, struct device_attribute + *devattr, char *buf) +{ + struct f71882fg_data *data = f71882fg_update_device(dev); + int nr = to_sensor_dev_attr(devattr)->index; + + return sprintf(buf, "%d\n", data->temp_type[nr]); +} + +static ssize_t show_temp_beep(struct device *dev, struct device_attribute + *devattr, char *buf) +{ + struct f71882fg_data *data = f71882fg_update_device(dev); + int nr = to_sensor_dev_attr(devattr)->index; + + if (data->temp_beep & (1 << (nr + 1))) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + +static ssize_t store_temp_beep(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count) +{ + struct f71882fg_data *data = dev_get_drvdata(dev); + int nr = to_sensor_dev_attr(devattr)->index; + int val = simple_strtoul(buf, NULL, 10); + + mutex_lock(&data->update_lock); + if (val) + data->temp_beep |= 1 << (nr + 1); + else + data->temp_beep &= ~(1 << (nr + 1)); + + f71882fg_write8(data, F71882FG_REG_TEMP_BEEP, data->temp_beep); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_temp_alarm(struct device *dev, struct device_attribute + *devattr, char *buf) +{ + struct f71882fg_data *data = f71882fg_update_device(dev); + int nr = to_sensor_dev_attr(devattr)->index; + + if (data->temp_status & (1 << (nr + 1))) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + +static ssize_t show_temp_fault(struct device *dev, struct device_attribute + *devattr, char *buf) +{ + struct f71882fg_data *data = f71882fg_update_device(dev); + int nr = to_sensor_dev_attr(devattr)->index; + + if (data->temp_diode_open & (1 << (nr + 1))) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + +static ssize_t show_name(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + return sprintf(buf, DRVNAME "\n"); +} + + +static int __devinit f71882fg_probe(struct platform_device * pdev) +{ + struct f71882fg_data *data; + int err, i; + u8 start_reg; + + if(!(data = kzalloc(sizeof(struct f71882fg_data), GFP_KERNEL))) + return -ENOMEM; + + data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start; + mutex_init(&data->update_lock); + platform_set_drvdata(pdev, data); + + /* Register sysfs interface files */ + for (i = 0; i < ARRAY_SIZE(f71882fg_dev_attr); i++) { + err = device_create_file(&pdev->dev, &f71882fg_dev_attr[i]); + if (err) + goto exit_unregister_sysfs; + } + + start_reg = f71882fg_read8(data, F71882FG_REG_START); + if (start_reg & 0x01) { + for (i = 0; i < ARRAY_SIZE(f71882fg_in_temp_attr); i++) { + err = device_create_file(&pdev->dev, + &f71882fg_in_temp_attr[i].dev_attr); + if (err) + goto exit_unregister_sysfs; + } + } + + if (start_reg & 0x02) { + for (i = 0; i < ARRAY_SIZE(f71882fg_fan_attr); i++) { + err = device_create_file(&pdev->dev, + &f71882fg_fan_attr[i].dev_attr); + if (err) + goto exit_unregister_sysfs; + } + } + + data->class_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(data->class_dev)) { + err = PTR_ERR(data->class_dev); + goto exit_unregister_sysfs; + } + + return 0; + +exit_unregister_sysfs: + for (i = 0; i < ARRAY_SIZE(f71882fg_dev_attr); i++) + device_remove_file(&pdev->dev, &f71882fg_dev_attr[i]); + + for (i = 0; i < ARRAY_SIZE(f71882fg_in_temp_attr); i++) + device_remove_file(&pdev->dev, + &f71882fg_in_temp_attr[i].dev_attr); + + for (i = 0; i < ARRAY_SIZE(f71882fg_fan_attr); i++) + device_remove_file(&pdev->dev, &f71882fg_fan_attr[i].dev_attr); + + kfree(data); + + return err; +} + +static int __devexit f71882fg_remove(struct platform_device *pdev) +{ + int i; + struct f71882fg_data *data = platform_get_drvdata(pdev); + + platform_set_drvdata(pdev, NULL); + hwmon_device_unregister(data->class_dev); + + for (i = 0; i < ARRAY_SIZE(f71882fg_dev_attr); i++) + device_remove_file(&pdev->dev, &f71882fg_dev_attr[i]); + + for (i = 0; i < ARRAY_SIZE(f71882fg_in_temp_attr); i++) + device_remove_file(&pdev->dev, + &f71882fg_in_temp_attr[i].dev_attr); + + for (i = 0; i < ARRAY_SIZE(f71882fg_fan_attr); i++) + device_remove_file(&pdev->dev, &f71882fg_fan_attr[i].dev_attr); + + kfree(data); + + return 0; +} + +static int __init f71882fg_find(int sioaddr, unsigned short *address) +{ + int err = -ENODEV; + u16 devid; + u8 start_reg; + struct f71882fg_data data; + + superio_enter(sioaddr); + + devid = superio_inw(sioaddr, SIO_REG_MANID); + if (devid != SIO_FINTEK_ID) { + printk(KERN_INFO DRVNAME ": Not a Fintek device\n"); + goto exit; + } + + devid = superio_inw(sioaddr, SIO_REG_DEVID); + if (devid != SIO_F71882_ID) { + printk(KERN_INFO DRVNAME ": Unsupported Fintek device\n"); + goto exit; + } + + superio_select(sioaddr, SIO_F71882FG_LD_HWM); + if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) { + printk(KERN_WARNING DRVNAME ": Device not activated\n"); + goto exit; + } + + *address = superio_inw(sioaddr, SIO_REG_ADDR); + if (*address == 0) + { + printk(KERN_WARNING DRVNAME ": Base address not set\n"); + goto exit; + } + *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ + + data.addr = *address; + start_reg = f71882fg_read8(&data, F71882FG_REG_START); + if (!(start_reg & 0x03)) { + printk(KERN_WARNING DRVNAME + ": Hardware monitoring not activated\n"); + goto exit; + } + + err = 0; + printk(KERN_INFO DRVNAME ": Found F71882FG chip at %#x, revision %d\n", + (unsigned int)*address, + (int)superio_inb(sioaddr, SIO_REG_DEVREV)); +exit: + superio_exit(sioaddr); + return err; +} + +static int __init f71882fg_device_add(unsigned short address) +{ + struct resource res = { + .start = address, + .end = address + REGION_LENGTH - 1, + .flags = IORESOURCE_IO, + }; + int err; + + f71882fg_pdev = platform_device_alloc(DRVNAME, address); + if(!f71882fg_pdev) + return -ENOMEM; + + res.name = f71882fg_pdev->name; + err = platform_device_add_resources(f71882fg_pdev, &res, 1); + if(err) { + printk(KERN_ERR DRVNAME ": Device resource addition failed\n"); + goto exit_device_put; + } + + err = platform_device_add(f71882fg_pdev); + if(err) { + printk(KERN_ERR DRVNAME ": Device addition failed\n"); + goto exit_device_put; + } + + return 0; + +exit_device_put: + platform_device_put(f71882fg_pdev); + + return err; +} + +static int __init f71882fg_init(void) +{ + int err = -ENODEV; + unsigned short address; + + if (f71882fg_find(0x2e, &address) && f71882fg_find(0x4e, &address)) + goto exit; + + if ((err = platform_driver_register(&f71882fg_driver))) + goto exit; + + if ((err = f71882fg_device_add(address))) + goto exit_driver; + + return 0; + +exit_driver: + platform_driver_unregister(&f71882fg_driver); +exit: + return err; +} + +static void __exit f71882fg_exit(void) +{ + platform_device_unregister(f71882fg_pdev); + platform_driver_unregister(&f71882fg_driver); +} + +MODULE_DESCRIPTION("F71882FG Hardware Monitoring Driver"); +MODULE_AUTHOR("Hans Edgington (hans@edgington.nl)"); +MODULE_LICENSE("GPL"); + +module_init(f71882fg_init); +module_exit(f71882fg_exit); -- cgit v1.2.3 From 8afb10490b18e916e33707baa7d1cfc615d545ea Mon Sep 17 00:00:00 2001 From: "Mark M. Hoffman" Date: Tue, 21 Aug 2007 23:10:46 -0400 Subject: hwmon: (f71882fg) trivial whitespace cleanup Signed-off-by: Mark M. Hoffman --- drivers/hwmon/f71882fg.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 68f5102110b..b4ff0f9a6af 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -384,7 +384,7 @@ static struct f71882fg_data *f71882fg_update_device(struct device * dev) } /* Update every second */ - if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { + if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { data->temp_status = f71882fg_read8(data, F71882FG_REG_TEMP_STATUS); data->temp_diode_open = f71882fg_read8(data, @@ -614,7 +614,7 @@ static ssize_t store_temp_max_hyst(struct device *dev, struct device_attribute data->temp_hyst[nr] = val; /* convert value to register contents */ - switch(nr) { + switch (nr) { case 0: val = val << 4; break; @@ -748,7 +748,7 @@ static int __devinit f71882fg_probe(struct platform_device * pdev) int err, i; u8 start_reg; - if(!(data = kzalloc(sizeof(struct f71882fg_data), GFP_KERNEL))) + if (!(data = kzalloc(sizeof(struct f71882fg_data), GFP_KERNEL))) return -ENOMEM; data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start; @@ -850,7 +850,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address) } superio_select(sioaddr, SIO_F71882FG_LD_HWM); - if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) { + if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) { printk(KERN_WARNING DRVNAME ": Device not activated\n"); goto exit; } @@ -890,18 +890,18 @@ static int __init f71882fg_device_add(unsigned short address) int err; f71882fg_pdev = platform_device_alloc(DRVNAME, address); - if(!f71882fg_pdev) + if (!f71882fg_pdev) return -ENOMEM; res.name = f71882fg_pdev->name; err = platform_device_add_resources(f71882fg_pdev, &res, 1); - if(err) { + if (err) { printk(KERN_ERR DRVNAME ": Device resource addition failed\n"); goto exit_device_put; } err = platform_device_add(f71882fg_pdev); - if(err) { + if (err) { printk(KERN_ERR DRVNAME ": Device addition failed\n"); goto exit_device_put; } -- cgit v1.2.3 From 6f9703d0be16f694ce24dde1ce1fc4a4e4e5ed55 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Tue, 31 Jul 2007 11:06:52 -0700 Subject: hwmon: add support for adt7470 New driver to expose temperature and fan controls attached to Analog Devices ADT7470 hwmon chips. Signed-off-by: Darrick J. Wong Signed-off-by: Mark M. Hoffman --- drivers/hwmon/Kconfig | 10 + drivers/hwmon/Makefile | 1 + drivers/hwmon/adt7470.c | 1050 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1061 insertions(+) create mode 100644 drivers/hwmon/adt7470.c (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 73177933ae8..da15d535be6 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -133,6 +133,16 @@ config SENSORS_ADM9240 This driver can also be built as a module. If so, the module will be called adm9240. +config SENSORS_ADT7470 + tristate "Analog Devices ADT7470" + depends on I2C && EXPERIMENTAL + help + If you say yes here you get support for the Analog Devices + ADT7470 temperature monitoring chips. + + This driver can also be built as a module. If so, the module + will be called adt7470. + config SENSORS_K8TEMP tristate "AMD Athlon64/FX or Opteron temperature sensor" depends on X86 && PCI && EXPERIMENTAL diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 6e9fdc29061..fb4e0d8a7f5 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_SENSORS_ADM1026) += adm1026.o obj-$(CONFIG_SENSORS_ADM1029) += adm1029.o obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o +obj-$(CONFIG_SENSORS_ADT7470) += adt7470.o obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o obj-$(CONFIG_SENSORS_AMS) += ams/ obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c new file mode 100644 index 00000000000..c4dc20546ec --- /dev/null +++ b/drivers/hwmon/adt7470.c @@ -0,0 +1,1050 @@ +/* + * A hwmon driver for the Analog Devices ADT7470 + * Copyright (C) 2007 IBM + * + * Author: Darrick J. Wong + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Addresses to scan */ +static unsigned short normal_i2c[] = { 0x2C, 0x2E, 0x2F, I2C_CLIENT_END }; + +/* Insmod parameters */ +I2C_CLIENT_INSMOD_1(adt7470); + +/* ADT7470 registers */ +#define ADT7470_REG_BASE_ADDR 0x20 +#define ADT7470_REG_TEMP_BASE_ADDR 0x20 +#define ADT7470_REG_TEMP_MAX_ADDR 0x29 +#define ADT7470_REG_FAN_BASE_ADDR 0x2A +#define ADT7470_REG_FAN_MAX_ADDR 0x31 +#define ADT7470_REG_PWM_BASE_ADDR 0x32 +#define ADT7470_REG_PWM_MAX_ADDR 0x35 +#define ADT7470_REG_PWM_MAX_BASE_ADDR 0x38 +#define ADT7470_REG_PWM_MAX_MAX_ADDR 0x3B +#define ADT7470_REG_CFG 0x40 +#define ADT7470_FSPD_MASK 0x04 +#define ADT7470_REG_ALARM1 0x41 +#define ADT7470_REG_ALARM2 0x42 +#define ADT7470_REG_TEMP_LIMITS_BASE_ADDR 0x44 +#define ADT7470_REG_TEMP_LIMITS_MAX_ADDR 0x57 +#define ADT7470_REG_FAN_MIN_BASE_ADDR 0x58 +#define ADT7470_REG_FAN_MIN_MAX_ADDR 0x5F +#define ADT7470_REG_FAN_MAX_BASE_ADDR 0x60 +#define ADT7470_REG_FAN_MAX_MAX_ADDR 0x67 +#define ADT7470_REG_PWM_CFG_BASE_ADDR 0x68 +#define ADT7470_REG_PWM12_CFG 0x68 +#define ADT7470_PWM2_AUTO_MASK 0x40 +#define ADT7470_PWM1_AUTO_MASK 0x80 +#define ADT7470_REG_PWM34_CFG 0x69 +#define ADT7470_PWM3_AUTO_MASK 0x40 +#define ADT7470_PWM4_AUTO_MASK 0x80 +#define ADT7470_REG_PWM_MIN_BASE_ADDR 0x6A +#define ADT7470_REG_PWM_MIN_MAX_ADDR 0x6D +#define ADT7470_REG_PWM_TEMP_MIN_BASE_ADDR 0x6E +#define ADT7470_REG_PWM_TEMP_MIN_MAX_ADDR 0x71 +#define ADT7470_REG_ACOUSTICS12 0x75 +#define ADT7470_REG_ACOUSTICS34 0x76 +#define ADT7470_REG_DEVICE 0x3D +#define ADT7470_REG_VENDOR 0x3E +#define ADT7470_REG_REVISION 0x3F +#define ADT7470_REG_ALARM1_MASK 0x72 +#define ADT7470_REG_ALARM2_MASK 0x73 +#define ADT7470_REG_PWM_AUTO_TEMP_BASE_ADDR 0x7C +#define ADT7470_REG_PWM_AUTO_TEMP_MAX_ADDR 0x7D +#define ADT7470_REG_MAX_ADDR 0x81 + +#define ADT7470_TEMP_COUNT 10 +#define ADT7470_TEMP_REG(x) (ADT7470_REG_TEMP_BASE_ADDR + (x)) +#define ADT7470_TEMP_MIN_REG(x) (ADT7470_REG_TEMP_LIMITS_BASE_ADDR + ((x) * 2)) +#define ADT7470_TEMP_MAX_REG(x) (ADT7470_REG_TEMP_LIMITS_BASE_ADDR + \ + ((x) * 2) + 1) + +#define ADT7470_FAN_COUNT 4 +#define ADT7470_REG_FAN(x) (ADT7470_REG_FAN_BASE_ADDR + ((x) * 2)) +#define ADT7470_REG_FAN_MIN(x) (ADT7470_REG_FAN_MIN_BASE_ADDR + ((x) * 2)) +#define ADT7470_REG_FAN_MAX(x) (ADT7470_REG_FAN_MAX_BASE_ADDR + ((x) * 2)) + +#define ADT7470_PWM_COUNT 4 +#define ADT7470_REG_PWM(x) (ADT7470_REG_PWM_BASE_ADDR + (x)) +#define ADT7470_REG_PWM_MAX(x) (ADT7470_REG_PWM_MAX_BASE_ADDR + (x)) +#define ADT7470_REG_PWM_MIN(x) (ADT7470_REG_PWM_MIN_BASE_ADDR + (x)) +#define ADT7470_REG_PWM_TMIN(x) (ADT7470_REG_PWM_TEMP_MIN_BASE_ADDR + (x)) +#define ADT7470_REG_PWM_CFG(x) (ADT7470_REG_PWM_CFG_BASE_ADDR + ((x) / 2)) +#define ADT7470_REG_PWM_AUTO_TEMP(x) (ADT7470_REG_PWM_AUTO_TEMP_BASE_ADDR + \ + ((x) / 2)) + +#define ADT7470_VENDOR 0x41 +#define ADT7470_DEVICE 0x70 +/* datasheet only mentions a revision 2 */ +#define ADT7470_REVISION 0x02 + +/* "all temps" according to hwmon sysfs interface spec */ +#define ADT7470_PWM_ALL_TEMPS 0x3FF + +/* How often do we reread sensors values? (In jiffies) */ +#define SENSOR_REFRESH_INTERVAL (5 * HZ) + +/* How often do we reread sensor limit values? (In jiffies) */ +#define LIMIT_REFRESH_INTERVAL (60 * HZ) + +/* sleep 1s while gathering temperature data */ +#define TEMP_COLLECTION_TIME 1000 + +#define power_of_2(x) (((x) & ((x) - 1)) == 0) + +/* datasheet says to divide this number by the fan reading to get fan rpm */ +#define FAN_PERIOD_TO_RPM(x) ((90000 * 60) / (x)) +#define FAN_RPM_TO_PERIOD FAN_PERIOD_TO_RPM +#define FAN_PERIOD_INVALID 65535 +#define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID) + +struct adt7470_data { + struct i2c_client client; + struct class_device *class_dev; + struct attribute_group attrs; + struct mutex lock; + char sensors_valid; + char limits_valid; + unsigned long sensors_last_updated; /* In jiffies */ + unsigned long limits_last_updated; /* In jiffies */ + + s8 temp[ADT7470_TEMP_COUNT]; + s8 temp_min[ADT7470_TEMP_COUNT]; + s8 temp_max[ADT7470_TEMP_COUNT]; + u16 fan[ADT7470_FAN_COUNT]; + u16 fan_min[ADT7470_FAN_COUNT]; + u16 fan_max[ADT7470_FAN_COUNT]; + u16 alarms, alarms_mask; + u8 force_pwm_max; + u8 pwm[ADT7470_PWM_COUNT]; + u8 pwm_max[ADT7470_PWM_COUNT]; + u8 pwm_automatic[ADT7470_PWM_COUNT]; + u8 pwm_min[ADT7470_PWM_COUNT]; + s8 pwm_tmin[ADT7470_PWM_COUNT]; + u8 pwm_auto_temp[ADT7470_PWM_COUNT]; +}; + +static int adt7470_attach_adapter(struct i2c_adapter *adapter); +static int adt7470_detect(struct i2c_adapter *adapter, int address, int kind); +static int adt7470_detach_client(struct i2c_client *client); + +static struct i2c_driver adt7470_driver = { + .driver = { + .name = "adt7470", + }, + .attach_adapter = adt7470_attach_adapter, + .detach_client = adt7470_detach_client, +}; + +/* + * 16-bit registers on the ADT7470 are low-byte first. The data sheet says + * that the low byte must be read before the high byte. + */ +static inline int adt7470_read_word_data(struct i2c_client *client, u8 reg) +{ + u16 foo; + foo = i2c_smbus_read_byte_data(client, reg); + foo |= ((u16)i2c_smbus_read_byte_data(client, reg + 1) << 8); + return foo; +} + +static inline int adt7470_write_word_data(struct i2c_client *client, u8 reg, + u16 value) +{ + return i2c_smbus_write_byte_data(client, reg, value & 0xFF) + && i2c_smbus_write_byte_data(client, reg + 1, value >> 8); +} + +static void adt7470_init_client(struct i2c_client *client) +{ + int reg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG); + + if (reg < 0) { + dev_err(&client->dev, "cannot read configuration register\n"); + } else { + /* start monitoring (and do a self-test) */ + i2c_smbus_write_byte_data(client, ADT7470_REG_CFG, reg | 3); + } +} + +static struct adt7470_data *adt7470_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct adt7470_data *data = i2c_get_clientdata(client); + unsigned long local_jiffies = jiffies; + u8 cfg; + int i; + + mutex_lock(&data->lock); + if (time_before(local_jiffies, data->sensors_last_updated + + SENSOR_REFRESH_INTERVAL) + && data->sensors_valid) + goto no_sensor_update; + + /* start reading temperature sensors */ + cfg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG); + cfg |= 0x80; + i2c_smbus_write_byte_data(client, ADT7470_REG_CFG, cfg); + + /* + * Delay is 200ms * number of tmp05 sensors. Too bad + * there's no way to figure out how many are connected. + * For now, assume 1s will work. + */ + msleep(TEMP_COLLECTION_TIME); + + /* done reading temperature sensors */ + cfg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG); + cfg &= ~0x80; + i2c_smbus_write_byte_data(client, ADT7470_REG_CFG, cfg); + + for (i = 0; i < ADT7470_TEMP_COUNT; i++) + data->temp[i] = i2c_smbus_read_byte_data(client, + ADT7470_TEMP_REG(i)); + + for (i = 0; i < ADT7470_FAN_COUNT; i++) + data->fan[i] = adt7470_read_word_data(client, + ADT7470_REG_FAN(i)); + + for (i = 0; i < ADT7470_PWM_COUNT; i++) { + int reg; + int reg_mask; + + data->pwm[i] = i2c_smbus_read_byte_data(client, + ADT7470_REG_PWM(i)); + + if (i % 2) + reg_mask = ADT7470_PWM2_AUTO_MASK; + else + reg_mask = ADT7470_PWM1_AUTO_MASK; + + reg = ADT7470_REG_PWM_CFG(i); + if (i2c_smbus_read_byte_data(client, reg) & reg_mask) + data->pwm_automatic[i] = 1; + else + data->pwm_automatic[i] = 0; + + reg = ADT7470_REG_PWM_AUTO_TEMP(i); + cfg = i2c_smbus_read_byte_data(client, reg); + if (!(i % 2)) + data->pwm_auto_temp[i] = cfg >> 4; + else + data->pwm_auto_temp[i] = cfg & 0xF; + } + + if (i2c_smbus_read_byte_data(client, ADT7470_REG_CFG) & + ADT7470_FSPD_MASK) + data->force_pwm_max = 1; + else + data->force_pwm_max = 0; + + data->alarms = adt7470_read_word_data(client, ADT7470_REG_ALARM1); + data->alarms_mask = adt7470_read_word_data(client, + ADT7470_REG_ALARM1_MASK); + + data->sensors_last_updated = local_jiffies; + data->sensors_valid = 1; + +no_sensor_update: + if (time_before(local_jiffies, data->limits_last_updated + + LIMIT_REFRESH_INTERVAL) + && data->limits_valid) + goto out; + + for (i = 0; i < ADT7470_TEMP_COUNT; i++) { + data->temp_min[i] = i2c_smbus_read_byte_data(client, + ADT7470_TEMP_MIN_REG(i)); + data->temp_max[i] = i2c_smbus_read_byte_data(client, + ADT7470_TEMP_MAX_REG(i)); + } + + for (i = 0; i < ADT7470_FAN_COUNT; i++) { + data->fan_min[i] = adt7470_read_word_data(client, + ADT7470_REG_FAN_MIN(i)); + data->fan_max[i] = adt7470_read_word_data(client, + ADT7470_REG_FAN_MAX(i)); + } + + for (i = 0; i < ADT7470_PWM_COUNT; i++) { + data->pwm_max[i] = i2c_smbus_read_byte_data(client, + ADT7470_REG_PWM_MAX(i)); + data->pwm_min[i] = i2c_smbus_read_byte_data(client, + ADT7470_REG_PWM_MIN(i)); + data->pwm_tmin[i] = i2c_smbus_read_byte_data(client, + ADT7470_REG_PWM_TMIN(i)); + } + + data->limits_last_updated = local_jiffies; + data->limits_valid = 1; + +out: + mutex_unlock(&data->lock); + return data; +} + +static ssize_t show_temp_min(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adt7470_data *data = adt7470_update_device(dev); + return sprintf(buf, "%d\n", 1000 * data->temp_min[attr->index]); +} + +static ssize_t set_temp_min(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct adt7470_data *data = i2c_get_clientdata(client); + int temp = simple_strtol(buf, NULL, 10) / 1000; + + mutex_lock(&data->lock); + data->temp_min[attr->index] = temp; + i2c_smbus_write_byte_data(client, ADT7470_TEMP_MIN_REG(attr->index), + temp); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t show_temp_max(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adt7470_data *data = adt7470_update_device(dev); + return sprintf(buf, "%d\n", 1000 * data->temp_max[attr->index]); +} + +static ssize_t set_temp_max(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct adt7470_data *data = i2c_get_clientdata(client); + int temp = simple_strtol(buf, NULL, 10) / 1000; + + mutex_lock(&data->lock); + data->temp_max[attr->index] = temp; + i2c_smbus_write_byte_data(client, ADT7470_TEMP_MAX_REG(attr->index), + temp); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adt7470_data *data = adt7470_update_device(dev); + return sprintf(buf, "%d\n", 1000 * data->temp[attr->index]); +} + +static ssize_t show_alarms(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adt7470_data *data = adt7470_update_device(dev); + + if (attr->index) + return sprintf(buf, "%x\n", data->alarms); + else + return sprintf(buf, "%x\n", data->alarms_mask); +} + +static ssize_t show_fan_max(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adt7470_data *data = adt7470_update_device(dev); + + if (FAN_DATA_VALID(data->fan_max[attr->index])) + return sprintf(buf, "%d\n", + FAN_PERIOD_TO_RPM(data->fan_max[attr->index])); + else + return sprintf(buf, "0\n"); +} + +static ssize_t set_fan_max(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct adt7470_data *data = i2c_get_clientdata(client); + int temp = simple_strtol(buf, NULL, 10); + + if (!temp) + return -EINVAL; + temp = FAN_RPM_TO_PERIOD(temp); + + mutex_lock(&data->lock); + data->fan_max[attr->index] = temp; + adt7470_write_word_data(client, ADT7470_REG_FAN_MAX(attr->index), temp); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t show_fan_min(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adt7470_data *data = adt7470_update_device(dev); + + if (FAN_DATA_VALID(data->fan_min[attr->index])) + return sprintf(buf, "%d\n", + FAN_PERIOD_TO_RPM(data->fan_min[attr->index])); + else + return sprintf(buf, "0\n"); +} + +static ssize_t set_fan_min(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct adt7470_data *data = i2c_get_clientdata(client); + int temp = simple_strtol(buf, NULL, 10); + + if (!temp) + return -EINVAL; + temp = FAN_RPM_TO_PERIOD(temp); + + mutex_lock(&data->lock); + data->fan_min[attr->index] = temp; + adt7470_write_word_data(client, ADT7470_REG_FAN_MIN(attr->index), temp); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adt7470_data *data = adt7470_update_device(dev); + + if (FAN_DATA_VALID(data->fan[attr->index])) + return sprintf(buf, "%d\n", + FAN_PERIOD_TO_RPM(data->fan[attr->index])); + else + return sprintf(buf, "0\n"); +} + +static ssize_t show_force_pwm_max(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct adt7470_data *data = adt7470_update_device(dev); + return sprintf(buf, "%d\n", data->force_pwm_max); +} + +static ssize_t set_force_pwm_max(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct adt7470_data *data = i2c_get_clientdata(client); + int temp = simple_strtol(buf, NULL, 10); + u8 reg; + + mutex_lock(&data->lock); + data->force_pwm_max = temp; + reg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG); + if (temp) + reg |= ADT7470_FSPD_MASK; + else + reg &= ~ADT7470_FSPD_MASK; + i2c_smbus_write_byte_data(client, ADT7470_REG_CFG, reg); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adt7470_data *data = adt7470_update_device(dev); + return sprintf(buf, "%d\n", data->pwm[attr->index]); +} + +static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct adt7470_data *data = i2c_get_clientdata(client); + int temp = simple_strtol(buf, NULL, 10); + + mutex_lock(&data->lock); + data->pwm[attr->index] = temp; + i2c_smbus_write_byte_data(client, ADT7470_REG_PWM(attr->index), temp); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t show_pwm_max(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adt7470_data *data = adt7470_update_device(dev); + return sprintf(buf, "%d\n", data->pwm_max[attr->index]); +} + +static ssize_t set_pwm_max(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct adt7470_data *data = i2c_get_clientdata(client); + int temp = simple_strtol(buf, NULL, 10); + + mutex_lock(&data->lock); + data->pwm_max[attr->index] = temp; + i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_MAX(attr->index), + temp); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t show_pwm_min(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adt7470_data *data = adt7470_update_device(dev); + return sprintf(buf, "%d\n", data->pwm_min[attr->index]); +} + +static ssize_t set_pwm_min(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct adt7470_data *data = i2c_get_clientdata(client); + int temp = simple_strtol(buf, NULL, 10); + + mutex_lock(&data->lock); + data->pwm_min[attr->index] = temp; + i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_MIN(attr->index), + temp); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t show_pwm_tmax(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adt7470_data *data = adt7470_update_device(dev); + /* the datasheet says that tmax = tmin + 20C */ + return sprintf(buf, "%d\n", 1000 * (20 + data->pwm_tmin[attr->index])); +} + +static ssize_t show_pwm_tmin(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adt7470_data *data = adt7470_update_device(dev); + return sprintf(buf, "%d\n", 1000 * data->pwm_tmin[attr->index]); +} + +static ssize_t set_pwm_tmin(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct adt7470_data *data = i2c_get_clientdata(client); + int temp = simple_strtol(buf, NULL, 10) / 1000; + + mutex_lock(&data->lock); + data->pwm_tmin[attr->index] = temp; + i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_TMIN(attr->index), + temp); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t show_pwm_auto(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adt7470_data *data = adt7470_update_device(dev); + return sprintf(buf, "%d\n", 1 + data->pwm_automatic[attr->index]); +} + +static ssize_t set_pwm_auto(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct adt7470_data *data = i2c_get_clientdata(client); + int temp = simple_strtol(buf, NULL, 10); + int pwm_auto_reg = ADT7470_REG_PWM_CFG(attr->index); + int pwm_auto_reg_mask; + u8 reg; + + if (attr->index % 2) + pwm_auto_reg_mask = ADT7470_PWM2_AUTO_MASK; + else + pwm_auto_reg_mask = ADT7470_PWM1_AUTO_MASK; + + if (temp != 2 && temp != 1) + return -EINVAL; + temp--; + + mutex_lock(&data->lock); + data->pwm_automatic[attr->index] = temp; + reg = i2c_smbus_read_byte_data(client, pwm_auto_reg); + if (temp) + reg |= pwm_auto_reg_mask; + else + reg &= ~pwm_auto_reg_mask; + i2c_smbus_write_byte_data(client, pwm_auto_reg, reg); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t show_pwm_auto_temp(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adt7470_data *data = adt7470_update_device(dev); + u8 ctrl = data->pwm_auto_temp[attr->index]; + + if (ctrl) + return sprintf(buf, "%d\n", 1 << (ctrl - 1)); + else + return sprintf(buf, "%d\n", ADT7470_PWM_ALL_TEMPS); +} + +static int cvt_auto_temp(int input) +{ + if (input == ADT7470_PWM_ALL_TEMPS) + return 0; + if (input < 1 || !power_of_2(input)) + return -EINVAL; + return ilog2(input) + 1; +} + +static ssize_t set_pwm_auto_temp(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct adt7470_data *data = i2c_get_clientdata(client); + int temp = cvt_auto_temp(simple_strtol(buf, NULL, 10)); + int pwm_auto_reg = ADT7470_REG_PWM_AUTO_TEMP(attr->index); + u8 reg; + + if (temp < 0) + return temp; + + mutex_lock(&data->lock); + data->pwm_automatic[attr->index] = temp; + reg = i2c_smbus_read_byte_data(client, pwm_auto_reg); + + if (!(attr->index % 2)) { + reg &= 0xF; + reg |= (temp << 4) & 0xF0; + } else { + reg &= 0xF0; + reg |= temp & 0xF; + } + + i2c_smbus_write_byte_data(client, pwm_auto_reg, reg); + mutex_unlock(&data->lock); + + return count; +} + +static SENSOR_DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL, 0); +static SENSOR_DEVICE_ATTR(alarm_mask, S_IRUGO, show_alarms, NULL, 1); + +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, + set_temp_max, 0); +static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_max, + set_temp_max, 1); +static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_temp_max, + set_temp_max, 2); +static SENSOR_DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_temp_max, + set_temp_max, 3); +static SENSOR_DEVICE_ATTR(temp5_max, S_IWUSR | S_IRUGO, show_temp_max, + set_temp_max, 4); +static SENSOR_DEVICE_ATTR(temp6_max, S_IWUSR | S_IRUGO, show_temp_max, + set_temp_max, 5); +static SENSOR_DEVICE_ATTR(temp7_max, S_IWUSR | S_IRUGO, show_temp_max, + set_temp_max, 6); +static SENSOR_DEVICE_ATTR(temp8_max, S_IWUSR | S_IRUGO, show_temp_max, + set_temp_max, 7); +static SENSOR_DEVICE_ATTR(temp9_max, S_IWUSR | S_IRUGO, show_temp_max, + set_temp_max, 8); +static SENSOR_DEVICE_ATTR(temp10_max, S_IWUSR | S_IRUGO, show_temp_max, + set_temp_max, 9); + +static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp_min, + set_temp_min, 0); +static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp_min, + set_temp_min, 1); +static SENSOR_DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_temp_min, + set_temp_min, 2); +static SENSOR_DEVICE_ATTR(temp4_min, S_IWUSR | S_IRUGO, show_temp_min, + set_temp_min, 3); +static SENSOR_DEVICE_ATTR(temp5_min, S_IWUSR | S_IRUGO, show_temp_min, + set_temp_min, 4); +static SENSOR_DEVICE_ATTR(temp6_min, S_IWUSR | S_IRUGO, show_temp_min, + set_temp_min, 5); +static SENSOR_DEVICE_ATTR(temp7_min, S_IWUSR | S_IRUGO, show_temp_min, + set_temp_min, 6); +static SENSOR_DEVICE_ATTR(temp8_min, S_IWUSR | S_IRUGO, show_temp_min, + set_temp_min, 7); +static SENSOR_DEVICE_ATTR(temp9_min, S_IWUSR | S_IRUGO, show_temp_min, + set_temp_min, 8); +static SENSOR_DEVICE_ATTR(temp10_min, S_IWUSR | S_IRUGO, show_temp_min, + set_temp_min, 9); + +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); +static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); +static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); +static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3); +static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp, NULL, 4); +static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_temp, NULL, 5); +static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO, show_temp, NULL, 6); +static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, show_temp, NULL, 7); +static SENSOR_DEVICE_ATTR(temp9_input, S_IRUGO, show_temp, NULL, 8); +static SENSOR_DEVICE_ATTR(temp10_input, S_IRUGO, show_temp, NULL, 9); + +static SENSOR_DEVICE_ATTR(fan1_max, S_IWUSR | S_IRUGO, show_fan_max, + set_fan_max, 0); +static SENSOR_DEVICE_ATTR(fan2_max, S_IWUSR | S_IRUGO, show_fan_max, + set_fan_max, 1); +static SENSOR_DEVICE_ATTR(fan3_max, S_IWUSR | S_IRUGO, show_fan_max, + set_fan_max, 2); +static SENSOR_DEVICE_ATTR(fan4_max, S_IWUSR | S_IRUGO, show_fan_max, + set_fan_max, 3); + +static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, + set_fan_min, 0); +static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, + set_fan_min, 1); +static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, + set_fan_min, 2); +static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min, + set_fan_min, 3); + +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); +static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2); +static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3); + +static SENSOR_DEVICE_ATTR(force_pwm_max, S_IWUSR | S_IRUGO, + show_force_pwm_max, set_force_pwm_max, 0); + +static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0); +static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1); +static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2); +static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 3); + +static SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IWUSR | S_IRUGO, + show_pwm_min, set_pwm_min, 0); +static SENSOR_DEVICE_ATTR(pwm2_auto_point1_pwm, S_IWUSR | S_IRUGO, + show_pwm_min, set_pwm_min, 1); +static SENSOR_DEVICE_ATTR(pwm3_auto_point1_pwm, S_IWUSR | S_IRUGO, + show_pwm_min, set_pwm_min, 2); +static SENSOR_DEVICE_ATTR(pwm4_auto_point1_pwm, S_IWUSR | S_IRUGO, + show_pwm_min, set_pwm_min, 3); + +static SENSOR_DEVICE_ATTR(pwm1_auto_point2_pwm, S_IWUSR | S_IRUGO, + show_pwm_max, set_pwm_max, 0); +static SENSOR_DEVICE_ATTR(pwm2_auto_point2_pwm, S_IWUSR | S_IRUGO, + show_pwm_max, set_pwm_max, 1); +static SENSOR_DEVICE_ATTR(pwm3_auto_point2_pwm, S_IWUSR | S_IRUGO, + show_pwm_max, set_pwm_max, 2); +static SENSOR_DEVICE_ATTR(pwm4_auto_point2_pwm, S_IWUSR | S_IRUGO, + show_pwm_max, set_pwm_max, 3); + +static SENSOR_DEVICE_ATTR(pwm1_auto_point1_temp, S_IWUSR | S_IRUGO, + show_pwm_tmin, set_pwm_tmin, 0); +static SENSOR_DEVICE_ATTR(pwm2_auto_point1_temp, S_IWUSR | S_IRUGO, + show_pwm_tmin, set_pwm_tmin, 1); +static SENSOR_DEVICE_ATTR(pwm3_auto_point1_temp, S_IWUSR | S_IRUGO, + show_pwm_tmin, set_pwm_tmin, 2); +static SENSOR_DEVICE_ATTR(pwm4_auto_point1_temp, S_IWUSR | S_IRUGO, + show_pwm_tmin, set_pwm_tmin, 3); + +static SENSOR_DEVICE_ATTR(pwm1_auto_point2_temp, S_IRUGO, show_pwm_tmax, + NULL, 0); +static SENSOR_DEVICE_ATTR(pwm2_auto_point2_temp, S_IRUGO, show_pwm_tmax, + NULL, 1); +static SENSOR_DEVICE_ATTR(pwm3_auto_point2_temp, S_IRUGO, show_pwm_tmax, + NULL, 2); +static SENSOR_DEVICE_ATTR(pwm4_auto_point2_temp, S_IRUGO, show_pwm_tmax, + NULL, 3); + +static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_auto, + set_pwm_auto, 0); +static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_auto, + set_pwm_auto, 1); +static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, show_pwm_auto, + set_pwm_auto, 2); +static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, show_pwm_auto, + set_pwm_auto, 3); + +static SENSOR_DEVICE_ATTR(pwm1_auto_channels_temp, S_IWUSR | S_IRUGO, + show_pwm_auto_temp, set_pwm_auto_temp, 0); +static SENSOR_DEVICE_ATTR(pwm2_auto_channels_temp, S_IWUSR | S_IRUGO, + show_pwm_auto_temp, set_pwm_auto_temp, 1); +static SENSOR_DEVICE_ATTR(pwm3_auto_channels_temp, S_IWUSR | S_IRUGO, + show_pwm_auto_temp, set_pwm_auto_temp, 2); +static SENSOR_DEVICE_ATTR(pwm4_auto_channels_temp, S_IWUSR | S_IRUGO, + show_pwm_auto_temp, set_pwm_auto_temp, 3); + +static struct attribute *adt7470_attr[] = +{ + &sensor_dev_attr_alarms.dev_attr.attr, + &sensor_dev_attr_alarm_mask.dev_attr.attr, + &sensor_dev_attr_temp1_max.dev_attr.attr, + &sensor_dev_attr_temp2_max.dev_attr.attr, + &sensor_dev_attr_temp3_max.dev_attr.attr, + &sensor_dev_attr_temp4_max.dev_attr.attr, + &sensor_dev_attr_temp5_max.dev_attr.attr, + &sensor_dev_attr_temp6_max.dev_attr.attr, + &sensor_dev_attr_temp7_max.dev_attr.attr, + &sensor_dev_attr_temp8_max.dev_attr.attr, + &sensor_dev_attr_temp9_max.dev_attr.attr, + &sensor_dev_attr_temp10_max.dev_attr.attr, + &sensor_dev_attr_temp1_min.dev_attr.attr, + &sensor_dev_attr_temp2_min.dev_attr.attr, + &sensor_dev_attr_temp3_min.dev_attr.attr, + &sensor_dev_attr_temp4_min.dev_attr.attr, + &sensor_dev_attr_temp5_min.dev_attr.attr, + &sensor_dev_attr_temp6_min.dev_attr.attr, + &sensor_dev_attr_temp7_min.dev_attr.attr, + &sensor_dev_attr_temp8_min.dev_attr.attr, + &sensor_dev_attr_temp9_min.dev_attr.attr, + &sensor_dev_attr_temp10_min.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp3_input.dev_attr.attr, + &sensor_dev_attr_temp4_input.dev_attr.attr, + &sensor_dev_attr_temp5_input.dev_attr.attr, + &sensor_dev_attr_temp6_input.dev_attr.attr, + &sensor_dev_attr_temp7_input.dev_attr.attr, + &sensor_dev_attr_temp8_input.dev_attr.attr, + &sensor_dev_attr_temp9_input.dev_attr.attr, + &sensor_dev_attr_temp10_input.dev_attr.attr, + &sensor_dev_attr_fan1_max.dev_attr.attr, + &sensor_dev_attr_fan2_max.dev_attr.attr, + &sensor_dev_attr_fan3_max.dev_attr.attr, + &sensor_dev_attr_fan4_max.dev_attr.attr, + &sensor_dev_attr_fan1_min.dev_attr.attr, + &sensor_dev_attr_fan2_min.dev_attr.attr, + &sensor_dev_attr_fan3_min.dev_attr.attr, + &sensor_dev_attr_fan4_min.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan3_input.dev_attr.attr, + &sensor_dev_attr_fan4_input.dev_attr.attr, + &sensor_dev_attr_force_pwm_max.dev_attr.attr, + &sensor_dev_attr_pwm1.dev_attr.attr, + &sensor_dev_attr_pwm2.dev_attr.attr, + &sensor_dev_attr_pwm3.dev_attr.attr, + &sensor_dev_attr_pwm4.dev_attr.attr, + &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, + &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr, + &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr, + &sensor_dev_attr_pwm4_auto_point1_pwm.dev_attr.attr, + &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr, + &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr, + &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr, + &sensor_dev_attr_pwm4_auto_point2_pwm.dev_attr.attr, + &sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr, + &sensor_dev_attr_pwm2_auto_point1_temp.dev_attr.attr, + &sensor_dev_attr_pwm3_auto_point1_temp.dev_attr.attr, + &sensor_dev_attr_pwm4_auto_point1_temp.dev_attr.attr, + &sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr, + &sensor_dev_attr_pwm2_auto_point2_temp.dev_attr.attr, + &sensor_dev_attr_pwm3_auto_point2_temp.dev_attr.attr, + &sensor_dev_attr_pwm4_auto_point2_temp.dev_attr.attr, + &sensor_dev_attr_pwm1_enable.dev_attr.attr, + &sensor_dev_attr_pwm2_enable.dev_attr.attr, + &sensor_dev_attr_pwm3_enable.dev_attr.attr, + &sensor_dev_attr_pwm4_enable.dev_attr.attr, + &sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr, + &sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr, + &sensor_dev_attr_pwm3_auto_channels_temp.dev_attr.attr, + &sensor_dev_attr_pwm4_auto_channels_temp.dev_attr.attr, + NULL +}; + +static int adt7470_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, adt7470_detect); +} + +static int adt7470_detect(struct i2c_adapter *adapter, int address, int kind) +{ + struct i2c_client *client; + struct adt7470_data *data; + int err = 0; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + goto exit; + + if (!(data = kzalloc(sizeof(struct adt7470_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + client = &data->client; + client->addr = address; + client->adapter = adapter; + client->driver = &adt7470_driver; + + i2c_set_clientdata(client, data); + + mutex_init(&data->lock); + + if (kind <= 0) { + int vendor, device, revision; + + vendor = i2c_smbus_read_byte_data(client, ADT7470_REG_VENDOR); + if (vendor != ADT7470_VENDOR) { + err = -ENODEV; + goto exit_free; + } + + device = i2c_smbus_read_byte_data(client, ADT7470_REG_DEVICE); + if (device != ADT7470_DEVICE) { + err = -ENODEV; + goto exit_free; + } + + revision = i2c_smbus_read_byte_data(client, + ADT7470_REG_REVISION); + if (revision != ADT7470_REVISION) { + err = -ENODEV; + goto exit_free; + } + } else + dev_dbg(&adapter->dev, "detection forced\n"); + + strlcpy(client->name, "adt7470", I2C_NAME_SIZE); + + if ((err = i2c_attach_client(client))) + goto exit_free; + + dev_info(&client->dev, "%s chip found\n", client->name); + + /* Initialize the ADT7470 chip */ + adt7470_init_client(client); + + /* Register sysfs hooks */ + data->attrs.attrs = adt7470_attr; + if ((err = sysfs_create_group(&client->dev.kobj, &data->attrs))) + goto exit_detach; + + data->class_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->class_dev)) { + err = PTR_ERR(data->class_dev); + goto exit_remove; + } + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &data->attrs); +exit_detach: + i2c_detach_client(client); +exit_free: + kfree(data); +exit: + return err; +} + +static int adt7470_detach_client(struct i2c_client *client) +{ + struct adt7470_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->class_dev); + sysfs_remove_group(&client->dev.kobj, &data->attrs); + i2c_detach_client(client); + kfree(data); + return 0; +} + +static int __init adt7470_init(void) +{ + return i2c_add_driver(&adt7470_driver); +} + +static void __exit adt7470_exit(void) +{ + i2c_del_driver(&adt7470_driver); +} + +MODULE_AUTHOR("Darrick J. Wong "); +MODULE_DESCRIPTION("ADT7470 driver"); +MODULE_LICENSE("GPL"); + +module_init(adt7470_init); +module_exit(adt7470_exit); -- cgit v1.2.3 From dcf3b5fb7fb6e1b56bfaf705e665b04870213768 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Wed, 22 Aug 2007 14:05:22 -0400 Subject: hwmon: (thmc50) add individual alarm & fault files This patch adds individual alarm and fault files to the thmc50 driver. These sysfs entries are required for a new libsensors library. Signed-off-by: Krzysztof Helt Acked-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/thmc50.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/thmc50.c b/drivers/hwmon/thmc50.c index 9395b52d9b9..c920f394a5c 100644 --- a/drivers/hwmon/thmc50.c +++ b/drivers/hwmon/thmc50.c @@ -46,6 +46,11 @@ I2C_CLIENT_MODULE_PARM(adm1022_temp3, "List of adapter,address pairs " #define THMC50_REG_COMPANY_ID 0x3E #define THMC50_REG_DIE_CODE 0x3F #define THMC50_REG_ANALOG_OUT 0x19 +/* + * We use mirror status register for reading alarms + * so ACPI can use the primary status register. + */ +#define THMC50_REG_INTR_MIRROR 0x4C const static u8 THMC50_REG_TEMP[] = { 0x27, 0x26, 0x20 }; const static u8 THMC50_REG_TEMP_MIN[] = { 0x3A, 0x38, 0x2C }; @@ -69,6 +74,7 @@ struct thmc50_data { s8 temp_max[3]; s8 temp_min[3]; u8 analog_out; + u8 alarms; }; static int thmc50_attach_adapter(struct i2c_adapter *adapter); @@ -180,6 +186,15 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, return count; } +static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int index = to_sensor_dev_attr(attr)->index; + struct thmc50_data *data = thmc50_update_device(dev); + + return sprintf(buf, "%u\n", (data->alarms >> index) & 1); +} + #define temp_reg(offset) \ static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp, \ NULL, offset - 1); \ @@ -192,6 +207,12 @@ temp_reg(1); temp_reg(2); temp_reg(3); +static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 0); +static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5); +static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 7); +static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 2); + static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_analog_out, set_analog_out, 0); static SENSOR_DEVICE_ATTR(pwm1_mode, S_IRUGO, show_pwm_mode, NULL, 0); @@ -200,9 +221,12 @@ static struct attribute *thmc50_attributes[] = { &sensor_dev_attr_temp1_max.dev_attr.attr, &sensor_dev_attr_temp1_min.dev_attr.attr, &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp1_alarm.dev_attr.attr, &sensor_dev_attr_temp2_max.dev_attr.attr, &sensor_dev_attr_temp2_min.dev_attr.attr, &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp2_alarm.dev_attr.attr, + &sensor_dev_attr_temp2_fault.dev_attr.attr, &sensor_dev_attr_pwm1.dev_attr.attr, &sensor_dev_attr_pwm1_mode.dev_attr.attr, NULL @@ -217,6 +241,8 @@ static struct attribute *adm1022_attributes[] = { &sensor_dev_attr_temp3_max.dev_attr.attr, &sensor_dev_attr_temp3_min.dev_attr.attr, &sensor_dev_attr_temp3_input.dev_attr.attr, + &sensor_dev_attr_temp3_alarm.dev_attr.attr, + &sensor_dev_attr_temp3_fault.dev_attr.attr, NULL }; @@ -414,6 +440,8 @@ static struct thmc50_data *thmc50_update_device(struct device *dev) } data->analog_out = i2c_smbus_read_byte_data(client, THMC50_REG_ANALOG_OUT); + data->alarms = + i2c_smbus_read_byte_data(client, THMC50_REG_INTR_MIRROR); data->last_updated = jiffies; data->valid = 1; } -- cgit v1.2.3 From 5bfedac045082a97e20d47d876071279ef984d28 Mon Sep 17 00:00:00 2001 From: Christian Hohnstaedt Date: Thu, 16 Aug 2007 11:40:10 +0200 Subject: hwmon: Allow writing of negative trigger temperatures - replace differing temperature variable types by long - use strtol() instead of strtoul() for conversion Signed-off-by: Christian Hohnstaedt Acked-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/ad7418.c | 2 +- drivers/hwmon/adm1021.c | 2 +- drivers/hwmon/asb100.c | 4 ++-- drivers/hwmon/ds1621.c | 2 +- drivers/hwmon/lm75.c | 2 +- drivers/hwmon/lm75.h | 2 +- drivers/hwmon/lm77.c | 2 +- drivers/hwmon/lm93.c | 10 +++++----- drivers/hwmon/w83627ehf.c | 6 +++--- drivers/hwmon/w83627hf.c | 6 +++--- drivers/hwmon/w83781d.c | 2 +- 11 files changed, 20 insertions(+), 20 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/ad7418.c b/drivers/hwmon/ad7418.c index cc8b624a1e5..879ea72ee3b 100644 --- a/drivers/hwmon/ad7418.c +++ b/drivers/hwmon/ad7418.c @@ -172,7 +172,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *devattr, struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct i2c_client *client = to_i2c_client(dev); struct ad7418_data *data = i2c_get_clientdata(client); - int temp = simple_strtol(buf, NULL, 10); + long temp = simple_strtol(buf, NULL, 10); mutex_lock(&data->lock); data->temp[attr->index] = LM75_TEMP_TO_REG(temp); diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c index 5418a675bb6..6649e068836 100644 --- a/drivers/hwmon/adm1021.c +++ b/drivers/hwmon/adm1021.c @@ -162,7 +162,7 @@ static ssize_t set_##value(struct device *dev, \ { \ struct i2c_client *client = to_i2c_client(dev); \ struct adm1021_data *data = i2c_get_clientdata(client); \ - int temp = simple_strtoul(buf, NULL, 10); \ + long temp = simple_strtol(buf, NULL, 10); \ \ mutex_lock(&data->update_lock); \ data->value = TEMP_TO_REG(temp); \ diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c index 57b1c7b7ac3..55d92e1e27d 100644 --- a/drivers/hwmon/asb100.c +++ b/drivers/hwmon/asb100.c @@ -143,7 +143,7 @@ static int FAN_FROM_REG(u8 val, int div) /* TEMP: 0.001C/bit (-128C to +127C) REG: 1C/bit, two's complement */ -static u8 TEMP_TO_REG(int temp) +static u8 TEMP_TO_REG(long temp) { int ntemp = SENSORS_LIMIT(temp, ASB100_TEMP_MIN, ASB100_TEMP_MAX); ntemp += (ntemp<0 ? -500 : 500); @@ -448,7 +448,7 @@ static ssize_t set_##reg(struct device *dev, const char *buf, \ { \ struct i2c_client *client = to_i2c_client(dev); \ struct asb100_data *data = i2c_get_clientdata(client); \ - unsigned long val = simple_strtoul(buf, NULL, 10); \ + long val = simple_strtol(buf, NULL, 10); \ \ mutex_lock(&data->update_lock); \ switch (nr) { \ diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c index 1212d6b7f31..5a861f93612 100644 --- a/drivers/hwmon/ds1621.c +++ b/drivers/hwmon/ds1621.c @@ -151,7 +151,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da, struct sensor_device_attribute *attr = to_sensor_dev_attr(da); struct i2c_client *client = to_i2c_client(dev); struct ds1621_data *data = ds1621_update_client(dev); - u16 val = LM75_TEMP_TO_REG(simple_strtoul(buf, NULL, 10)); + u16 val = LM75_TEMP_TO_REG(simple_strtol(buf, NULL, 10)); mutex_lock(&data->update_lock); data->temp[attr->index] = val; diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c index a40166ffad1..4fa32205e44 100644 --- a/drivers/hwmon/lm75.c +++ b/drivers/hwmon/lm75.c @@ -95,7 +95,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da, struct i2c_client *client = to_i2c_client(dev); struct lm75_data *data = i2c_get_clientdata(client); int nr = attr->index; - unsigned long temp = simple_strtoul(buf, NULL, 10); + long temp = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); data->temp[nr] = LM75_TEMP_TO_REG(temp); diff --git a/drivers/hwmon/lm75.h b/drivers/hwmon/lm75.h index af7dc650ee1..7c93454bb4e 100644 --- a/drivers/hwmon/lm75.h +++ b/drivers/hwmon/lm75.h @@ -33,7 +33,7 @@ /* TEMP: 0.001C/bit (-55C to +125C) REG: (0.5C/bit, two's complement) << 7 */ -static inline u16 LM75_TEMP_TO_REG(int temp) +static inline u16 LM75_TEMP_TO_REG(long temp) { int ntemp = SENSORS_LIMIT(temp, LM75_TEMP_MIN, LM75_TEMP_MAX); ntemp += (ntemp<0 ? -250 : 250); diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c index dd969f1e841..46e3abad720 100644 --- a/drivers/hwmon/lm77.c +++ b/drivers/hwmon/lm77.c @@ -138,7 +138,7 @@ static ssize_t set_##value(struct device *dev, struct device_attribute *attr, co { \ struct i2c_client *client = to_i2c_client(dev); \ struct lm77_data *data = i2c_get_clientdata(client); \ - long val = simple_strtoul(buf, NULL, 10); \ + long val = simple_strtol(buf, NULL, 10); \ \ mutex_lock(&data->update_lock); \ data->value = val; \ diff --git a/drivers/hwmon/lm93.c b/drivers/hwmon/lm93.c index d84f8bf6f28..86c6c6ea074 100644 --- a/drivers/hwmon/lm93.c +++ b/drivers/hwmon/lm93.c @@ -413,7 +413,7 @@ static int LM93_TEMP_FROM_REG(u8 reg) /* TEMP: 1/1000 degrees C (-128C to +127C) REG: 1C/bit, two's complement */ -static u8 LM93_TEMP_TO_REG(int temp) +static u8 LM93_TEMP_TO_REG(long temp) { int ntemp = SENSORS_LIMIT(temp, LM93_TEMP_MIN, LM93_TEMP_MAX); ntemp += (ntemp<0 ? -500 : 500); @@ -1268,7 +1268,7 @@ static ssize_t store_temp_min(struct device *dev, struct device_attribute *attr, int nr = (to_sensor_dev_attr(attr))->index; struct i2c_client *client = to_i2c_client(dev); struct lm93_data *data = i2c_get_clientdata(client); - u32 val = simple_strtoul(buf, NULL, 10); + long val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); data->temp_lim[nr].min = LM93_TEMP_TO_REG(val); @@ -1298,7 +1298,7 @@ static ssize_t store_temp_max(struct device *dev, struct device_attribute *attr, int nr = (to_sensor_dev_attr(attr))->index; struct i2c_client *client = to_i2c_client(dev); struct lm93_data *data = i2c_get_clientdata(client); - u32 val = simple_strtoul(buf, NULL, 10); + long val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); data->temp_lim[nr].max = LM93_TEMP_TO_REG(val); @@ -1329,7 +1329,7 @@ static ssize_t store_temp_auto_base(struct device *dev, int nr = (to_sensor_dev_attr(attr))->index; struct i2c_client *client = to_i2c_client(dev); struct lm93_data *data = i2c_get_clientdata(client); - u32 val = simple_strtoul(buf, NULL, 10); + long val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); data->block10.base[nr] = LM93_TEMP_TO_REG(val); @@ -1360,7 +1360,7 @@ static ssize_t store_temp_auto_boost(struct device *dev, int nr = (to_sensor_dev_attr(attr))->index; struct i2c_client *client = to_i2c_client(dev); struct lm93_data *data = i2c_get_clientdata(client); - u32 val = simple_strtoul(buf, NULL, 10); + long val = simple_strtol(buf, NULL, 10); mutex_lock(&data->update_lock); data->boost[nr] = LM93_TEMP_TO_REG(val); diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index d9a9ec7dd84..e3dfc52b599 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c @@ -223,7 +223,7 @@ temp1_from_reg(s8 reg) } static inline s8 -temp1_to_reg(int temp, int min, int max) +temp1_to_reg(long temp, int min, int max) { if (temp <= min) return min / 1000; @@ -805,7 +805,7 @@ store_temp1_##reg(struct device *dev, struct device_attribute *attr, \ const char *buf, size_t count) \ { \ struct w83627ehf_data *data = dev_get_drvdata(dev); \ - u32 val = simple_strtoul(buf, NULL, 10); \ + long val = simple_strtol(buf, NULL, 10); \ \ mutex_lock(&data->update_lock); \ data->temp1_##reg = temp1_to_reg(val, -128000, 127000); \ @@ -840,7 +840,7 @@ store_##reg(struct device *dev, struct device_attribute *attr, \ struct w83627ehf_data *data = dev_get_drvdata(dev); \ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \ int nr = sensor_attr->index; \ - u32 val = simple_strtoul(buf, NULL, 10); \ + long val = simple_strtol(buf, NULL, 10); \ \ mutex_lock(&data->update_lock); \ data->reg[nr] = LM75_TEMP_TO_REG(val); \ diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 7a4a15f4bf8..0866739a227 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -263,7 +263,7 @@ static inline u8 FAN_TO_REG(long rpm, int div) /* TEMP: 0.001C/bit (-128C to +127C) REG: 1C/bit, two's complement */ -static u8 TEMP_TO_REG(int temp) +static u8 TEMP_TO_REG(long temp) { int ntemp = SENSORS_LIMIT(temp, TEMP_MIN, TEMP_MAX); ntemp += (ntemp<0 ? -500 : 500); @@ -642,9 +642,9 @@ static ssize_t \ store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \ { \ struct w83627hf_data *data = dev_get_drvdata(dev); \ - u32 val; \ + long val; \ \ - val = simple_strtoul(buf, NULL, 10); \ + val = simple_strtol(buf, NULL, 10); \ \ mutex_lock(&data->update_lock); \ \ diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index dcc941a5aaf..8ed88f3d576 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c @@ -410,7 +410,7 @@ static ssize_t store_temp_##reg (struct device *dev, \ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \ struct w83781d_data *data = dev_get_drvdata(dev); \ int nr = attr->index; \ - s32 val; \ + long val; \ \ val = simple_strtol(buf, NULL, 10); \ \ -- cgit v1.2.3 From b26f93309282bdfebb3edb8939e022a4bbe56dfe Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 16 Aug 2007 14:30:01 +0200 Subject: hwmon: Don't export thermistor beta Deprecate the use of thermistor beta values as thermal sensor types. No driver supports changing the beta value anyway. Signed-off-by: Jean Delvare Acked-by: Hans de Goede Signed-off-by: Mark M. Hoffman --- drivers/hwmon/w83627hf.c | 19 ++++++++++--------- drivers/hwmon/w83781d.c | 16 +++++++++------- 2 files changed, 19 insertions(+), 16 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 0866739a227..f0e0e208be9 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -372,11 +372,8 @@ struct w83627hf_data { u8 beep_enable; /* Boolean */ u8 pwm[3]; /* Register value */ u8 pwm_freq[3]; /* Register value */ - u16 sens[3]; /* 782D/783S only. - 1 = pentium diode; 2 = 3904 diode; - 3000-5000 = thermistor beta. - Default = 3435. - Other Betas unimplemented */ + u16 sens[3]; /* 1 = pentium diode; 2 = 3904 diode; + 4 = thermistor */ u8 vrm; u8 vrm_ovt; /* Register value, 627THF/637HF/687THF only */ }; @@ -1001,7 +998,11 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr) tmp & ~BIT_SCFG2[nr - 1]); data->sens[nr - 1] = val; break; - case W83781D_DEFAULT_BETA: /* thermistor */ + case W83781D_DEFAULT_BETA: + dev_warn(dev, "Sensor type %d is deprecated, please use 4 " + "instead\n", W83781D_DEFAULT_BETA); + /* fall through */ + case 4: /* thermistor */ tmp = w83627hf_read_value(data, W83781D_REG_SCFG1); w83627hf_write_value(data, W83781D_REG_SCFG1, tmp & ~BIT_SCFG1[nr - 1]); @@ -1009,8 +1010,8 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr) break; default: dev_err(dev, - "Invalid sensor type %ld; must be 1, 2, or %d\n", - (long) val, W83781D_DEFAULT_BETA); + "Invalid sensor type %ld; must be 1, 2, or 4\n", + (long) val); break; } @@ -1513,7 +1514,7 @@ static void __devinit w83627hf_init_device(struct platform_device *pdev) tmp = w83627hf_read_value(data, W83781D_REG_SCFG1); for (i = 1; i <= 3; i++) { if (!(tmp & BIT_SCFG1[i - 1])) { - data->sens[i - 1] = W83781D_DEFAULT_BETA; + data->sens[i - 1] = 4; } else { if (w83627hf_read_value (data, diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index 8ed88f3d576..c12bdf9d9e1 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c @@ -251,9 +251,7 @@ struct w83781d_data { u8 pwm2_enable; /* Boolean */ u16 sens[3]; /* 782D/783S only. 1 = pentium diode; 2 = 3904 diode; - 3000-5000 = thermistor beta. - Default = 3435. - Other Betas unimplemented */ + 4 = thermistor */ u8 vrm; }; @@ -721,15 +719,19 @@ store_sensor(struct device *dev, struct device_attribute *da, tmp & ~BIT_SCFG2[nr]); data->sens[nr] = val; break; - case W83781D_DEFAULT_BETA: /* thermistor */ + case W83781D_DEFAULT_BETA: + dev_warn(dev, "Sensor type %d is deprecated, please use 4 " + "instead\n", W83781D_DEFAULT_BETA); + /* fall through */ + case 4: /* thermistor */ tmp = w83781d_read_value(data, W83781D_REG_SCFG1); w83781d_write_value(data, W83781D_REG_SCFG1, tmp & ~BIT_SCFG1[nr]); data->sens[nr] = val; break; default: - dev_err(dev, "Invalid sensor type %ld; must be 1, 2, or %d\n", - (long) val, W83781D_DEFAULT_BETA); + dev_err(dev, "Invalid sensor type %ld; must be 1, 2, or 4\n", + (long) val); break; } @@ -1485,7 +1487,7 @@ w83781d_init_device(struct device *dev) tmp = w83781d_read_value(data, W83781D_REG_SCFG1); for (i = 1; i <= 3; i++) { if (!(tmp & BIT_SCFG1[i - 1])) { - data->sens[i - 1] = W83781D_DEFAULT_BETA; + data->sens[i - 1] = 4; } else { if (w83781d_read_value (data, -- cgit v1.2.3 From 67f921d164a046c957f06fb456cabc23c48667ab Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Fri, 17 Aug 2007 17:31:35 +0200 Subject: hwmon: (lm70) Add a name attribute Add a name attribute to the lm70 devices. This is required for libsensors to recognize them. Also drop the "+" before the temperature value, even though it did not cause problems to libsensors, other hardware monitoring drivers don't print it, so it's more consistent that way. Signed-off-by: Jean Delvare Acked-by: Hans de Goede Acked-by: Kaiwan Signed-off-by: Mark M. Hoffman --- drivers/hwmon/lm70.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c index 275d392eca6..30b9b2be87b 100644 --- a/drivers/hwmon/lm70.c +++ b/drivers/hwmon/lm70.c @@ -81,7 +81,7 @@ static ssize_t lm70_sense_temp(struct device *dev, * So it's equivalent to multiplying by 0.25 * 1000 = 250. */ val = ((int)raw/32) * 250; - status = sprintf(buf, "%+d\n", val); /* millidegrees Celsius */ + status = sprintf(buf, "%d\n", val); /* millidegrees Celsius */ out: up(&p_lm70->sem); return status; @@ -89,6 +89,14 @@ out: static DEVICE_ATTR(temp1_input, S_IRUGO, lm70_sense_temp, NULL); +static ssize_t lm70_show_name(struct device *dev, struct device_attribute + *devattr, char *buf) +{ + return sprintf(buf, "lm70\n"); +} + +static DEVICE_ATTR(name, S_IRUGO, lm70_show_name, NULL); + /*----------------------------------------------------------------------*/ static int __devinit lm70_probe(struct spi_device *spi) @@ -115,7 +123,8 @@ static int __devinit lm70_probe(struct spi_device *spi) } dev_set_drvdata(&spi->dev, p_lm70); - if ((status = device_create_file(&spi->dev, &dev_attr_temp1_input))) { + if ((status = device_create_file(&spi->dev, &dev_attr_temp1_input)) + || (status = device_create_file(&spi->dev, &dev_attr_name))) { dev_dbg(&spi->dev, "device_create_file failure.\n"); goto out_dev_create_file_failed; } @@ -123,6 +132,7 @@ static int __devinit lm70_probe(struct spi_device *spi) return 0; out_dev_create_file_failed: + device_remove_file(&spi->dev, &dev_attr_temp1_input); hwmon_device_unregister(p_lm70->cdev); out_dev_reg_failed: dev_set_drvdata(&spi->dev, NULL); @@ -135,6 +145,7 @@ static int __devexit lm70_remove(struct spi_device *spi) struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev); device_remove_file(&spi->dev, &dev_attr_temp1_input); + device_remove_file(&spi->dev, &dev_attr_name); hwmon_device_unregister(p_lm70->cdev); dev_set_drvdata(&spi->dev, NULL); kfree(p_lm70); -- cgit v1.2.3 From 8477d026893d42b00474e9a13ab01ccce7fc2673 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 16 Aug 2007 14:33:37 +0200 Subject: hwmon: (smsc47m1) No confusing debugging messages It's confusing to display debugging messages for fan3 and pwm3 for chips which don't have them. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/smsc47m1.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c index d3181967f16..71792778d6f 100644 --- a/drivers/hwmon/smsc47m1.c +++ b/drivers/hwmon/smsc47m1.c @@ -553,7 +553,7 @@ static int __devinit smsc47m1_probe(struct platform_device *pdev) || (err = device_create_file(dev, &sensor_dev_attr_fan3_div.dev_attr))) goto error_remove_files; - } else + } else if (data->type == smsc47m2) dev_dbg(dev, "Fan 3 not enabled by hardware, skipping\n"); if (pwm1) { @@ -580,7 +580,7 @@ static int __devinit smsc47m1_probe(struct platform_device *pdev) || (err = device_create_file(dev, &sensor_dev_attr_pwm3_enable.dev_attr))) goto error_remove_files; - } else + } else if (data->type == smsc47m2) dev_dbg(dev, "PWM 3 not enabled by hardware, skipping\n"); if ((err = device_create_file(dev, &dev_attr_alarms))) -- cgit v1.2.3 From 84f1e442968a9c754647a6f42accd9560c22ff39 Mon Sep 17 00:00:00 2001 From: Riku Voipio Date: Fri, 24 Aug 2007 13:03:09 +0300 Subject: hwmon: Add f75375s driver Add support for Fintek F75375S/SP and F75373. Signed-off-by: Riku Voipio Signed-off-by: Mark M. Hoffman --- drivers/hwmon/Kconfig | 10 + drivers/hwmon/Makefile | 1 + drivers/hwmon/f75375s.c | 691 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 702 insertions(+) create mode 100644 drivers/hwmon/f75375s.c (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index da15d535be6..a2f60748951 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -236,6 +236,16 @@ config SENSORS_F71882FG This driver can also be built as a module. If so, the module will be called f71882fg. +config SENSORS_F75375S + tristate "Fintek F75375S/SP and F75373"; + depends on I2C && EXPERIMENTAL + help + If you say yes here you get support for hardware monitoring + features of the Fintek F75375S/SP and F75373 + + This driver can also be built as a module. If so, the module + will be called f75375s. + config SENSORS_FSCHER tristate "FSC Hermes" depends on I2C diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index fb4e0d8a7f5..19da12ec140 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -31,6 +31,7 @@ obj-$(CONFIG_SENSORS_DME1737) += dme1737.o obj-$(CONFIG_SENSORS_DS1621) += ds1621.o obj-$(CONFIG_SENSORS_F71805F) += f71805f.o obj-$(CONFIG_SENSORS_F71882FG) += f71882fg.o +obj-$(CONFIG_SENSORS_F75375S) += f75375s.o obj-$(CONFIG_SENSORS_FSCHER) += fscher.o obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c new file mode 100644 index 00000000000..6425184d931 --- /dev/null +++ b/drivers/hwmon/f75375s.c @@ -0,0 +1,691 @@ +/* + * f75375s.c - driver for the Fintek F75375/SP and F75373 + * hardware monitoring features + * Copyright (C) 2006-2007 Riku Voipio + * + * Datasheets available at: + * + * f75375: + * http://www.fintek.com.tw/files/productfiles/2005111152950.pdf + * + * f75373: + * http://www.fintek.com.tw/files/productfiles/2005111153128.pdf + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Addresses to scan */ +static unsigned short normal_i2c[] = { 0x2d, 0x2e, I2C_CLIENT_END }; + +/* Insmod parameters */ +I2C_CLIENT_INSMOD_2(f75373, f75375); + +/* Fintek F75375 registers */ +#define F75375_REG_CONFIG0 0x0 +#define F75375_REG_CONFIG1 0x1 +#define F75375_REG_CONFIG2 0x2 +#define F75375_REG_CONFIG3 0x3 +#define F75375_REG_ADDR 0x4 +#define F75375_REG_INTR 0x31 +#define F75375_CHIP_ID 0x5A +#define F75375_REG_VERSION 0x5C +#define F75375_REG_VENDOR 0x5D +#define F75375_REG_FAN_TIMER 0x60 + +#define F75375_REG_VOLT(nr) (0x10 + (nr)) +#define F75375_REG_VOLT_HIGH(nr) (0x20 + (nr) * 2) +#define F75375_REG_VOLT_LOW(nr) (0x21 + (nr) * 2) + +#define F75375_REG_TEMP(nr) (0x14 + (nr)) +#define F75375_REG_TEMP_HIGH(nr) (0x28 + (nr) * 2) +#define F75375_REG_TEMP_HYST(nr) (0x29 + (nr) * 2) + +#define F75375_REG_FAN(nr) (0x16 + (nr) * 2) +#define F75375_REG_FAN_MIN(nr) (0x2C + (nr) * 2) +#define F75375_REG_FAN_FULL(nr) (0x70 + (nr) * 0x10) +#define F75375_REG_FAN_PWM_DUTY(nr) (0x76 + (nr) * 0x10) +#define F75375_REG_FAN_PWM_CLOCK(nr) (0x7D + (nr) * 0x10) + +#define F75375_REG_FAN_EXP(nr) (0x74 + (nr) * 0x10) +#define F75375_REG_FAN_B_TEMP(nr, step) ((0xA0 + (nr) * 0x10) + (step)) +#define F75375_REG_FAN_B_SPEED(nr, step) \ + ((0xA5 + (nr) * 0x10) + (step) * 2) + +#define F75375_REG_PWM1_RAISE_DUTY 0x69 +#define F75375_REG_PWM2_RAISE_DUTY 0x6A +#define F75375_REG_PWM1_DROP_DUTY 0x6B +#define F75375_REG_PWM2_DROP_DUTY 0x6C + +#define FAN_CTRL_LINEAR(nr) (4 + nr) +#define FAN_CTRL_MODE(nr) (5 + ((nr) * 2)) + +/* + * Data structures and manipulation thereof + */ + +struct f75375_data { + unsigned short addr; + struct i2c_client client; + struct class_device *class_dev; + + const char *name; + int kind; + struct mutex update_lock; /* protect register access */ + char valid; + unsigned long last_updated; /* In jiffies */ + unsigned long last_limits; /* In jiffies */ + + /* Register values */ + u8 in[4]; + u8 in_max[4]; + u8 in_min[4]; + u16 fan[2]; + u16 fan_min[2]; + u16 fan_full[2]; + u16 fan_exp[2]; + u8 fan_timer; + u8 pwm[2]; + u8 pwm_mode[2]; + u8 pwm_enable[2]; + s8 temp[2]; + s8 temp_high[2]; + s8 temp_max_hyst[2]; +}; + +static int f75375_attach_adapter(struct i2c_adapter *adapter); +static int f75375_detect(struct i2c_adapter *adapter, int address, int kind); +static int f75375_detach_client(struct i2c_client *client); + +static struct i2c_driver f75375_driver = { + .driver = { + .name = "f75375", + }, + .attach_adapter = f75375_attach_adapter, + .detach_client = f75375_detach_client, +}; + +static inline int f75375_read8(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +/* in most cases, should be called while holding update_lock */ +static inline u16 f75375_read16(struct i2c_client *client, u8 reg) +{ + return ((i2c_smbus_read_byte_data(client, reg) << 8) + | i2c_smbus_read_byte_data(client, reg + 1)); +} + +static inline void f75375_write8(struct i2c_client *client, u8 reg, + u8 value) +{ + i2c_smbus_write_byte_data(client, reg, value); +} + +static inline void f75375_write16(struct i2c_client *client, u8 reg, + u16 value) +{ + int err = i2c_smbus_write_byte_data(client, reg, (value << 8)); + if (err) + return; + i2c_smbus_write_byte_data(client, reg + 1, (value & 0xFF)); +} + +static struct f75375_data *f75375_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct f75375_data *data = i2c_get_clientdata(client); + int nr; + + mutex_lock(&data->update_lock); + + /* Limit registers cache is refreshed after 60 seconds */ + if (time_after(jiffies, data->last_limits + 60 * HZ) + || !data->valid) { + for (nr = 0; nr < 2; nr++) { + data->temp_high[nr] = + f75375_read8(client, F75375_REG_TEMP_HIGH(nr)); + data->temp_max_hyst[nr] = + f75375_read8(client, F75375_REG_TEMP_HYST(nr)); + data->fan_full[nr] = + f75375_read16(client, F75375_REG_FAN_FULL(nr)); + data->fan_min[nr] = + f75375_read16(client, F75375_REG_FAN_MIN(nr)); + data->fan_exp[nr] = + f75375_read16(client, F75375_REG_FAN_EXP(nr)); + data->pwm[nr] = f75375_read8(client, + F75375_REG_FAN_PWM_DUTY(nr)); + + } + for (nr = 0; nr < 4; nr++) { + data->in_max[nr] = + f75375_read8(client, F75375_REG_VOLT_HIGH(nr)); + data->in_min[nr] = + f75375_read8(client, F75375_REG_VOLT_LOW(nr)); + } + data->fan_timer = f75375_read8(client, F75375_REG_FAN_TIMER); + data->last_limits = jiffies; + } + + /* Measurement registers cache is refreshed after 2 second */ + if (time_after(jiffies, data->last_updated + 2 * HZ) + || !data->valid) { + for (nr = 0; nr < 2; nr++) { + data->temp[nr] = + f75375_read8(client, F75375_REG_TEMP(nr)); + data->fan[nr] = + f75375_read16(client, F75375_REG_FAN(nr)); + } + for (nr = 0; nr < 4; nr++) + data->in[nr] = + f75375_read8(client, F75375_REG_VOLT(nr)); + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + return data; +} + +static inline u16 rpm_from_reg(u16 reg) +{ + if (reg == 0 || reg == 0xffff) + return 0; + return (1500000 / reg); +} + +static inline u16 rpm_to_reg(int rpm) +{ + if (rpm < 367 || rpm > 0xffff) + return 0xffff; + return (1500000 / rpm); +} + +static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct i2c_client *client = to_i2c_client(dev); + struct f75375_data *data = i2c_get_clientdata(client); + int val = simple_strtoul(buf, NULL, 10); + + mutex_lock(&data->update_lock); + data->fan_min[nr] = rpm_to_reg(val); + f75375_write16(client, F75375_REG_FAN_MIN(nr), data->fan_min[nr]); + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t set_fan_exp(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct i2c_client *client = to_i2c_client(dev); + struct f75375_data *data = i2c_get_clientdata(client); + int val = simple_strtoul(buf, NULL, 10); + + mutex_lock(&data->update_lock); + data->fan_exp[nr] = rpm_to_reg(val); + f75375_write16(client, F75375_REG_FAN_EXP(nr), data->fan_exp[nr]); + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct i2c_client *client = to_i2c_client(dev); + struct f75375_data *data = i2c_get_clientdata(client); + int val = simple_strtoul(buf, NULL, 10); + + mutex_lock(&data->update_lock); + data->pwm[nr] = SENSORS_LIMIT(val, 0, 255); + f75375_write8(client, F75375_REG_FAN_PWM_DUTY(nr), data->pwm[nr]); + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t show_pwm_enable(struct device *dev, struct device_attribute + *attr, char *buf) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct f75375_data *data = f75375_update_device(dev); + return sprintf(buf, "%d\n", data->pwm_enable[nr]); +} + +static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct i2c_client *client = to_i2c_client(dev); + struct f75375_data *data = i2c_get_clientdata(client); + int val = simple_strtoul(buf, NULL, 10); + u8 fanmode; + + if (val < 0 || val > 4) + return -EINVAL; + + mutex_lock(&data->update_lock); + fanmode = f75375_read8(client, F75375_REG_FAN_TIMER); + fanmode = ~(3 << FAN_CTRL_MODE(nr)); + + switch (val) { + case 0: /* Full speed */ + fanmode |= (3 << FAN_CTRL_MODE(nr)); + data->pwm[nr] = 255; + f75375_write8(client, F75375_REG_FAN_PWM_DUTY(nr), + data->pwm[nr]); + break; + case 1: /* PWM */ + fanmode |= (3 << FAN_CTRL_MODE(nr)); + break; + case 2: /* AUTOMATIC*/ + fanmode |= (2 << FAN_CTRL_MODE(nr)); + break; + case 3: /* fan speed */ + break; + } + f75375_write8(client, F75375_REG_FAN_TIMER, fanmode); + data->pwm_enable[nr] = val; + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t set_pwm_mode(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct i2c_client *client = to_i2c_client(dev); + struct f75375_data *data = i2c_get_clientdata(client); + int val = simple_strtoul(buf, NULL, 10); + u8 conf = 0; + + if (val != 0 || val != 1 || data->kind == f75373) + return -EINVAL; + + mutex_lock(&data->update_lock); + conf = f75375_read8(client, F75375_REG_CONFIG1); + conf = ~(1 << FAN_CTRL_LINEAR(nr)); + + if (val == 0) + conf |= (1 << FAN_CTRL_LINEAR(nr)) ; + + f75375_write8(client, F75375_REG_CONFIG1, conf); + data->pwm_mode[nr] = val; + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t show_pwm(struct device *dev, struct device_attribute + *attr, char *buf) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct f75375_data *data = f75375_update_device(dev); + return sprintf(buf, "%d\n", data->pwm[nr]); +} + +static ssize_t show_pwm_mode(struct device *dev, struct device_attribute + *attr, char *buf) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct f75375_data *data = f75375_update_device(dev); + return sprintf(buf, "%d\n", data->pwm_mode[nr]); +} + +#define VOLT_FROM_REG(val) ((val) * 8) +#define VOLT_TO_REG(val) ((val) / 8) + +static ssize_t show_in(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct f75375_data *data = f75375_update_device(dev); + return sprintf(buf, "%d\n", VOLT_FROM_REG(data->in[nr])); +} + +static ssize_t show_in_max(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct f75375_data *data = f75375_update_device(dev); + return sprintf(buf, "%d\n", VOLT_FROM_REG(data->in_max[nr])); +} + +static ssize_t show_in_min(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct f75375_data *data = f75375_update_device(dev); + return sprintf(buf, "%d\n", VOLT_FROM_REG(data->in_min[nr])); +} + +static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct i2c_client *client = to_i2c_client(dev); + struct f75375_data *data = i2c_get_clientdata(client); + int val = simple_strtoul(buf, NULL, 10); + val = SENSORS_LIMIT(VOLT_TO_REG(val), 0, 0xff); + mutex_lock(&data->update_lock); + data->in_max[nr] = val; + f75375_write8(client, F75375_REG_VOLT_HIGH(nr), data->in_max[nr]); + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct i2c_client *client = to_i2c_client(dev); + struct f75375_data *data = i2c_get_clientdata(client); + int val = simple_strtoul(buf, NULL, 10); + val = SENSORS_LIMIT(VOLT_TO_REG(val), 0, 0xff); + mutex_lock(&data->update_lock); + data->in_min[nr] = val; + f75375_write8(client, F75375_REG_VOLT_LOW(nr), data->in_min[nr]); + mutex_unlock(&data->update_lock); + return count; +} +#define TEMP_FROM_REG(val) ((val) * 1000) +#define TEMP_TO_REG(val) ((val) / 1000) + +static ssize_t show_temp(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct f75375_data *data = f75375_update_device(dev); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr])); +} + +static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct f75375_data *data = f75375_update_device(dev); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_high[nr])); +} + +static ssize_t show_temp_max_hyst(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct f75375_data *data = f75375_update_device(dev); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max_hyst[nr])); +} + +static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct i2c_client *client = to_i2c_client(dev); + struct f75375_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + val = SENSORS_LIMIT(TEMP_TO_REG(val), 0, 127); + mutex_lock(&data->update_lock); + data->temp_high[nr] = val; + f75375_write8(client, F75375_REG_TEMP_HIGH(nr), data->temp_high[nr]); + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t set_temp_max_hyst(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct i2c_client *client = to_i2c_client(dev); + struct f75375_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + val = SENSORS_LIMIT(TEMP_TO_REG(val), 0, 127); + mutex_lock(&data->update_lock); + data->temp_max_hyst[nr] = val; + f75375_write8(client, F75375_REG_TEMP_HYST(nr), + data->temp_max_hyst[nr]); + mutex_unlock(&data->update_lock); + return count; +} + +#define show_fan(thing) \ +static ssize_t show_##thing(struct device *dev, struct device_attribute *attr, \ + char *buf)\ +{\ + int nr = to_sensor_dev_attr(attr)->index;\ + struct f75375_data *data = f75375_update_device(dev); \ + return sprintf(buf, "%d\n", rpm_from_reg(data->thing[nr])); \ +} + +show_fan(fan); +show_fan(fan_min); +show_fan(fan_full); +show_fan(fan_exp); + +static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_in, NULL, 0); +static SENSOR_DEVICE_ATTR(in0_max, S_IRUGO|S_IWUSR, + show_in_max, set_in_max, 0); +static SENSOR_DEVICE_ATTR(in0_min, S_IRUGO|S_IWUSR, + show_in_min, set_in_min, 0); +static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 1); +static SENSOR_DEVICE_ATTR(in1_max, S_IRUGO|S_IWUSR, + show_in_max, set_in_max, 1); +static SENSOR_DEVICE_ATTR(in1_min, S_IRUGO|S_IWUSR, + show_in_min, set_in_min, 1); +static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in, NULL, 2); +static SENSOR_DEVICE_ATTR(in2_max, S_IRUGO|S_IWUSR, + show_in_max, set_in_max, 2); +static SENSOR_DEVICE_ATTR(in2_min, S_IRUGO|S_IWUSR, + show_in_min, set_in_min, 2); +static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in, NULL, 3); +static SENSOR_DEVICE_ATTR(in3_max, S_IRUGO|S_IWUSR, + show_in_max, set_in_max, 3); +static SENSOR_DEVICE_ATTR(in3_min, S_IRUGO|S_IWUSR, + show_in_min, set_in_min, 3); +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); +static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO|S_IWUSR, + show_temp_max_hyst, set_temp_max_hyst, 0); +static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO|S_IWUSR, + show_temp_max, set_temp_max, 0); +static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); +static SENSOR_DEVICE_ATTR(temp2_max_hyst, S_IRUGO|S_IWUSR, + show_temp_max_hyst, set_temp_max_hyst, 1); +static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO|S_IWUSR, + show_temp_max, set_temp_max, 1); +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); +static SENSOR_DEVICE_ATTR(fan1_full, S_IRUGO, show_fan_full, NULL, 0); +static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO|S_IWUSR, + show_fan_min, set_fan_min, 0); +static SENSOR_DEVICE_ATTR(fan1_exp, S_IRUGO|S_IWUSR, + show_fan_exp, set_fan_exp, 0); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); +static SENSOR_DEVICE_ATTR(fan2_full, S_IRUGO, show_fan_full, NULL, 1); +static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO|S_IWUSR, + show_fan_min, set_fan_min, 1); +static SENSOR_DEVICE_ATTR(fan2_exp, S_IRUGO|S_IWUSR, + show_fan_exp, set_fan_exp, 1); +static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO|S_IWUSR, + show_pwm, set_pwm, 0); +static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO|S_IWUSR, + show_pwm_enable, set_pwm_enable, 0); +static SENSOR_DEVICE_ATTR(pwm1_mode, S_IRUGO|S_IWUSR, + show_pwm_mode, set_pwm_mode, 0); +static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, + show_pwm, set_pwm, 1); +static SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO|S_IWUSR, + show_pwm_enable, set_pwm_enable, 1); +static SENSOR_DEVICE_ATTR(pwm2_mode, S_IRUGO|S_IWUSR, + show_pwm_mode, set_pwm_mode, 1); + +static struct attribute *f75375_attributes[] = { + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp1_max.dev_attr.attr, + &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, + &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp2_max.dev_attr.attr, + &sensor_dev_attr_temp2_max_hyst.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan1_full.dev_attr.attr, + &sensor_dev_attr_fan1_min.dev_attr.attr, + &sensor_dev_attr_fan1_exp.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan2_full.dev_attr.attr, + &sensor_dev_attr_fan2_min.dev_attr.attr, + &sensor_dev_attr_fan2_exp.dev_attr.attr, + &sensor_dev_attr_pwm1.dev_attr.attr, + &sensor_dev_attr_pwm1_enable.dev_attr.attr, + &sensor_dev_attr_pwm1_mode.dev_attr.attr, + &sensor_dev_attr_pwm2.dev_attr.attr, + &sensor_dev_attr_pwm2_enable.dev_attr.attr, + &sensor_dev_attr_pwm2_mode.dev_attr.attr, + &sensor_dev_attr_in0_input.dev_attr.attr, + &sensor_dev_attr_in0_max.dev_attr.attr, + &sensor_dev_attr_in0_min.dev_attr.attr, + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_in1_max.dev_attr.attr, + &sensor_dev_attr_in1_min.dev_attr.attr, + &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_in2_max.dev_attr.attr, + &sensor_dev_attr_in2_min.dev_attr.attr, + &sensor_dev_attr_in3_input.dev_attr.attr, + &sensor_dev_attr_in3_max.dev_attr.attr, + &sensor_dev_attr_in3_min.dev_attr.attr, + NULL +}; + +static const struct attribute_group f75375_group = { + .attrs = f75375_attributes, +}; + +static int f75375_detach_client(struct i2c_client *client) +{ + struct f75375_data *data = i2c_get_clientdata(client); + int err; + + hwmon_device_unregister(data->class_dev); + sysfs_remove_group(&client->dev.kobj, &f75375_group); + + err = i2c_detach_client(client); + if (err) { + dev_err(&client->dev, + "Client deregistration failed, " + "client not detached.\n"); + return err; + } + kfree(data); + return 0; +} + +static int f75375_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, f75375_detect); +} + +/* This function is called by i2c_probe */ +static int f75375_detect(struct i2c_adapter *adapter, int address, int kind) +{ + struct i2c_client *client; + struct f75375_data *data; + u8 version = 0; + int err = 0; + const char *name = ""; + + if (!(data = kzalloc(sizeof(struct f75375_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &f75375_driver; + + if (kind < 0) { + u16 vendid = f75375_read16(client, F75375_REG_VENDOR); + u16 chipid = f75375_read16(client, F75375_CHIP_ID); + version = f75375_read8(client, F75375_REG_VERSION); + if (chipid == 0x0306 && vendid == 0x1934) { + kind = f75375; + } else if (chipid == 0x0204 && vendid == 0x1934) { + kind = f75373; + } else { + dev_err(&adapter->dev, + "failed,%02X,%02X,%02X\n", + chipid, version, vendid); + goto exit_free; + } + } + + if (kind == f75375) { + name = "f75375"; + } else if (kind == f75373) { + name = "f75373"; + } + + dev_info(&adapter->dev, "found %s version: %02X\n", name, version); + strlcpy(client->name, name, I2C_NAME_SIZE); + data->kind = kind; + mutex_init(&data->update_lock); + if ((err = i2c_attach_client(client))) + goto exit_free; + + if ((err = sysfs_create_group(&client->dev.kobj, &f75375_group))) + goto exit_detach; + + data->class_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->class_dev)) { + err = PTR_ERR(data->class_dev); + goto exit_remove; + } + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &f75375_group); +exit_detach: + i2c_detach_client(client); +exit_free: + kfree(data); +exit: + return err; +} + +static int __init sensors_f75375_init(void) +{ + return i2c_add_driver(&f75375_driver); +} + +static void __exit sensors_f75375_exit(void) +{ + i2c_del_driver(&f75375_driver); +} + +MODULE_AUTHOR("Riku Voipio "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("F75373/F75375 hardware monitoring driver"); + +module_init(sensors_f75375_init); +module_exit(sensors_f75375_exit); -- cgit v1.2.3 From 59a35bafb223bbb0553ba1a3bb9280bda668a8d8 Mon Sep 17 00:00:00 2001 From: Satyam Sharma Date: Thu, 23 Aug 2007 09:14:25 +0530 Subject: hwmon: (coretemp) Remove bogus __cpuinitdata etc cleanup The CPU hotplug notifier_block coretemp_cpu_notifier is already defined inside an #ifdef HOTPLUG_CPU, therefore marking it as __cpuinitdata is quite a pointless thing to do. Also, remove duplicate prototype of function coretemp_update_device() at the top of this file (another one already exists barely 10 lines above this one :-) Signed-off-by: Satyam Sharma Acked-by: Rudolf Marek Signed-off-by: Mark M. Hoffman --- drivers/hwmon/coretemp.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 7c1795225b0..f7b0ef41d9c 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -58,8 +58,6 @@ struct coretemp_data { u8 alarm; }; -static struct coretemp_data *coretemp_update_device(struct device *dev); - /* * Sysfs stuff */ @@ -350,7 +348,7 @@ static int coretemp_cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata coretemp_cpu_notifier = { +static struct notifier_block coretemp_cpu_notifier = { .notifier_call = coretemp_cpu_callback, }; #endif /* !CONFIG_HOTPLUG_CPU */ -- cgit v1.2.3 From 1beeffe43311f64df8dd0ab08ff6b1858c58363f Mon Sep 17 00:00:00 2001 From: Tony Jones Date: Mon, 20 Aug 2007 13:46:20 -0700 Subject: hwmon: Convert from class_device to device Convert from class_device to device for hwmon_device_register/unregister Signed-off-by: Tony Jones Signed-off-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers Signed-off-by: Mark M. Hoffman --- drivers/hwmon/abituguru.c | 10 +++++----- drivers/hwmon/abituguru3.c | 10 +++++----- drivers/hwmon/ad7418.c | 10 +++++----- drivers/hwmon/adm1021.c | 10 +++++----- drivers/hwmon/adm1025.c | 10 +++++----- drivers/hwmon/adm1026.c | 10 +++++----- drivers/hwmon/adm1029.c | 10 +++++----- drivers/hwmon/adm1031.c | 10 +++++----- drivers/hwmon/adm9240.c | 10 +++++----- drivers/hwmon/adt7470.c | 10 +++++----- drivers/hwmon/applesmc.c | 10 +++++----- drivers/hwmon/asb100.c | 10 +++++----- drivers/hwmon/atxp1.c | 10 +++++----- drivers/hwmon/coretemp.c | 10 +++++----- drivers/hwmon/dme1737.c | 10 +++++----- drivers/hwmon/ds1621.c | 10 +++++----- drivers/hwmon/f71805f.c | 10 +++++----- drivers/hwmon/f71882fg.c | 10 +++++----- drivers/hwmon/f75375s.c | 10 +++++----- drivers/hwmon/fscher.c | 10 +++++----- drivers/hwmon/fscpos.c | 10 +++++----- drivers/hwmon/gl518sm.c | 10 +++++----- drivers/hwmon/gl520sm.c | 10 +++++----- drivers/hwmon/hwmon.c | 27 +++++++++++++-------------- drivers/hwmon/it87.c | 10 +++++----- drivers/hwmon/k8temp.c | 10 +++++----- drivers/hwmon/lm63.c | 10 +++++----- drivers/hwmon/lm70.c | 12 ++++++------ drivers/hwmon/lm75.c | 10 +++++----- drivers/hwmon/lm77.c | 10 +++++----- drivers/hwmon/lm78.c | 18 +++++++++--------- drivers/hwmon/lm80.c | 10 +++++----- drivers/hwmon/lm83.c | 10 +++++----- drivers/hwmon/lm85.c | 10 +++++----- drivers/hwmon/lm87.c | 10 +++++----- drivers/hwmon/lm90.c | 10 +++++----- drivers/hwmon/lm92.c | 10 +++++----- drivers/hwmon/lm93.c | 10 +++++----- drivers/hwmon/max1619.c | 10 +++++----- drivers/hwmon/max6650.c | 10 +++++----- drivers/hwmon/pc87360.c | 10 +++++----- drivers/hwmon/pc87427.c | 10 +++++----- drivers/hwmon/sis5595.c | 10 +++++----- drivers/hwmon/smsc47b397.c | 10 +++++----- drivers/hwmon/smsc47m1.c | 10 +++++----- drivers/hwmon/smsc47m192.c | 10 +++++----- drivers/hwmon/thmc50.c | 10 +++++----- drivers/hwmon/via686a.c | 10 +++++----- drivers/hwmon/vt1211.c | 10 +++++----- drivers/hwmon/vt8231.c | 10 +++++----- drivers/hwmon/w83627ehf.c | 10 +++++----- drivers/hwmon/w83627hf.c | 10 +++++----- drivers/hwmon/w83781d.c | 18 +++++++++--------- drivers/hwmon/w83791d.c | 10 +++++----- drivers/hwmon/w83792d.c | 10 +++++----- drivers/hwmon/w83793.c | 10 +++++----- drivers/hwmon/w83l785ts.c | 10 +++++----- 57 files changed, 302 insertions(+), 303 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c index d575ee958de..719151a92fe 100644 --- a/drivers/hwmon/abituguru.c +++ b/drivers/hwmon/abituguru.c @@ -176,7 +176,7 @@ MODULE_PARM_DESC(verbose, "How verbose should the driver be? (0-3):\n" The structure is dynamically allocated, at the same time when a new abituguru device is allocated. */ struct abituguru_data { - struct class_device *class_dev; /* hwmon registered device */ + struct device *hwmon_dev; /* hwmon registered device */ struct mutex update_lock; /* protect access to data and uGuru */ unsigned long last_updated; /* In jiffies */ unsigned short addr; /* uguru base address */ @@ -1287,11 +1287,11 @@ static int __devinit abituguru_probe(struct platform_device *pdev) &abituguru_sysfs_attr[i].dev_attr)) goto abituguru_probe_error; - data->class_dev = hwmon_device_register(&pdev->dev); - if (!IS_ERR(data->class_dev)) + data->hwmon_dev = hwmon_device_register(&pdev->dev); + if (!IS_ERR(data->hwmon_dev)) return 0; /* success */ - res = PTR_ERR(data->class_dev); + res = PTR_ERR(data->hwmon_dev); abituguru_probe_error: for (i = 0; data->sysfs_attr[i].dev_attr.attr.name; i++) device_remove_file(&pdev->dev, &data->sysfs_attr[i].dev_attr); @@ -1308,7 +1308,7 @@ static int __devexit abituguru_remove(struct platform_device *pdev) int i; struct abituguru_data *data = platform_get_drvdata(pdev); - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); for (i = 0; data->sysfs_attr[i].dev_attr.attr.name; i++) device_remove_file(&pdev->dev, &data->sysfs_attr[i].dev_attr); for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++) diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c index cdd8b6dea16..cb2331bfd9d 100644 --- a/drivers/hwmon/abituguru3.c +++ b/drivers/hwmon/abituguru3.c @@ -124,7 +124,7 @@ struct abituguru3_motherboard_info { The structure is dynamically allocated, at the same time when a new abituguru3 device is allocated. */ struct abituguru3_data { - struct class_device *class_dev; /* hwmon registered device */ + struct device *hwmon_dev; /* hwmon registered device */ struct mutex update_lock; /* protect access to data and uGuru */ unsigned short addr; /* uguru base address */ char valid; /* !=0 if following fields are valid */ @@ -933,9 +933,9 @@ static int __devinit abituguru3_probe(struct platform_device *pdev) &abituguru3_sysfs_attr[i].dev_attr)) goto abituguru3_probe_error; - data->class_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(data->class_dev)) { - res = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(data->hwmon_dev)) { + res = PTR_ERR(data->hwmon_dev); goto abituguru3_probe_error; } @@ -957,7 +957,7 @@ static int __devexit abituguru3_remove(struct platform_device *pdev) struct abituguru3_data *data = platform_get_drvdata(pdev); platform_set_drvdata(pdev, NULL); - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); for (i = 0; data->sysfs_attr[i].dev_attr.attr.name; i++) device_remove_file(&pdev->dev, &data->sysfs_attr[i].dev_attr); for (i = 0; i < ARRAY_SIZE(abituguru3_sysfs_attr); i++) diff --git a/drivers/hwmon/ad7418.c b/drivers/hwmon/ad7418.c index 879ea72ee3b..fcd7fe78f3f 100644 --- a/drivers/hwmon/ad7418.c +++ b/drivers/hwmon/ad7418.c @@ -47,7 +47,7 @@ static const u8 AD7418_REG_TEMP[] = { AD7418_REG_TEMP_IN, struct ad7418_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; struct attribute_group attrs; enum chips type; struct mutex lock; @@ -326,9 +326,9 @@ static int ad7418_detect(struct i2c_adapter *adapter, int address, int kind) if ((err = sysfs_create_group(&client->dev.kobj, &data->attrs))) goto exit_detach; - data->class_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove; } @@ -347,7 +347,7 @@ exit: static int ad7418_detach_client(struct i2c_client *client) { struct ad7418_data *data = i2c_get_clientdata(client); - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &data->attrs); i2c_detach_client(client); kfree(data); diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c index 6649e068836..5667630ac05 100644 --- a/drivers/hwmon/adm1021.c +++ b/drivers/hwmon/adm1021.c @@ -91,7 +91,7 @@ clearing it. Weird, ey? --Phil */ /* Each client has this additional data */ struct adm1021_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; enum chips type; struct mutex update_lock; @@ -319,9 +319,9 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind) if ((err = sysfs_create_group(&client->dev.kobj, &adm1021_group))) goto error2; - data->class_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto error3; } @@ -351,7 +351,7 @@ static int adm1021_detach_client(struct i2c_client *client) struct adm1021_data *data = i2c_get_clientdata(client); int err; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &adm1021_group); if ((err = i2c_detach_client(client))) diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c index 8c562885b54..a67e133bfd3 100644 --- a/drivers/hwmon/adm1025.c +++ b/drivers/hwmon/adm1025.c @@ -133,7 +133,7 @@ static struct i2c_driver adm1025_driver = { struct adm1025_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -472,9 +472,9 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind) goto exit_remove; } - data->class_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&new_client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove; } @@ -538,7 +538,7 @@ static int adm1025_detach_client(struct i2c_client *client) struct adm1025_data *data = i2c_get_clientdata(client); int err; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &adm1025_group); sysfs_remove_group(&client->dev.kobj, &adm1025_group_opt); diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c index ba80cd3258c..b85370c7358 100644 --- a/drivers/hwmon/adm1026.c +++ b/drivers/hwmon/adm1026.c @@ -260,7 +260,7 @@ struct pwm_data { struct adm1026_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; enum chips type; struct mutex update_lock; @@ -1676,9 +1676,9 @@ static int adm1026_detect(struct i2c_adapter *adapter, int address, if ((err = sysfs_create_group(&new_client->dev.kobj, &adm1026_group))) goto exitdetach; - data->class_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&new_client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exitremove; } @@ -1698,7 +1698,7 @@ exit: static int adm1026_detach_client(struct i2c_client *client) { struct adm1026_data *data = i2c_get_clientdata(client); - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &adm1026_group); i2c_detach_client(client); kfree(data); diff --git a/drivers/hwmon/adm1029.c b/drivers/hwmon/adm1029.c index 73ce31b3151..0bc897dffa2 100644 --- a/drivers/hwmon/adm1029.c +++ b/drivers/hwmon/adm1029.c @@ -141,7 +141,7 @@ static struct i2c_driver adm1029_driver = { struct adm1029_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -391,9 +391,9 @@ static int adm1029_detect(struct i2c_adapter *adapter, int address, int kind) if ((err = sysfs_create_group(&client->dev.kobj, &adm1029_group))) goto exit_detach; - data->class_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove_files; } @@ -431,7 +431,7 @@ static int adm1029_detach_client(struct i2c_client *client) struct adm1029_data *data = i2c_get_clientdata(client); int err; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &adm1029_group); if ((err = i2c_detach_client(client))) diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c index 122683fc91d..37cfc101da5 100644 --- a/drivers/hwmon/adm1031.c +++ b/drivers/hwmon/adm1031.c @@ -70,7 +70,7 @@ typedef u8 auto_chan_table_t[8][2]; /* Each client has this additional data */ struct adm1031_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; int chip_type; char valid; /* !=0 if following fields are valid */ @@ -853,9 +853,9 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind) goto exit_remove; } - data->class_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&new_client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove; } @@ -877,7 +877,7 @@ static int adm1031_detach_client(struct i2c_client *client) struct adm1031_data *data = i2c_get_clientdata(client); int ret; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &adm1031_group); sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt); if ((ret = i2c_detach_client(client)) != 0) { diff --git a/drivers/hwmon/adm9240.c b/drivers/hwmon/adm9240.c index aad594adf0c..c17d0b6b328 100644 --- a/drivers/hwmon/adm9240.c +++ b/drivers/hwmon/adm9240.c @@ -150,7 +150,7 @@ static struct i2c_driver adm9240_driver = { struct adm9240_data { enum chips type; struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; char valid; unsigned long last_updated_measure; @@ -590,9 +590,9 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind) if ((err = sysfs_create_group(&new_client->dev.kobj, &adm9240_group))) goto exit_detach; - data->class_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&new_client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove; } @@ -620,7 +620,7 @@ static int adm9240_detach_client(struct i2c_client *client) struct adm9240_data *data = i2c_get_clientdata(client); int err; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &adm9240_group); if ((err = i2c_detach_client(client))) diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c index c4dc20546ec..9810aaa0489 100644 --- a/drivers/hwmon/adt7470.c +++ b/drivers/hwmon/adt7470.c @@ -124,7 +124,7 @@ I2C_CLIENT_INSMOD_1(adt7470); struct adt7470_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; struct attribute_group attrs; struct mutex lock; char sensors_valid; @@ -1003,9 +1003,9 @@ static int adt7470_detect(struct i2c_adapter *adapter, int address, int kind) if ((err = sysfs_create_group(&client->dev.kobj, &data->attrs))) goto exit_detach; - data->class_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove; } @@ -1025,7 +1025,7 @@ static int adt7470_detach_client(struct i2c_client *client) { struct adt7470_data *data = i2c_get_clientdata(client); - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &data->attrs); i2c_detach_client(client); kfree(data); diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index 941729a131f..21ff8e12688 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c @@ -127,7 +127,7 @@ static s16 rest_x; static s16 rest_y; static struct timer_list applesmc_timer; static struct input_dev *applesmc_idev; -static struct class_device *hwmon_class_dev; +static struct device *hwmon_dev; /* Indicates whether this computer has an accelerometer. */ static unsigned int applesmc_accelerometer; @@ -1287,9 +1287,9 @@ static int __init applesmc_init(void) goto out_light_wq; } - hwmon_class_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(hwmon_class_dev)) { - ret = PTR_ERR(hwmon_class_dev); + hwmon_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(hwmon_dev)) { + ret = PTR_ERR(hwmon_dev); goto out_light_ledclass; } @@ -1331,7 +1331,7 @@ out: static void __exit applesmc_exit(void) { - hwmon_device_unregister(hwmon_class_dev); + hwmon_device_unregister(hwmon_dev); if (applesmc_light) { led_classdev_unregister(&applesmc_backlight); destroy_workqueue(applesmc_led_wq); diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c index 55d92e1e27d..745bf264bcf 100644 --- a/drivers/hwmon/asb100.c +++ b/drivers/hwmon/asb100.c @@ -182,7 +182,7 @@ static u8 DIV_TO_REG(long val) dynamically allocated, at the same time the client itself is allocated. */ struct asb100_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex lock; enum chips type; @@ -844,9 +844,9 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind) if ((err = sysfs_create_group(&new_client->dev.kobj, &asb100_group))) goto ERROR3; - data->class_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&new_client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto ERROR4; } @@ -874,7 +874,7 @@ static int asb100_detach_client(struct i2c_client *client) /* main client */ if (data) { - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &asb100_group); } diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c index 0ccdd0750c4..cce3350e539 100644 --- a/drivers/hwmon/atxp1.c +++ b/drivers/hwmon/atxp1.c @@ -61,7 +61,7 @@ static struct i2c_driver atxp1_driver = { struct atxp1_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; unsigned long last_updated; u8 valid; @@ -335,9 +335,9 @@ static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind) if ((err = sysfs_create_group(&new_client->dev.kobj, &atxp1_group))) goto exit_detach; - data->class_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&new_client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove_files; } @@ -361,7 +361,7 @@ static int atxp1_detach_client(struct i2c_client * client) struct atxp1_data * data = i2c_get_clientdata(client); int err; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &atxp1_group); err = i2c_detach_client(client); diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index f7b0ef41d9c..1a0ff8d42bb 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -47,7 +47,7 @@ typedef enum { SHOW_TEMP, SHOW_TJMAX, SHOW_LABEL, SHOW_NAME } SHOW; static struct coretemp_data *coretemp_update_device(struct device *dev); struct coretemp_data { - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; const char *name; u32 id; @@ -226,9 +226,9 @@ static int __devinit coretemp_probe(struct platform_device *pdev) if ((err = sysfs_create_group(&pdev->dev.kobj, &coretemp_group))) goto exit_free; - data->class_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); dev_err(&pdev->dev, "Class registration failed (%d)\n", err); goto exit_class; @@ -248,7 +248,7 @@ static int __devexit coretemp_remove(struct platform_device *pdev) { struct coretemp_data *data = platform_get_drvdata(pdev); - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&pdev->dev.kobj, &coretemp_group); platform_set_drvdata(pdev, NULL); kfree(data); diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c index e9cbc727664..14ebbfb3b14 100644 --- a/drivers/hwmon/dme1737.c +++ b/drivers/hwmon/dme1737.c @@ -155,7 +155,7 @@ static const u8 DME1737_BIT_ALARM_FAN[] = {10, 11, 12, 13, 22, 23}; struct dme1737_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; int valid; /* !=0 if following fields are valid */ @@ -1983,9 +1983,9 @@ static int dme1737_detect(struct i2c_adapter *adapter, int address, } /* Register device */ - data->class_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove; } @@ -2030,7 +2030,7 @@ static int dme1737_detach_client(struct i2c_client *client) struct dme1737_data *data = i2c_get_clientdata(client); int ix, err; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); for (ix = 0; ix < ARRAY_SIZE(dme1737_fan_group); ix++) { if (data->has_fan & (1 << ix)) { diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c index 5a861f93612..b7bd000b130 100644 --- a/drivers/hwmon/ds1621.c +++ b/drivers/hwmon/ds1621.c @@ -73,7 +73,7 @@ static const u8 DS1621_REG_TEMP[3] = { /* Each client has this additional data */ struct ds1621_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -266,9 +266,9 @@ static int ds1621_detect(struct i2c_adapter *adapter, int address, if ((err = sysfs_create_group(&client->dev.kobj, &ds1621_group))) goto exit_detach; - data->class_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove_files; } @@ -289,7 +289,7 @@ static int ds1621_detach_client(struct i2c_client *client) struct ds1621_data *data = i2c_get_clientdata(client); int err; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &ds1621_group); if ((err = i2c_detach_client(client))) diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c index 1cd71a5be0e..5d9d5cc816a 100644 --- a/drivers/hwmon/f71805f.c +++ b/drivers/hwmon/f71805f.c @@ -162,7 +162,7 @@ struct f71805f_auto_point { struct f71805f_data { unsigned short addr; const char *name; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; char valid; /* !=0 if following fields are valid */ @@ -1381,9 +1381,9 @@ static int __devinit f71805f_probe(struct platform_device *pdev) } } - data->class_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); dev_err(&pdev->dev, "Class registration failed (%d)\n", err); goto exit_remove_files; } @@ -1410,7 +1410,7 @@ static int __devexit f71805f_remove(struct platform_device *pdev) struct resource *res; int i; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&pdev->dev.kobj, &f71805f_group); for (i = 0; i < 4; i++) sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_optin[i]); diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index b4ff0f9a6af..6db74434a02 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -87,7 +87,7 @@ static inline u16 fan_from_reg ( u16 reg ); struct f71882fg_data { unsigned short addr; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; char valid; /* !=0 if following fields are valid */ @@ -781,9 +781,9 @@ static int __devinit f71882fg_probe(struct platform_device * pdev) } } - data->class_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_unregister_sysfs; } @@ -811,7 +811,7 @@ static int __devexit f71882fg_remove(struct platform_device *pdev) struct f71882fg_data *data = platform_get_drvdata(pdev); platform_set_drvdata(pdev, NULL); - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); for (i = 0; i < ARRAY_SIZE(f71882fg_dev_attr); i++) device_remove_file(&pdev->dev, &f71882fg_dev_attr[i]); diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c index 6425184d931..13a041326a0 100644 --- a/drivers/hwmon/f75375s.c +++ b/drivers/hwmon/f75375s.c @@ -87,7 +87,7 @@ I2C_CLIENT_INSMOD_2(f75373, f75375); struct f75375_data { unsigned short addr; struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; const char *name; int kind; @@ -583,7 +583,7 @@ static int f75375_detach_client(struct i2c_client *client) struct f75375_data *data = i2c_get_clientdata(client); int err; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &f75375_group); err = i2c_detach_client(client); @@ -655,9 +655,9 @@ static int f75375_detect(struct i2c_adapter *adapter, int address, int kind) if ((err = sysfs_create_group(&client->dev.kobj, &f75375_group))) goto exit_detach; - data->class_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove; } diff --git a/drivers/hwmon/fscher.c b/drivers/hwmon/fscher.c index b34b546c68b..e67c36953b2 100644 --- a/drivers/hwmon/fscher.c +++ b/drivers/hwmon/fscher.c @@ -134,7 +134,7 @@ static struct i2c_driver fscher_driver = { struct fscher_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -344,9 +344,9 @@ static int fscher_detect(struct i2c_adapter *adapter, int address, int kind) if ((err = sysfs_create_group(&new_client->dev.kobj, &fscher_group))) goto exit_detach; - data->class_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&new_client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove_files; } @@ -367,7 +367,7 @@ static int fscher_detach_client(struct i2c_client *client) struct fscher_data *data = i2c_get_clientdata(client); int err; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &fscher_group); if ((err = i2c_detach_client(client))) diff --git a/drivers/hwmon/fscpos.c b/drivers/hwmon/fscpos.c index ea506a77f9c..92c9703d0ac 100644 --- a/drivers/hwmon/fscpos.c +++ b/drivers/hwmon/fscpos.c @@ -115,7 +115,7 @@ static struct i2c_driver fscpos_driver = { */ struct fscpos_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; char valid; /* 0 until following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -539,9 +539,9 @@ static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind) if ((err = sysfs_create_group(&new_client->dev.kobj, &fscpos_group))) goto exit_detach; - data->class_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&new_client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove_files; } @@ -562,7 +562,7 @@ static int fscpos_detach_client(struct i2c_client *client) struct fscpos_data *data = i2c_get_clientdata(client); int err; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &fscpos_group); if ((err = i2c_detach_client(client))) diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c index c103640455a..bb58d9866a3 100644 --- a/drivers/hwmon/gl518sm.c +++ b/drivers/hwmon/gl518sm.c @@ -119,7 +119,7 @@ static inline u8 FAN_TO_REG(long rpm, int div) /* Each client has this additional data */ struct gl518_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; enum chips type; struct mutex update_lock; @@ -460,9 +460,9 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind) if ((err = sysfs_create_group(&new_client->dev.kobj, &gl518_group))) goto exit_detach; - data->class_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&new_client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove_files; } @@ -502,7 +502,7 @@ static int gl518_detach_client(struct i2c_client *client) struct gl518_data *data = i2c_get_clientdata(client); int err; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &gl518_group); if ((err = i2c_detach_client(client))) diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c index ebe7b9aaa91..a3b56c816e1 100644 --- a/drivers/hwmon/gl520sm.c +++ b/drivers/hwmon/gl520sm.c @@ -122,7 +122,7 @@ static struct i2c_driver gl520_driver = { /* Client data */ struct gl520_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until the following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -622,9 +622,9 @@ static int gl520_detect(struct i2c_adapter *adapter, int address, int kind) } - data->class_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&new_client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove_files; } @@ -685,7 +685,7 @@ static int gl520_detach_client(struct i2c_client *client) struct gl520_data *data = i2c_get_clientdata(client); int err; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &gl520_group); sysfs_remove_group(&client->dev.kobj, &gl520_group_opt); diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c index affcc00764d..3db28450a3b 100644 --- a/drivers/hwmon/hwmon.c +++ b/drivers/hwmon/hwmon.c @@ -28,17 +28,17 @@ static DEFINE_IDR(hwmon_idr); static DEFINE_SPINLOCK(idr_lock); /** - * hwmon_device_register - register w/ hwmon sysfs class + * hwmon_device_register - register w/ hwmon * @dev: the device to register * - * hwmon_device_unregister() must be called when the class device is no + * hwmon_device_unregister() must be called when the device is no * longer needed. * - * Returns the pointer to the new struct class device. + * Returns the pointer to the new device. */ -struct class_device *hwmon_device_register(struct device *dev) +struct device *hwmon_device_register(struct device *dev) { - struct class_device *cdev; + struct device *hwdev; int id, err; again: @@ -55,34 +55,33 @@ again: return ERR_PTR(err); id = id & MAX_ID_MASK; - cdev = class_device_create(hwmon_class, NULL, MKDEV(0,0), dev, - HWMON_ID_FORMAT, id); + hwdev = device_create(hwmon_class, dev, MKDEV(0,0), HWMON_ID_FORMAT, id); - if (IS_ERR(cdev)) { + if (IS_ERR(hwdev)) { spin_lock(&idr_lock); idr_remove(&hwmon_idr, id); spin_unlock(&idr_lock); } - return cdev; + return hwdev; } /** * hwmon_device_unregister - removes the previously registered class device * - * @cdev: the class device to destroy + * @dev: the class device to destroy */ -void hwmon_device_unregister(struct class_device *cdev) +void hwmon_device_unregister(struct device *dev) { int id; - if (likely(sscanf(cdev->class_id, HWMON_ID_FORMAT, &id) == 1)) { - class_device_unregister(cdev); + if (likely(sscanf(dev->bus_id, HWMON_ID_FORMAT, &id) == 1)) { + device_unregister(dev); spin_lock(&idr_lock); idr_remove(&hwmon_idr, id); spin_unlock(&idr_lock); } else - dev_dbg(cdev->dev, + dev_dbg(dev->parent, "hwmon_device_unregister() failed: bad class ID!\n"); } diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index d75dba9b810..41a90e5613b 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -222,7 +222,7 @@ struct it87_sio_data { /* For each registered chip, we need to keep some data in memory. The structure is dynamically allocated. */ struct it87_data { - struct class_device *class_dev; + struct device *hwmon_dev; enum chips type; unsigned short addr; @@ -1089,9 +1089,9 @@ static int __devinit it87_probe(struct platform_device *pdev) goto ERROR4; } - data->class_dev = hwmon_device_register(dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto ERROR4; } @@ -1113,7 +1113,7 @@ static int __devexit it87_remove(struct platform_device *pdev) { struct it87_data *data = platform_get_drvdata(pdev); - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&pdev->dev.kobj, &it87_group); sysfs_remove_group(&pdev->dev.kobj, &it87_group_opt); diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c index 5d8d0ca08fa..bd2bde0ef95 100644 --- a/drivers/hwmon/k8temp.c +++ b/drivers/hwmon/k8temp.c @@ -38,7 +38,7 @@ #define SEL_CORE 0x04 struct k8temp_data { - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; const char *name; char valid; /* zero until following fields are valid */ @@ -225,10 +225,10 @@ static int __devinit k8temp_probe(struct pci_dev *pdev, if (err) goto exit_remove; - data->class_dev = hwmon_device_register(&pdev->dev); + data->hwmon_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove; } @@ -255,7 +255,7 @@ static void __devexit k8temp_remove(struct pci_dev *pdev) { struct k8temp_data *data = dev_get_drvdata(&pdev->dev); - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); device_remove_file(&pdev->dev, &sensor_dev_attr_temp1_input.dev_attr); device_remove_file(&pdev->dev, diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c index 2162d69a8c0..f207434730d 100644 --- a/drivers/hwmon/lm63.c +++ b/drivers/hwmon/lm63.c @@ -154,7 +154,7 @@ static struct i2c_driver lm63_driver = { struct lm63_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -502,9 +502,9 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind) goto exit_remove_files; } - data->class_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&new_client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove_files; } @@ -561,7 +561,7 @@ static int lm63_detach_client(struct i2c_client *client) struct lm63_data *data = i2c_get_clientdata(client); int err; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm63_group); sysfs_remove_group(&client->dev.kobj, &lm63_group_fan1); diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c index 30b9b2be87b..dd366889ce9 100644 --- a/drivers/hwmon/lm70.c +++ b/drivers/hwmon/lm70.c @@ -37,7 +37,7 @@ #define DRVNAME "lm70" struct lm70 { - struct class_device *cdev; + struct device *hwmon_dev; struct semaphore sem; }; @@ -115,10 +115,10 @@ static int __devinit lm70_probe(struct spi_device *spi) init_MUTEX(&p_lm70->sem); /* sysfs hook */ - p_lm70->cdev = hwmon_device_register(&spi->dev); - if (IS_ERR(p_lm70->cdev)) { + p_lm70->hwmon_dev = hwmon_device_register(&spi->dev); + if (IS_ERR(p_lm70->hwmon_dev)) { dev_dbg(&spi->dev, "hwmon_device_register failed.\n"); - status = PTR_ERR(p_lm70->cdev); + status = PTR_ERR(p_lm70->hwmon_dev); goto out_dev_reg_failed; } dev_set_drvdata(&spi->dev, p_lm70); @@ -133,7 +133,7 @@ static int __devinit lm70_probe(struct spi_device *spi) out_dev_create_file_failed: device_remove_file(&spi->dev, &dev_attr_temp1_input); - hwmon_device_unregister(p_lm70->cdev); + hwmon_device_unregister(p_lm70->hwmon_dev); out_dev_reg_failed: dev_set_drvdata(&spi->dev, NULL); kfree(p_lm70); @@ -146,7 +146,7 @@ static int __devexit lm70_remove(struct spi_device *spi) device_remove_file(&spi->dev, &dev_attr_temp1_input); device_remove_file(&spi->dev, &dev_attr_name); - hwmon_device_unregister(p_lm70->cdev); + hwmon_device_unregister(p_lm70->hwmon_dev); dev_set_drvdata(&spi->dev, NULL); kfree(p_lm70); diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c index 4fa32205e44..37a8cc032ff 100644 --- a/drivers/hwmon/lm75.c +++ b/drivers/hwmon/lm75.c @@ -50,7 +50,7 @@ static const u8 LM75_REG_TEMP[3] = { /* Each client has this additional data */ struct lm75_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -219,9 +219,9 @@ static int lm75_detect(struct i2c_adapter *adapter, int address, int kind) if ((err = sysfs_create_group(&new_client->dev.kobj, &lm75_group))) goto exit_detach; - data->class_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&new_client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove; } @@ -240,7 +240,7 @@ exit: static int lm75_detach_client(struct i2c_client *client) { struct lm75_data *data = i2c_get_clientdata(client); - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm75_group); i2c_detach_client(client); kfree(data); diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c index 46e3abad720..cee5c2e8cfa 100644 --- a/drivers/hwmon/lm77.c +++ b/drivers/hwmon/lm77.c @@ -51,7 +51,7 @@ I2C_CLIENT_INSMOD_1(lm77); /* Each client has this additional data */ struct lm77_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; char valid; unsigned long last_updated; /* In jiffies */ @@ -337,9 +337,9 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind) if ((err = sysfs_create_group(&new_client->dev.kobj, &lm77_group))) goto exit_detach; - data->class_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&new_client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove; } @@ -358,7 +358,7 @@ exit: static int lm77_detach_client(struct i2c_client *client) { struct lm77_data *data = i2c_get_clientdata(client); - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm77_group); i2c_detach_client(client); kfree(data); diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c index 6eea3476b90..f5278fda826 100644 --- a/drivers/hwmon/lm78.c +++ b/drivers/hwmon/lm78.c @@ -131,7 +131,7 @@ static inline int TEMP_FROM_REG(s8 val) the driver field to differentiate between I2C and ISA chips. */ struct lm78_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex lock; enum chips type; @@ -585,9 +585,9 @@ static int lm78_detect(struct i2c_adapter *adapter, int address, int kind) if ((err = sysfs_create_group(&new_client->dev.kobj, &lm78_group))) goto ERROR3; - data->class_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&new_client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto ERROR4; } @@ -608,7 +608,7 @@ static int lm78_detach_client(struct i2c_client *client) struct lm78_data *data = i2c_get_clientdata(client); int err; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm78_group); if ((err = i2c_detach_client(client))) @@ -659,9 +659,9 @@ static int __devinit lm78_isa_probe(struct platform_device *pdev) || (err = device_create_file(&pdev->dev, &dev_attr_name))) goto exit_remove_files; - data->class_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove_files; } @@ -681,7 +681,7 @@ static int __devexit lm78_isa_remove(struct platform_device *pdev) { struct lm78_data *data = platform_get_drvdata(pdev); - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&pdev->dev.kobj, &lm78_group); device_remove_file(&pdev->dev, &dev_attr_name); release_region(data->client.addr, LM78_EXTENT); diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c index 064516d824a..063cdba00a8 100644 --- a/drivers/hwmon/lm80.c +++ b/drivers/hwmon/lm80.c @@ -108,7 +108,7 @@ static inline long TEMP_FROM_REG(u16 temp) struct lm80_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -497,9 +497,9 @@ static int lm80_detect(struct i2c_adapter *adapter, int address, int kind) if ((err = sysfs_create_group(&new_client->dev.kobj, &lm80_group))) goto error_detach; - data->class_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&new_client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto error_remove; } @@ -520,7 +520,7 @@ static int lm80_detach_client(struct i2c_client *client) struct lm80_data *data = i2c_get_clientdata(client); int err; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm80_group); if ((err = i2c_detach_client(client))) return err; diff --git a/drivers/hwmon/lm83.c b/drivers/hwmon/lm83.c index 654c0f73464..0336b4572a6 100644 --- a/drivers/hwmon/lm83.c +++ b/drivers/hwmon/lm83.c @@ -144,7 +144,7 @@ static struct i2c_driver lm83_driver = { struct lm83_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -400,9 +400,9 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind) goto exit_remove_files; } - data->class_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&new_client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove_files; } @@ -424,7 +424,7 @@ static int lm83_detach_client(struct i2c_client *client) struct lm83_data *data = i2c_get_clientdata(client); int err; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm83_group); sysfs_remove_group(&client->dev.kobj, &lm83_group_opt); diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index 20a8c648280..954c364f38b 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c @@ -328,7 +328,7 @@ struct lm85_autofan { The structure is dynamically allocated. */ struct lm85_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; enum chips type; struct mutex update_lock; @@ -1257,9 +1257,9 @@ static int lm85_detect(struct i2c_adapter *adapter, int address, &dev_attr_in4_max))) goto ERROR3; - data->class_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&new_client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto ERROR3; } @@ -1280,7 +1280,7 @@ static int lm85_detect(struct i2c_adapter *adapter, int address, static int lm85_detach_client(struct i2c_client *client) { struct lm85_data *data = i2c_get_clientdata(client); - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm85_group); sysfs_remove_group(&client->dev.kobj, &lm85_group_opt); i2c_detach_client(client); diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c index 988ae1c4aad..e60076e8b59 100644 --- a/drivers/hwmon/lm87.c +++ b/drivers/hwmon/lm87.c @@ -176,7 +176,7 @@ static struct i2c_driver lm87_driver = { struct lm87_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -755,9 +755,9 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind) goto exit_remove; } - data->class_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&new_client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove; } @@ -816,7 +816,7 @@ static int lm87_detach_client(struct i2c_client *client) struct lm87_data *data = i2c_get_clientdata(client); int err; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm87_group); sysfs_remove_group(&client->dev.kobj, &lm87_group_opt); diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index af541d67245..98b53b119c2 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c @@ -214,7 +214,7 @@ static struct i2c_driver lm90_driver = { struct lm90_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -653,9 +653,9 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) goto exit_remove_files; } - data->class_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&new_client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove_files; } @@ -707,7 +707,7 @@ static int lm90_detach_client(struct i2c_client *client) struct lm90_data *data = i2c_get_clientdata(client); int err; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm90_group); device_remove_file(&client->dev, &dev_attr_pec); diff --git a/drivers/hwmon/lm92.c b/drivers/hwmon/lm92.c index 30b536333f1..61d1bd1d5b6 100644 --- a/drivers/hwmon/lm92.c +++ b/drivers/hwmon/lm92.c @@ -96,7 +96,7 @@ static struct i2c_driver lm92_driver; /* Client data (each client gets its own) */ struct lm92_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -379,9 +379,9 @@ static int lm92_detect(struct i2c_adapter *adapter, int address, int kind) if ((err = sysfs_create_group(&new_client->dev.kobj, &lm92_group))) goto exit_detach; - data->class_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&new_client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove; } @@ -409,7 +409,7 @@ static int lm92_detach_client(struct i2c_client *client) struct lm92_data *data = i2c_get_clientdata(client); int err; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm92_group); if ((err = i2c_detach_client(client))) diff --git a/drivers/hwmon/lm93.c b/drivers/hwmon/lm93.c index 86c6c6ea074..b9899b93c25 100644 --- a/drivers/hwmon/lm93.c +++ b/drivers/hwmon/lm93.c @@ -201,7 +201,7 @@ struct block1_t { */ struct lm93_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; unsigned long last_updated; /* In jiffies */ @@ -2590,11 +2590,11 @@ static int lm93_detect(struct i2c_adapter *adapter, int address, int kind) goto err_detach; /* Register hwmon driver class */ - data->class_dev = hwmon_device_register(&client->dev); - if ( !IS_ERR(data->class_dev)) + data->hwmon_dev = hwmon_device_register(&client->dev); + if ( !IS_ERR(data->hwmon_dev)) return 0; - err = PTR_ERR(data->class_dev); + err = PTR_ERR(data->hwmon_dev); dev_err(&client->dev, "error registering hwmon device.\n"); sysfs_remove_group(&client->dev.kobj, &lm93_attr_grp); err_detach: @@ -2619,7 +2619,7 @@ static int lm93_detach_client(struct i2c_client *client) struct lm93_data *data = i2c_get_clientdata(client); int err = 0; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm93_attr_grp); err = i2c_detach_client(client); diff --git a/drivers/hwmon/max1619.c b/drivers/hwmon/max1619.c index 2f58f651f03..38a44c3d6ce 100644 --- a/drivers/hwmon/max1619.c +++ b/drivers/hwmon/max1619.c @@ -105,7 +105,7 @@ static struct i2c_driver max1619_driver = { struct max1619_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -293,9 +293,9 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind) if ((err = sysfs_create_group(&new_client->dev.kobj, &max1619_group))) goto exit_detach; - data->class_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&new_client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove_files; } @@ -331,7 +331,7 @@ static int max1619_detach_client(struct i2c_client *client) struct max1619_data *data = i2c_get_clientdata(client); int err; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &max1619_group); if ((err = i2c_detach_client(client))) diff --git a/drivers/hwmon/max6650.c b/drivers/hwmon/max6650.c index 8415664f33c..755570c1f4e 100644 --- a/drivers/hwmon/max6650.c +++ b/drivers/hwmon/max6650.c @@ -128,7 +128,7 @@ static struct i2c_driver max6650_driver = { struct max6650_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -523,11 +523,11 @@ static int max6650_detect(struct i2c_adapter *adapter, int address, int kind) if (err) goto err_detach; - data->class_dev = hwmon_device_register(&client->dev); - if (!IS_ERR(data->class_dev)) + data->hwmon_dev = hwmon_device_register(&client->dev); + if (!IS_ERR(data->hwmon_dev)) return 0; - err = PTR_ERR(data->class_dev); + err = PTR_ERR(data->hwmon_dev); dev_err(&client->dev, "error registering hwmon device.\n"); sysfs_remove_group(&client->dev.kobj, &max6650_attr_grp); err_detach: @@ -543,7 +543,7 @@ static int max6650_detach_client(struct i2c_client *client) int err; sysfs_remove_group(&client->dev.kobj, &max6650_attr_grp); - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); err = i2c_detach_client(client); if (!err) kfree(data); diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c index f57c75d59a5..91cf51034b5 100644 --- a/drivers/hwmon/pc87360.c +++ b/drivers/hwmon/pc87360.c @@ -180,7 +180,7 @@ static inline u8 PWM_TO_REG(int val, int inv) struct pc87360_data { const char *name; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex lock; struct mutex update_lock; char valid; /* !=0 if following fields are valid */ @@ -1054,9 +1054,9 @@ static int __devinit pc87360_probe(struct platform_device *pdev) if ((err = device_create_file(dev, &dev_attr_name))) goto ERROR3; - data->class_dev = hwmon_device_register(dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto ERROR3; } return 0; @@ -1083,7 +1083,7 @@ static int __devexit pc87360_remove(struct platform_device *pdev) struct pc87360_data *data = platform_get_drvdata(pdev); int i; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); device_remove_file(&pdev->dev, &dev_attr_name); sysfs_remove_group(&pdev->dev.kobj, &pc8736x_temp_group); diff --git a/drivers/hwmon/pc87427.c b/drivers/hwmon/pc87427.c index 2915bc4ad0d..d40509ad6ae 100644 --- a/drivers/hwmon/pc87427.c +++ b/drivers/hwmon/pc87427.c @@ -42,7 +42,7 @@ static struct platform_device *pdev; device is using banked registers) and the register cache (needed to keep the data in the registers and the cache in sync at any time). */ struct pc87427_data { - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex lock; int address[2]; const char *name; @@ -454,9 +454,9 @@ static int __devinit pc87427_probe(struct platform_device *pdev) goto exit_remove_files; } - data->class_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); dev_err(&pdev->dev, "Class registration failed (%d)\n", err); goto exit_remove_files; } @@ -484,7 +484,7 @@ static int __devexit pc87427_remove(struct platform_device *pdev) struct resource *res; int i; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); device_remove_file(&pdev->dev, &dev_attr_name); for (i = 0; i < 8; i++) { if (!(data->fan_enabled & (1 << i))) diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c index 92956eb3f3c..3de9721aa67 100644 --- a/drivers/hwmon/sis5595.c +++ b/drivers/hwmon/sis5595.c @@ -163,7 +163,7 @@ static inline u8 DIV_TO_REG(int val) struct sis5595_data { unsigned short addr; const char *name; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex lock; struct mutex update_lock; @@ -557,9 +557,9 @@ static int __devinit sis5595_probe(struct platform_device *pdev) goto exit_remove_files; } - data->class_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove_files; } @@ -580,7 +580,7 @@ static int __devexit sis5595_remove(struct platform_device *pdev) { struct sis5595_data *data = platform_get_drvdata(pdev); - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&pdev->dev.kobj, &sis5595_group); sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_opt); diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c index 45266b30ce1..0b57d2ea2cf 100644 --- a/drivers/hwmon/smsc47b397.c +++ b/drivers/hwmon/smsc47b397.c @@ -94,7 +94,7 @@ static u8 smsc47b397_reg_temp[] = {0x25, 0x26, 0x27, 0x80}; struct smsc47b397_data { unsigned short addr; const char *name; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex lock; struct mutex update_lock; @@ -222,7 +222,7 @@ static int __devexit smsc47b397_remove(struct platform_device *pdev) struct smsc47b397_data *data = platform_get_drvdata(pdev); struct resource *res; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&pdev->dev.kobj, &smsc47b397_group); res = platform_get_resource(pdev, IORESOURCE_IO, 0); release_region(res->start, SMSC_EXTENT); @@ -272,9 +272,9 @@ static int __devinit smsc47b397_probe(struct platform_device *pdev) if ((err = sysfs_create_group(&dev->kobj, &smsc47b397_group))) goto error_free; - data->class_dev = hwmon_device_register(dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto error_remove; } diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c index 71792778d6f..a10a380868e 100644 --- a/drivers/hwmon/smsc47m1.c +++ b/drivers/hwmon/smsc47m1.c @@ -116,7 +116,7 @@ struct smsc47m1_data { unsigned short addr; const char *name; enum chips type; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; unsigned long last_updated; /* In jiffies */ @@ -588,9 +588,9 @@ static int __devinit smsc47m1_probe(struct platform_device *pdev) if ((err = device_create_file(dev, &dev_attr_name))) goto error_remove_files; - data->class_dev = hwmon_device_register(dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto error_remove_files; } @@ -611,7 +611,7 @@ static int __devexit smsc47m1_remove(struct platform_device *pdev) struct smsc47m1_data *data = platform_get_drvdata(pdev); struct resource *res; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&pdev->dev.kobj, &smsc47m1_group); res = platform_get_resource(pdev, IORESOURCE_IO, 0); diff --git a/drivers/hwmon/smsc47m192.c b/drivers/hwmon/smsc47m192.c index d3a3ba04cb0..0efcd27b252 100644 --- a/drivers/hwmon/smsc47m192.c +++ b/drivers/hwmon/smsc47m192.c @@ -97,7 +97,7 @@ static inline int TEMP_FROM_REG(s8 val) struct smsc47m192_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -553,9 +553,9 @@ static int smsc47m192_detect(struct i2c_adapter *adapter, int address, goto exit_remove_files; } - data->class_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove_files; } @@ -577,7 +577,7 @@ static int smsc47m192_detach_client(struct i2c_client *client) struct smsc47m192_data *data = i2c_get_clientdata(client); int err; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &smsc47m192_group); sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4); diff --git a/drivers/hwmon/thmc50.c b/drivers/hwmon/thmc50.c index c920f394a5c..981d1f1dc61 100644 --- a/drivers/hwmon/thmc50.c +++ b/drivers/hwmon/thmc50.c @@ -61,7 +61,7 @@ const static u8 THMC50_REG_TEMP_MAX[] = { 0x39, 0x37, 0x2B }; /* Each client has this additional data */ struct thmc50_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; enum chips type; @@ -351,9 +351,9 @@ static int thmc50_detect(struct i2c_adapter *adapter, int address, int kind) goto exit_remove_sysfs_thmc50; /* Register a new directory entry with module sensors */ - data->class_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove_sysfs; } @@ -384,7 +384,7 @@ static int thmc50_detach_client(struct i2c_client *client) struct thmc50_data *data = i2c_get_clientdata(client); int err; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &thmc50_group); if (data->type == adm1022) sysfs_remove_group(&client->dev.kobj, &adm1022_group); diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c index 696c8a2e537..8f63dada601 100644 --- a/drivers/hwmon/via686a.c +++ b/drivers/hwmon/via686a.c @@ -294,7 +294,7 @@ static inline long TEMP_FROM_REG10(u16 val) struct via686a_data { unsigned short addr; const char *name; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -627,9 +627,9 @@ static int __devinit via686a_probe(struct platform_device *pdev) if ((err = sysfs_create_group(&pdev->dev.kobj, &via686a_group))) goto exit_free; - data->class_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove_files; } @@ -648,7 +648,7 @@ static int __devexit via686a_remove(struct platform_device *pdev) { struct via686a_data *data = platform_get_drvdata(pdev); - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&pdev->dev.kobj, &via686a_group); release_region(data->addr, VIA686A_EXTENT); diff --git a/drivers/hwmon/vt1211.c b/drivers/hwmon/vt1211.c index 9f3e332c5b7..e69416465e6 100644 --- a/drivers/hwmon/vt1211.c +++ b/drivers/hwmon/vt1211.c @@ -108,7 +108,7 @@ static const u8 bitalarmfan[] = {6, 7}; struct vt1211_data { unsigned short addr; const char *name; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; char valid; /* !=0 if following fields are valid */ @@ -1191,9 +1191,9 @@ static int __devinit vt1211_probe(struct platform_device *pdev) } /* Register device */ - data->class_dev = hwmon_device_register(dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); dev_err(dev, "Class registration failed (%d)\n", err); goto EXIT_DEV_REMOVE_SILENT; } @@ -1217,7 +1217,7 @@ static int __devexit vt1211_remove(struct platform_device *pdev) struct vt1211_data *data = platform_get_drvdata(pdev); struct resource *res; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); vt1211_remove_sysfs(pdev); platform_set_drvdata(pdev, NULL); kfree(data); diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c index 3e63eaf1904..8806302b5f3 100644 --- a/drivers/hwmon/vt8231.c +++ b/drivers/hwmon/vt8231.c @@ -148,7 +148,7 @@ struct vt8231_data { const char *name; struct mutex update_lock; - struct class_device *class_dev; + struct device *hwmon_dev; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -726,9 +726,9 @@ int vt8231_probe(struct platform_device *pdev) } } - data->class_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove_files; } return 0; @@ -756,7 +756,7 @@ static int __devexit vt8231_remove(struct platform_device *pdev) struct vt8231_data *data = platform_get_drvdata(pdev); int i; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); for (i = 0; i < ARRAY_SIZE(vt8231_group_volts); i++) sysfs_remove_group(&pdev->dev.kobj, &vt8231_group_volts[i]); diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index e3dfc52b599..b15c6a998b7 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c @@ -256,7 +256,7 @@ struct w83627ehf_data { int addr; /* IO base of hw monitor block */ const char *name; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex lock; struct mutex update_lock; @@ -1384,9 +1384,9 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev) goto exit_remove; } - data->class_dev = hwmon_device_register(dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove; } @@ -1406,7 +1406,7 @@ static int __devexit w83627ehf_remove(struct platform_device *pdev) { struct w83627ehf_data *data = platform_get_drvdata(pdev); - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); w83627ehf_device_remove_files(&pdev->dev); release_region(data->addr, IOREGION_LENGTH); platform_set_drvdata(pdev, NULL); diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index f0e0e208be9..b1943ec29c4 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -346,7 +346,7 @@ static inline u8 DIV_TO_REG(long val) struct w83627hf_data { unsigned short addr; const char *name; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex lock; enum chips type; @@ -1295,9 +1295,9 @@ static int __devinit w83627hf_probe(struct platform_device *pdev) || (err = device_create_file(dev, &dev_attr_pwm3_freq))) goto ERROR4; - data->class_dev = hwmon_device_register(dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto ERROR4; } @@ -1320,7 +1320,7 @@ static int __devexit w83627hf_remove(struct platform_device *pdev) struct w83627hf_data *data = platform_get_drvdata(pdev); struct resource *res; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group); sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group_opt); diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index c12bdf9d9e1..e622ec5b092 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c @@ -220,7 +220,7 @@ DIV_TO_REG(long val, enum chips type) the driver field to differentiate between I2C and ISA chips. */ struct w83781d_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex lock; enum chips type; @@ -1158,9 +1158,9 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) if (err) goto ERROR4; - data->class_dev = hwmon_device_register(dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto ERROR4; } @@ -1194,7 +1194,7 @@ w83781d_detach_client(struct i2c_client *client) /* main client */ if (data) { - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &w83781d_group); sysfs_remove_group(&client->dev.kobj, &w83781d_group_opt); } @@ -1261,9 +1261,9 @@ w83781d_isa_probe(struct platform_device *pdev) if (err) goto exit_remove_files; - data->class_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove_files; } @@ -1285,7 +1285,7 @@ w83781d_isa_remove(struct platform_device *pdev) { struct w83781d_data *data = platform_get_drvdata(pdev); - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&pdev->dev.kobj, &w83781d_group); sysfs_remove_group(&pdev->dev.kobj, &w83781d_group_opt); device_remove_file(&pdev->dev, &dev_attr_name); diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c index 9e5f885368b..a3cb89455ea 100644 --- a/drivers/hwmon/w83791d.c +++ b/drivers/hwmon/w83791d.c @@ -247,7 +247,7 @@ static u8 div_to_reg(int nr, long val) struct w83791d_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; char valid; /* !=0 if following fields are valid */ @@ -1017,9 +1017,9 @@ static int w83791d_detect(struct i2c_adapter *adapter, int address, int kind) goto error3; /* Everything is ready, now register the working device */ - data->class_dev = hwmon_device_register(dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto error4; } @@ -1051,7 +1051,7 @@ static int w83791d_detach_client(struct i2c_client *client) /* main client */ if (data) { - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &w83791d_group); } diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c index f6dee380062..f836198b705 100644 --- a/drivers/hwmon/w83792d.c +++ b/drivers/hwmon/w83792d.c @@ -267,7 +267,7 @@ DIV_TO_REG(long val) struct w83792d_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; enum chips type; struct mutex update_lock; @@ -1443,9 +1443,9 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind) &w83792d_group_fan[3]))) goto exit_remove_files; - data->class_dev = hwmon_device_register(dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove_files; } @@ -1480,7 +1480,7 @@ w83792d_detach_client(struct i2c_client *client) /* main client */ if (data) { - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &w83792d_group); for (i = 0; i < ARRAY_SIZE(w83792d_group_fan); i++) sysfs_remove_group(&client->dev.kobj, diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c index 253ffaf1568..48599e1cc55 100644 --- a/drivers/hwmon/w83793.c +++ b/drivers/hwmon/w83793.c @@ -179,7 +179,7 @@ static inline s8 TEMP_TO_REG(long val, s8 min, s8 max) struct w83793_data { struct i2c_client client; struct i2c_client *lm75[2]; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -1075,7 +1075,7 @@ static int w83793_detach_client(struct i2c_client *client) /* main client */ if (data) { - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++) device_remove_file(dev, @@ -1434,9 +1434,9 @@ static int w83793_detect(struct i2c_adapter *adapter, int address, int kind) } } - data->class_dev = hwmon_device_register(dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove; } diff --git a/drivers/hwmon/w83l785ts.c b/drivers/hwmon/w83l785ts.c index a3fcace412f..b5db354e2f1 100644 --- a/drivers/hwmon/w83l785ts.c +++ b/drivers/hwmon/w83l785ts.c @@ -107,7 +107,7 @@ static struct i2c_driver w83l785ts_driver = { struct w83l785ts_data { struct i2c_client client; - struct class_device *class_dev; + struct device *hwmon_dev; struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -247,9 +247,9 @@ static int w83l785ts_detect(struct i2c_adapter *adapter, int address, int kind) goto exit_remove; /* Register sysfs hooks */ - data->class_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); + data->hwmon_dev = hwmon_device_register(&new_client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); goto exit_remove; } @@ -272,7 +272,7 @@ static int w83l785ts_detach_client(struct i2c_client *client) struct w83l785ts_data *data = i2c_get_clientdata(client); int err; - hwmon_device_unregister(data->class_dev); + hwmon_device_unregister(data->hwmon_dev); device_remove_file(&client->dev, &sensor_dev_attr_temp1_input.dev_attr); device_remove_file(&client->dev, -- cgit v1.2.3 From b353a487b9d835da331edb443afedfd7977b3d76 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 5 Jul 2007 20:36:12 +0200 Subject: hwmon: (lm85) Use dynamic sysfs callbacks This lets us get rid of macro-generated functions and shrinks the driver size by about 10%. I used a new style suggested by Mark M. Hoffman to retrieve the channel number. Instead of: struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); int nr = sda->index; I do: int nr = to_sensor_dev_attr(attr)->index; This looks better, and even allows the compiler to do some minor optimizations. Signed-off-by: Jean Delvare Acked-by: Krzysztof Helt Signed-off-by: Mark M. Hoffman --- drivers/hwmon/lm85.c | 551 +++++++++++++++++++++++---------------------------- 1 file changed, 244 insertions(+), 307 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index 954c364f38b..111c2c80010 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -387,19 +388,26 @@ static struct i2c_driver lm85_driver = { /* 4 Fans */ -static ssize_t show_fan(struct device *dev, char *buf, int nr) +static ssize_t show_fan(struct device *dev, struct device_attribute *attr, + char *buf) { + int nr = to_sensor_dev_attr(attr)->index; struct lm85_data *data = lm85_update_device(dev); return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan[nr]) ); } -static ssize_t show_fan_min(struct device *dev, char *buf, int nr) + +static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr, + char *buf) { + int nr = to_sensor_dev_attr(attr)->index; struct lm85_data *data = lm85_update_device(dev); return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan_min[nr]) ); } -static ssize_t set_fan_min(struct device *dev, const char *buf, - size_t count, int nr) + +static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { + int nr = to_sensor_dev_attr(attr)->index; struct i2c_client *client = to_i2c_client(dev); struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); @@ -412,23 +420,10 @@ static ssize_t set_fan_min(struct device *dev, const char *buf, } #define show_fan_offset(offset) \ -static ssize_t show_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_fan(dev, buf, offset - 1); \ -} \ -static ssize_t show_fan_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_fan_min(dev, buf, offset - 1); \ -} \ -static ssize_t set_fan_##offset##_min (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_fan_min(dev, buf, count, offset - 1); \ -} \ -static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, \ - NULL); \ -static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ - show_fan_##offset##_min, set_fan_##offset##_min); +static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ + show_fan, NULL, offset - 1); \ +static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ + show_fan_min, set_fan_min, offset - 1) show_fan_offset(1); show_fan_offset(2); @@ -484,14 +479,18 @@ static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); /* pwm */ -static ssize_t show_pwm(struct device *dev, char *buf, int nr) +static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, + char *buf) { + int nr = to_sensor_dev_attr(attr)->index; struct lm85_data *data = lm85_update_device(dev); return sprintf(buf,"%d\n", PWM_FROM_REG(data->pwm[nr]) ); } -static ssize_t set_pwm(struct device *dev, const char *buf, - size_t count, int nr) + +static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { + int nr = to_sensor_dev_attr(attr)->index; struct i2c_client *client = to_i2c_client(dev); struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); @@ -502,8 +501,11 @@ static ssize_t set_pwm(struct device *dev, const char *buf, mutex_unlock(&data->update_lock); return count; } -static ssize_t show_pwm_enable(struct device *dev, char *buf, int nr) + +static ssize_t show_pwm_enable(struct device *dev, struct device_attribute + *attr, char *buf) { + int nr = to_sensor_dev_attr(attr)->index; struct lm85_data *data = lm85_update_device(dev); int pwm_zone; @@ -512,23 +514,10 @@ static ssize_t show_pwm_enable(struct device *dev, char *buf, int nr) } #define show_pwm_reg(offset) \ -static ssize_t show_pwm_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_pwm(dev, buf, offset - 1); \ -} \ -static ssize_t set_pwm_##offset (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_pwm(dev, buf, count, offset - 1); \ -} \ -static ssize_t show_pwm_enable##offset (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_pwm_enable(dev, buf, offset - 1); \ -} \ -static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ - show_pwm_##offset, set_pwm_##offset); \ -static DEVICE_ATTR(pwm##offset##_enable, S_IRUGO, \ - show_pwm_enable##offset, NULL); +static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ + show_pwm, set_pwm, offset - 1); \ +static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO, \ + show_pwm_enable, NULL, offset - 1) show_pwm_reg(1); show_pwm_reg(2); @@ -536,22 +525,29 @@ show_pwm_reg(3); /* Voltages */ -static ssize_t show_in(struct device *dev, char *buf, int nr) +static ssize_t show_in(struct device *dev, struct device_attribute *attr, + char *buf) { + int nr = to_sensor_dev_attr(attr)->index; struct lm85_data *data = lm85_update_device(dev); return sprintf( buf, "%d\n", INSEXT_FROM_REG(nr, data->in[nr], data->in_ext[nr], data->adc_scale) ); } -static ssize_t show_in_min(struct device *dev, char *buf, int nr) + +static ssize_t show_in_min(struct device *dev, struct device_attribute *attr, + char *buf) { + int nr = to_sensor_dev_attr(attr)->index; struct lm85_data *data = lm85_update_device(dev); return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in_min[nr]) ); } -static ssize_t set_in_min(struct device *dev, const char *buf, - size_t count, int nr) + +static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { + int nr = to_sensor_dev_attr(attr)->index; struct i2c_client *client = to_i2c_client(dev); struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); @@ -562,14 +558,19 @@ static ssize_t set_in_min(struct device *dev, const char *buf, mutex_unlock(&data->update_lock); return count; } -static ssize_t show_in_max(struct device *dev, char *buf, int nr) + +static ssize_t show_in_max(struct device *dev, struct device_attribute *attr, + char *buf) { + int nr = to_sensor_dev_attr(attr)->index; struct lm85_data *data = lm85_update_device(dev); return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in_max[nr]) ); } -static ssize_t set_in_max(struct device *dev, const char *buf, - size_t count, int nr) + +static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { + int nr = to_sensor_dev_attr(attr)->index; struct i2c_client *client = to_i2c_client(dev); struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); @@ -580,35 +581,14 @@ static ssize_t set_in_max(struct device *dev, const char *buf, mutex_unlock(&data->update_lock); return count; } + #define show_in_reg(offset) \ -static ssize_t show_in_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_in(dev, buf, offset); \ -} \ -static ssize_t show_in_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_in_min(dev, buf, offset); \ -} \ -static ssize_t show_in_##offset##_max (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_in_max(dev, buf, offset); \ -} \ -static ssize_t set_in_##offset##_min (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_in_min(dev, buf, count, offset); \ -} \ -static ssize_t set_in_##offset##_max (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_in_max(dev, buf, count, offset); \ -} \ -static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in_##offset, \ - NULL); \ -static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ - show_in_##offset##_min, set_in_##offset##_min); \ -static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ - show_in_##offset##_max, set_in_##offset##_max); +static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ + show_in, NULL, offset); \ +static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ + show_in_min, set_in_min, offset); \ +static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ + show_in_max, set_in_max, offset) show_in_reg(0); show_in_reg(1); @@ -618,21 +598,28 @@ show_in_reg(4); /* Temps */ -static ssize_t show_temp(struct device *dev, char *buf, int nr) +static ssize_t show_temp(struct device *dev, struct device_attribute *attr, + char *buf) { + int nr = to_sensor_dev_attr(attr)->index; struct lm85_data *data = lm85_update_device(dev); return sprintf(buf,"%d\n", TEMPEXT_FROM_REG(data->temp[nr], data->temp_ext[nr], data->adc_scale) ); } -static ssize_t show_temp_min(struct device *dev, char *buf, int nr) + +static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr, + char *buf) { + int nr = to_sensor_dev_attr(attr)->index; struct lm85_data *data = lm85_update_device(dev); return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_min[nr]) ); } -static ssize_t set_temp_min(struct device *dev, const char *buf, - size_t count, int nr) + +static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { + int nr = to_sensor_dev_attr(attr)->index; struct i2c_client *client = to_i2c_client(dev); struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); @@ -643,14 +630,19 @@ static ssize_t set_temp_min(struct device *dev, const char *buf, mutex_unlock(&data->update_lock); return count; } -static ssize_t show_temp_max(struct device *dev, char *buf, int nr) + +static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr, + char *buf) { + int nr = to_sensor_dev_attr(attr)->index; struct lm85_data *data = lm85_update_device(dev); return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_max[nr]) ); } -static ssize_t set_temp_max(struct device *dev, const char *buf, - size_t count, int nr) + +static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { + int nr = to_sensor_dev_attr(attr)->index; struct i2c_client *client = to_i2c_client(dev); struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); @@ -661,35 +653,14 @@ static ssize_t set_temp_max(struct device *dev, const char *buf, mutex_unlock(&data->update_lock); return count; } + #define show_temp_reg(offset) \ -static ssize_t show_temp_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_temp(dev, buf, offset - 1); \ -} \ -static ssize_t show_temp_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_temp_min(dev, buf, offset - 1); \ -} \ -static ssize_t show_temp_##offset##_max (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_temp_max(dev, buf, offset - 1); \ -} \ -static ssize_t set_temp_##offset##_min (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_temp_min(dev, buf, count, offset - 1); \ -} \ -static ssize_t set_temp_##offset##_max (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_temp_max(dev, buf, count, offset - 1); \ -} \ -static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, \ - NULL); \ -static DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \ - show_temp_##offset##_min, set_temp_##offset##_min); \ -static DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ - show_temp_##offset##_max, set_temp_##offset##_max); +static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ + show_temp, NULL, offset - 1); \ +static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \ + show_temp_min, set_temp_min, offset - 1); \ +static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ + show_temp_max, set_temp_max, offset - 1); show_temp_reg(1); show_temp_reg(2); @@ -698,14 +669,18 @@ show_temp_reg(3); /* Automatic PWM control */ -static ssize_t show_pwm_auto_channels(struct device *dev, char *buf, int nr) +static ssize_t show_pwm_auto_channels(struct device *dev, + struct device_attribute *attr, char *buf) { + int nr = to_sensor_dev_attr(attr)->index; struct lm85_data *data = lm85_update_device(dev); return sprintf(buf,"%d\n", ZONE_FROM_REG(data->autofan[nr].config)); } -static ssize_t set_pwm_auto_channels(struct device *dev, const char *buf, - size_t count, int nr) + +static ssize_t set_pwm_auto_channels(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { + int nr = to_sensor_dev_attr(attr)->index; struct i2c_client *client = to_i2c_client(dev); struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); @@ -718,14 +693,19 @@ static ssize_t set_pwm_auto_channels(struct device *dev, const char *buf, mutex_unlock(&data->update_lock); return count; } -static ssize_t show_pwm_auto_pwm_min(struct device *dev, char *buf, int nr) + +static ssize_t show_pwm_auto_pwm_min(struct device *dev, + struct device_attribute *attr, char *buf) { + int nr = to_sensor_dev_attr(attr)->index; struct lm85_data *data = lm85_update_device(dev); return sprintf(buf,"%d\n", PWM_FROM_REG(data->autofan[nr].min_pwm)); } -static ssize_t set_pwm_auto_pwm_min(struct device *dev, const char *buf, - size_t count, int nr) + +static ssize_t set_pwm_auto_pwm_min(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { + int nr = to_sensor_dev_attr(attr)->index; struct i2c_client *client = to_i2c_client(dev); struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); @@ -737,14 +717,19 @@ static ssize_t set_pwm_auto_pwm_min(struct device *dev, const char *buf, mutex_unlock(&data->update_lock); return count; } -static ssize_t show_pwm_auto_pwm_minctl(struct device *dev, char *buf, int nr) + +static ssize_t show_pwm_auto_pwm_minctl(struct device *dev, + struct device_attribute *attr, char *buf) { + int nr = to_sensor_dev_attr(attr)->index; struct lm85_data *data = lm85_update_device(dev); return sprintf(buf,"%d\n", data->autofan[nr].min_off); } -static ssize_t set_pwm_auto_pwm_minctl(struct device *dev, const char *buf, - size_t count, int nr) + +static ssize_t set_pwm_auto_pwm_minctl(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { + int nr = to_sensor_dev_attr(attr)->index; struct i2c_client *client = to_i2c_client(dev); struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); @@ -760,14 +745,19 @@ static ssize_t set_pwm_auto_pwm_minctl(struct device *dev, const char *buf, mutex_unlock(&data->update_lock); return count; } -static ssize_t show_pwm_auto_pwm_freq(struct device *dev, char *buf, int nr) + +static ssize_t show_pwm_auto_pwm_freq(struct device *dev, + struct device_attribute *attr, char *buf) { + int nr = to_sensor_dev_attr(attr)->index; struct lm85_data *data = lm85_update_device(dev); return sprintf(buf,"%d\n", FREQ_FROM_REG(data->autofan[nr].freq)); } -static ssize_t set_pwm_auto_pwm_freq(struct device *dev, const char *buf, - size_t count, int nr) + +static ssize_t set_pwm_auto_pwm_freq(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { + int nr = to_sensor_dev_attr(attr)->index; struct i2c_client *client = to_i2c_client(dev); struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); @@ -781,74 +771,40 @@ static ssize_t set_pwm_auto_pwm_freq(struct device *dev, const char *buf, mutex_unlock(&data->update_lock); return count; } + #define pwm_auto(offset) \ -static ssize_t show_pwm##offset##_auto_channels (struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - return show_pwm_auto_channels(dev, buf, offset - 1); \ -} \ -static ssize_t set_pwm##offset##_auto_channels (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_pwm_auto_channels(dev, buf, count, offset - 1); \ -} \ -static ssize_t show_pwm##offset##_auto_pwm_min (struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - return show_pwm_auto_pwm_min(dev, buf, offset - 1); \ -} \ -static ssize_t set_pwm##offset##_auto_pwm_min (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_pwm_auto_pwm_min(dev, buf, count, offset - 1); \ -} \ -static ssize_t show_pwm##offset##_auto_pwm_minctl (struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - return show_pwm_auto_pwm_minctl(dev, buf, offset - 1); \ -} \ -static ssize_t set_pwm##offset##_auto_pwm_minctl (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_pwm_auto_pwm_minctl(dev, buf, count, offset - 1); \ -} \ -static ssize_t show_pwm##offset##_auto_pwm_freq (struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - return show_pwm_auto_pwm_freq(dev, buf, offset - 1); \ -} \ -static ssize_t set_pwm##offset##_auto_pwm_freq(struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_pwm_auto_pwm_freq(dev, buf, count, offset - 1); \ -} \ -static DEVICE_ATTR(pwm##offset##_auto_channels, S_IRUGO | S_IWUSR, \ - show_pwm##offset##_auto_channels, \ - set_pwm##offset##_auto_channels); \ -static DEVICE_ATTR(pwm##offset##_auto_pwm_min, S_IRUGO | S_IWUSR, \ - show_pwm##offset##_auto_pwm_min, \ - set_pwm##offset##_auto_pwm_min); \ -static DEVICE_ATTR(pwm##offset##_auto_pwm_minctl, S_IRUGO | S_IWUSR, \ - show_pwm##offset##_auto_pwm_minctl, \ - set_pwm##offset##_auto_pwm_minctl); \ -static DEVICE_ATTR(pwm##offset##_auto_pwm_freq, S_IRUGO | S_IWUSR, \ - show_pwm##offset##_auto_pwm_freq, \ - set_pwm##offset##_auto_pwm_freq); +static SENSOR_DEVICE_ATTR(pwm##offset##_auto_channels, \ + S_IRUGO | S_IWUSR, show_pwm_auto_channels, \ + set_pwm_auto_channels, offset - 1); \ +static SENSOR_DEVICE_ATTR(pwm##offset##_auto_pwm_min, \ + S_IRUGO | S_IWUSR, show_pwm_auto_pwm_min, \ + set_pwm_auto_pwm_min, offset - 1); \ +static SENSOR_DEVICE_ATTR(pwm##offset##_auto_pwm_minctl, \ + S_IRUGO | S_IWUSR, show_pwm_auto_pwm_minctl, \ + set_pwm_auto_pwm_minctl, offset - 1); \ +static SENSOR_DEVICE_ATTR(pwm##offset##_auto_pwm_freq, \ + S_IRUGO | S_IWUSR, show_pwm_auto_pwm_freq, \ + set_pwm_auto_pwm_freq, offset - 1); + pwm_auto(1); pwm_auto(2); pwm_auto(3); /* Temperature settings for automatic PWM control */ -static ssize_t show_temp_auto_temp_off(struct device *dev, char *buf, int nr) +static ssize_t show_temp_auto_temp_off(struct device *dev, + struct device_attribute *attr, char *buf) { + int nr = to_sensor_dev_attr(attr)->index; struct lm85_data *data = lm85_update_device(dev); return sprintf(buf,"%d\n", TEMP_FROM_REG(data->zone[nr].limit) - HYST_FROM_REG(data->zone[nr].hyst)); } -static ssize_t set_temp_auto_temp_off(struct device *dev, const char *buf, - size_t count, int nr) + +static ssize_t set_temp_auto_temp_off(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { + int nr = to_sensor_dev_attr(attr)->index; struct i2c_client *client = to_i2c_client(dev); struct lm85_data *data = i2c_get_clientdata(client); int min; @@ -871,14 +827,19 @@ static ssize_t set_temp_auto_temp_off(struct device *dev, const char *buf, mutex_unlock(&data->update_lock); return count; } -static ssize_t show_temp_auto_temp_min(struct device *dev, char *buf, int nr) + +static ssize_t show_temp_auto_temp_min(struct device *dev, + struct device_attribute *attr, char *buf) { + int nr = to_sensor_dev_attr(attr)->index; struct lm85_data *data = lm85_update_device(dev); return sprintf(buf,"%d\n", TEMP_FROM_REG(data->zone[nr].limit) ); } -static ssize_t set_temp_auto_temp_min(struct device *dev, const char *buf, - size_t count, int nr) + +static ssize_t set_temp_auto_temp_min(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { + int nr = to_sensor_dev_attr(attr)->index; struct i2c_client *client = to_i2c_client(dev); struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); @@ -913,15 +874,20 @@ static ssize_t set_temp_auto_temp_min(struct device *dev, const char *buf, mutex_unlock(&data->update_lock); return count; } -static ssize_t show_temp_auto_temp_max(struct device *dev, char *buf, int nr) + +static ssize_t show_temp_auto_temp_max(struct device *dev, + struct device_attribute *attr, char *buf) { + int nr = to_sensor_dev_attr(attr)->index; struct lm85_data *data = lm85_update_device(dev); return sprintf(buf,"%d\n", TEMP_FROM_REG(data->zone[nr].limit) + RANGE_FROM_REG(data->zone[nr].range)); } -static ssize_t set_temp_auto_temp_max(struct device *dev, const char *buf, - size_t count, int nr) + +static ssize_t set_temp_auto_temp_max(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { + int nr = to_sensor_dev_attr(attr)->index; struct i2c_client *client = to_i2c_client(dev); struct lm85_data *data = i2c_get_clientdata(client); int min; @@ -938,14 +904,19 @@ static ssize_t set_temp_auto_temp_max(struct device *dev, const char *buf, mutex_unlock(&data->update_lock); return count; } -static ssize_t show_temp_auto_temp_crit(struct device *dev, char *buf, int nr) + +static ssize_t show_temp_auto_temp_crit(struct device *dev, + struct device_attribute *attr, char *buf) { + int nr = to_sensor_dev_attr(attr)->index; struct lm85_data *data = lm85_update_device(dev); return sprintf(buf,"%d\n", TEMP_FROM_REG(data->zone[nr].critical)); } -static ssize_t set_temp_auto_temp_crit(struct device *dev, const char *buf, - size_t count, int nr) + +static ssize_t set_temp_auto_temp_crit(struct device *dev, + struct device_attribute *attr,const char *buf, size_t count) { + int nr = to_sensor_dev_attr(attr)->index; struct i2c_client *client = to_i2c_client(dev); struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); @@ -957,59 +928,21 @@ static ssize_t set_temp_auto_temp_crit(struct device *dev, const char *buf, mutex_unlock(&data->update_lock); return count; } + #define temp_auto(offset) \ -static ssize_t show_temp##offset##_auto_temp_off (struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - return show_temp_auto_temp_off(dev, buf, offset - 1); \ -} \ -static ssize_t set_temp##offset##_auto_temp_off (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_temp_auto_temp_off(dev, buf, count, offset - 1); \ -} \ -static ssize_t show_temp##offset##_auto_temp_min (struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - return show_temp_auto_temp_min(dev, buf, offset - 1); \ -} \ -static ssize_t set_temp##offset##_auto_temp_min (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_temp_auto_temp_min(dev, buf, count, offset - 1); \ -} \ -static ssize_t show_temp##offset##_auto_temp_max (struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - return show_temp_auto_temp_max(dev, buf, offset - 1); \ -} \ -static ssize_t set_temp##offset##_auto_temp_max (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_temp_auto_temp_max(dev, buf, count, offset - 1); \ -} \ -static ssize_t show_temp##offset##_auto_temp_crit (struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - return show_temp_auto_temp_crit(dev, buf, offset - 1); \ -} \ -static ssize_t set_temp##offset##_auto_temp_crit (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return set_temp_auto_temp_crit(dev, buf, count, offset - 1); \ -} \ -static DEVICE_ATTR(temp##offset##_auto_temp_off, S_IRUGO | S_IWUSR, \ - show_temp##offset##_auto_temp_off, \ - set_temp##offset##_auto_temp_off); \ -static DEVICE_ATTR(temp##offset##_auto_temp_min, S_IRUGO | S_IWUSR, \ - show_temp##offset##_auto_temp_min, \ - set_temp##offset##_auto_temp_min); \ -static DEVICE_ATTR(temp##offset##_auto_temp_max, S_IRUGO | S_IWUSR, \ - show_temp##offset##_auto_temp_max, \ - set_temp##offset##_auto_temp_max); \ -static DEVICE_ATTR(temp##offset##_auto_temp_crit, S_IRUGO | S_IWUSR, \ - show_temp##offset##_auto_temp_crit, \ - set_temp##offset##_auto_temp_crit); +static SENSOR_DEVICE_ATTR(temp##offset##_auto_temp_off, \ + S_IRUGO | S_IWUSR, show_temp_auto_temp_off, \ + set_temp_auto_temp_off, offset - 1); \ +static SENSOR_DEVICE_ATTR(temp##offset##_auto_temp_min, \ + S_IRUGO | S_IWUSR, show_temp_auto_temp_min, \ + set_temp_auto_temp_min, offset - 1); \ +static SENSOR_DEVICE_ATTR(temp##offset##_auto_temp_max, \ + S_IRUGO | S_IWUSR, show_temp_auto_temp_max, \ + set_temp_auto_temp_max, offset - 1); \ +static SENSOR_DEVICE_ATTR(temp##offset##_auto_temp_crit, \ + S_IRUGO | S_IWUSR, show_temp_auto_temp_crit, \ + set_temp_auto_temp_crit, offset - 1); + temp_auto(1); temp_auto(2); temp_auto(3); @@ -1022,69 +955,74 @@ static int lm85_attach_adapter(struct i2c_adapter *adapter) } static struct attribute *lm85_attributes[] = { - &dev_attr_fan1_input.attr, - &dev_attr_fan2_input.attr, - &dev_attr_fan3_input.attr, - &dev_attr_fan4_input.attr, - &dev_attr_fan1_min.attr, - &dev_attr_fan2_min.attr, - &dev_attr_fan3_min.attr, - &dev_attr_fan4_min.attr, - &dev_attr_pwm1.attr, - &dev_attr_pwm2.attr, - &dev_attr_pwm3.attr, - &dev_attr_pwm1_enable.attr, - &dev_attr_pwm2_enable.attr, - &dev_attr_pwm3_enable.attr, - &dev_attr_in0_input.attr, - &dev_attr_in1_input.attr, - &dev_attr_in2_input.attr, - &dev_attr_in3_input.attr, - &dev_attr_in0_min.attr, - &dev_attr_in1_min.attr, - &dev_attr_in2_min.attr, - &dev_attr_in3_min.attr, - &dev_attr_in0_max.attr, - &dev_attr_in1_max.attr, - &dev_attr_in2_max.attr, - &dev_attr_in3_max.attr, - &dev_attr_temp1_input.attr, - &dev_attr_temp2_input.attr, - &dev_attr_temp3_input.attr, - &dev_attr_temp1_min.attr, - &dev_attr_temp2_min.attr, - &dev_attr_temp3_min.attr, - &dev_attr_temp1_max.attr, - &dev_attr_temp2_max.attr, - &dev_attr_temp3_max.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan3_input.dev_attr.attr, + &sensor_dev_attr_fan4_input.dev_attr.attr, + &sensor_dev_attr_fan1_min.dev_attr.attr, + &sensor_dev_attr_fan2_min.dev_attr.attr, + &sensor_dev_attr_fan3_min.dev_attr.attr, + &sensor_dev_attr_fan4_min.dev_attr.attr, + + &sensor_dev_attr_pwm1.dev_attr.attr, + &sensor_dev_attr_pwm2.dev_attr.attr, + &sensor_dev_attr_pwm3.dev_attr.attr, + &sensor_dev_attr_pwm1_enable.dev_attr.attr, + &sensor_dev_attr_pwm2_enable.dev_attr.attr, + &sensor_dev_attr_pwm3_enable.dev_attr.attr, + + &sensor_dev_attr_in0_input.dev_attr.attr, + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_in3_input.dev_attr.attr, + &sensor_dev_attr_in0_min.dev_attr.attr, + &sensor_dev_attr_in1_min.dev_attr.attr, + &sensor_dev_attr_in2_min.dev_attr.attr, + &sensor_dev_attr_in3_min.dev_attr.attr, + &sensor_dev_attr_in0_max.dev_attr.attr, + &sensor_dev_attr_in1_max.dev_attr.attr, + &sensor_dev_attr_in2_max.dev_attr.attr, + &sensor_dev_attr_in3_max.dev_attr.attr, + + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp3_input.dev_attr.attr, + &sensor_dev_attr_temp1_min.dev_attr.attr, + &sensor_dev_attr_temp2_min.dev_attr.attr, + &sensor_dev_attr_temp3_min.dev_attr.attr, + &sensor_dev_attr_temp1_max.dev_attr.attr, + &sensor_dev_attr_temp2_max.dev_attr.attr, + &sensor_dev_attr_temp3_max.dev_attr.attr, + + &sensor_dev_attr_pwm1_auto_channels.dev_attr.attr, + &sensor_dev_attr_pwm2_auto_channels.dev_attr.attr, + &sensor_dev_attr_pwm3_auto_channels.dev_attr.attr, + &sensor_dev_attr_pwm1_auto_pwm_min.dev_attr.attr, + &sensor_dev_attr_pwm2_auto_pwm_min.dev_attr.attr, + &sensor_dev_attr_pwm3_auto_pwm_min.dev_attr.attr, + &sensor_dev_attr_pwm1_auto_pwm_minctl.dev_attr.attr, + &sensor_dev_attr_pwm2_auto_pwm_minctl.dev_attr.attr, + &sensor_dev_attr_pwm3_auto_pwm_minctl.dev_attr.attr, + &sensor_dev_attr_pwm1_auto_pwm_freq.dev_attr.attr, + &sensor_dev_attr_pwm2_auto_pwm_freq.dev_attr.attr, + &sensor_dev_attr_pwm3_auto_pwm_freq.dev_attr.attr, + + &sensor_dev_attr_temp1_auto_temp_off.dev_attr.attr, + &sensor_dev_attr_temp2_auto_temp_off.dev_attr.attr, + &sensor_dev_attr_temp3_auto_temp_off.dev_attr.attr, + &sensor_dev_attr_temp1_auto_temp_min.dev_attr.attr, + &sensor_dev_attr_temp2_auto_temp_min.dev_attr.attr, + &sensor_dev_attr_temp3_auto_temp_min.dev_attr.attr, + &sensor_dev_attr_temp1_auto_temp_max.dev_attr.attr, + &sensor_dev_attr_temp2_auto_temp_max.dev_attr.attr, + &sensor_dev_attr_temp3_auto_temp_max.dev_attr.attr, + &sensor_dev_attr_temp1_auto_temp_crit.dev_attr.attr, + &sensor_dev_attr_temp2_auto_temp_crit.dev_attr.attr, + &sensor_dev_attr_temp3_auto_temp_crit.dev_attr.attr, + &dev_attr_vrm.attr, &dev_attr_cpu0_vid.attr, &dev_attr_alarms.attr, - &dev_attr_pwm1_auto_channels.attr, - &dev_attr_pwm2_auto_channels.attr, - &dev_attr_pwm3_auto_channels.attr, - &dev_attr_pwm1_auto_pwm_min.attr, - &dev_attr_pwm2_auto_pwm_min.attr, - &dev_attr_pwm3_auto_pwm_min.attr, - &dev_attr_pwm1_auto_pwm_minctl.attr, - &dev_attr_pwm2_auto_pwm_minctl.attr, - &dev_attr_pwm3_auto_pwm_minctl.attr, - &dev_attr_pwm1_auto_pwm_freq.attr, - &dev_attr_pwm2_auto_pwm_freq.attr, - &dev_attr_pwm3_auto_pwm_freq.attr, - &dev_attr_temp1_auto_temp_off.attr, - &dev_attr_temp2_auto_temp_off.attr, - &dev_attr_temp3_auto_temp_off.attr, - &dev_attr_temp1_auto_temp_min.attr, - &dev_attr_temp2_auto_temp_min.attr, - &dev_attr_temp3_auto_temp_min.attr, - &dev_attr_temp1_auto_temp_max.attr, - &dev_attr_temp2_auto_temp_max.attr, - &dev_attr_temp3_auto_temp_max.attr, - &dev_attr_temp1_auto_temp_crit.attr, - &dev_attr_temp2_auto_temp_crit.attr, - &dev_attr_temp3_auto_temp_crit.attr, - NULL }; @@ -1093,10 +1031,9 @@ static const struct attribute_group lm85_group = { }; static struct attribute *lm85_attributes_opt[] = { - &dev_attr_in4_input.attr, - &dev_attr_in4_min.attr, - &dev_attr_in4_max.attr, - + &sensor_dev_attr_in4_input.dev_attr.attr, + &sensor_dev_attr_in4_min.dev_attr.attr, + &sensor_dev_attr_in4_max.dev_attr.attr, NULL }; @@ -1250,11 +1187,11 @@ static int lm85_detect(struct i2c_adapter *adapter, int address, data->vid = lm85_read_value(new_client, LM85_REG_VID); if (!(kind == adt7463 && (data->vid & 0x80))) if ((err = device_create_file(&new_client->dev, - &dev_attr_in4_input)) + &sensor_dev_attr_in4_input.dev_attr)) || (err = device_create_file(&new_client->dev, - &dev_attr_in4_min)) + &sensor_dev_attr_in4_min.dev_attr)) || (err = device_create_file(&new_client->dev, - &dev_attr_in4_max))) + &sensor_dev_attr_in4_max.dev_attr))) goto ERROR3; data->hwmon_dev = hwmon_device_register(&new_client->dev); -- cgit v1.2.3 From 6b9aad2d8acf309f99213875dd94f2ec691fe820 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 5 Jul 2007 20:37:21 +0200 Subject: hwmon: (lm85) Export in5, in6 and in7 voltage channels The SMSC EMC6D100 supports 3 additional voltage channels. The lm85 driver reads the register values for these, but doesn't create the corresponding sysfs files, so the user can't read the values nor write the limits. Create the missing sysfs files. Signed-off-by: Jean Delvare Acked-by: Juerg Haefliger Signed-off-by: Mark M. Hoffman --- drivers/hwmon/lm85.c | 48 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 11 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index 111c2c80010..6229e7d488c 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c @@ -595,6 +595,9 @@ show_in_reg(1); show_in_reg(2); show_in_reg(3); show_in_reg(4); +show_in_reg(5); +show_in_reg(6); +show_in_reg(7); /* Temps */ @@ -1030,15 +1033,32 @@ static const struct attribute_group lm85_group = { .attrs = lm85_attributes, }; -static struct attribute *lm85_attributes_opt[] = { +static struct attribute *lm85_attributes_in4[] = { &sensor_dev_attr_in4_input.dev_attr.attr, &sensor_dev_attr_in4_min.dev_attr.attr, &sensor_dev_attr_in4_max.dev_attr.attr, NULL }; -static const struct attribute_group lm85_group_opt = { - .attrs = lm85_attributes_opt, +static const struct attribute_group lm85_group_in4 = { + .attrs = lm85_attributes_in4, +}; + +static struct attribute *lm85_attributes_in567[] = { + &sensor_dev_attr_in5_input.dev_attr.attr, + &sensor_dev_attr_in6_input.dev_attr.attr, + &sensor_dev_attr_in7_input.dev_attr.attr, + &sensor_dev_attr_in5_min.dev_attr.attr, + &sensor_dev_attr_in6_min.dev_attr.attr, + &sensor_dev_attr_in7_min.dev_attr.attr, + &sensor_dev_attr_in5_max.dev_attr.attr, + &sensor_dev_attr_in6_max.dev_attr.attr, + &sensor_dev_attr_in7_max.dev_attr.attr, + NULL +}; + +static const struct attribute_group lm85_group_in567 = { + .attrs = lm85_attributes_in567, }; static int lm85_detect(struct i2c_adapter *adapter, int address, @@ -1186,12 +1206,14 @@ static int lm85_detect(struct i2c_adapter *adapter, int address, as a sixth digital VID input rather than an analog input. */ data->vid = lm85_read_value(new_client, LM85_REG_VID); if (!(kind == adt7463 && (data->vid & 0x80))) - if ((err = device_create_file(&new_client->dev, - &sensor_dev_attr_in4_input.dev_attr)) - || (err = device_create_file(&new_client->dev, - &sensor_dev_attr_in4_min.dev_attr)) - || (err = device_create_file(&new_client->dev, - &sensor_dev_attr_in4_max.dev_attr))) + if ((err = sysfs_create_group(&new_client->dev.kobj, + &lm85_group_in4))) + goto ERROR3; + + /* The EMC6D100 has 3 additional voltage inputs */ + if (kind == emc6d100) + if ((err = sysfs_create_group(&new_client->dev.kobj, + &lm85_group_in567))) goto ERROR3; data->hwmon_dev = hwmon_device_register(&new_client->dev); @@ -1205,7 +1227,9 @@ static int lm85_detect(struct i2c_adapter *adapter, int address, /* Error out and cleanup code */ ERROR3: sysfs_remove_group(&new_client->dev.kobj, &lm85_group); - sysfs_remove_group(&new_client->dev.kobj, &lm85_group_opt); + sysfs_remove_group(&new_client->dev.kobj, &lm85_group_in4); + if (kind == emc6d100) + sysfs_remove_group(&new_client->dev.kobj, &lm85_group_in567); ERROR2: i2c_detach_client(new_client); ERROR1: @@ -1219,7 +1243,9 @@ static int lm85_detach_client(struct i2c_client *client) struct lm85_data *data = i2c_get_clientdata(client); hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm85_group); - sysfs_remove_group(&client->dev.kobj, &lm85_group_opt); + sysfs_remove_group(&client->dev.kobj, &lm85_group_in4); + if (data->type == emc6d100) + sysfs_remove_group(&client->dev.kobj, &lm85_group_in567); i2c_detach_client(client); kfree(data); return 0; -- cgit v1.2.3 From bf76e9d3c42fae879feabe26a10bf8ebf27ab328 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 5 Jul 2007 20:37:58 +0200 Subject: hwmon: (lm85) Add individual alarm files The future libsensors needs these individual alarm and fault files. Also delete old and unused alarm defines. Signed-off-by: Jean Delvare Acked-by: Juerg Haefliger Signed-off-by: Mark M. Hoffman --- drivers/hwmon/lm85.c | 60 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 17 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index 6229e7d488c..3b70815ab98 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c @@ -123,23 +123,6 @@ I2C_CLIENT_INSMOD_6(lm85b, lm85c, adm1027, adt7463, emc6d100, emc6d102); #define EMC6D102_REG_EXTEND_ADC3 0x87 #define EMC6D102_REG_EXTEND_ADC4 0x88 -#define LM85_ALARM_IN0 0x0001 -#define LM85_ALARM_IN1 0x0002 -#define LM85_ALARM_IN2 0x0004 -#define LM85_ALARM_IN3 0x0008 -#define LM85_ALARM_TEMP1 0x0010 -#define LM85_ALARM_TEMP2 0x0020 -#define LM85_ALARM_TEMP3 0x0040 -#define LM85_ALARM_ALARM2 0x0080 -#define LM85_ALARM_IN4 0x0100 -#define LM85_ALARM_RESERVED 0x0200 -#define LM85_ALARM_FAN1 0x0400 -#define LM85_ALARM_FAN2 0x0800 -#define LM85_ALARM_FAN3 0x1000 -#define LM85_ALARM_FAN4 0x2000 -#define LM85_ALARM_TEMP1_FAULT 0x4000 -#define LM85_ALARM_TEMP3_FAULT 0x8000 - /* Conversions. Rounding and limit checking is only done on the TO_REG variants. Note that you should be a bit careful with which arguments @@ -477,6 +460,32 @@ static ssize_t show_alarms_reg(struct device *dev, struct device_attribute *attr static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); +static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int nr = to_sensor_dev_attr(attr)->index; + struct lm85_data *data = lm85_update_device(dev); + return sprintf(buf, "%u\n", (data->alarms >> nr) & 1); +} + +static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0); +static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2); +static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3); +static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8); +static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 18); +static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 16); +static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 17); +static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4); +static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_alarm, NULL, 14); +static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5); +static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 6); +static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 15); +static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 10); +static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 11); +static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 12); +static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 13); + /* pwm */ static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, @@ -966,6 +975,10 @@ static struct attribute *lm85_attributes[] = { &sensor_dev_attr_fan2_min.dev_attr.attr, &sensor_dev_attr_fan3_min.dev_attr.attr, &sensor_dev_attr_fan4_min.dev_attr.attr, + &sensor_dev_attr_fan1_alarm.dev_attr.attr, + &sensor_dev_attr_fan2_alarm.dev_attr.attr, + &sensor_dev_attr_fan3_alarm.dev_attr.attr, + &sensor_dev_attr_fan4_alarm.dev_attr.attr, &sensor_dev_attr_pwm1.dev_attr.attr, &sensor_dev_attr_pwm2.dev_attr.attr, @@ -986,6 +999,10 @@ static struct attribute *lm85_attributes[] = { &sensor_dev_attr_in1_max.dev_attr.attr, &sensor_dev_attr_in2_max.dev_attr.attr, &sensor_dev_attr_in3_max.dev_attr.attr, + &sensor_dev_attr_in0_alarm.dev_attr.attr, + &sensor_dev_attr_in1_alarm.dev_attr.attr, + &sensor_dev_attr_in2_alarm.dev_attr.attr, + &sensor_dev_attr_in3_alarm.dev_attr.attr, &sensor_dev_attr_temp1_input.dev_attr.attr, &sensor_dev_attr_temp2_input.dev_attr.attr, @@ -996,6 +1013,11 @@ static struct attribute *lm85_attributes[] = { &sensor_dev_attr_temp1_max.dev_attr.attr, &sensor_dev_attr_temp2_max.dev_attr.attr, &sensor_dev_attr_temp3_max.dev_attr.attr, + &sensor_dev_attr_temp1_alarm.dev_attr.attr, + &sensor_dev_attr_temp2_alarm.dev_attr.attr, + &sensor_dev_attr_temp3_alarm.dev_attr.attr, + &sensor_dev_attr_temp1_fault.dev_attr.attr, + &sensor_dev_attr_temp3_fault.dev_attr.attr, &sensor_dev_attr_pwm1_auto_channels.dev_attr.attr, &sensor_dev_attr_pwm2_auto_channels.dev_attr.attr, @@ -1037,6 +1059,7 @@ static struct attribute *lm85_attributes_in4[] = { &sensor_dev_attr_in4_input.dev_attr.attr, &sensor_dev_attr_in4_min.dev_attr.attr, &sensor_dev_attr_in4_max.dev_attr.attr, + &sensor_dev_attr_in4_alarm.dev_attr.attr, NULL }; @@ -1054,6 +1077,9 @@ static struct attribute *lm85_attributes_in567[] = { &sensor_dev_attr_in5_max.dev_attr.attr, &sensor_dev_attr_in6_max.dev_attr.attr, &sensor_dev_attr_in7_max.dev_attr.attr, + &sensor_dev_attr_in5_alarm.dev_attr.attr, + &sensor_dev_attr_in6_alarm.dev_attr.attr, + &sensor_dev_attr_in7_alarm.dev_attr.attr, NULL }; -- cgit v1.2.3 From 5a4d3ef317c845893fe3f9d3517cb0a99375da53 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 5 Jul 2007 20:38:32 +0200 Subject: hwmon: (lm85) Clean up the handling of additional resolution bits The way the lm85 driver currently handles the additional resolution bits some chips have for the voltage and temperature measurements is quite complex. This is my attempt to make it simpler. Signed-off-by: Jean Delvare Acked-by: Juerg Haefliger Signed-off-by: Mark M. Hoffman --- drivers/hwmon/lm85.c | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index 3b70815ab98..0c61fa36c83 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c @@ -139,10 +139,10 @@ static int lm85_scaling[] = { /* .001 Volts */ #define INS_TO_REG(n,val) \ SENSORS_LIMIT(SCALE(val,lm85_scaling[n],192),0,255) -#define INSEXT_FROM_REG(n,val,ext,scale) \ - SCALE((val)*(scale) + (ext),192*(scale),lm85_scaling[n]) +#define INSEXT_FROM_REG(n,val,ext) \ + SCALE(((val) << 4) + (ext), 192 << 4, lm85_scaling[n]) -#define INS_FROM_REG(n,val) INSEXT_FROM_REG(n,val,0,1) +#define INS_FROM_REG(n,val) SCALE((val), 192, lm85_scaling[n]) /* FAN speed is measured using 90kHz clock */ #define FAN_TO_REG(val) (SENSORS_LIMIT( (val)<=0?0: 5400000/(val),0,65534)) @@ -151,10 +151,9 @@ static int lm85_scaling[] = { /* .001 Volts */ /* Temperature is reported in .001 degC increments */ #define TEMP_TO_REG(val) \ SENSORS_LIMIT(SCALE(val,1000,1),-127,127) -#define TEMPEXT_FROM_REG(val,ext,scale) \ - SCALE((val)*scale + (ext),scale,1000) -#define TEMP_FROM_REG(val) \ - TEMPEXT_FROM_REG(val,0,1) +#define TEMPEXT_FROM_REG(val,ext) \ + SCALE(((val) << 4) + (ext), 16, 1000) +#define TEMP_FROM_REG(val) ((val) * 1000) #define PWM_TO_REG(val) (SENSORS_LIMIT(val,0,255)) #define PWM_FROM_REG(val) (val) @@ -334,7 +333,6 @@ struct lm85_data { u8 tach_mode; /* Register encoding, combined */ u8 temp_ext[3]; /* Decoded values */ u8 in_ext[8]; /* Decoded values */ - u8 adc_scale; /* ADC Extended bits scaling factor */ u8 fan_ppr; /* Register value */ u8 smooth[3]; /* Register encoding */ u8 vid; /* Register value */ @@ -541,8 +539,7 @@ static ssize_t show_in(struct device *dev, struct device_attribute *attr, struct lm85_data *data = lm85_update_device(dev); return sprintf( buf, "%d\n", INSEXT_FROM_REG(nr, data->in[nr], - data->in_ext[nr], - data->adc_scale) ); + data->in_ext[nr])); } static ssize_t show_in_min(struct device *dev, struct device_attribute *attr, @@ -616,8 +613,7 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *attr, int nr = to_sensor_dev_attr(attr)->index; struct lm85_data *data = lm85_update_device(dev); return sprintf(buf,"%d\n", TEMPEXT_FROM_REG(data->temp[nr], - data->temp_ext[nr], - data->adc_scale) ); + data->temp_ext[nr])); } static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr, @@ -1394,6 +1390,8 @@ static struct lm85_data *lm85_update_device(struct device *dev) /* Have to read extended bits first to "freeze" the * more significant bits that are read later. + * There are 2 additional resolution bits per channel and we + * have room for 4, so we shift them to the left. */ if ( (data->type == adm1027) || (data->type == adt7463) ) { int ext1 = lm85_read_value(client, @@ -1403,18 +1401,12 @@ static struct lm85_data *lm85_update_device(struct device *dev) int val = (ext1 << 8) + ext2; for(i = 0; i <= 4; i++) - data->in_ext[i] = (val>>(i * 2))&0x03; + data->in_ext[i] = ((val>>(i * 2))&0x03) << 2; for(i = 0; i <= 2; i++) - data->temp_ext[i] = (val>>((i + 5) * 2))&0x03; + data->temp_ext[i] = (val>>((i + 4) * 2))&0x0c; } - /* adc_scale is 2^(number of LSBs). There are 4 extra bits in - the emc6d102 and 2 in the adt7463 and adm1027. In all - other chips ext is always 0 and the value of scale is - irrelevant. So it is left in 4*/ - data->adc_scale = (data->type == emc6d102 ) ? 16 : 4; - data->vid = lm85_read_value(client, LM85_REG_VID); for (i = 0; i <= 3; ++i) { -- cgit v1.2.3 From 63f281a6e32ebc93c62dac0d399d8e054eb7b2ec Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 5 Jul 2007 20:39:40 +0200 Subject: hwmon: (lm85) Let the user set the fan min limit to 0 Trying to set the fan min limit to 0 currently writes 0 to the register, which is an invalid value. It's read back as -1 and the alarm flag is raised. Instead we should write 0xffff (maximum value), which reads back as 0 and no alarm flag is raised. Signed-off-by: Jean Delvare Acked-by: Juerg Haefliger Signed-off-by: Mark M. Hoffman --- drivers/hwmon/lm85.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index 0c61fa36c83..2ca616d7c1c 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c @@ -145,7 +145,12 @@ static int lm85_scaling[] = { /* .001 Volts */ #define INS_FROM_REG(n,val) SCALE((val), 192, lm85_scaling[n]) /* FAN speed is measured using 90kHz clock */ -#define FAN_TO_REG(val) (SENSORS_LIMIT( (val)<=0?0: 5400000/(val),0,65534)) +static inline u16 FAN_TO_REG(unsigned long val) +{ + if (!val) + return 0xffff; + return SENSORS_LIMIT(5400000 / val, 1, 0xfffe); +} #define FAN_FROM_REG(val) ((val)==0?-1:(val)==0xffff?0:5400000/(val)) /* Temperature is reported in .001 degC increments */ @@ -391,7 +396,7 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, int nr = to_sensor_dev_attr(attr)->index; struct i2c_client *client = to_i2c_client(dev); struct lm85_data *data = i2c_get_clientdata(client); - long val = simple_strtol(buf, NULL, 10); + unsigned long val = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); data->fan_min[nr] = FAN_TO_REG(val); -- cgit v1.2.3 From e7f62303b8a7f34ce6f97a1722b6907f0ddbd0a9 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 4 Sep 2007 14:03:43 +0200 Subject: hwmon: (lm93) Use standard names for vid files The lm93 driver doesn't follow the standard naming convention for its vid files. Fix this so that libsensors will pick them. Signed-off-by: Jean Delvare Acked-by: Hans J. Koch Signed-off-by: Mark M. Hoffman --- drivers/hwmon/lm93.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/lm93.c b/drivers/hwmon/lm93.c index b9899b93c25..ea61946a4bf 100644 --- a/drivers/hwmon/lm93.c +++ b/drivers/hwmon/lm93.c @@ -2078,8 +2078,8 @@ static ssize_t show_vid(struct device *dev, struct device_attribute *attr, return sprintf(buf,"%d\n",LM93_VID_FROM_REG(data->vid[nr])); } -static SENSOR_DEVICE_ATTR(vid1, S_IRUGO, show_vid, NULL, 0); -static SENSOR_DEVICE_ATTR(vid2, S_IRUGO, show_vid, NULL, 1); +static SENSOR_DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL, 0); +static SENSOR_DEVICE_ATTR(cpu1_vid, S_IRUGO, show_vid, NULL, 1); static ssize_t show_prochot(struct device *dev, struct device_attribute *attr, char *buf) @@ -2431,8 +2431,8 @@ static struct attribute *lm93_attrs[] = { &sensor_dev_attr_pwm2_auto_spinup_time.dev_attr.attr, &dev_attr_pwm_auto_prochot_ramp.attr, &dev_attr_pwm_auto_vrdhot_ramp.attr, - &sensor_dev_attr_vid1.dev_attr.attr, - &sensor_dev_attr_vid2.dev_attr.attr, + &sensor_dev_attr_cpu0_vid.dev_attr.attr, + &sensor_dev_attr_cpu1_vid.dev_attr.attr, &sensor_dev_attr_prochot1.dev_attr.attr, &sensor_dev_attr_prochot2.dev_attr.attr, &sensor_dev_attr_prochot1_avg.dev_attr.attr, -- cgit v1.2.3 From 7b6d1f044d95395ca103bfb6869caa996fedbbd2 Mon Sep 17 00:00:00 2001 From: Auke Kok Date: Mon, 27 Aug 2007 16:17:01 -0700 Subject: hwmon: (sis5595) re-use s_bridge->revision Signed-off-by: Auke Kok Acked-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/sis5595.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c index 3de9721aa67..79a5376a8d8 100644 --- a/drivers/hwmon/sis5595.c +++ b/drivers/hwmon/sis5595.c @@ -517,7 +517,7 @@ static int __devinit sis5595_probe(struct platform_device *pdev) platform_set_drvdata(pdev, data); /* Check revision and pin registers to determine whether 4 or 5 voltages */ - pci_read_config_byte(s_bridge, PCI_REVISION_ID, &data->revision); + data->revision = s_bridge->revision; /* 4 voltages, 1 temp */ data->maxins = 3; if (data->revision >= REV2MIN) { -- cgit v1.2.3 From 6438312367523b26bd628b60cfd16f25a7a6f7ae Mon Sep 17 00:00:00 2001 From: Charles Spirakis Date: Tue, 4 Sep 2007 13:31:56 -0700 Subject: hwmon: (w83791d) new sysfs beep/alarm methodology Add new sysfs alarm methodology to w83791d driver Signed-off-by: Charles Spirakis Acked-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/w83791d.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 118 insertions(+), 4 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c index a3cb89455ea..de4eb3e7b27 100644 --- a/drivers/hwmon/w83791d.c +++ b/drivers/hwmon/w83791d.c @@ -2,7 +2,7 @@ w83791d.c - Part of lm_sensors, Linux kernel modules for hardware monitoring - Copyright (C) 2006 Charles Spirakis + Copyright (C) 2006-2007 Charles Spirakis 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 @@ -384,6 +384,85 @@ static struct sensor_device_attribute sda_in_max[] = { SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9), }; + +static ssize_t show_beep(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *sensor_attr = + to_sensor_dev_attr(attr); + struct w83791d_data *data = w83791d_update_device(dev); + int bitnr = sensor_attr->index; + + return sprintf(buf, "%d\n", (data->beep_mask >> bitnr) & 1); +} + +static ssize_t store_beep(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *sensor_attr = + to_sensor_dev_attr(attr); + struct i2c_client *client = to_i2c_client(dev); + struct w83791d_data *data = i2c_get_clientdata(client); + int bitnr = sensor_attr->index; + int bytenr = bitnr / 8; + long val = simple_strtol(buf, NULL, 10) ? 1 : 0; + + mutex_lock(&data->update_lock); + + data->beep_mask &= ~(0xff << (bytenr * 8)); + data->beep_mask |= w83791d_read(client, W83791D_REG_BEEP_CTRL[bytenr]) + << (bytenr * 8); + + data->beep_mask &= ~(1 << bitnr); + data->beep_mask |= val << bitnr; + + w83791d_write(client, W83791D_REG_BEEP_CTRL[bytenr], + (data->beep_mask >> (bytenr * 8)) & 0xff); + + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *sensor_attr = + to_sensor_dev_attr(attr); + struct w83791d_data *data = w83791d_update_device(dev); + int bitnr = sensor_attr->index; + + return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1); +} + +/* Note: The bitmask for the beep enable/disable is different than + the bitmask for the alarm. */ +static struct sensor_device_attribute sda_in_beep[] = { + SENSOR_ATTR(in0_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 0), + SENSOR_ATTR(in1_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 13), + SENSOR_ATTR(in2_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 2), + SENSOR_ATTR(in3_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 3), + SENSOR_ATTR(in4_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 8), + SENSOR_ATTR(in5_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 9), + SENSOR_ATTR(in6_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 10), + SENSOR_ATTR(in7_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 16), + SENSOR_ATTR(in8_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 17), + SENSOR_ATTR(in9_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 14), +}; + +static struct sensor_device_attribute sda_in_alarm[] = { + SENSOR_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0), + SENSOR_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1), + SENSOR_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2), + SENSOR_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3), + SENSOR_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8), + SENSOR_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9), + SENSOR_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 10), + SENSOR_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 19), + SENSOR_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 20), + SENSOR_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 14), +}; + #define show_fan_reg(reg) \ static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ char *buf) \ @@ -536,6 +615,22 @@ static struct sensor_device_attribute sda_fan_div[] = { show_fan_div, store_fan_div, 4), }; +static struct sensor_device_attribute sda_fan_beep[] = { + SENSOR_ATTR(fan1_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 6), + SENSOR_ATTR(fan2_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 7), + SENSOR_ATTR(fan3_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 11), + SENSOR_ATTR(fan4_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 21), + SENSOR_ATTR(fan5_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 22), +}; + +static struct sensor_device_attribute sda_fan_alarm[] = { + SENSOR_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6), + SENSOR_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7), + SENSOR_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11), + SENSOR_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 21), + SENSOR_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 22), +}; + /* read/write the temperature1, includes measured value and limits */ static ssize_t show_temp1(struct device *dev, struct device_attribute *devattr, char *buf) @@ -618,6 +713,19 @@ static struct sensor_device_attribute_2 sda_temp_max_hyst[] = { show_temp23, store_temp23, 1, 2), }; +/* Note: The bitmask for the beep enable/disable is different than + the bitmask for the alarm. */ +static struct sensor_device_attribute sda_temp_beep[] = { + SENSOR_ATTR(temp1_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 4), + SENSOR_ATTR(temp2_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 5), + SENSOR_ATTR(temp3_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 1), +}; + +static struct sensor_device_attribute sda_temp_alarm[] = { + SENSOR_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4), + SENSOR_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5), + SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13), +}; /* get reatime status of all sensors items: voltage, temp, fan */ static ssize_t show_alarms_reg(struct device *dev, @@ -749,17 +857,23 @@ static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); #define IN_UNIT_ATTRS(X) \ &sda_in_input[X].dev_attr.attr, \ &sda_in_min[X].dev_attr.attr, \ - &sda_in_max[X].dev_attr.attr + &sda_in_max[X].dev_attr.attr, \ + &sda_in_beep[X].dev_attr.attr, \ + &sda_in_alarm[X].dev_attr.attr #define FAN_UNIT_ATTRS(X) \ &sda_fan_input[X].dev_attr.attr, \ &sda_fan_min[X].dev_attr.attr, \ - &sda_fan_div[X].dev_attr.attr + &sda_fan_div[X].dev_attr.attr, \ + &sda_fan_beep[X].dev_attr.attr, \ + &sda_fan_alarm[X].dev_attr.attr #define TEMP_UNIT_ATTRS(X) \ &sda_temp_input[X].dev_attr.attr, \ &sda_temp_max[X].dev_attr.attr, \ - &sda_temp_max_hyst[X].dev_attr.attr + &sda_temp_max_hyst[X].dev_attr.attr, \ + &sda_temp_beep[X].dev_attr.attr, \ + &sda_temp_alarm[X].dev_attr.attr static struct attribute *w83791d_attributes[] = { IN_UNIT_ATTRS(0), -- cgit v1.2.3 From c7f1f7166a83f8f5607cc03c7a6c5f936cde6b0d Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 3 Sep 2007 17:11:46 +0200 Subject: hwmon: (it87) Add support for fan4 and fan5 Add support for the IT8716F and IT8718F fan4 and fan5. The late revisions of the IT8712F have these too but support is harder to add and nobody asked for it yet, so I didn't include it. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/it87.c | 54 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 15 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 41a90e5613b..cd741b79c17 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -141,10 +141,10 @@ static int fix_pwm_polarity; /* Monitors: 9 voltage (0 to 7, battery), 3 temp (1 to 3), 3 fan (1 to 3) */ -#define IT87_REG_FAN(nr) (0x0d + (nr)) -#define IT87_REG_FAN_MIN(nr) (0x10 + (nr)) -#define IT87_REG_FANX(nr) (0x18 + (nr)) -#define IT87_REG_FANX_MIN(nr) (0x1b + (nr)) +static const u8 IT87_REG_FAN[] = { 0x0d, 0x0e, 0x0f, 0x80, 0x82 }; +static const u8 IT87_REG_FAN_MIN[] = { 0x10, 0x11, 0x12, 0x84, 0x86 }; +static const u8 IT87_REG_FANX[] = { 0x18, 0x19, 0x1a, 0x81, 0x83 }; +static const u8 IT87_REG_FANX_MIN[] = { 0x1b, 0x1c, 0x1d, 0x85, 0x87 }; #define IT87_REG_FAN_MAIN_CTRL 0x13 #define IT87_REG_FAN_CTL 0x14 #define IT87_REG_PWM(nr) (0x15 + (nr)) @@ -235,8 +235,8 @@ struct it87_data { u8 in_max[8]; /* Register value */ u8 in_min[8]; /* Register value */ u8 has_fan; /* Bitfield, fans enabled */ - u16 fan[3]; /* Register values, possibly combined */ - u16 fan_min[3]; /* Register values, possibly combined */ + u16 fan[5]; /* Register values, possibly combined */ + u16 fan_min[5]; /* Register values, possibly combined */ u8 temp[3]; /* Register value */ u8 temp_high[3]; /* Register value */ u8 temp_low[3]; /* Register value */ @@ -555,7 +555,7 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, } data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); - it87_write_value(data, IT87_REG_FAN_MIN(nr), data->fan_min[nr]); + it87_write_value(data, IT87_REG_FAN_MIN[nr], data->fan_min[nr]); mutex_unlock(&data->update_lock); return count; } @@ -596,7 +596,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, /* Restore fan min limit */ data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); - it87_write_value(data, IT87_REG_FAN_MIN(nr), data->fan_min[nr]); + it87_write_value(data, IT87_REG_FAN_MIN[nr], data->fan_min[nr]); mutex_unlock(&data->update_lock); return count; @@ -729,9 +729,9 @@ static ssize_t set_fan16_min(struct device *dev, struct device_attribute *attr, mutex_lock(&data->update_lock); data->fan_min[nr] = FAN16_TO_REG(val); - it87_write_value(data, IT87_REG_FAN_MIN(nr), + it87_write_value(data, IT87_REG_FAN_MIN[nr], data->fan_min[nr] & 0xff); - it87_write_value(data, IT87_REG_FANX_MIN(nr), + it87_write_value(data, IT87_REG_FANX_MIN[nr], data->fan_min[nr] >> 8); mutex_unlock(&data->update_lock); return count; @@ -751,6 +751,8 @@ static struct sensor_device_attribute sensor_dev_attr_fan##offset##_min16 \ show_fan16_offset(1); show_fan16_offset(2); show_fan16_offset(3); +show_fan16_offset(4); +show_fan16_offset(5); /* Alarms */ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf) @@ -851,6 +853,10 @@ static struct attribute *it87_attributes_opt[] = { &sensor_dev_attr_fan2_min16.dev_attr.attr, &sensor_dev_attr_fan3_input16.dev_attr.attr, &sensor_dev_attr_fan3_min16.dev_attr.attr, + &sensor_dev_attr_fan4_input16.dev_attr.attr, + &sensor_dev_attr_fan4_min16.dev_attr.attr, + &sensor_dev_attr_fan5_input16.dev_attr.attr, + &sensor_dev_attr_fan5_min16.dev_attr.attr, &sensor_dev_attr_fan1_input.dev_attr.attr, &sensor_dev_attr_fan1_min.dev_attr.attr, @@ -1024,6 +1030,20 @@ static int __devinit it87_probe(struct platform_device *pdev) &sensor_dev_attr_fan3_min16.dev_attr))) goto ERROR4; } + if (data->has_fan & (1 << 3)) { + if ((err = device_create_file(dev, + &sensor_dev_attr_fan4_input16.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_fan4_min16.dev_attr))) + goto ERROR4; + } + if (data->has_fan & (1 << 4)) { + if ((err = device_create_file(dev, + &sensor_dev_attr_fan5_input16.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_fan5_min16.dev_attr))) + goto ERROR4; + } } else { /* 8-bit tachometers with clock divider */ if (data->has_fan & (1 << 0)) { @@ -1260,6 +1280,10 @@ static void __devinit it87_init_device(struct platform_device *pdev) it87_write_value(data, IT87_REG_FAN_16BIT, tmp | 0x07); } + if (tmp & (1 << 4)) + data->has_fan |= (1 << 3); /* fan4 enabled */ + if (tmp & (1 << 5)) + data->has_fan |= (1 << 4); /* fan5 enabled */ } /* Set current fan mode registers and the default settings for the @@ -1314,21 +1338,21 @@ static struct it87_data *it87_update_device(struct device *dev) data->in[8] = it87_read_value(data, IT87_REG_VIN(8)); - for (i = 0; i < 3; i++) { + for (i = 0; i < 5; i++) { /* Skip disabled fans */ if (!(data->has_fan & (1 << i))) continue; data->fan_min[i] = - it87_read_value(data, IT87_REG_FAN_MIN(i)); + it87_read_value(data, IT87_REG_FAN_MIN[i]); data->fan[i] = it87_read_value(data, - IT87_REG_FAN(i)); + IT87_REG_FAN[i]); /* Add high byte if in 16-bit mode */ if (data->type == it8716 || data->type == it8718) { data->fan[i] |= it87_read_value(data, - IT87_REG_FANX(i)) << 8; + IT87_REG_FANX[i]) << 8; data->fan_min[i] |= it87_read_value(data, - IT87_REG_FANX_MIN(i)) << 8; + IT87_REG_FANX_MIN[i]) << 8; } } for (i = 0; i < 3; i++) { -- cgit v1.2.3 From bba891c24a77419e9dcf76f866bd0d8ecf66d770 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Sun, 9 Sep 2007 17:35:34 +0200 Subject: hwmon: (thmc50) Fix alarms clearing This patch make use the interrupt status register instead of the interrupt status mirror register. Reading of the mirror register does not clear alarms. Signed-off-by: Krzysztof Helt Signed-off-by: Mark M. Hoffman --- drivers/hwmon/thmc50.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/thmc50.c b/drivers/hwmon/thmc50.c index 981d1f1dc61..f79c7504204 100644 --- a/drivers/hwmon/thmc50.c +++ b/drivers/hwmon/thmc50.c @@ -47,10 +47,10 @@ I2C_CLIENT_MODULE_PARM(adm1022_temp3, "List of adapter,address pairs " #define THMC50_REG_DIE_CODE 0x3F #define THMC50_REG_ANALOG_OUT 0x19 /* - * We use mirror status register for reading alarms - * so ACPI can use the primary status register. + * The mirror status register cannot be used as + * reading it does not clear alarms. */ -#define THMC50_REG_INTR_MIRROR 0x4C +#define THMC50_REG_INTR 0x41 const static u8 THMC50_REG_TEMP[] = { 0x27, 0x26, 0x20 }; const static u8 THMC50_REG_TEMP_MIN[] = { 0x3A, 0x38, 0x2C }; @@ -441,7 +441,7 @@ static struct thmc50_data *thmc50_update_device(struct device *dev) data->analog_out = i2c_smbus_read_byte_data(client, THMC50_REG_ANALOG_OUT); data->alarms = - i2c_smbus_read_byte_data(client, THMC50_REG_INTR_MIRROR); + i2c_smbus_read_byte_data(client, THMC50_REG_INTR); data->last_updated = jiffies; data->valid = 1; } -- cgit v1.2.3 From a8d6646e24fa72de38de5838df8bd1f21af59710 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Sun, 9 Sep 2007 19:51:14 +0200 Subject: hwmon: (adm1021) dynamic sysfs callbacks conversion This is conversion of the driver to the dynamic sysfs callbacks. Signed-off-by: Krzysztof Helt Acked-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/adm1021.c | 194 ++++++++++++++++++++++++++---------------------- 1 file changed, 106 insertions(+), 88 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c index 5667630ac05..cc409709428 100644 --- a/drivers/hwmon/adm1021.c +++ b/drivers/hwmon/adm1021.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -43,8 +44,8 @@ I2C_CLIENT_INSMOD_8(adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm, /* The adm1021 registers */ /* Read-only */ -#define ADM1021_REG_TEMP 0x00 -#define ADM1021_REG_REMOTE_TEMP 0x01 +/* For nr in 0-1 */ +#define ADM1021_REG_TEMP(nr) (nr) #define ADM1021_REG_STATUS 0x02 /* 0x41 = AD, 0x49 = TI, 0x4D = Maxim, 0x23 = Genesys , 0x54 = Onsemi */ #define ADM1021_REG_MAN_ID 0xFE @@ -62,25 +63,14 @@ I2C_CLIENT_INSMOD_8(adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm, #define ADM1023_REG_REM_TOS_PREC 0x13 #define ADM1023_REG_REM_THYST_PREC 0x14 /* limits */ -#define ADM1021_REG_TOS_R 0x05 -#define ADM1021_REG_TOS_W 0x0B -#define ADM1021_REG_REMOTE_TOS_R 0x07 -#define ADM1021_REG_REMOTE_TOS_W 0x0D -#define ADM1021_REG_THYST_R 0x06 -#define ADM1021_REG_THYST_W 0x0C -#define ADM1021_REG_REMOTE_THYST_R 0x08 -#define ADM1021_REG_REMOTE_THYST_W 0x0E +/* For nr in 0-1 */ +#define ADM1021_REG_TOS_R(nr) (0x05 + 2 * (nr)) +#define ADM1021_REG_TOS_W(nr) (0x0B + 2 * (nr)) +#define ADM1021_REG_THYST_R(nr) (0x06 + 2 * (nr)) +#define ADM1021_REG_THYST_W(nr) (0x0C + 2 * (nr)) /* write-only */ #define ADM1021_REG_ONESHOT 0x0F - -/* Conversions. Rounding and limit checking is only done on the TO_REG - variants. Note that you should be a bit careful with which arguments - these macros are called: arguments may be evaluated more than once. - Fixing this is just not worth it. */ -/* Conversions note: 1021 uses normal integer signed-byte format*/ -#define TEMP_TO_REG(val) SENSORS_LIMIT((val) / 1000, -128, 127) - /* Initial values */ /* Note: Even though I left the low and high limits named os and hyst, @@ -98,19 +88,16 @@ struct adm1021_data { char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ - s8 temp_max; /* Register values */ - s8 temp_hyst; - s8 temp_input; - s8 remote_temp_max; - s8 remote_temp_hyst; - s8 remote_temp_input; - u8 alarms; - /* Special values for ADM1023 only */ - u8 remote_temp_prec; - u8 remote_temp_os_prec; - u8 remote_temp_hyst_prec; - u8 remote_temp_offset; - u8 remote_temp_offset_prec; + s8 temp_max[2]; /* Register values */ + s8 temp_min[2]; + s8 temp[2]; + u8 alarms; + /* Special values for ADM1023 only */ + u8 remote_temp_prec; + u8 remote_temp_os_prec; + u8 remote_temp_hyst_prec; + u8 remote_temp_offset; + u8 remote_temp_offset_prec; }; static int adm1021_attach_adapter(struct i2c_adapter *adapter); @@ -133,19 +120,32 @@ static struct i2c_driver adm1021_driver = { .detach_client = adm1021_detach_client, }; -#define show(value) \ -static ssize_t show_##value(struct device *dev, \ - struct device_attribute *attr, char *buf) \ -{ \ - struct adm1021_data *data = adm1021_update_device(dev); \ - return sprintf(buf, "%d\n", 1000 * data->value); \ +static ssize_t show_temp(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct adm1021_data *data = adm1021_update_device(dev); + + return sprintf(buf, "%d\n", 1000 * data->temp[index]); +} + +static ssize_t show_temp_max(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct adm1021_data *data = adm1021_update_device(dev); + + return sprintf(buf, "%d\n", 1000 * data->temp_max[index]); +} + +static ssize_t show_temp_min(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct adm1021_data *data = adm1021_update_device(dev); + + return sprintf(buf, "%d\n", 1000 * data->temp_min[index]); } -show(temp_max); -show(temp_hyst); -show(temp_input); -show(remote_temp_max); -show(remote_temp_hyst); -show(remote_temp_input); static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, @@ -155,35 +155,55 @@ static ssize_t show_alarms(struct device *dev, return sprintf(buf, "%u\n", data->alarms); } -#define set(value, reg) \ -static ssize_t set_##value(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct i2c_client *client = to_i2c_client(dev); \ - struct adm1021_data *data = i2c_get_clientdata(client); \ - long temp = simple_strtol(buf, NULL, 10); \ - \ - mutex_lock(&data->update_lock); \ - data->value = TEMP_TO_REG(temp); \ - if (!read_only) \ - i2c_smbus_write_byte_data(client, reg, data->value); \ - mutex_unlock(&data->update_lock); \ - return count; \ +static ssize_t set_temp_max(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct i2c_client *client = to_i2c_client(dev); + struct adm1021_data *data = i2c_get_clientdata(client); + long temp = simple_strtol(buf, NULL, 10) / 1000; + + mutex_lock(&data->update_lock); + data->temp_max[index] = SENSORS_LIMIT(temp, -128, 127); + if (!read_only) + i2c_smbus_write_byte_data(client, ADM1021_REG_TOS_W(index), + data->temp_max[index]); + mutex_unlock(&data->update_lock); + + return count; } -set(temp_max, ADM1021_REG_TOS_W); -set(temp_hyst, ADM1021_REG_THYST_W); -set(remote_temp_max, ADM1021_REG_REMOTE_TOS_W); -set(remote_temp_hyst, ADM1021_REG_REMOTE_THYST_W); - -static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max); -static DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp_hyst, set_temp_hyst); -static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL); -static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_remote_temp_max, set_remote_temp_max); -static DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_remote_temp_hyst, set_remote_temp_hyst); -static DEVICE_ATTR(temp2_input, S_IRUGO, show_remote_temp_input, NULL); -static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); +static ssize_t set_temp_min(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct i2c_client *client = to_i2c_client(dev); + struct adm1021_data *data = i2c_get_clientdata(client); + long temp = simple_strtol(buf, NULL, 10) / 1000; + + mutex_lock(&data->update_lock); + data->temp_min[index] = SENSORS_LIMIT(temp, -128, 127); + if (!read_only) + i2c_smbus_write_byte_data(client, ADM1021_REG_THYST_W(index), + data->temp_min[index]); + mutex_unlock(&data->update_lock); + + return count; +} + +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, + set_temp_max, 0); +static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp_min, + set_temp_min, 0); +static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); +static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_max, + set_temp_max, 1); +static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp_min, + set_temp_min, 1); +static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); static int adm1021_attach_adapter(struct i2c_adapter *adapter) { @@ -193,12 +213,12 @@ static int adm1021_attach_adapter(struct i2c_adapter *adapter) } static struct attribute *adm1021_attributes[] = { - &dev_attr_temp1_max.attr, - &dev_attr_temp1_min.attr, - &dev_attr_temp1_input.attr, - &dev_attr_temp2_max.attr, - &dev_attr_temp2_min.attr, - &dev_attr_temp2_input.attr, + &sensor_dev_attr_temp1_max.dev_attr.attr, + &sensor_dev_attr_temp1_min.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp2_max.dev_attr.attr, + &sensor_dev_attr_temp2_min.dev_attr.attr, + &sensor_dev_attr_temp2_input.dev_attr.attr, &dev_attr_alarms.attr, NULL }; @@ -370,20 +390,18 @@ static struct adm1021_data *adm1021_update_device(struct device *dev) if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid) { + int i; + dev_dbg(&client->dev, "Starting adm1021 update\n"); - data->temp_input = i2c_smbus_read_byte_data(client, - ADM1021_REG_TEMP); - data->temp_max = i2c_smbus_read_byte_data(client, - ADM1021_REG_TOS_R); - data->temp_hyst = i2c_smbus_read_byte_data(client, - ADM1021_REG_THYST_R); - data->remote_temp_input = i2c_smbus_read_byte_data(client, - ADM1021_REG_REMOTE_TEMP); - data->remote_temp_max = i2c_smbus_read_byte_data(client, - ADM1021_REG_REMOTE_TOS_R); - data->remote_temp_hyst = i2c_smbus_read_byte_data(client, - ADM1021_REG_REMOTE_THYST_R); + for (i = 0; i < 2; i++) { + data->temp[i] = i2c_smbus_read_byte_data(client, + ADM1021_REG_TEMP(i)); + data->temp_max[i] = i2c_smbus_read_byte_data(client, + ADM1021_REG_TOS_R(i)); + data->temp_min[i] = i2c_smbus_read_byte_data(client, + ADM1021_REG_THYST_R(i)); + } data->alarms = i2c_smbus_read_byte_data(client, ADM1021_REG_STATUS) & 0x7c; if (data->type == adm1023) { -- cgit v1.2.3 From 739ba2486e8444b27a3ec975205798ef17def963 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Sun, 9 Sep 2007 19:16:03 +0200 Subject: hwmon: (adm1021) individual alarm files This patch converts the driver to individual alarm files as required by the new lmsensors library. Signed-off-by: Krzysztof Helt Acked-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/adm1021.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c index cc409709428..ebdc6d7db23 100644 --- a/drivers/hwmon/adm1021.c +++ b/drivers/hwmon/adm1021.c @@ -147,6 +147,14 @@ static ssize_t show_temp_min(struct device *dev, return sprintf(buf, "%d\n", 1000 * data->temp_min[index]); } +static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int index = to_sensor_dev_attr(attr)->index; + struct adm1021_data *data = adm1021_update_device(dev); + return sprintf(buf, "%u\n", (data->alarms >> index) & 1); +} + static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf) @@ -203,6 +211,12 @@ static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max, 1); static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp_min, set_temp_min, 1); +static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6); +static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 5); +static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4); +static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 3); +static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 2); + static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); static int adm1021_attach_adapter(struct i2c_adapter *adapter) @@ -219,6 +233,11 @@ static struct attribute *adm1021_attributes[] = { &sensor_dev_attr_temp2_max.dev_attr.attr, &sensor_dev_attr_temp2_min.dev_attr.attr, &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, + &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, + &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, + &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, + &sensor_dev_attr_temp2_fault.dev_attr.attr, &dev_attr_alarms.attr, NULL }; -- cgit v1.2.3 From dabf375b87407757ec4c8ea54f936918ec88b7ca Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 29 Aug 2007 12:19:00 +0200 Subject: hwmon: Kconfig dependency cleanups * Drop HWMON from the dependency list of ABITUGURU3 and LM93: this is now handled at menu level. * Make the Abit, Asus and FSC chip drivers depend on X86. These are custom chips which can only be found on their respective manufacturer's systems, and these manufacturers only do x86 hardware AFAIK. Signed-off-by: Jean Delvare Acked-by: Hans de Goede Signed-off-by: Mark M. Hoffman --- drivers/hwmon/Kconfig | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index a2f60748951..52511742b33 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -30,7 +30,7 @@ config HWMON_VID config SENSORS_ABITUGURU tristate "Abit uGuru (rev 1 & 2)" - depends on EXPERIMENTAL + depends on X86 && EXPERIMENTAL help If you say yes here you get support for the sensor part of the first and second revision of the Abit uGuru chip. The voltage and frequency @@ -45,7 +45,7 @@ config SENSORS_ABITUGURU config SENSORS_ABITUGURU3 tristate "Abit uGuru (rev 3)" - depends on HWMON && EXPERIMENTAL + depends on X86 && EXPERIMENTAL help If you say yes here you get support for the sensor part of the third revision of the Abit uGuru chip. Only reading the sensors @@ -182,7 +182,7 @@ config SENSORS_AMS_I2C config SENSORS_ASB100 tristate "Asus ASB100 Bach" - depends on I2C && EXPERIMENTAL + depends on X86 && I2C && EXPERIMENTAL select HWMON_VID help If you say yes here you get support for the ASB100 Bach sensor @@ -248,7 +248,7 @@ config SENSORS_F75375S config SENSORS_FSCHER tristate "FSC Hermes" - depends on I2C + depends on X86 && I2C help If you say yes here you get support for Fujitsu Siemens Computers Hermes sensor chips. @@ -258,7 +258,7 @@ config SENSORS_FSCHER config SENSORS_FSCPOS tristate "FSC Poseidon" - depends on I2C + depends on X86 && I2C help If you say yes here you get support for Fujitsu Siemens Computers Poseidon sensor chips. @@ -431,7 +431,7 @@ config SENSORS_LM92 config SENSORS_LM93 tristate "National Semiconductor LM93 and compatibles" - depends on HWMON && I2C + depends on I2C select HWMON_VID help If you say yes here you get support for National Semiconductor LM93 -- cgit v1.2.3 From 69f2f96d9c189070ed5e40ec186b755ef697288d Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 5 Sep 2007 14:15:37 +0200 Subject: hwmon: (lm90) Export temperature offset values Now that we have standard sysfs names to export temperature offset values, add this feature to the lm90 driver. All supported chips except the MAX6657, MAX6658 and MAX6659 support it. Signed-off-by: Jean Delvare Acked-by: Hans de Goede Signed-off-by: Mark M. Hoffman --- drivers/hwmon/lm90.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index 98b53b119c2..960df9fa75a 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c @@ -41,7 +41,8 @@ * http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2578 * Note that there is no easy way to differentiate between the three * variants. The extra address and features of the MAX6659 are not - * supported by this driver. + * supported by this driver. These chips lack the remote temperature + * offset feature. * * This driver also supports the MAX6680 and MAX6681, two other sensor * chips made by Maxim. These are quite similar to the other Maxim @@ -226,9 +227,10 @@ struct lm90_data { 2: local high limit 3: local critical limit 4: remote critical limit */ - s16 temp11[3]; /* 0: remote input + s16 temp11[4]; /* 0: remote input 1: remote low limit - 2: remote high limit */ + 2: remote high limit + 3: remote offset (except max6657) */ u8 temp_hyst; u8 alarms; /* bitvector */ }; @@ -282,11 +284,13 @@ static ssize_t show_temp11(struct device *dev, struct device_attribute *devattr, static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { - static const u8 reg[4] = { + static const u8 reg[6] = { LM90_REG_W_REMOTE_LOWH, LM90_REG_W_REMOTE_LOWL, LM90_REG_W_REMOTE_HIGHH, LM90_REG_W_REMOTE_HIGHL, + LM90_REG_W_REMOTE_OFFSH, + LM90_REG_W_REMOTE_OFFSL, }; struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -367,6 +371,8 @@ static SENSOR_DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp8, static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temphyst, set_temphyst, 3); static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_temphyst, NULL, 4); +static SENSOR_DEVICE_ATTR(temp2_offset, S_IWUSR | S_IRUGO, show_temp11, + set_temp11, 3); /* Individual alarm files */ static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 0); @@ -652,6 +658,11 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind) &dev_attr_pec))) goto exit_remove_files; } + if (data->kind != max6657) { + if ((err = device_create_file(&new_client->dev, + &sensor_dev_attr_temp2_offset.dev_attr))) + goto exit_remove_files; + } data->hwmon_dev = hwmon_device_register(&new_client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -710,6 +721,9 @@ static int lm90_detach_client(struct i2c_client *client) hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm90_group); device_remove_file(&client->dev, &dev_attr_pec); + if (data->kind != max6657) + device_remove_file(&client->dev, + &sensor_dev_attr_temp2_offset.dev_attr); if ((err = i2c_detach_client(client))) return err; @@ -763,6 +777,13 @@ static struct lm90_data *lm90_update_device(struct device *dev) if (lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHH, &newh) == 0 && lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHL, &l) == 0) data->temp11[2] = (newh << 8) | l; + if (data->kind != max6657) { + if (lm90_read_reg(client, LM90_REG_R_REMOTE_OFFSH, + &newh) == 0 + && lm90_read_reg(client, LM90_REG_R_REMOTE_OFFSL, + &l) == 0) + data->temp11[3] = (newh << 8) | l; + } lm90_read_reg(client, LM90_REG_R_STATUS, &data->alarms); data->last_updated = jiffies; -- cgit v1.2.3 From 428a7039c5717695935b946af9413e59f68928a4 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 4 Sep 2007 23:25:33 +0200 Subject: hwmon: (lm78) Add individual alarm files Add individual alarm files to the lm78 driver, these are needed by the next version of libsensors. Signed-off-by: Jean Delvare Acked-by: Hans de Goede Signed-off-by: Mark M. Hoffman --- drivers/hwmon/lm78.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c index f5278fda826..3f7055ee679 100644 --- a/drivers/hwmon/lm78.c +++ b/drivers/hwmon/lm78.c @@ -438,6 +438,25 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *da, } static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); +static ssize_t show_alarm(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct lm78_data *data = lm78_update_device(dev); + int nr = to_sensor_dev_attr(da)->index; + return sprintf(buf, "%u\n", (data->alarms >> nr) & 1); +} +static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0); +static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2); +static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3); +static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8); +static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9); +static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 10); +static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6); +static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7); +static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11); +static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4); + /* This function is called when: * lm78_driver is inserted (when this module is loaded), for each available adapter @@ -453,36 +472,47 @@ static struct attribute *lm78_attributes[] = { &sensor_dev_attr_in0_input.dev_attr.attr, &sensor_dev_attr_in0_min.dev_attr.attr, &sensor_dev_attr_in0_max.dev_attr.attr, + &sensor_dev_attr_in0_alarm.dev_attr.attr, &sensor_dev_attr_in1_input.dev_attr.attr, &sensor_dev_attr_in1_min.dev_attr.attr, &sensor_dev_attr_in1_max.dev_attr.attr, + &sensor_dev_attr_in1_alarm.dev_attr.attr, &sensor_dev_attr_in2_input.dev_attr.attr, &sensor_dev_attr_in2_min.dev_attr.attr, &sensor_dev_attr_in2_max.dev_attr.attr, + &sensor_dev_attr_in2_alarm.dev_attr.attr, &sensor_dev_attr_in3_input.dev_attr.attr, &sensor_dev_attr_in3_min.dev_attr.attr, &sensor_dev_attr_in3_max.dev_attr.attr, + &sensor_dev_attr_in3_alarm.dev_attr.attr, &sensor_dev_attr_in4_input.dev_attr.attr, &sensor_dev_attr_in4_min.dev_attr.attr, &sensor_dev_attr_in4_max.dev_attr.attr, + &sensor_dev_attr_in4_alarm.dev_attr.attr, &sensor_dev_attr_in5_input.dev_attr.attr, &sensor_dev_attr_in5_min.dev_attr.attr, &sensor_dev_attr_in5_max.dev_attr.attr, + &sensor_dev_attr_in5_alarm.dev_attr.attr, &sensor_dev_attr_in6_input.dev_attr.attr, &sensor_dev_attr_in6_min.dev_attr.attr, &sensor_dev_attr_in6_max.dev_attr.attr, + &sensor_dev_attr_in6_alarm.dev_attr.attr, &dev_attr_temp1_input.attr, &dev_attr_temp1_max.attr, &dev_attr_temp1_max_hyst.attr, + &sensor_dev_attr_temp1_alarm.dev_attr.attr, &sensor_dev_attr_fan1_input.dev_attr.attr, &sensor_dev_attr_fan1_min.dev_attr.attr, &sensor_dev_attr_fan1_div.dev_attr.attr, + &sensor_dev_attr_fan1_alarm.dev_attr.attr, &sensor_dev_attr_fan2_input.dev_attr.attr, &sensor_dev_attr_fan2_min.dev_attr.attr, &sensor_dev_attr_fan2_div.dev_attr.attr, + &sensor_dev_attr_fan2_alarm.dev_attr.attr, &sensor_dev_attr_fan3_input.dev_attr.attr, &sensor_dev_attr_fan3_min.dev_attr.attr, &sensor_dev_attr_fan3_div.dev_attr.attr, + &sensor_dev_attr_fan3_alarm.dev_attr.attr, &dev_attr_alarms.attr, &dev_attr_cpu0_vid.attr, -- cgit v1.2.3 From b965d4b7f614522170af6a7e450be0333792ccd2 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 26 Sep 2007 22:16:56 +0200 Subject: hwmon: (lm87) Fix a division by zero Missing parentheses in the definition of FAN_FROM_REG cause a division by zero for a specific register value. Signed-off-by: Jean Delvare Acked-by: Hans de Goede Signed-off-by: Mark M. Hoffman --- drivers/hwmon/lm87.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c index e60076e8b59..ef8a9b251cd 100644 --- a/drivers/hwmon/lm87.c +++ b/drivers/hwmon/lm87.c @@ -129,7 +129,7 @@ static u8 LM87_REG_TEMP_LOW[3] = { 0x3A, 0x38, 0x2C }; (((val) < 0 ? (val)-500 : (val)+500) / 1000)) #define FAN_FROM_REG(reg,div) ((reg) == 255 || (reg) == 0 ? 0 : \ - 1350000 + (reg)*(div) / 2) / ((reg)*(div)) + (1350000 + (reg)*(div) / 2) / ((reg)*(div))) #define FAN_TO_REG(val,div) ((val)*(div) * 255 <= 1350000 ? 255 : \ (1350000 + (val)*(div) / 2) / ((val)*(div))) -- cgit v1.2.3 From c2803b98557c10464f3a1fc65f56d0c8c01991bd Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 26 Sep 2007 23:39:01 +0200 Subject: hwmon: (lm87) Add individual alarm files Add individual alarm files to the lm87 driver. The new libsensors needs this. Signed-off-by: Jean Delvare Acked-by: Hans de Goede Signed-off-by: Mark M. Hoffman --- drivers/hwmon/lm87.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 61 insertions(+), 6 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c index ef8a9b251cd..86537af0a0b 100644 --- a/drivers/hwmon/lm87.c +++ b/drivers/hwmon/lm87.c @@ -58,6 +58,7 @@ #include #include #include +#include #include #include #include @@ -531,6 +532,29 @@ static ssize_t set_aout(struct device *dev, struct device_attribute *attr, const } static DEVICE_ATTR(aout_output, S_IRUGO | S_IWUSR, show_aout, set_aout); +static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct lm87_data *data = lm87_update_device(dev); + int bitnr = to_sensor_dev_attr(attr)->index; + return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); +} +static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0); +static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2); +static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3); +static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8); +static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9); +static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 6); +static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 7); +static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4); +static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5); +static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 5); +static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6); +static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7); +static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 14); +static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 15); + /* * Real code */ @@ -546,24 +570,31 @@ static struct attribute *lm87_attributes[] = { &dev_attr_in1_input.attr, &dev_attr_in1_min.attr, &dev_attr_in1_max.attr, + &sensor_dev_attr_in1_alarm.dev_attr.attr, &dev_attr_in2_input.attr, &dev_attr_in2_min.attr, &dev_attr_in2_max.attr, + &sensor_dev_attr_in2_alarm.dev_attr.attr, &dev_attr_in3_input.attr, &dev_attr_in3_min.attr, &dev_attr_in3_max.attr, + &sensor_dev_attr_in3_alarm.dev_attr.attr, &dev_attr_in4_input.attr, &dev_attr_in4_min.attr, &dev_attr_in4_max.attr, + &sensor_dev_attr_in4_alarm.dev_attr.attr, &dev_attr_temp1_input.attr, &dev_attr_temp1_max.attr, &dev_attr_temp1_min.attr, &dev_attr_temp1_crit.attr, + &sensor_dev_attr_temp1_alarm.dev_attr.attr, &dev_attr_temp2_input.attr, &dev_attr_temp2_max.attr, &dev_attr_temp2_min.attr, &dev_attr_temp2_crit.attr, + &sensor_dev_attr_temp2_alarm.dev_attr.attr, + &sensor_dev_attr_temp2_fault.dev_attr.attr, &dev_attr_alarms.attr, &dev_attr_aout_output.attr, @@ -579,30 +610,38 @@ static struct attribute *lm87_attributes_opt[] = { &dev_attr_in6_input.attr, &dev_attr_in6_min.attr, &dev_attr_in6_max.attr, + &sensor_dev_attr_in6_alarm.dev_attr.attr, &dev_attr_fan1_input.attr, &dev_attr_fan1_min.attr, &dev_attr_fan1_div.attr, + &sensor_dev_attr_fan1_alarm.dev_attr.attr, &dev_attr_in7_input.attr, &dev_attr_in7_min.attr, &dev_attr_in7_max.attr, + &sensor_dev_attr_in7_alarm.dev_attr.attr, &dev_attr_fan2_input.attr, &dev_attr_fan2_min.attr, &dev_attr_fan2_div.attr, + &sensor_dev_attr_fan2_alarm.dev_attr.attr, &dev_attr_temp3_input.attr, &dev_attr_temp3_max.attr, &dev_attr_temp3_min.attr, &dev_attr_temp3_crit.attr, + &sensor_dev_attr_temp3_alarm.dev_attr.attr, + &sensor_dev_attr_temp3_fault.dev_attr.attr, &dev_attr_in0_input.attr, &dev_attr_in0_min.attr, &dev_attr_in0_max.attr, + &sensor_dev_attr_in0_alarm.dev_attr.attr, &dev_attr_in5_input.attr, &dev_attr_in5_min.attr, &dev_attr_in5_max.attr, + &sensor_dev_attr_in5_alarm.dev_attr.attr, &dev_attr_cpu0_vid.attr, &dev_attr_vrm.attr, @@ -690,7 +729,9 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind) || (err = device_create_file(&new_client->dev, &dev_attr_in6_min)) || (err = device_create_file(&new_client->dev, - &dev_attr_in6_max))) + &dev_attr_in6_max)) + || (err = device_create_file(&new_client->dev, + &sensor_dev_attr_in6_alarm.dev_attr))) goto exit_remove; } else { if ((err = device_create_file(&new_client->dev, @@ -698,7 +739,9 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind) || (err = device_create_file(&new_client->dev, &dev_attr_fan1_min)) || (err = device_create_file(&new_client->dev, - &dev_attr_fan1_div))) + &dev_attr_fan1_div)) + || (err = device_create_file(&new_client->dev, + &sensor_dev_attr_fan1_alarm.dev_attr))) goto exit_remove; } @@ -708,7 +751,9 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind) || (err = device_create_file(&new_client->dev, &dev_attr_in7_min)) || (err = device_create_file(&new_client->dev, - &dev_attr_in7_max))) + &dev_attr_in7_max)) + || (err = device_create_file(&new_client->dev, + &sensor_dev_attr_in7_alarm.dev_attr))) goto exit_remove; } else { if ((err = device_create_file(&new_client->dev, @@ -716,7 +761,9 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind) || (err = device_create_file(&new_client->dev, &dev_attr_fan2_min)) || (err = device_create_file(&new_client->dev, - &dev_attr_fan2_div))) + &dev_attr_fan2_div)) + || (err = device_create_file(&new_client->dev, + &sensor_dev_attr_fan2_alarm.dev_attr))) goto exit_remove; } @@ -728,7 +775,11 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind) || (err = device_create_file(&new_client->dev, &dev_attr_temp3_min)) || (err = device_create_file(&new_client->dev, - &dev_attr_temp3_crit))) + &dev_attr_temp3_crit)) + || (err = device_create_file(&new_client->dev, + &sensor_dev_attr_temp3_alarm.dev_attr)) + || (err = device_create_file(&new_client->dev, + &sensor_dev_attr_temp3_fault.dev_attr))) goto exit_remove; } else { if ((err = device_create_file(&new_client->dev, @@ -737,12 +788,16 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind) &dev_attr_in0_min)) || (err = device_create_file(&new_client->dev, &dev_attr_in0_max)) + || (err = device_create_file(&new_client->dev, + &sensor_dev_attr_in0_alarm.dev_attr)) || (err = device_create_file(&new_client->dev, &dev_attr_in5_input)) || (err = device_create_file(&new_client->dev, &dev_attr_in5_min)) || (err = device_create_file(&new_client->dev, - &dev_attr_in5_max))) + &dev_attr_in5_max)) + || (err = device_create_file(&new_client->dev, + &sensor_dev_attr_in5_alarm.dev_attr))) goto exit_remove; } -- cgit v1.2.3 From 894c00cf3805670faddd41d3d5dcb3c0ab75a39d Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 18 Sep 2007 18:44:42 +0200 Subject: hwmon: (thmc50) Don't create temp3 if not enabled Signed-off-by: Jean Delvare Acked-by: Krzysztof Helt Signed-off-by: Mark M. Hoffman --- drivers/hwmon/thmc50.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/thmc50.c b/drivers/hwmon/thmc50.c index f79c7504204..fb02834897f 100644 --- a/drivers/hwmon/thmc50.c +++ b/drivers/hwmon/thmc50.c @@ -237,7 +237,7 @@ static const struct attribute_group thmc50_group = { }; /* for ADM1022 3rd temperature mode */ -static struct attribute *adm1022_attributes[] = { +static struct attribute *temp3_attributes[] = { &sensor_dev_attr_temp3_max.dev_attr.attr, &sensor_dev_attr_temp3_min.dev_attr.attr, &sensor_dev_attr_temp3_input.dev_attr.attr, @@ -246,8 +246,8 @@ static struct attribute *adm1022_attributes[] = { NULL }; -static const struct attribute_group adm1022_group = { - .attrs = adm1022_attributes, +static const struct attribute_group temp3_group = { + .attrs = temp3_attributes, }; static int thmc50_detect(struct i2c_adapter *adapter, int address, int kind) @@ -345,9 +345,9 @@ static int thmc50_detect(struct i2c_adapter *adapter, int address, int kind) goto exit_detach; /* Register ADM1022 sysfs hooks */ - if (data->type == adm1022) + if (data->has_temp3) if ((err = sysfs_create_group(&client->dev.kobj, - &adm1022_group))) + &temp3_group))) goto exit_remove_sysfs_thmc50; /* Register a new directory entry with module sensors */ @@ -360,8 +360,8 @@ static int thmc50_detect(struct i2c_adapter *adapter, int address, int kind) return 0; exit_remove_sysfs: - if (data->type == adm1022) - sysfs_remove_group(&client->dev.kobj, &adm1022_group); + if (data->has_temp3) + sysfs_remove_group(&client->dev.kobj, &temp3_group); exit_remove_sysfs_thmc50: sysfs_remove_group(&client->dev.kobj, &thmc50_group); exit_detach: @@ -386,8 +386,8 @@ static int thmc50_detach_client(struct i2c_client *client) hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &thmc50_group); - if (data->type == adm1022) - sysfs_remove_group(&client->dev.kobj, &adm1022_group); + if (data->has_temp3) + sysfs_remove_group(&client->dev.kobj, &temp3_group); if ((err = i2c_detach_client(client))) return err; -- cgit v1.2.3 From cc28a610d4fcce1831d26f2099e23fbb3eb7260c Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 18 Sep 2007 18:48:16 +0200 Subject: hwmon: (thmc50) Fix a debug message type_name was used before being set. See why I don't like play-it-safe variable initializations: they prevent the compiler from warning you about such mistakes. So fix that as well. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/thmc50.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/thmc50.c b/drivers/hwmon/thmc50.c index fb02834897f..04dd7699b3a 100644 --- a/drivers/hwmon/thmc50.c +++ b/drivers/hwmon/thmc50.c @@ -259,7 +259,7 @@ static int thmc50_detect(struct i2c_adapter *adapter, int address, int kind) struct thmc50_data *data; struct device *dev; int err = 0; - const char *type_name = ""; + const char *type_name; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { pr_debug("thmc50: detect failed, " @@ -309,13 +309,9 @@ static int thmc50_detect(struct i2c_adapter *adapter, int address, int kind) pr_debug("thmc50: Detection of THMC50/ADM1022 failed\n"); goto exit_free; } - pr_debug("thmc50: Detected %s (version %x, revision %x)\n", - type_name, (revision >> 4) - 0xc, revision & 0xf); data->type = kind; - if (kind == thmc50) - type_name = "thmc50"; - else if (kind == adm1022) { + if (kind == adm1022) { int id = i2c_adapter_id(client->adapter); int i; @@ -328,7 +324,11 @@ static int thmc50_detect(struct i2c_adapter *adapter, int address, int kind) data->has_temp3 = 1; break; } + } else { + type_name = "thmc50"; } + pr_debug("thmc50: Detected %s (version %x, revision %x)\n", + type_name, (revision >> 4) - 0xc, revision & 0xf); /* Fill in the remaining client fields & put it into the global list */ strlcpy(client->name, type_name, I2C_NAME_SIZE); -- cgit v1.2.3 From 90d6619a916062cb75a176aacb318d108758b4a5 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 8 Oct 2007 18:24:35 +0200 Subject: hwmon: VRM is not read from registers The VRM value is not read from chip registers, so there's no need to update the device data cache before exporting the VRM value to user-space. Signed-off-by: Jean Delvare Acked-by: Hans de Goede Signed-off-by: Mark M. Hoffman --- drivers/hwmon/adm1025.c | 2 +- drivers/hwmon/adm1026.c | 2 +- drivers/hwmon/asb100.c | 2 +- drivers/hwmon/it87.c | 2 +- drivers/hwmon/lm85.c | 2 +- drivers/hwmon/lm87.c | 2 +- drivers/hwmon/pc87360.c | 2 +- drivers/hwmon/smsc47m192.c | 2 +- drivers/hwmon/w83627hf.c | 2 +- drivers/hwmon/w83781d.c | 2 +- drivers/hwmon/w83791d.c | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c index a67e133bfd3..041ecb0bdf4 100644 --- a/drivers/hwmon/adm1025.c +++ b/drivers/hwmon/adm1025.c @@ -292,7 +292,7 @@ static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf) { - struct adm1025_data *data = adm1025_update_device(dev); + struct adm1025_data *data = dev_get_drvdata(dev); return sprintf(buf, "%u\n", data->vrm); } static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c index b85370c7358..aa875ca50d9 100644 --- a/drivers/hwmon/adm1026.c +++ b/drivers/hwmon/adm1026.c @@ -1221,7 +1221,7 @@ static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf) { - struct adm1026_data *data = adm1026_update_device(dev); + struct adm1026_data *data = dev_get_drvdata(dev); return sprintf(buf,"%d\n", data->vrm); } static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c index 745bf264bcf..9460dba4cf7 100644 --- a/drivers/hwmon/asb100.c +++ b/drivers/hwmon/asb100.c @@ -514,7 +514,7 @@ static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); /* VRM */ static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf) { - struct asb100_data *data = asb100_update_device(dev); + struct asb100_data *data = dev_get_drvdata(dev); return sprintf(buf, "%d\n", data->vrm); } diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index cd741b79c17..6a182e14cf5 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -765,7 +765,7 @@ static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf) { - struct it87_data *data = it87_update_device(dev); + struct it87_data *data = dev_get_drvdata(dev); return sprintf(buf, "%u\n", data->vrm); } static ssize_t diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index 2ca616d7c1c..a02480be65f 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c @@ -438,7 +438,7 @@ static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf) { - struct lm85_data *data = lm85_update_device(dev); + struct lm85_data *data = dev_get_drvdata(dev); return sprintf(buf, "%ld\n", (long) data->vrm); } diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c index 86537af0a0b..7f806a05890 100644 --- a/drivers/hwmon/lm87.c +++ b/drivers/hwmon/lm87.c @@ -501,7 +501,7 @@ static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf) { - struct lm87_data *data = lm87_update_device(dev); + struct lm87_data *data = dev_get_drvdata(dev); return sprintf(buf, "%d\n", data->vrm); } static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c index 91cf51034b5..9d660133d51 100644 --- a/drivers/hwmon/pc87360.c +++ b/drivers/hwmon/pc87360.c @@ -500,7 +500,7 @@ static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf) { - struct pc87360_data *data = pc87360_update_device(dev); + struct pc87360_data *data = dev_get_drvdata(dev); return sprintf(buf, "%u\n", data->vrm); } static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) diff --git a/drivers/hwmon/smsc47m192.c b/drivers/hwmon/smsc47m192.c index 0efcd27b252..b8755265258 100644 --- a/drivers/hwmon/smsc47m192.c +++ b/drivers/hwmon/smsc47m192.c @@ -334,7 +334,7 @@ static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf) { - struct smsc47m192_data *data = smsc47m192_update_device(dev); + struct smsc47m192_data *data = dev_get_drvdata(dev); return sprintf(buf, "%d\n", data->vrm); } diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index b1943ec29c4..a2ccf93521c 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -703,7 +703,7 @@ static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf) { - struct w83627hf_data *data = w83627hf_update_device(dev); + struct w83627hf_data *data = dev_get_drvdata(dev); return sprintf(buf, "%ld\n", (long) data->vrm); } static ssize_t diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index e622ec5b092..d2cb9978a2a 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c @@ -454,7 +454,7 @@ static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf) { - struct w83781d_data *data = w83781d_update_device(dev); + struct w83781d_data *data = dev_get_drvdata(dev); return sprintf(buf, "%ld\n", (long) data->vrm); } diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c index de4eb3e7b27..b6f2ebf9f9c 100644 --- a/drivers/hwmon/w83791d.c +++ b/drivers/hwmon/w83791d.c @@ -832,7 +832,7 @@ static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf) { - struct w83791d_data *data = w83791d_update_device(dev); + struct w83791d_data *data = dev_get_drvdata(dev); return sprintf(buf, "%d\n", data->vrm); } -- cgit v1.2.3 From 7d4a137491d96927ffca5e8557c328902a2d4de9 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 8 Oct 2007 18:29:43 +0200 Subject: hwmon: (w83781d) Add individual alarm and beep files The upcoming libsensors 3 needs these individual alarm and beep files. For the W83781D, this is quirky because this chip has a single alarm bit for both temp2 and temp3. Signed-off-by: Jean Delvare Acked-by: Hans de Goede Signed-off-by: Mark M. Hoffman --- drivers/hwmon/w83781d.c | 168 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 162 insertions(+), 6 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index d2cb9978a2a..a6a1edfe761 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c @@ -481,6 +481,39 @@ show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf) static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); +static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct w83781d_data *data = w83781d_update_device(dev); + int bitnr = to_sensor_dev_attr(attr)->index; + return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); +} + +/* The W83781D has a single alarm bit for temp2 and temp3 */ +static ssize_t show_temp3_alarm(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct w83781d_data *data = w83781d_update_device(dev); + int bitnr = (data->type == w83781d) ? 5 : 13; + return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); +} + +static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0); +static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1); +static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2); +static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3); +static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8); +static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9); +static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 10); +static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 16); +static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 17); +static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6); +static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7); +static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11); +static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4); +static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5); +static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_temp3_alarm, NULL, 0); + static ssize_t show_beep_mask (struct device *dev, struct device_attribute *attr, char *buf) { struct w83781d_data *data = w83781d_update_device(dev); @@ -544,6 +577,100 @@ static DEVICE_ATTR(beep_mask, S_IRUGO | S_IWUSR, static DEVICE_ATTR(beep_enable, S_IRUGO | S_IWUSR, show_beep_enable, store_beep_enable); +static ssize_t show_beep(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct w83781d_data *data = w83781d_update_device(dev); + int bitnr = to_sensor_dev_attr(attr)->index; + return sprintf(buf, "%u\n", (data->beep_mask >> bitnr) & 1); +} + +static ssize_t +store_beep(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct w83781d_data *data = dev_get_drvdata(dev); + int bitnr = to_sensor_dev_attr(attr)->index; + unsigned long bit; + u8 reg; + + bit = simple_strtoul(buf, NULL, 10); + if (bit & ~1) + return -EINVAL; + + mutex_lock(&data->update_lock); + if (bit) + data->beep_mask |= (1 << bitnr); + else + data->beep_mask &= ~(1 << bitnr); + + if (bitnr < 8) { + reg = w83781d_read_value(data, W83781D_REG_BEEP_INTS1); + if (bit) + reg |= (1 << bitnr); + else + reg &= ~(1 << bitnr); + w83781d_write_value(data, W83781D_REG_BEEP_INTS1, reg); + } else if (bitnr < 16) { + reg = w83781d_read_value(data, W83781D_REG_BEEP_INTS2); + if (bit) + reg |= (1 << (bitnr - 8)); + else + reg &= ~(1 << (bitnr - 8)); + w83781d_write_value(data, W83781D_REG_BEEP_INTS2, reg); + } else { + reg = w83781d_read_value(data, W83781D_REG_BEEP_INTS3); + if (bit) + reg |= (1 << (bitnr - 16)); + else + reg &= ~(1 << (bitnr - 16)); + w83781d_write_value(data, W83781D_REG_BEEP_INTS3, reg); + } + mutex_unlock(&data->update_lock); + + return count; +} + +/* The W83781D has a single beep bit for temp2 and temp3 */ +static ssize_t show_temp3_beep(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct w83781d_data *data = w83781d_update_device(dev); + int bitnr = (data->type == w83781d) ? 5 : 13; + return sprintf(buf, "%u\n", (data->beep_mask >> bitnr) & 1); +} + +static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO | S_IWUSR, + show_beep, store_beep, 0); +static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO | S_IWUSR, + show_beep, store_beep, 1); +static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO | S_IWUSR, + show_beep, store_beep, 2); +static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO | S_IWUSR, + show_beep, store_beep, 3); +static SENSOR_DEVICE_ATTR(in4_beep, S_IRUGO | S_IWUSR, + show_beep, store_beep, 8); +static SENSOR_DEVICE_ATTR(in5_beep, S_IRUGO | S_IWUSR, + show_beep, store_beep, 9); +static SENSOR_DEVICE_ATTR(in6_beep, S_IRUGO | S_IWUSR, + show_beep, store_beep, 10); +static SENSOR_DEVICE_ATTR(in7_beep, S_IRUGO | S_IWUSR, + show_beep, store_beep, 16); +static SENSOR_DEVICE_ATTR(in8_beep, S_IRUGO | S_IWUSR, + show_beep, store_beep, 17); +static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO | S_IWUSR, + show_beep, store_beep, 6); +static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO | S_IWUSR, + show_beep, store_beep, 7); +static SENSOR_DEVICE_ATTR(fan3_beep, S_IRUGO | S_IWUSR, + show_beep, store_beep, 11); +static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR, + show_beep, store_beep, 4); +static SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO | S_IWUSR, + show_beep, store_beep, 5); +static SENSOR_DEVICE_ATTR(temp3_beep, S_IRUGO, + show_temp3_beep, store_beep, 13); + static ssize_t show_fan_div(struct device *dev, struct device_attribute *da, char *buf) { @@ -877,17 +1004,23 @@ ERROR_SC_0: #define IN_UNIT_ATTRS(X) \ &sensor_dev_attr_in##X##_input.dev_attr.attr, \ &sensor_dev_attr_in##X##_min.dev_attr.attr, \ - &sensor_dev_attr_in##X##_max.dev_attr.attr + &sensor_dev_attr_in##X##_max.dev_attr.attr, \ + &sensor_dev_attr_in##X##_alarm.dev_attr.attr, \ + &sensor_dev_attr_in##X##_beep.dev_attr.attr #define FAN_UNIT_ATTRS(X) \ &sensor_dev_attr_fan##X##_input.dev_attr.attr, \ &sensor_dev_attr_fan##X##_min.dev_attr.attr, \ - &sensor_dev_attr_fan##X##_div.dev_attr.attr + &sensor_dev_attr_fan##X##_div.dev_attr.attr, \ + &sensor_dev_attr_fan##X##_alarm.dev_attr.attr, \ + &sensor_dev_attr_fan##X##_beep.dev_attr.attr #define TEMP_UNIT_ATTRS(X) \ &sensor_dev_attr_temp##X##_input.dev_attr.attr, \ &sensor_dev_attr_temp##X##_max.dev_attr.attr, \ - &sensor_dev_attr_temp##X##_max_hyst.dev_attr.attr + &sensor_dev_attr_temp##X##_max_hyst.dev_attr.attr, \ + &sensor_dev_attr_temp##X##_alarm.dev_attr.attr, \ + &sensor_dev_attr_temp##X##_beep.dev_attr.attr static struct attribute* w83781d_attributes[] = { IN_UNIT_ATTRS(0), @@ -946,7 +1079,11 @@ w83781d_create_files(struct device *dev, int kind, int is_isa) || (err = device_create_file(dev, &sensor_dev_attr_in1_min.dev_attr)) || (err = device_create_file(dev, - &sensor_dev_attr_in1_max.dev_attr))) + &sensor_dev_attr_in1_max.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_in1_alarm.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_in1_beep.dev_attr))) return err; } if (kind != as99127f && kind != w83781d && kind != w83783s) { @@ -956,12 +1093,20 @@ w83781d_create_files(struct device *dev, int kind, int is_isa) &sensor_dev_attr_in7_min.dev_attr)) || (err = device_create_file(dev, &sensor_dev_attr_in7_max.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_in7_alarm.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_in7_beep.dev_attr)) || (err = device_create_file(dev, &sensor_dev_attr_in8_input.dev_attr)) || (err = device_create_file(dev, &sensor_dev_attr_in8_min.dev_attr)) || (err = device_create_file(dev, - &sensor_dev_attr_in8_max.dev_attr))) + &sensor_dev_attr_in8_max.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_in8_alarm.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_in8_beep.dev_attr))) return err; } if (kind != w83783s) { @@ -970,8 +1115,19 @@ w83781d_create_files(struct device *dev, int kind, int is_isa) || (err = device_create_file(dev, &sensor_dev_attr_temp3_max.dev_attr)) || (err = device_create_file(dev, - &sensor_dev_attr_temp3_max_hyst.dev_attr))) + &sensor_dev_attr_temp3_max_hyst.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_temp3_alarm.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_temp3_beep.dev_attr))) return err; + + if (kind != w83781d) + err = sysfs_chmod_file(&dev->kobj, + &sensor_dev_attr_temp3_alarm.dev_attr.attr, + S_IRUGO | S_IWUSR); + if (err) + return err; } if (kind != w83781d && kind != as99127f) { -- cgit v1.2.3 From 889af3d5d9586db795a06c619e416b4baee11da8 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 8 Oct 2007 22:48:10 +0200 Subject: hwmon: (lm87) Disable VID when it should be A stupid bit shifting bug caused the VID value to be always exported even when the hardware is configured for something different. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/lm87.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c index 7f806a05890..28cdff0c556 100644 --- a/drivers/hwmon/lm87.c +++ b/drivers/hwmon/lm87.c @@ -146,7 +146,7 @@ static u8 LM87_REG_TEMP_LOW[3] = { 0x3A, 0x38, 0x2C }; #define CHAN_NO_FAN(nr) (1 << (nr)) #define CHAN_TEMP3 (1 << 2) #define CHAN_VCC_5V (1 << 3) -#define CHAN_NO_VID (1 << 8) +#define CHAN_NO_VID (1 << 7) /* * Functions declaration -- cgit v1.2.3 From c940336b4403540c498fceb102c7142799252129 Mon Sep 17 00:00:00 2001 From: Rudolf Marek Date: Sun, 7 Oct 2007 13:42:09 +0200 Subject: hwmon: (coretemp) Add support for Celeron 4xx This patch adds support for the Celeron 4xx based on Core 2 core. Signed-off-by: Rudolf Marek Signed-off-by: Mark M. Hoffman --- drivers/hwmon/coretemp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 1a0ff8d42bb..6f66551d9e5 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -369,9 +369,10 @@ static int __init coretemp_init(void) for_each_online_cpu(i) { struct cpuinfo_x86 *c = &(cpu_data)[i]; - /* check if family 6, models e, f */ + /* check if family 6, models e, f, 16 */ if ((c->cpuid_level < 0) || (c->x86 != 0x6) || - !((c->x86_model == 0xe) || (c->x86_model == 0xf))) { + !((c->x86_model == 0xe) || (c->x86_model == 0xf) || + (c->x86_model == 0x16))) { /* supported CPU not found, but report the unknown family 6 CPU */ -- cgit v1.2.3 From 57c7c3a0fdea95eddcaeba31e7ca7dfc917682ab Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Fri, 14 Sep 2007 12:33:46 -0700 Subject: hwmon: IBM power meter driver Add a driver to export IBM PowerExecutive power meter sensors. Signed-off-by: Darrick J. Wong Signed-off-by: Mark M. Hoffman --- drivers/hwmon/Kconfig | 13 ++ drivers/hwmon/Makefile | 1 + drivers/hwmon/ibmpex.c | 608 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 622 insertions(+) create mode 100644 drivers/hwmon/ibmpex.c (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 52511742b33..b8854b94807 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -295,6 +295,19 @@ config SENSORS_CORETEMP sensor inside your CPU. Supported all are all known variants of Intel Core family. +config SENSORS_IBMPEX + tristate "IBM PowerExecutive temperature/power sensors" + select IPMI_SI + depends on IPMI_HANDLER + help + If you say yes here you get support for the temperature and + power sensors in various IBM System X servers that support + PowerExecutive. So far this includes the x3550, x3650, x3655, + x3755, and certain HS20 blades. + + This driver can also be built as a module. If so, the module + will be called ibmpex. + config SENSORS_IT87 tristate "ITE IT87xx and compatibles" select HWMON_VID diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 19da12ec140..2f592e2e01b 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -37,6 +37,7 @@ obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o +obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o obj-$(CONFIG_SENSORS_IT87) += it87.o obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o obj-$(CONFIG_SENSORS_LM63) += lm63.o diff --git a/drivers/hwmon/ibmpex.c b/drivers/hwmon/ibmpex.c new file mode 100644 index 00000000000..fe2c2616c6b --- /dev/null +++ b/drivers/hwmon/ibmpex.c @@ -0,0 +1,608 @@ +/* + * A hwmon driver for the IBM PowerExecutive temperature/power sensors + * Copyright (C) 2007 IBM + * + * Author: Darrick J. Wong + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include + +#define REFRESH_INTERVAL (2 * HZ) +#define DRVNAME "ibmpex" + +#define PEX_GET_VERSION 1 +#define PEX_GET_SENSOR_COUNT 2 +#define PEX_GET_SENSOR_NAME 3 +#define PEX_RESET_HIGH_LOW 4 +#define PEX_GET_SENSOR_DATA 6 + +#define PEX_NET_FUNCTION 0x3A +#define PEX_COMMAND 0x3C + +static inline u16 extract_value(const char *data, int offset) +{ + return be16_to_cpup((u16 *)&data[offset]); +} + +#define TEMP_SENSOR 1 +#define POWER_SENSOR 2 + +#define PEX_SENSOR_TYPE_LEN 3 +static u8 const power_sensor_sig[] = {0x70, 0x77, 0x72}; +static u8 const temp_sensor_sig[] = {0x74, 0x65, 0x6D}; + +#define PEX_MULT_LEN 2 +static u8 const watt_sensor_sig[] = {0x41, 0x43}; + +#define PEX_NUM_SENSOR_FUNCS 3 +static char const * const power_sensor_name_templates[] = { + "%s%d_average", + "%s%d_average_lowest", + "%s%d_average_highest" +}; +static char const * const temp_sensor_name_templates[] = { + "%s%d_input", + "%s%d_input_lowest", + "%s%d_input_highest" +}; + +static void ibmpex_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); +static void ibmpex_register_bmc(int iface, struct device *dev); +static void ibmpex_bmc_gone(int iface); + +struct ibmpex_sensor_data { + int in_use; + s16 values[PEX_NUM_SENSOR_FUNCS]; + int multiplier; + + struct sensor_device_attribute_2 attr[PEX_NUM_SENSOR_FUNCS]; +}; + +struct ibmpex_bmc_data { + struct list_head list; + struct device *hwmon_dev; + struct device *bmc_device; + struct mutex lock; + char valid; + unsigned long last_updated; /* In jiffies */ + + struct ipmi_addr address; + struct completion read_complete; + ipmi_user_t user; + int interface; + + struct kernel_ipmi_msg tx_message; + unsigned char tx_msg_data[IPMI_MAX_MSG_LENGTH]; + long tx_msgid; + + unsigned char rx_msg_data[IPMI_MAX_MSG_LENGTH]; + unsigned long rx_msg_len; + unsigned char rx_result; + int rx_recv_type; + + unsigned char sensor_major; + unsigned char sensor_minor; + + unsigned char num_sensors; + struct ibmpex_sensor_data *sensors; +}; + +struct ibmpex_driver_data { + struct list_head bmc_data; + struct ipmi_smi_watcher bmc_events; + struct ipmi_user_hndl ipmi_hndlrs; +}; + +static struct ibmpex_driver_data driver_data = { + .bmc_data = LIST_HEAD_INIT(driver_data.bmc_data), + .bmc_events = { + .owner = THIS_MODULE, + .new_smi = ibmpex_register_bmc, + .smi_gone = ibmpex_bmc_gone, + }, + .ipmi_hndlrs = { + .ipmi_recv_hndl = ibmpex_msg_handler, + }, +}; + +static int ibmpex_send_message(struct ibmpex_bmc_data *data) +{ + int err; + + err = ipmi_validate_addr(&data->address, sizeof(data->address)); + if (err) + goto out; + + data->tx_msgid++; + err = ipmi_request_settime(data->user, &data->address, data->tx_msgid, + &data->tx_message, data, 0, 0, 0); + if (err) + goto out1; + + return 0; +out1: + printk(KERN_ERR "%s: request_settime=%x\n", __FUNCTION__, err); + return err; +out: + printk(KERN_ERR "%s: validate_addr=%x\n", __FUNCTION__, err); + return err; +} + +static int ibmpex_ver_check(struct ibmpex_bmc_data *data) +{ + data->tx_msg_data[0] = PEX_GET_VERSION; + data->tx_message.data_len = 1; + ibmpex_send_message(data); + + wait_for_completion(&data->read_complete); + + if (data->rx_result || data->rx_msg_len != 6) + return -ENOENT; + + data->sensor_major = data->rx_msg_data[0]; + data->sensor_minor = data->rx_msg_data[1]; + + printk(KERN_INFO DRVNAME ": Found BMC with sensor interface " + "v%d.%d %d-%02d-%02d on interface %d\n", + data->sensor_major, + data->sensor_minor, + extract_value(data->rx_msg_data, 2), + data->rx_msg_data[4], + data->rx_msg_data[5], + data->interface); + + return 0; +} + +static int ibmpex_query_sensor_count(struct ibmpex_bmc_data *data) +{ + data->tx_msg_data[0] = PEX_GET_SENSOR_COUNT; + data->tx_message.data_len = 1; + ibmpex_send_message(data); + + wait_for_completion(&data->read_complete); + + if (data->rx_result || data->rx_msg_len != 1) + return -ENOENT; + + return data->rx_msg_data[0]; +} + +static int ibmpex_query_sensor_name(struct ibmpex_bmc_data *data, int sensor) +{ + data->tx_msg_data[0] = PEX_GET_SENSOR_NAME; + data->tx_msg_data[1] = sensor; + data->tx_message.data_len = 2; + ibmpex_send_message(data); + + wait_for_completion(&data->read_complete); + + if (data->rx_result || data->rx_msg_len < 1) + return -ENOENT; + + return 0; +} + +static int ibmpex_query_sensor_data(struct ibmpex_bmc_data *data, int sensor) +{ + data->tx_msg_data[0] = PEX_GET_SENSOR_DATA; + data->tx_msg_data[1] = sensor; + data->tx_message.data_len = 2; + ibmpex_send_message(data); + + wait_for_completion(&data->read_complete); + + if (data->rx_result || data->rx_msg_len < 26) { + printk(KERN_ERR "Error reading sensor %d, please check.\n", + sensor); + return -ENOENT; + } + + return 0; +} + +static int ibmpex_reset_high_low_data(struct ibmpex_bmc_data *data) +{ + data->tx_msg_data[0] = PEX_RESET_HIGH_LOW; + data->tx_message.data_len = 1; + ibmpex_send_message(data); + + wait_for_completion(&data->read_complete); + + return 0; +} + +static void ibmpex_update_device(struct ibmpex_bmc_data *data) +{ + int i, err; + + mutex_lock(&data->lock); + if (time_before(jiffies, data->last_updated + REFRESH_INTERVAL) && + data->valid) + goto out; + + for (i = 0; i < data->num_sensors; i++) { + if (!data->sensors[i].in_use) + continue; + err = ibmpex_query_sensor_data(data, i); + if (err) + continue; + data->sensors[i].values[0] = + extract_value(data->rx_msg_data, 16); + data->sensors[i].values[1] = + extract_value(data->rx_msg_data, 18); + data->sensors[i].values[2] = + extract_value(data->rx_msg_data, 20); + } + + data->last_updated = jiffies; + data->valid = 1; + +out: + mutex_unlock(&data->lock); +} + +static struct ibmpex_bmc_data *get_bmc_data(int iface) +{ + struct ibmpex_bmc_data *p, *next; + + list_for_each_entry_safe(p, next, &driver_data.bmc_data, list) + if (p->interface == iface) + return p; + + return NULL; +} + +static ssize_t show_name(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + return sprintf(buf, "%s\n", DRVNAME); +} +static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); + +static ssize_t ibmpex_show_sensor(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct ibmpex_bmc_data *data = dev_get_drvdata(dev); + int mult = data->sensors[attr->index].multiplier; + ibmpex_update_device(data); + + return sprintf(buf, "%d\n", + data->sensors[attr->index].values[attr->nr] * mult); +} + +static ssize_t ibmpex_reset_high_low(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct ibmpex_bmc_data *data = dev_get_drvdata(dev); + + ibmpex_reset_high_low_data(data); + + return count; +} + +static SENSOR_DEVICE_ATTR(reset_high_low, S_IWUSR, NULL, + ibmpex_reset_high_low, 0); + +static int is_power_sensor(const char *sensor_id, int len) +{ + if (len < PEX_SENSOR_TYPE_LEN) + return 0; + + if (!memcmp(sensor_id, power_sensor_sig, PEX_SENSOR_TYPE_LEN)) + return 1; + return 0; +} + +static int is_temp_sensor(const char *sensor_id, int len) +{ + if (len < PEX_SENSOR_TYPE_LEN) + return 0; + + if (!memcmp(sensor_id, temp_sensor_sig, PEX_SENSOR_TYPE_LEN)) + return 1; + return 0; +} + +static int power_sensor_multiplier(const char *sensor_id, int len) +{ + int i; + + for (i = PEX_SENSOR_TYPE_LEN; i < len - 1; i++) + if (!memcmp(&sensor_id[i], watt_sensor_sig, PEX_MULT_LEN)) + return 1000000; + + return 100000; +} + +static int create_sensor(struct ibmpex_bmc_data *data, int type, + int counter, int sensor, int func) +{ + int err; + char *n; + + n = kmalloc(32, GFP_KERNEL); + if (!n) + return -ENOMEM; + + if (type == TEMP_SENSOR) + sprintf(n, temp_sensor_name_templates[func], "temp", counter); + else if (type == POWER_SENSOR) + sprintf(n, power_sensor_name_templates[func], "power", counter); + + data->sensors[sensor].attr[func].dev_attr.attr.name = n; + data->sensors[sensor].attr[func].dev_attr.attr.mode = S_IRUGO; + data->sensors[sensor].attr[func].dev_attr.show = ibmpex_show_sensor; + data->sensors[sensor].attr[func].index = sensor; + data->sensors[sensor].attr[func].nr = func; + + err = device_create_file(data->bmc_device, + &data->sensors[sensor].attr[func].dev_attr); + if (err) { + data->sensors[sensor].attr[func].dev_attr.attr.name = NULL; + kfree(n); + return err; + } + + return 0; +} + +static int ibmpex_find_sensors(struct ibmpex_bmc_data *data) +{ + int i, j, err; + int sensor_type; + int sensor_counter; + int num_power = 0; + int num_temp = 0; + + err = ibmpex_query_sensor_count(data); + if (err <= 0) + return -ENOENT; + data->num_sensors = err; + + data->sensors = kzalloc(data->num_sensors * sizeof(*data->sensors), + GFP_KERNEL); + if (!data->sensors) + return -ENOMEM; + + for (i = 0; i < data->num_sensors; i++) { + err = ibmpex_query_sensor_name(data, i); + if (err) + continue; + + if (is_power_sensor(data->rx_msg_data, data->rx_msg_len)) { + sensor_type = POWER_SENSOR; + num_power++; + sensor_counter = num_power; + data->sensors[i].multiplier = + power_sensor_multiplier(data->rx_msg_data, + data->rx_msg_len); + } else if (is_temp_sensor(data->rx_msg_data, + data->rx_msg_len)) { + sensor_type = TEMP_SENSOR; + num_temp++; + sensor_counter = num_temp; + data->sensors[i].multiplier = 1; + } else + continue; + + data->sensors[i].in_use = 1; + + /* Create attributes */ + for (j = 0; j < PEX_NUM_SENSOR_FUNCS; j++) { + err = create_sensor(data, sensor_type, sensor_counter, + i, j); + if (err) + goto exit_remove; + } + } + + err = device_create_file(data->bmc_device, + &sensor_dev_attr_reset_high_low.dev_attr); + if (err) + goto exit_remove; + + err = device_create_file(data->bmc_device, + &sensor_dev_attr_name.dev_attr); + if (err) + goto exit_remove; + + return 0; + +exit_remove: + device_remove_file(data->bmc_device, + &sensor_dev_attr_reset_high_low.dev_attr); + device_remove_file(data->bmc_device, &sensor_dev_attr_name.dev_attr); + for (i = 0; i < data->num_sensors; i++) + for (j = 0; j < PEX_NUM_SENSOR_FUNCS; j++) { + if (!data->sensors[i].attr[j].dev_attr.attr.name) + continue; + device_remove_file(data->bmc_device, + &data->sensors[i].attr[j].dev_attr); + kfree(data->sensors[i].attr[j].dev_attr.attr.name); + } + + kfree(data->sensors); + return err; +} + +static void ibmpex_register_bmc(int iface, struct device *dev) +{ + struct ibmpex_bmc_data *data; + int err; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) { + printk(KERN_ERR DRVNAME ": Insufficient memory for BMC " + "interface %d.\n", data->interface); + return; + } + + data->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + data->address.channel = IPMI_BMC_CHANNEL; + data->address.data[0] = 0; + data->interface = iface; + data->bmc_device = dev; + + /* Create IPMI messaging interface user */ + err = ipmi_create_user(data->interface, &driver_data.ipmi_hndlrs, + data, &data->user); + if (err < 0) { + printk(KERN_ERR DRVNAME ": Error, unable to register user with " + "ipmi interface %d\n", + data->interface); + goto out; + } + + mutex_init(&data->lock); + + /* Initialize message */ + data->tx_msgid = 0; + init_completion(&data->read_complete); + data->tx_message.netfn = PEX_NET_FUNCTION; + data->tx_message.cmd = PEX_COMMAND; + data->tx_message.data = data->tx_msg_data; + + /* Does this BMC support PowerExecutive? */ + err = ibmpex_ver_check(data); + if (err) + goto out_user; + + /* Register the BMC as a HWMON class device */ + data->hwmon_dev = hwmon_device_register(data->bmc_device); + + if (IS_ERR(data->hwmon_dev)) { + printk(KERN_ERR DRVNAME ": Error, unable to register hwmon " + "class device for interface %d\n", + data->interface); + kfree(data); + return; + } + + /* finally add the new bmc data to the bmc data list */ + dev_set_drvdata(dev, data); + list_add_tail(&data->list, &driver_data.bmc_data); + + /* Now go find all the sensors */ + err = ibmpex_find_sensors(data); + if (err) { + printk(KERN_ERR "Error %d allocating memory\n", err); + goto out_register; + } + + return; + +out_register: + hwmon_device_unregister(data->hwmon_dev); +out_user: + ipmi_destroy_user(data->user); +out: + kfree(data); +} + +static void ibmpex_bmc_delete(struct ibmpex_bmc_data *data) +{ + int i, j; + + device_remove_file(data->bmc_device, + &sensor_dev_attr_reset_high_low.dev_attr); + device_remove_file(data->bmc_device, &sensor_dev_attr_name.dev_attr); + for (i = 0; i < data->num_sensors; i++) + for (j = 0; j < PEX_NUM_SENSOR_FUNCS; j++) { + if (!data->sensors[i].attr[j].dev_attr.attr.name) + continue; + device_remove_file(data->bmc_device, + &data->sensors[i].attr[j].dev_attr); + kfree(data->sensors[i].attr[j].dev_attr.attr.name); + } + + list_del(&data->list); + dev_set_drvdata(data->bmc_device, NULL); + hwmon_device_unregister(data->hwmon_dev); + ipmi_destroy_user(data->user); + kfree(data->sensors); + kfree(data); +} + +static void ibmpex_bmc_gone(int iface) +{ + struct ibmpex_bmc_data *data = get_bmc_data(iface); + + if (!data) + return; + + ibmpex_bmc_delete(data); +} + +static void ibmpex_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) +{ + struct ibmpex_bmc_data *data = (struct ibmpex_bmc_data *)user_msg_data; + + if (msg->msgid != data->tx_msgid) { + printk(KERN_ERR "Received msgid (%02x) and transmitted " + "msgid (%02x) mismatch!\n", + (int)msg->msgid, + (int)data->tx_msgid); + ipmi_free_recv_msg(msg); + return; + } + + data->rx_recv_type = msg->recv_type; + if (msg->msg.data_len > 0) + data->rx_result = msg->msg.data[0]; + else + data->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE; + + if (msg->msg.data_len > 1) { + data->rx_msg_len = msg->msg.data_len - 1; + memcpy(data->rx_msg_data, msg->msg.data + 1, data->rx_msg_len); + } else + data->rx_msg_len = 0; + + ipmi_free_recv_msg(msg); + complete(&data->read_complete); +} + +static int __init ibmpex_init(void) +{ + return ipmi_smi_watcher_register(&driver_data.bmc_events); +} + +static void __exit ibmpex_exit(void) +{ + struct ibmpex_bmc_data *p, *next; + + ipmi_smi_watcher_unregister(&driver_data.bmc_events); + list_for_each_entry_safe(p, next, &driver_data.bmc_data, list) + ibmpex_bmc_delete(p); +} + +MODULE_AUTHOR("Darrick J. Wong "); +MODULE_DESCRIPTION("IBM PowerExecutive power/temperature sensor driver"); +MODULE_LICENSE("GPL"); + +module_init(ibmpex_init); +module_exit(ibmpex_exit); -- cgit v1.2.3 From b237eb25d8e81c31ba561990445cfe4448c9de14 Mon Sep 17 00:00:00 2001 From: Juerg Haefliger Date: Mon, 1 Oct 2007 21:19:04 -0700 Subject: hwmon: (dme1737) cleanups This patch cleans up and prepares the dme1737 driver for support of the sch311x chips. (Almost) no functional changes. - Replaced whitespaces with tabs. - Removed empty lines. - Added _i2c_ to names of functions that are strictly I2C related. - Added 4 new functions: dme1737_create_files, dme1737_remove_files, dme1737_sio_enter, and dme1737_sio_exit. - Added error messages in case client attach/detach fails. Signed-off-by: Juerg Haefliger Acked-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/dme1737.c | 491 +++++++++++++++++++++++++----------------------- 1 file changed, 258 insertions(+), 233 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c index e9cbc727664..cef662c6af9 100644 --- a/drivers/hwmon/dme1737.c +++ b/drivers/hwmon/dme1737.c @@ -493,8 +493,8 @@ static s32 dme1737_write(struct i2c_client *client, u8 reg, u8 value) static struct dme1737_data *dme1737_update_device(struct device *dev) { - struct i2c_client *client = to_i2c_client(dev); - struct dme1737_data *data = i2c_get_clientdata(client); + struct dme1737_data *data = dev_get_drvdata(dev); + struct i2c_client *client = &data->client; int ix; u8 lsb[5]; @@ -674,7 +674,7 @@ static ssize_t show_in(struct device *dev, struct device_attribute *attr, break; default: res = 0; - dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); + dev_dbg(dev, "Unknown function %d.\n", fn); } return sprintf(buf, "%d\n", res); @@ -683,8 +683,8 @@ static ssize_t show_in(struct device *dev, struct device_attribute *attr, static ssize_t set_in(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct dme1737_data *data = i2c_get_clientdata(client); + struct dme1737_data *data = dev_get_drvdata(dev); + struct i2c_client *client = &data->client; struct sensor_device_attribute_2 *sensor_attr_2 = to_sensor_dev_attr_2(attr); int ix = sensor_attr_2->index; @@ -704,7 +704,7 @@ static ssize_t set_in(struct device *dev, struct device_attribute *attr, data->in_max[ix]); break; default: - dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); + dev_dbg(dev, "Unknown function %d.\n", fn); } mutex_unlock(&data->update_lock); @@ -754,7 +754,7 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *attr, break; default: res = 0; - dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); + dev_dbg(dev, "Unknown function %d.\n", fn); } return sprintf(buf, "%d\n", res); @@ -763,8 +763,8 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *attr, static ssize_t set_temp(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct dme1737_data *data = i2c_get_clientdata(client); + struct dme1737_data *data = dev_get_drvdata(dev); + struct i2c_client *client = &data->client; struct sensor_device_attribute_2 *sensor_attr_2 = to_sensor_dev_attr_2(attr); int ix = sensor_attr_2->index; @@ -789,7 +789,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *attr, data->temp_offset[ix]); break; default: - dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); + dev_dbg(dev, "Unknown function %d.\n", fn); } mutex_unlock(&data->update_lock); @@ -843,7 +843,7 @@ static ssize_t show_zone(struct device *dev, struct device_attribute *attr, break; default: res = 0; - dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); + dev_dbg(dev, "Unknown function %d.\n", fn); } return sprintf(buf, "%d\n", res); @@ -852,8 +852,8 @@ static ssize_t show_zone(struct device *dev, struct device_attribute *attr, static ssize_t set_zone(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct dme1737_data *data = i2c_get_clientdata(client); + struct dme1737_data *data = dev_get_drvdata(dev); + struct i2c_client *client = &data->client; struct sensor_device_attribute_2 *sensor_attr_2 = to_sensor_dev_attr_2(attr); int ix = sensor_attr_2->index; @@ -898,7 +898,7 @@ static ssize_t set_zone(struct device *dev, struct device_attribute *attr, data->zone_abs[ix]); break; default: - dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); + dev_dbg(dev, "Unknown function %d.\n", fn); } mutex_unlock(&data->update_lock); @@ -950,7 +950,7 @@ static ssize_t show_fan(struct device *dev, struct device_attribute *attr, break; default: res = 0; - dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); + dev_dbg(dev, "Unknown function %d.\n", fn); } return sprintf(buf, "%d\n", res); @@ -959,8 +959,8 @@ static ssize_t show_fan(struct device *dev, struct device_attribute *attr, static ssize_t set_fan(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct dme1737_data *data = i2c_get_clientdata(client); + struct dme1737_data *data = dev_get_drvdata(dev); + struct i2c_client *client = &data->client; struct sensor_device_attribute_2 *sensor_attr_2 = to_sensor_dev_attr_2(attr); int ix = sensor_attr_2->index; @@ -1006,7 +1006,7 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *attr, data->fan_opt[ix]); break; default: - dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); + dev_dbg(dev, "Unknown function %d.\n", fn); } exit: mutex_unlock(&data->update_lock); @@ -1086,20 +1086,20 @@ static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, break; default: res = 0; - dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); + dev_dbg(dev, "Unknown function %d.\n", fn); } return sprintf(buf, "%d\n", res); } static struct attribute *dme1737_attr_pwm[]; -static void dme1737_chmod_file(struct i2c_client*, struct attribute*, mode_t); +static void dme1737_chmod_file(struct device*, struct attribute*, mode_t); static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct dme1737_data *data = i2c_get_clientdata(client); + struct dme1737_data *data = dev_get_drvdata(dev); + struct i2c_client *client = &data->client; struct sensor_device_attribute_2 *sensor_attr_2 = to_sensor_dev_attr_2(attr); int ix = sensor_attr_2->index; @@ -1156,7 +1156,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, switch (val) { case 0: /* Change permissions of pwm[ix] to read-only */ - dme1737_chmod_file(client, dme1737_attr_pwm[ix], + dme1737_chmod_file(dev, dme1737_attr_pwm[ix], S_IRUGO); /* Turn fan fully on */ data->pwm_config[ix] = PWM_EN_TO_REG(0, @@ -1171,12 +1171,12 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, dme1737_write(client, DME1737_REG_PWM_CONFIG(ix), data->pwm_config[ix]); /* Change permissions of pwm[ix] to read-writeable */ - dme1737_chmod_file(client, dme1737_attr_pwm[ix], + dme1737_chmod_file(dev, dme1737_attr_pwm[ix], S_IRUGO | S_IWUSR); break; case 2: /* Change permissions of pwm[ix] to read-only */ - dme1737_chmod_file(client, dme1737_attr_pwm[ix], + dme1737_chmod_file(dev, dme1737_attr_pwm[ix], S_IRUGO); /* Turn on auto mode using the saved zone channel * assignment */ @@ -1257,12 +1257,10 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, data->pwm_rr[0] = PWM_OFF_TO_REG(1, ix, dme1737_read(client, DME1737_REG_PWM_RR(0))); - } else { data->pwm_rr[0] = PWM_OFF_TO_REG(0, ix, dme1737_read(client, DME1737_REG_PWM_RR(0))); - } dme1737_write(client, DME1737_REG_PWM_RR(0), data->pwm_rr[0]); @@ -1274,7 +1272,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, data->pwm_min[ix]); break; default: - dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); + dev_dbg(dev, "Unknown function %d.\n", fn); } exit: mutex_unlock(&data->update_lock); @@ -1298,8 +1296,7 @@ static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct dme1737_data *data = i2c_get_clientdata(client); + struct dme1737_data *data = dev_get_drvdata(dev); long val = simple_strtol(buf, NULL, 10); data->vrm = val; @@ -1322,13 +1319,13 @@ static ssize_t show_vid(struct device *dev, struct device_attribute *attr, #define SENSOR_DEVICE_ATTR_IN(ix) \ static SENSOR_DEVICE_ATTR_2(in##ix##_input, S_IRUGO, \ - show_in, NULL, SYS_IN_INPUT, ix); \ + show_in, NULL, SYS_IN_INPUT, ix); \ static SENSOR_DEVICE_ATTR_2(in##ix##_min, S_IRUGO | S_IWUSR, \ - show_in, set_in, SYS_IN_MIN, ix); \ + show_in, set_in, SYS_IN_MIN, ix); \ static SENSOR_DEVICE_ATTR_2(in##ix##_max, S_IRUGO | S_IWUSR, \ - show_in, set_in, SYS_IN_MAX, ix); \ + show_in, set_in, SYS_IN_MAX, ix); \ static SENSOR_DEVICE_ATTR_2(in##ix##_alarm, S_IRUGO, \ - show_in, NULL, SYS_IN_ALARM, ix) + show_in, NULL, SYS_IN_ALARM, ix) SENSOR_DEVICE_ATTR_IN(0); SENSOR_DEVICE_ATTR_IN(1); @@ -1342,17 +1339,17 @@ SENSOR_DEVICE_ATTR_IN(6); #define SENSOR_DEVICE_ATTR_TEMP(ix) \ static SENSOR_DEVICE_ATTR_2(temp##ix##_input, S_IRUGO, \ - show_temp, NULL, SYS_TEMP_INPUT, ix-1); \ + show_temp, NULL, SYS_TEMP_INPUT, ix-1); \ static SENSOR_DEVICE_ATTR_2(temp##ix##_min, S_IRUGO | S_IWUSR, \ - show_temp, set_temp, SYS_TEMP_MIN, ix-1); \ + show_temp, set_temp, SYS_TEMP_MIN, ix-1); \ static SENSOR_DEVICE_ATTR_2(temp##ix##_max, S_IRUGO | S_IWUSR, \ - show_temp, set_temp, SYS_TEMP_MAX, ix-1); \ + show_temp, set_temp, SYS_TEMP_MAX, ix-1); \ static SENSOR_DEVICE_ATTR_2(temp##ix##_offset, S_IRUGO, \ - show_temp, set_temp, SYS_TEMP_OFFSET, ix-1); \ + show_temp, set_temp, SYS_TEMP_OFFSET, ix-1); \ static SENSOR_DEVICE_ATTR_2(temp##ix##_alarm, S_IRUGO, \ - show_temp, NULL, SYS_TEMP_ALARM, ix-1); \ + show_temp, NULL, SYS_TEMP_ALARM, ix-1); \ static SENSOR_DEVICE_ATTR_2(temp##ix##_fault, S_IRUGO, \ - show_temp, NULL, SYS_TEMP_FAULT, ix-1) + show_temp, NULL, SYS_TEMP_FAULT, ix-1) SENSOR_DEVICE_ATTR_TEMP(1); SENSOR_DEVICE_ATTR_TEMP(2); @@ -1362,15 +1359,15 @@ SENSOR_DEVICE_ATTR_TEMP(3); #define SENSOR_DEVICE_ATTR_ZONE(ix) \ static SENSOR_DEVICE_ATTR_2(zone##ix##_auto_channels_temp, S_IRUGO, \ - show_zone, NULL, SYS_ZONE_AUTO_CHANNELS_TEMP, ix-1); \ + show_zone, NULL, SYS_ZONE_AUTO_CHANNELS_TEMP, ix-1); \ static SENSOR_DEVICE_ATTR_2(zone##ix##_auto_point1_temp_hyst, S_IRUGO, \ - show_zone, set_zone, SYS_ZONE_AUTO_POINT1_TEMP_HYST, ix-1); \ + show_zone, set_zone, SYS_ZONE_AUTO_POINT1_TEMP_HYST, ix-1); \ static SENSOR_DEVICE_ATTR_2(zone##ix##_auto_point1_temp, S_IRUGO, \ - show_zone, set_zone, SYS_ZONE_AUTO_POINT1_TEMP, ix-1); \ + show_zone, set_zone, SYS_ZONE_AUTO_POINT1_TEMP, ix-1); \ static SENSOR_DEVICE_ATTR_2(zone##ix##_auto_point2_temp, S_IRUGO, \ - show_zone, set_zone, SYS_ZONE_AUTO_POINT2_TEMP, ix-1); \ + show_zone, set_zone, SYS_ZONE_AUTO_POINT2_TEMP, ix-1); \ static SENSOR_DEVICE_ATTR_2(zone##ix##_auto_point3_temp, S_IRUGO, \ - show_zone, set_zone, SYS_ZONE_AUTO_POINT3_TEMP, ix-1) + show_zone, set_zone, SYS_ZONE_AUTO_POINT3_TEMP, ix-1) SENSOR_DEVICE_ATTR_ZONE(1); SENSOR_DEVICE_ATTR_ZONE(2); @@ -1380,13 +1377,13 @@ SENSOR_DEVICE_ATTR_ZONE(3); #define SENSOR_DEVICE_ATTR_FAN_1TO4(ix) \ static SENSOR_DEVICE_ATTR_2(fan##ix##_input, S_IRUGO, \ - show_fan, NULL, SYS_FAN_INPUT, ix-1); \ + show_fan, NULL, SYS_FAN_INPUT, ix-1); \ static SENSOR_DEVICE_ATTR_2(fan##ix##_min, S_IRUGO | S_IWUSR, \ - show_fan, set_fan, SYS_FAN_MIN, ix-1); \ + show_fan, set_fan, SYS_FAN_MIN, ix-1); \ static SENSOR_DEVICE_ATTR_2(fan##ix##_alarm, S_IRUGO, \ - show_fan, NULL, SYS_FAN_ALARM, ix-1); \ + show_fan, NULL, SYS_FAN_ALARM, ix-1); \ static SENSOR_DEVICE_ATTR_2(fan##ix##_type, S_IRUGO | S_IWUSR, \ - show_fan, set_fan, SYS_FAN_TYPE, ix-1) + show_fan, set_fan, SYS_FAN_TYPE, ix-1) SENSOR_DEVICE_ATTR_FAN_1TO4(1); SENSOR_DEVICE_ATTR_FAN_1TO4(2); @@ -1397,13 +1394,13 @@ SENSOR_DEVICE_ATTR_FAN_1TO4(4); #define SENSOR_DEVICE_ATTR_FAN_5TO6(ix) \ static SENSOR_DEVICE_ATTR_2(fan##ix##_input, S_IRUGO, \ - show_fan, NULL, SYS_FAN_INPUT, ix-1); \ + show_fan, NULL, SYS_FAN_INPUT, ix-1); \ static SENSOR_DEVICE_ATTR_2(fan##ix##_min, S_IRUGO | S_IWUSR, \ - show_fan, set_fan, SYS_FAN_MIN, ix-1); \ + show_fan, set_fan, SYS_FAN_MIN, ix-1); \ static SENSOR_DEVICE_ATTR_2(fan##ix##_alarm, S_IRUGO, \ - show_fan, NULL, SYS_FAN_ALARM, ix-1); \ + show_fan, NULL, SYS_FAN_ALARM, ix-1); \ static SENSOR_DEVICE_ATTR_2(fan##ix##_max, S_IRUGO | S_IWUSR, \ - show_fan, set_fan, SYS_FAN_MAX, ix-1) + show_fan, set_fan, SYS_FAN_MAX, ix-1) SENSOR_DEVICE_ATTR_FAN_5TO6(5); SENSOR_DEVICE_ATTR_FAN_5TO6(6); @@ -1412,21 +1409,21 @@ SENSOR_DEVICE_ATTR_FAN_5TO6(6); #define SENSOR_DEVICE_ATTR_PWM_1TO3(ix) \ static SENSOR_DEVICE_ATTR_2(pwm##ix, S_IRUGO, \ - show_pwm, set_pwm, SYS_PWM, ix-1); \ + show_pwm, set_pwm, SYS_PWM, ix-1); \ static SENSOR_DEVICE_ATTR_2(pwm##ix##_freq, S_IRUGO, \ - show_pwm, set_pwm, SYS_PWM_FREQ, ix-1); \ + show_pwm, set_pwm, SYS_PWM_FREQ, ix-1); \ static SENSOR_DEVICE_ATTR_2(pwm##ix##_enable, S_IRUGO, \ - show_pwm, set_pwm, SYS_PWM_ENABLE, ix-1); \ + show_pwm, set_pwm, SYS_PWM_ENABLE, ix-1); \ static SENSOR_DEVICE_ATTR_2(pwm##ix##_ramp_rate, S_IRUGO, \ - show_pwm, set_pwm, SYS_PWM_RAMP_RATE, ix-1); \ + show_pwm, set_pwm, SYS_PWM_RAMP_RATE, ix-1); \ static SENSOR_DEVICE_ATTR_2(pwm##ix##_auto_channels_zone, S_IRUGO, \ - show_pwm, set_pwm, SYS_PWM_AUTO_CHANNELS_ZONE, ix-1); \ + show_pwm, set_pwm, SYS_PWM_AUTO_CHANNELS_ZONE, ix-1); \ static SENSOR_DEVICE_ATTR_2(pwm##ix##_auto_pwm_min, S_IRUGO, \ - show_pwm, set_pwm, SYS_PWM_AUTO_PWM_MIN, ix-1); \ + show_pwm, set_pwm, SYS_PWM_AUTO_PWM_MIN, ix-1); \ static SENSOR_DEVICE_ATTR_2(pwm##ix##_auto_point1_pwm, S_IRUGO, \ - show_pwm, set_pwm, SYS_PWM_AUTO_POINT1_PWM, ix-1); \ + show_pwm, set_pwm, SYS_PWM_AUTO_POINT1_PWM, ix-1); \ static SENSOR_DEVICE_ATTR_2(pwm##ix##_auto_point2_pwm, S_IRUGO, \ - show_pwm, NULL, SYS_PWM_AUTO_POINT2_PWM, ix-1) + show_pwm, NULL, SYS_PWM_AUTO_POINT2_PWM, ix-1) SENSOR_DEVICE_ATTR_PWM_1TO3(1); SENSOR_DEVICE_ATTR_PWM_1TO3(2); @@ -1436,11 +1433,11 @@ SENSOR_DEVICE_ATTR_PWM_1TO3(3); #define SENSOR_DEVICE_ATTR_PWM_5TO6(ix) \ static SENSOR_DEVICE_ATTR_2(pwm##ix, S_IRUGO | S_IWUSR, \ - show_pwm, set_pwm, SYS_PWM, ix-1); \ + show_pwm, set_pwm, SYS_PWM, ix-1); \ static SENSOR_DEVICE_ATTR_2(pwm##ix##_freq, S_IRUGO | S_IWUSR, \ - show_pwm, set_pwm, SYS_PWM_FREQ, ix-1); \ + show_pwm, set_pwm, SYS_PWM_FREQ, ix-1); \ static SENSOR_DEVICE_ATTR_2(pwm##ix##_enable, S_IRUGO, \ - show_pwm, NULL, SYS_PWM_ENABLE, ix-1) + show_pwm, NULL, SYS_PWM_ENABLE, ix-1) SENSOR_DEVICE_ATTR_PWM_5TO6(5); SENSOR_DEVICE_ATTR_PWM_5TO6(6); @@ -1519,53 +1516,53 @@ SENSOR_DEV_ATTR_PWM_5TO6_LOCK(ix), \ * permissions are created read-only and write permissions are added or removed * on the fly when required */ static struct attribute *dme1737_attr[] ={ - /* Voltages */ - SENSOR_DEV_ATTR_IN(0), - SENSOR_DEV_ATTR_IN(1), - SENSOR_DEV_ATTR_IN(2), - SENSOR_DEV_ATTR_IN(3), - SENSOR_DEV_ATTR_IN(4), - SENSOR_DEV_ATTR_IN(5), - SENSOR_DEV_ATTR_IN(6), - /* Temperatures */ - SENSOR_DEV_ATTR_TEMP(1), - SENSOR_DEV_ATTR_TEMP(2), - SENSOR_DEV_ATTR_TEMP(3), - /* Zones */ - SENSOR_DEV_ATTR_ZONE(1), - SENSOR_DEV_ATTR_ZONE(2), - SENSOR_DEV_ATTR_ZONE(3), - /* Misc */ - &dev_attr_vrm.attr, - &dev_attr_cpu0_vid.attr, + /* Voltages */ + SENSOR_DEV_ATTR_IN(0), + SENSOR_DEV_ATTR_IN(1), + SENSOR_DEV_ATTR_IN(2), + SENSOR_DEV_ATTR_IN(3), + SENSOR_DEV_ATTR_IN(4), + SENSOR_DEV_ATTR_IN(5), + SENSOR_DEV_ATTR_IN(6), + /* Temperatures */ + SENSOR_DEV_ATTR_TEMP(1), + SENSOR_DEV_ATTR_TEMP(2), + SENSOR_DEV_ATTR_TEMP(3), + /* Zones */ + SENSOR_DEV_ATTR_ZONE(1), + SENSOR_DEV_ATTR_ZONE(2), + SENSOR_DEV_ATTR_ZONE(3), + /* Misc */ + &dev_attr_vrm.attr, + &dev_attr_cpu0_vid.attr, NULL }; static const struct attribute_group dme1737_group = { - .attrs = dme1737_attr, + .attrs = dme1737_attr, }; /* The following structs hold the PWM attributes, some of which are optional. * Their creation depends on the chip configuration which is determined during * module load. */ static struct attribute *dme1737_attr_pwm1[] = { - SENSOR_DEV_ATTR_PWM_1TO3(1), + SENSOR_DEV_ATTR_PWM_1TO3(1), NULL }; static struct attribute *dme1737_attr_pwm2[] = { - SENSOR_DEV_ATTR_PWM_1TO3(2), + SENSOR_DEV_ATTR_PWM_1TO3(2), NULL }; static struct attribute *dme1737_attr_pwm3[] = { - SENSOR_DEV_ATTR_PWM_1TO3(3), + SENSOR_DEV_ATTR_PWM_1TO3(3), NULL }; static struct attribute *dme1737_attr_pwm5[] = { - SENSOR_DEV_ATTR_PWM_5TO6(5), + SENSOR_DEV_ATTR_PWM_5TO6(5), NULL }; static struct attribute *dme1737_attr_pwm6[] = { - SENSOR_DEV_ATTR_PWM_5TO6(6), + SENSOR_DEV_ATTR_PWM_5TO6(6), NULL }; @@ -1582,27 +1579,27 @@ static const struct attribute_group dme1737_pwm_group[] = { * Their creation depends on the chip configuration which is determined during * module load. */ static struct attribute *dme1737_attr_fan1[] = { - SENSOR_DEV_ATTR_FAN_1TO4(1), + SENSOR_DEV_ATTR_FAN_1TO4(1), NULL }; static struct attribute *dme1737_attr_fan2[] = { - SENSOR_DEV_ATTR_FAN_1TO4(2), + SENSOR_DEV_ATTR_FAN_1TO4(2), NULL }; static struct attribute *dme1737_attr_fan3[] = { - SENSOR_DEV_ATTR_FAN_1TO4(3), + SENSOR_DEV_ATTR_FAN_1TO4(3), NULL }; static struct attribute *dme1737_attr_fan4[] = { - SENSOR_DEV_ATTR_FAN_1TO4(4), + SENSOR_DEV_ATTR_FAN_1TO4(4), NULL }; static struct attribute *dme1737_attr_fan5[] = { - SENSOR_DEV_ATTR_FAN_5TO6(5), + SENSOR_DEV_ATTR_FAN_5TO6(5), NULL }; static struct attribute *dme1737_attr_fan6[] = { - SENSOR_DEV_ATTR_FAN_5TO6(6), + SENSOR_DEV_ATTR_FAN_5TO6(6), NULL }; @@ -1637,23 +1634,23 @@ static const struct attribute_group dme1737_lock_group = { * writeable if the chip is *not* locked and the respective PWM is available. * Otherwise they stay read-only. */ static struct attribute *dme1737_attr_pwm1_lock[] = { - SENSOR_DEV_ATTR_PWM_1TO3_LOCK(1), + SENSOR_DEV_ATTR_PWM_1TO3_LOCK(1), NULL }; static struct attribute *dme1737_attr_pwm2_lock[] = { - SENSOR_DEV_ATTR_PWM_1TO3_LOCK(2), + SENSOR_DEV_ATTR_PWM_1TO3_LOCK(2), NULL }; static struct attribute *dme1737_attr_pwm3_lock[] = { - SENSOR_DEV_ATTR_PWM_1TO3_LOCK(3), + SENSOR_DEV_ATTR_PWM_1TO3_LOCK(3), NULL }; static struct attribute *dme1737_attr_pwm5_lock[] = { - SENSOR_DEV_ATTR_PWM_5TO6_LOCK(5), + SENSOR_DEV_ATTR_PWM_5TO6_LOCK(5), NULL }; static struct attribute *dme1737_attr_pwm6_lock[] = { - SENSOR_DEV_ATTR_PWM_5TO6_LOCK(6), + SENSOR_DEV_ATTR_PWM_5TO6_LOCK(6), NULL }; @@ -1678,6 +1675,16 @@ static struct attribute *dme1737_attr_pwm[] = { * Super-IO functions * --------------------------------------------------------------------- */ +static inline void dme1737_sio_enter(int sio_cip) +{ + outb(0x55, sio_cip); +} + +static inline void dme1737_sio_exit(int sio_cip) +{ + outb(0xaa, sio_cip); +} + static inline int dme1737_sio_inb(int sio_cip, int reg) { outb(reg, sio_cip); @@ -1690,14 +1697,12 @@ static inline void dme1737_sio_outb(int sio_cip, int reg, int val) outb(val, sio_cip + 1); } -static int dme1737_sio_get_features(int sio_cip, struct i2c_client *client) +static int dme1737_i2c_get_features(int sio_cip, struct dme1737_data *data) { - struct dme1737_data *data = i2c_get_clientdata(client); int err = 0, reg; u16 addr; - /* Enter configuration mode */ - outb(0x55, sio_cip); + dme1737_sio_enter(sio_cip); /* Check device ID * The DME1737 can return either 0x78 or 0x77 as its device ID. */ @@ -1734,8 +1739,7 @@ static int dme1737_sio_get_features(int sio_cip, struct i2c_client *client) } exit: - /* Exit configuration mode */ - outb(0xaa, sio_cip); + dme1737_sio_exit(sio_cip); return err; } @@ -1744,51 +1748,142 @@ exit: * Device detection, registration and initialization * --------------------------------------------------------------------- */ -static struct i2c_driver dme1737_driver; +static struct i2c_driver dme1737_i2c_driver; -static void dme1737_chmod_file(struct i2c_client *client, +static void dme1737_chmod_file(struct device *dev, struct attribute *attr, mode_t mode) { - if (sysfs_chmod_file(&client->dev.kobj, attr, mode)) { - dev_warn(&client->dev, "Failed to change permissions of %s.\n", + if (sysfs_chmod_file(&dev->kobj, attr, mode)) { + dev_warn(dev, "Failed to change permissions of %s.\n", attr->name); } } -static void dme1737_chmod_group(struct i2c_client *client, +static void dme1737_chmod_group(struct device *dev, const struct attribute_group *group, mode_t mode) { struct attribute **attr; for (attr = group->attrs; *attr; attr++) { - dme1737_chmod_file(client, *attr, mode); + dme1737_chmod_file(dev, *attr, mode); } } -static int dme1737_init_client(struct i2c_client *client) +static void dme1737_remove_files(struct device *dev) { - struct dme1737_data *data = i2c_get_clientdata(client); + struct dme1737_data *data = dev_get_drvdata(dev); + int ix; + + for (ix = 0; ix < ARRAY_SIZE(dme1737_fan_group); ix++) { + if (data->has_fan & (1 << ix)) { + sysfs_remove_group(&dev->kobj, + &dme1737_fan_group[ix]); + } + } + + for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_group); ix++) { + if (data->has_pwm & (1 << ix)) { + sysfs_remove_group(&dev->kobj, + &dme1737_pwm_group[ix]); + } + } + + sysfs_remove_group(&dev->kobj, &dme1737_group); +} + +static int dme1737_create_files(struct device *dev) +{ + struct dme1737_data *data = dev_get_drvdata(dev); + int err, ix; + + /* Create standard sysfs attributes */ + if ((err = sysfs_create_group(&dev->kobj, &dme1737_group))) { + goto exit; + } + + /* Create fan sysfs attributes */ + for (ix = 0; ix < ARRAY_SIZE(dme1737_fan_group); ix++) { + if (data->has_fan & (1 << ix)) { + if ((err = sysfs_create_group(&dev->kobj, + &dme1737_fan_group[ix]))) { + goto exit_remove; + } + } + } + + /* Create PWM sysfs attributes */ + for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_group); ix++) { + if (data->has_pwm & (1 << ix)) { + if ((err = sysfs_create_group(&dev->kobj, + &dme1737_pwm_group[ix]))) { + goto exit_remove; + } + } + } + + /* Inform if the device is locked. Otherwise change the permissions of + * selected attributes from read-only to read-writeable. */ + if (data->config & 0x02) { + dev_info(dev, "Device is locked. Some attributes " + "will be read-only.\n"); + } else { + /* Change permissions of standard attributes */ + dme1737_chmod_group(dev, &dme1737_lock_group, + S_IRUGO | S_IWUSR); + + /* Change permissions of PWM attributes */ + for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_lock_group); ix++) { + if (data->has_pwm & (1 << ix)) { + dme1737_chmod_group(dev, + &dme1737_pwm_lock_group[ix], + S_IRUGO | S_IWUSR); + } + } + + /* Change permissions of pwm[1-3] if in manual mode */ + for (ix = 0; ix < 3; ix++) { + if ((data->has_pwm & (1 << ix)) && + (PWM_EN_FROM_REG(data->pwm_config[ix]) == 1)) { + dme1737_chmod_file(dev, + dme1737_attr_pwm[ix], + S_IRUGO | S_IWUSR); + } + } + } + + return 0; + +exit_remove: + dme1737_remove_files(dev); +exit: + return err; +} + +static int dme1737_init_device(struct device *dev) +{ + struct dme1737_data *data = dev_get_drvdata(dev); + struct i2c_client *client = &data->client; int ix; u8 reg; - data->config = dme1737_read(client, DME1737_REG_CONFIG); - /* Inform if part is not monitoring/started */ - if (!(data->config & 0x01)) { - if (!force_start) { - dev_err(&client->dev, "Device is not monitoring. " - "Use the force_start load parameter to " - "override.\n"); - return -EFAULT; - } - - /* Force monitoring */ - data->config |= 0x01; - dme1737_write(client, DME1737_REG_CONFIG, data->config); - } + data->config = dme1737_read(client, DME1737_REG_CONFIG); + /* Inform if part is not monitoring/started */ + if (!(data->config & 0x01)) { + if (!force_start) { + dev_err(dev, "Device is not monitoring. " + "Use the force_start load parameter to " + "override.\n"); + return -EFAULT; + } + + /* Force monitoring */ + data->config |= 0x01; + dme1737_write(client, DME1737_REG_CONFIG, data->config); + } /* Inform if part is not ready */ if (!(data->config & 0x04)) { - dev_err(&client->dev, "Device is not ready.\n"); + dev_err(dev, "Device is not ready.\n"); return -EFAULT; } @@ -1809,9 +1904,9 @@ static int dme1737_init_client(struct i2c_client *client) /* Determine if the optional fan[5-6] and/or pwm[5-6] are enabled. * For this, we need to query the runtime registers through the * Super-IO LPC interface. Try both config ports 0x2e and 0x4e. */ - if (dme1737_sio_get_features(0x2e, client) && - dme1737_sio_get_features(0x4e, client)) { - dev_warn(&client->dev, "Failed to query Super-IO for optional " + if (dme1737_i2c_get_features(0x2e, data) && + dme1737_i2c_get_features(0x4e, data)) { + dev_warn(dev, "Failed to query Super-IO for optional " "features.\n"); } @@ -1819,7 +1914,7 @@ static int dme1737_init_client(struct i2c_client *client) data->has_fan |= 0x03; data->has_pwm |= 0x03; - dev_info(&client->dev, "Optional features: pwm3=%s, pwm5=%s, pwm6=%s, " + dev_info(dev, "Optional features: pwm3=%s, pwm5=%s, pwm6=%s, " "fan3=%s, fan4=%s, fan5=%s, fan6=%s.\n", (data->has_pwm & (1 << 2)) ? "yes" : "no", (data->has_pwm & (1 << 4)) ? "yes" : "no", @@ -1832,7 +1927,7 @@ static int dme1737_init_client(struct i2c_client *client) reg = dme1737_read(client, DME1737_REG_TACH_PWM); /* Inform if fan-to-pwm mapping differs from the default */ if (reg != 0xa4) { - dev_warn(&client->dev, "Non-standard fan to pwm mapping: " + dev_warn(dev, "Non-standard fan to pwm mapping: " "fan1->pwm%d, fan2->pwm%d, fan3->pwm%d, " "fan4->pwm%d. Please report to the driver " "maintainer.\n", @@ -1849,7 +1944,7 @@ static int dme1737_init_client(struct i2c_client *client) DME1737_REG_PWM_CONFIG(ix)); if ((data->has_pwm & (1 << ix)) && (PWM_EN_FROM_REG(data->pwm_config[ix]) == -1)) { - dev_info(&client->dev, "Switching pwm%d to " + dev_info(dev, "Switching pwm%d to " "manual mode.\n", ix + 1); data->pwm_config[ix] = PWM_EN_TO_REG(1, data->pwm_config[ix]); @@ -1872,13 +1967,14 @@ static int dme1737_init_client(struct i2c_client *client) return 0; } -static int dme1737_detect(struct i2c_adapter *adapter, int address, - int kind) +static int dme1737_i2c_detect(struct i2c_adapter *adapter, int address, + int kind) { u8 company, verstep = 0; struct i2c_client *client; struct dme1737_data *data; - int ix, err = 0; + struct device *dev; + int err = 0; const char *name; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { @@ -1894,7 +1990,8 @@ static int dme1737_detect(struct i2c_adapter *adapter, int address, i2c_set_clientdata(client, data); client->addr = address; client->adapter = adapter; - client->driver = &dme1737_driver; + client->driver = &dme1737_i2c_driver; + dev = &client->dev; /* A negative kind means that the driver was loaded with no force * parameter (default), so we must identify the chip. */ @@ -1922,92 +2019,33 @@ static int dme1737_detect(struct i2c_adapter *adapter, int address, goto exit_kfree; } + dev_info(dev, "Found a DME1737 chip at 0x%02x (rev 0x%02x).\n", + client->addr, verstep); + /* Initialize the DME1737 chip */ - if ((err = dme1737_init_client(client))) { + if ((err = dme1737_init_device(dev))) { + dev_err(dev, "Failed to initialize device.\n"); goto exit_detach; } - /* Create standard sysfs attributes */ - if ((err = sysfs_create_group(&client->dev.kobj, &dme1737_group))) { - goto exit_detach; - } - - /* Create fan sysfs attributes */ - for (ix = 0; ix < ARRAY_SIZE(dme1737_fan_group); ix++) { - if (data->has_fan & (1 << ix)) { - if ((err = sysfs_create_group(&client->dev.kobj, - &dme1737_fan_group[ix]))) { - goto exit_remove; - } - } - } - - /* Create PWM sysfs attributes */ - for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_group); ix++) { - if (data->has_pwm & (1 << ix)) { - if ((err = sysfs_create_group(&client->dev.kobj, - &dme1737_pwm_group[ix]))) { - goto exit_remove; - } - } - } - - /* Inform if the device is locked. Otherwise change the permissions of - * selected attributes from read-only to read-writeable. */ - if (data->config & 0x02) { - dev_info(&client->dev, "Device is locked. Some attributes " - "will be read-only.\n"); - } else { - /* Change permissions of standard attributes */ - dme1737_chmod_group(client, &dme1737_lock_group, - S_IRUGO | S_IWUSR); - - /* Change permissions of PWM attributes */ - for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_lock_group); ix++) { - if (data->has_pwm & (1 << ix)) { - dme1737_chmod_group(client, - &dme1737_pwm_lock_group[ix], - S_IRUGO | S_IWUSR); - } - } - - /* Change permissions of pwm[1-3] if in manual mode */ - for (ix = 0; ix < 3; ix++) { - if ((data->has_pwm & (1 << ix)) && - (PWM_EN_FROM_REG(data->pwm_config[ix]) == 1)) { - dme1737_chmod_file(client, - dme1737_attr_pwm[ix], - S_IRUGO | S_IWUSR); - } - } + /* Create sysfs files */ + if ((err = dme1737_create_files(dev))) { + dev_err(dev, "Failed to create sysfs files.\n"); + goto exit_detach; } /* Register device */ - data->class_dev = hwmon_device_register(&client->dev); + data->class_dev = hwmon_device_register(dev); if (IS_ERR(data->class_dev)) { + dev_err(dev, "Failed to register device.\n"); err = PTR_ERR(data->class_dev); goto exit_remove; } - dev_info(&adapter->dev, "Found a DME1737 chip at 0x%02x " - "(rev 0x%02x)\n", client->addr, verstep); - return 0; exit_remove: - for (ix = 0; ix < ARRAY_SIZE(dme1737_fan_group); ix++) { - if (data->has_fan & (1 << ix)) { - sysfs_remove_group(&client->dev.kobj, - &dme1737_fan_group[ix]); - } - } - for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_group); ix++) { - if (data->has_pwm & (1 << ix)) { - sysfs_remove_group(&client->dev.kobj, - &dme1737_pwm_group[ix]); - } - } - sysfs_remove_group(&client->dev.kobj, &dme1737_group); + dme1737_remove_files(dev); exit_detach: i2c_detach_client(client); exit_kfree: @@ -2016,35 +2054,22 @@ exit: return err; } -static int dme1737_attach_adapter(struct i2c_adapter *adapter) +static int dme1737_i2c_attach_adapter(struct i2c_adapter *adapter) { if (!(adapter->class & I2C_CLASS_HWMON)) { return 0; } - return i2c_probe(adapter, &addr_data, dme1737_detect); + return i2c_probe(adapter, &addr_data, dme1737_i2c_detect); } -static int dme1737_detach_client(struct i2c_client *client) +static int dme1737_i2c_detach_client(struct i2c_client *client) { struct dme1737_data *data = i2c_get_clientdata(client); - int ix, err; + int err; hwmon_device_unregister(data->class_dev); - - for (ix = 0; ix < ARRAY_SIZE(dme1737_fan_group); ix++) { - if (data->has_fan & (1 << ix)) { - sysfs_remove_group(&client->dev.kobj, - &dme1737_fan_group[ix]); - } - } - for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_group); ix++) { - if (data->has_pwm & (1 << ix)) { - sysfs_remove_group(&client->dev.kobj, - &dme1737_pwm_group[ix]); - } - } - sysfs_remove_group(&client->dev.kobj, &dme1737_group); + dme1737_remove_files(&client->dev); if ((err = i2c_detach_client(client))) { return err; @@ -2054,22 +2079,22 @@ static int dme1737_detach_client(struct i2c_client *client) return 0; } -static struct i2c_driver dme1737_driver = { +static struct i2c_driver dme1737_i2c_driver = { .driver = { .name = "dme1737", }, - .attach_adapter = dme1737_attach_adapter, - .detach_client = dme1737_detach_client, + .attach_adapter = dme1737_i2c_attach_adapter, + .detach_client = dme1737_i2c_detach_client, }; static int __init dme1737_init(void) { - return i2c_add_driver(&dme1737_driver); + return i2c_add_driver(&dme1737_i2c_driver); } static void __exit dme1737_exit(void) { - i2c_del_driver(&dme1737_driver); + i2c_del_driver(&dme1737_i2c_driver); } MODULE_AUTHOR("Juerg Haefliger "); -- cgit v1.2.3 From 67e2f3285ecff8ceaa555e7614d1603b76e09b95 Mon Sep 17 00:00:00 2001 From: Juerg Haefliger Date: Mon, 1 Oct 2007 21:20:28 -0700 Subject: hwmon: (dme1737) group functions logically Move functions to group them logically. Device and I2C functions go in separate places. No functional changes (really!). Signed-off-by: Juerg Haefliger Acked-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/dme1737.c | 106 ++++++++++++++++++++++++++---------------------- 1 file changed, 58 insertions(+), 48 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c index cef662c6af9..63cee3b6f9b 100644 --- a/drivers/hwmon/dme1737.c +++ b/drivers/hwmon/dme1737.c @@ -1697,58 +1697,11 @@ static inline void dme1737_sio_outb(int sio_cip, int reg, int val) outb(val, sio_cip + 1); } -static int dme1737_i2c_get_features(int sio_cip, struct dme1737_data *data) -{ - int err = 0, reg; - u16 addr; - - dme1737_sio_enter(sio_cip); - - /* Check device ID - * The DME1737 can return either 0x78 or 0x77 as its device ID. */ - reg = dme1737_sio_inb(sio_cip, 0x20); - if (!(reg == 0x77 || reg == 0x78)) { - err = -ENODEV; - goto exit; - } - - /* Select logical device A (runtime registers) */ - dme1737_sio_outb(sio_cip, 0x07, 0x0a); - - /* Get the base address of the runtime registers */ - if (!(addr = (dme1737_sio_inb(sio_cip, 0x60) << 8) | - dme1737_sio_inb(sio_cip, 0x61))) { - err = -ENODEV; - goto exit; - } - - /* Read the runtime registers to determine which optional features - * are enabled and available. Bits [3:2] of registers 0x43-0x46 are set - * to '10' if the respective feature is enabled. */ - if ((inb(addr + 0x43) & 0x0c) == 0x08) { /* fan6 */ - data->has_fan |= (1 << 5); - } - if ((inb(addr + 0x44) & 0x0c) == 0x08) { /* pwm6 */ - data->has_pwm |= (1 << 5); - } - if ((inb(addr + 0x45) & 0x0c) == 0x08) { /* fan5 */ - data->has_fan |= (1 << 4); - } - if ((inb(addr + 0x46) & 0x0c) == 0x08) { /* pwm5 */ - data->has_pwm |= (1 << 4); - } - -exit: - dme1737_sio_exit(sio_cip); - - return err; -} - /* --------------------------------------------------------------------- * Device detection, registration and initialization * --------------------------------------------------------------------- */ -static struct i2c_driver dme1737_i2c_driver; +static int dme1737_i2c_get_features(int, struct dme1737_data*); static void dme1737_chmod_file(struct device *dev, struct attribute *attr, mode_t mode) @@ -1967,6 +1920,59 @@ static int dme1737_init_device(struct device *dev) return 0; } +/* --------------------------------------------------------------------- + * I2C device detection and registration + * --------------------------------------------------------------------- */ + +static struct i2c_driver dme1737_i2c_driver; + +static int dme1737_i2c_get_features(int sio_cip, struct dme1737_data *data) +{ + int err = 0, reg; + u16 addr; + + dme1737_sio_enter(sio_cip); + + /* Check device ID + * The DME1737 can return either 0x78 or 0x77 as its device ID. */ + reg = dme1737_sio_inb(sio_cip, 0x20); + if (!(reg == 0x77 || reg == 0x78)) { + err = -ENODEV; + goto exit; + } + + /* Select logical device A (runtime registers) */ + dme1737_sio_outb(sio_cip, 0x07, 0x0a); + + /* Get the base address of the runtime registers */ + if (!(addr = (dme1737_sio_inb(sio_cip, 0x60) << 8) | + dme1737_sio_inb(sio_cip, 0x61))) { + err = -ENODEV; + goto exit; + } + + /* Read the runtime registers to determine which optional features + * are enabled and available. Bits [3:2] of registers 0x43-0x46 are set + * to '10' if the respective feature is enabled. */ + if ((inb(addr + 0x43) & 0x0c) == 0x08) { /* fan6 */ + data->has_fan |= (1 << 5); + } + if ((inb(addr + 0x44) & 0x0c) == 0x08) { /* pwm6 */ + data->has_pwm |= (1 << 5); + } + if ((inb(addr + 0x45) & 0x0c) == 0x08) { /* fan5 */ + data->has_fan |= (1 << 4); + } + if ((inb(addr + 0x46) & 0x0c) == 0x08) { /* pwm5 */ + data->has_pwm |= (1 << 4); + } + +exit: + dme1737_sio_exit(sio_cip); + + return err; +} + static int dme1737_i2c_detect(struct i2c_adapter *adapter, int address, int kind) { @@ -2087,6 +2093,10 @@ static struct i2c_driver dme1737_i2c_driver = { .detach_client = dme1737_i2c_detach_client, }; +/* --------------------------------------------------------------------- + * Module initialization and cleanup + * --------------------------------------------------------------------- */ + static int __init dme1737_init(void) { return i2c_add_driver(&dme1737_i2c_driver); -- cgit v1.2.3 From e95c237d78c0dc8fc0ae1207cec87af7a37dd366 Mon Sep 17 00:00:00 2001 From: Juerg Haefliger Date: Sun, 7 Oct 2007 21:27:35 -0700 Subject: hwmon: (dme1737) Add sch311x support This patch adds support for the SMSC SCH3112, SCH3114, and SCH3116 Super-I/O chips. These chips feature identical hardware monitoring capabilites with the expection that some of the fan inputs and pmw outputs don't exist. The hardware monitoring features of the SCH311x chips can only be accessed via the ISA bus. The driver therefore registers as a platform driver, if such a chip is detected. Signed-off-by: Juerg Haefliger Acked-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/Kconfig | 4 +- drivers/hwmon/dme1737.c | 375 ++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 336 insertions(+), 43 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index b8854b94807..c69de6c56d9 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -509,13 +509,13 @@ config SENSORS_SIS5595 will be called sis5595. config SENSORS_DME1737 - tristate "SMSC DME1737 and compatibles" + tristate "SMSC DME1737, SCH311x and compatibles" depends on I2C && EXPERIMENTAL select HWMON_VID help If you say yes here you get support for the hardware monitoring and fan control features of the SMSC DME1737 (and compatibles - like the Asus A8000) Super-I/O chip. + like the Asus A8000) and SCH311x Super-I/O chips. This driver can also be built as a module. If so, the module will be called dme1737. diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c index ec8edd2a8cb..a878c98e252 100644 --- a/drivers/hwmon/dme1737.c +++ b/drivers/hwmon/dme1737.c @@ -1,12 +1,12 @@ /* - * dme1737.c - driver for the SMSC DME1737 and Asus A8000 Super-I/O chips - * integrated hardware monitoring features. + * dme1737.c - Driver for the SMSC DME1737, Asus A8000, and SMSC SCH311x + * Super-I/O chips integrated hardware monitoring features. * Copyright (c) 2007 Juerg Haefliger * - * This driver is based on the LM85 driver. The hardware monitoring - * capabilities of the DME1737 are very similar to the LM85 with some - * additional features. Even though the DME1737 is a Super-I/O chip, the - * hardware monitoring registers are only accessible via SMBus. + * This driver is an I2C/ISA hybrid, meaning that it uses the I2C bus to access + * the chip registers if a DME1737 (or A8000) is found and the ISA bus if a + * SCH311x chip is found. Both types of chips have very similar hardware + * monitoring capabilities but differ in the way they can be accessed. * * 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 @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,9 @@ #include #include +/* ISA device, if found */ +static struct platform_device *pdev; + /* Module load parameters */ static int force_start; module_param(force_start, bool, 0); @@ -133,6 +137,7 @@ static const u8 DME1737_BIT_ALARM_TEMP[] = {4, 5, 6}; static const u8 DME1737_BIT_ALARM_FAN[] = {10, 11, 12, 13, 22, 23}; /* Miscellaneous registers */ +#define DME1737_REG_DEVICE 0x3d #define DME1737_REG_COMPANY 0x3e #define DME1737_REG_VERSTEP 0x3f #define DME1737_REG_CONFIG 0x40 @@ -148,11 +153,17 @@ static const u8 DME1737_BIT_ALARM_FAN[] = {10, 11, 12, 13, 22, 23}; #define DME1737_COMPANY_SMSC 0x5c #define DME1737_VERSTEP 0x88 #define DME1737_VERSTEP_MASK 0xf8 +#define SCH311X_DEVICE 0x8c + +/* Length of ISA address segment */ +#define DME1737_EXTENT 2 /* --------------------------------------------------------------------- * Data structures and manipulation thereof * --------------------------------------------------------------------- */ +/* For ISA chips, we abuse the i2c_client addr and name fields. We also use + the driver field to differentiate between I2C and ISA chips. */ struct dme1737_data { struct i2c_client client; struct device *hwmon_dev; @@ -465,27 +476,48 @@ static inline int PWM_OFF_TO_REG(int val, int ix, int reg) /* --------------------------------------------------------------------- * Device I/O access + * + * ISA access is performed through an index/data register pair and needs to + * be protected by a mutex during runtime (not required for initialization). + * We use data->update_lock for this and need to ensure that we acquire it + * before calling dme1737_read or dme1737_write. * --------------------------------------------------------------------- */ static u8 dme1737_read(struct i2c_client *client, u8 reg) { - s32 val = i2c_smbus_read_byte_data(client, reg); + s32 val; - if (val < 0) { - dev_warn(&client->dev, "Read from register 0x%02x failed! " - "Please report to the driver maintainer.\n", reg); + if (client->driver) { /* I2C device */ + val = i2c_smbus_read_byte_data(client, reg); + + if (val < 0) { + dev_warn(&client->dev, "Read from register " + "0x%02x failed! Please report to the driver " + "maintainer.\n", reg); + } + } else { /* ISA device */ + outb(reg, client->addr); + val = inb(client->addr + 1); } return val; } -static s32 dme1737_write(struct i2c_client *client, u8 reg, u8 value) +static s32 dme1737_write(struct i2c_client *client, u8 reg, u8 val) { - s32 res = i2c_smbus_write_byte_data(client, reg, value); + s32 res = 0; + + if (client->driver) { /* I2C device */ + res = i2c_smbus_write_byte_data(client, reg, val); - if (res < 0) { - dev_warn(&client->dev, "Write to register 0x%02x failed! " - "Please report to the driver maintainer.\n", reg); + if (res < 0) { + dev_warn(&client->dev, "Write to register " + "0x%02x failed! Please report to the driver " + "maintainer.\n", reg); + } + } else { /* ISA device */ + outb(reg, client->addr); + outb(val, client->addr + 1); } return res; @@ -630,6 +662,24 @@ static struct dme1737_data *dme1737_update_device(struct device *dev) DME1737_REG_ALARM3) << 16; } + /* The ISA chips require explicit clearing of alarm bits. + * Don't worry, an alarm will come back if the condition + * that causes it still exists */ + if (!client->driver) { + if (data->alarms & 0xff0000) { + dme1737_write(client, DME1737_REG_ALARM3, + 0xff); + } + if (data->alarms & 0xff00) { + dme1737_write(client, DME1737_REG_ALARM2, + 0xff); + } + if (data->alarms & 0xff) { + dme1737_write(client, DME1737_REG_ALARM1, + 0xff); + } + } + data->last_update = jiffies; data->valid = 1; } @@ -995,7 +1045,7 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *attr, /* Only valid for fan[1-4] */ if (!(val == 1 || val == 2 || val == 4)) { count = -EINVAL; - dev_warn(&client->dev, "Fan type value %ld not " + dev_warn(dev, "Fan type value %ld not " "supported. Choose one of 1, 2, or 4.\n", val); goto exit; @@ -1122,7 +1172,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, /* Only valid for pwm[1-3] */ if (val < 0 || val > 2) { count = -EINVAL; - dev_warn(&client->dev, "PWM enable %ld not " + dev_warn(dev, "PWM enable %ld not " "supported. Choose one of 0, 1, or 2.\n", val); goto exit; @@ -1223,7 +1273,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, if (!(val == 1 || val == 2 || val == 4 || val == 6 || val == 7)) { count = -EINVAL; - dev_warn(&client->dev, "PWM auto channels zone %ld " + dev_warn(dev, "PWM auto channels zone %ld " "not supported. Choose one of 1, 2, 4, 6, " "or 7.\n", val); goto exit; @@ -1311,6 +1361,14 @@ static ssize_t show_vid(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm)); } +static ssize_t show_name(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct dme1737_data *data = dev_get_drvdata(dev); + + return sprintf(buf, "%s\n", data->client.name); +} + /* --------------------------------------------------------------------- * Sysfs device attribute defines and structs * --------------------------------------------------------------------- */ @@ -1446,6 +1504,7 @@ SENSOR_DEVICE_ATTR_PWM_5TO6(6); static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm); static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); +static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); /* for ISA devices */ #define SENSOR_DEV_ATTR_IN(ix) \ &sensor_dev_attr_in##ix##_input.dev_attr.attr, \ @@ -1698,7 +1757,7 @@ static inline void dme1737_sio_outb(int sio_cip, int reg, int val) } /* --------------------------------------------------------------------- - * Device detection, registration and initialization + * Device initialization * --------------------------------------------------------------------- */ static int dme1737_i2c_get_features(int, struct dme1737_data*); @@ -1743,6 +1802,10 @@ static void dme1737_remove_files(struct device *dev) } sysfs_remove_group(&dev->kobj, &dme1737_group); + + if (!data->client.driver) { + sysfs_remove_file(&dev->kobj, &dev_attr_name.attr); + } } static int dme1737_create_files(struct device *dev) @@ -1750,9 +1813,15 @@ static int dme1737_create_files(struct device *dev) struct dme1737_data *data = dev_get_drvdata(dev); int err, ix; + /* Create a name attribute for ISA devices */ + if (!data->client.driver && + (err = sysfs_create_file(&dev->kobj, &dev_attr_name.attr))) { + goto exit; + } + /* Create standard sysfs attributes */ if ((err = sysfs_create_group(&dev->kobj, &dme1737_group))) { - goto exit; + goto exit_remove; } /* Create fan sysfs attributes */ @@ -1840,27 +1909,36 @@ static int dme1737_init_device(struct device *dev) return -EFAULT; } - data->config2 = dme1737_read(client, DME1737_REG_CONFIG2); - /* Check if optional fan3 input is enabled */ - if (data->config2 & 0x04) { - data->has_fan |= (1 << 2); - } + /* Determine which optional fan and pwm features are enabled/present */ + if (client->driver) { /* I2C chip */ + data->config2 = dme1737_read(client, DME1737_REG_CONFIG2); + /* Check if optional fan3 input is enabled */ + if (data->config2 & 0x04) { + data->has_fan |= (1 << 2); + } - /* Fan4 and pwm3 are only available if the client's I2C address - * is the default 0x2e. Otherwise the I/Os associated with these - * functions are used for addr enable/select. */ - if (client->addr == 0x2e) { - data->has_fan |= (1 << 3); - data->has_pwm |= (1 << 2); - } + /* Fan4 and pwm3 are only available if the client's I2C address + * is the default 0x2e. Otherwise the I/Os associated with + * these functions are used for addr enable/select. */ + if (data->client.addr == 0x2e) { + data->has_fan |= (1 << 3); + data->has_pwm |= (1 << 2); + } - /* Determine if the optional fan[5-6] and/or pwm[5-6] are enabled. - * For this, we need to query the runtime registers through the - * Super-IO LPC interface. Try both config ports 0x2e and 0x4e. */ - if (dme1737_i2c_get_features(0x2e, data) && - dme1737_i2c_get_features(0x4e, data)) { - dev_warn(dev, "Failed to query Super-IO for optional " - "features.\n"); + /* Determine which of the optional fan[5-6] and pwm[5-6] + * features are enabled. For this, we need to query the runtime + * registers through the Super-IO LPC interface. Try both + * config ports 0x2e and 0x4e. */ + if (dme1737_i2c_get_features(0x2e, data) && + dme1737_i2c_get_features(0x4e, data)) { + dev_warn(dev, "Failed to query Super-IO for optional " + "features.\n"); + } + } else { /* ISA chip */ + /* Fan3 and pwm3 are always available. Fan[4-5] and pwm[5-6] + * don't exist in the ISA chip. */ + data->has_fan |= (1 << 2); + data->has_pwm |= (1 << 2); } /* Fan1, fan2, pwm1, and pwm2 are always present */ @@ -1879,13 +1957,19 @@ static int dme1737_init_device(struct device *dev) reg = dme1737_read(client, DME1737_REG_TACH_PWM); /* Inform if fan-to-pwm mapping differs from the default */ - if (reg != 0xa4) { + if (client->driver && reg != 0xa4) { /* I2C chip */ dev_warn(dev, "Non-standard fan to pwm mapping: " "fan1->pwm%d, fan2->pwm%d, fan3->pwm%d, " "fan4->pwm%d. Please report to the driver " "maintainer.\n", (reg & 0x03) + 1, ((reg >> 2) & 0x03) + 1, ((reg >> 4) & 0x03) + 1, ((reg >> 6) & 0x03) + 1); + } else if (!client->driver && reg != 0x24) { /* ISA chip */ + dev_warn(dev, "Non-standard fan to pwm mapping: " + "fan1->pwm%d, fan2->pwm%d, fan3->pwm%d. " + "Please report to the driver maintainer.\n", + (reg & 0x03) + 1, ((reg >> 2) & 0x03) + 1, + ((reg >> 4) & 0x03) + 1); } /* Switch pwm[1-3] to manual mode if they are currently disabled and @@ -2093,17 +2177,226 @@ static struct i2c_driver dme1737_i2c_driver = { .detach_client = dme1737_i2c_detach_client, }; +/* --------------------------------------------------------------------- + * ISA device detection and registration + * --------------------------------------------------------------------- */ + +static int __init dme1737_isa_detect(int sio_cip, unsigned short *addr) +{ + int err = 0, reg; + unsigned short base_addr; + + dme1737_sio_enter(sio_cip); + + /* Check device ID + * We currently know about SCH3112 (0x7c), SCH3114 (0x7d), and + * SCH3116 (0x7f). */ + reg = dme1737_sio_inb(sio_cip, 0x20); + if (!(reg == 0x7c || reg == 0x7d || reg == 0x7f)) { + err = -ENODEV; + goto exit; + } + + /* Select logical device A (runtime registers) */ + dme1737_sio_outb(sio_cip, 0x07, 0x0a); + + /* Get the base address of the runtime registers */ + if (!(base_addr = (dme1737_sio_inb(sio_cip, 0x60) << 8) | + dme1737_sio_inb(sio_cip, 0x61))) { + printk(KERN_ERR "dme1737: Base address not set.\n"); + err = -ENODEV; + goto exit; + } + + /* Access to the hwmon registers is through an index/data register + * pair located at offset 0x70/0x71. */ + *addr = base_addr + 0x70; + +exit: + dme1737_sio_exit(sio_cip); + return err; +} + +static int __init dme1737_isa_device_add(unsigned short addr) +{ + struct resource res = { + .start = addr, + .end = addr + DME1737_EXTENT - 1, + .name = "dme1737", + .flags = IORESOURCE_IO, + }; + int err; + + if (!(pdev = platform_device_alloc("dme1737", addr))) { + printk(KERN_ERR "dme1737: Failed to allocate device.\n"); + err = -ENOMEM; + goto exit; + } + + if ((err = platform_device_add_resources(pdev, &res, 1))) { + printk(KERN_ERR "dme1737: Failed to add device resource " + "(err = %d).\n", err); + goto exit_device_put; + } + + if ((err = platform_device_add(pdev))) { + printk(KERN_ERR "dme1737: Failed to add device (err = %d).\n", + err); + goto exit_device_put; + } + + return 0; + +exit_device_put: + platform_device_put(pdev); + pdev = NULL; +exit: + return err; +} + +static int __devinit dme1737_isa_probe(struct platform_device *pdev) +{ + u8 company, device; + struct resource *res; + struct i2c_client *client; + struct dme1737_data *data; + struct device *dev = &pdev->dev; + int err; + + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (!request_region(res->start, DME1737_EXTENT, "dme1737")) { + dev_err(dev, "Failed to request region 0x%04x-0x%04x.\n", + (unsigned short)res->start, + (unsigned short)res->start + DME1737_EXTENT - 1); + err = -EBUSY; + goto exit; + } + + if (!(data = kzalloc(sizeof(struct dme1737_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit_release_region; + } + + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = res->start; + platform_set_drvdata(pdev, data); + + company = dme1737_read(client, DME1737_REG_COMPANY); + device = dme1737_read(client, DME1737_REG_DEVICE); + + if (!((company == DME1737_COMPANY_SMSC) && + (device == SCH311X_DEVICE))) { + err = -ENODEV; + goto exit_kfree; + } + + /* Fill in the remaining client fields and initialize the mutex */ + strlcpy(client->name, "sch311x", I2C_NAME_SIZE); + mutex_init(&data->update_lock); + + dev_info(dev, "Found a SCH311x chip at 0x%04x\n", client->addr); + + /* Initialize the chip */ + if ((err = dme1737_init_device(dev))) { + dev_err(dev, "Failed to initialize device.\n"); + goto exit_kfree; + } + + /* Create sysfs files */ + if ((err = dme1737_create_files(dev))) { + dev_err(dev, "Failed to create sysfs files.\n"); + goto exit_kfree; + } + + /* Register device */ + data->hwmon_dev = hwmon_device_register(dev); + if (IS_ERR(data->hwmon_dev)) { + dev_err(dev, "Failed to register device.\n"); + err = PTR_ERR(data->hwmon_dev); + goto exit_remove_files; + } + + return 0; + +exit_remove_files: + dme1737_remove_files(dev); +exit_kfree: + platform_set_drvdata(pdev, NULL); + kfree(data); +exit_release_region: + release_region(res->start, DME1737_EXTENT); +exit: + return err; +} + +static int __devexit dme1737_isa_remove(struct platform_device *pdev) +{ + struct dme1737_data *data = platform_get_drvdata(pdev); + + hwmon_device_unregister(data->hwmon_dev); + dme1737_remove_files(&pdev->dev); + release_region(data->client.addr, DME1737_EXTENT); + platform_set_drvdata(pdev, NULL); + kfree(data); + + return 0; +} + +static struct platform_driver dme1737_isa_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "dme1737", + }, + .probe = dme1737_isa_probe, + .remove = __devexit_p(dme1737_isa_remove), +}; + /* --------------------------------------------------------------------- * Module initialization and cleanup * --------------------------------------------------------------------- */ static int __init dme1737_init(void) { - return i2c_add_driver(&dme1737_i2c_driver); + int err; + unsigned short addr; + + if ((err = i2c_add_driver(&dme1737_i2c_driver))) { + goto exit; + } + + if (dme1737_isa_detect(0x2e, &addr) && + dme1737_isa_detect(0x4e, &addr)) { + /* Return 0 if we didn't find an ISA device */ + return 0; + } + + if ((err = platform_driver_register(&dme1737_isa_driver))) { + goto exit_del_i2c_driver; + } + + /* Sets global pdev as a side effect */ + if ((err = dme1737_isa_device_add(addr))) { + goto exit_del_isa_driver; + } + + return 0; + +exit_del_isa_driver: + platform_driver_unregister(&dme1737_isa_driver); +exit_del_i2c_driver: + i2c_del_driver(&dme1737_i2c_driver); +exit: + return err; } static void __exit dme1737_exit(void) { + if (pdev) { + platform_device_unregister(pdev); + platform_driver_unregister(&dme1737_isa_driver); + } + i2c_del_driver(&dme1737_i2c_driver); } -- cgit v1.2.3 From 4cfdbe7f6cfdc07c27ae8ac490cd3453440dd9d8 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Tue, 9 Oct 2007 15:08:24 -0700 Subject: hwmon: (ibmpex) Release IPMI user if hwmon registration fails Roel Kluin <12o3l@tiscali.nl> found a minor defect in the init code if hwmon device registration fails. Signed-off-by: Darrick J. Wong Signed-off-by: Mark M. Hoffman --- drivers/hwmon/ibmpex.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/ibmpex.c b/drivers/hwmon/ibmpex.c index fe2c2616c6b..c462824ffcc 100644 --- a/drivers/hwmon/ibmpex.c +++ b/drivers/hwmon/ibmpex.c @@ -498,8 +498,7 @@ static void ibmpex_register_bmc(int iface, struct device *dev) printk(KERN_ERR DRVNAME ": Error, unable to register hwmon " "class device for interface %d\n", data->interface); - kfree(data); - return; + goto out_user; } /* finally add the new bmc data to the bmc data list */ -- cgit v1.2.3 From 569ff1022662a88591b0a89ea316a3c44306d199 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 11 Oct 2007 08:06:29 -0400 Subject: hwmon: Add new combined driver for FSC chips This patch adds a new merged driver for FSC sensor chips, it merges the fscher and fscpos drivers and adds support for the FSC Scylla, Heracles and Heimdall chips. Signed-off-by: Hans de Goede Acked-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/Kconfig | 14 + drivers/hwmon/Makefile | 1 + drivers/hwmon/fschmd.c | 778 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 793 insertions(+) create mode 100644 drivers/hwmon/fschmd.c (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index c69de6c56d9..e47f8817080 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -266,6 +266,20 @@ config SENSORS_FSCPOS This driver can also be built as a module. If so, the module will be called fscpos. +config SENSORS_FSCHMD + tristate "FSC Poseidon, Scylla, Hermes, Heimdall and Heracles" + depends on X86 && I2C && EXPERIMENTAL + help + If you say yes here you get support for various Fujitsu Siemens + Computers sensor chips. + + This is a new merged driver for FSC sensor chips which is intended + as a replacment for the fscpos, fscscy and fscher drivers and adds + support for several other FCS sensor chips. + + This driver can also be built as a module. If so, the module + will be called fschmd. + config SENSORS_GL518SM tristate "Genesys Logic GL518SM" depends on I2C diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 2f592e2e01b..6da3eef9430 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_SENSORS_F71805F) += f71805f.o obj-$(CONFIG_SENSORS_F71882FG) += f71882fg.o obj-$(CONFIG_SENSORS_F75375S) += f75375s.o obj-$(CONFIG_SENSORS_FSCHER) += fscher.o +obj-$(CONFIG_SENSORS_FSCHMD) += fschmd.o obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c new file mode 100644 index 00000000000..63a4df0580d --- /dev/null +++ b/drivers/hwmon/fschmd.c @@ -0,0 +1,778 @@ +/* fschmd.c + * + * Copyright (C) 2007 Hans de Goede + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * Merged Fujitsu Siemens hwmon driver, supporting the Poseidon, Hermes, + * Scylla, Heracles and Heimdall chips + * + * Based on the original 2.4 fscscy, 2.6 fscpos, 2.6 fscher and 2.6 + * (candidate) fschmd drivers: + * Copyright (C) 2006 Thilo Cestonaro + * + * Copyright (C) 2004, 2005 Stefan Ott + * Copyright (C) 2003, 2004 Reinhard Nissl + * Copyright (c) 2001 Martin Knoblauch + * Copyright (C) 2000 Hermann Jung + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Addresses to scan */ +static unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END }; + +/* Insmod parameters */ +I2C_CLIENT_INSMOD_5(fscpos, fscher, fscscy, fschrc, fschmd); + +/* + * The FSCHMD registers and other defines + */ + +/* chip identification */ +#define FSCHMD_REG_IDENT_0 0x00 +#define FSCHMD_REG_IDENT_1 0x01 +#define FSCHMD_REG_IDENT_2 0x02 +#define FSCHMD_REG_REVISION 0x03 + +/* global control and status */ +#define FSCHMD_REG_EVENT_STATE 0x04 +#define FSCHMD_REG_CONTROL 0x05 + +#define FSCHMD_CONTROL_ALERT_LED_MASK 0x01 + +/* watchdog (support to be implemented) */ +#define FSCHMD_REG_WDOG_PRESET 0x28 +#define FSCHMD_REG_WDOG_STATE 0x23 +#define FSCHMD_REG_WDOG_CONTROL 0x21 + +/* voltages, weird order is to keep the same order as the old drivers */ +static const u8 FSCHMD_REG_VOLT[3] = { 0x45, 0x42, 0x48 }; + +/* minimum pwm at which the fan is driven (pwm can by increased depending on + the temp. Notice that for the scy some fans share there minimum speed. + Also notice that with the scy the sensor order is different then with the + other chips, this order was in the 2.4 driver and kept for consistency. */ +static const u8 FSCHMD_REG_FAN_MIN[5][6] = { + { 0x55, 0x65 }, /* pos */ + { 0x55, 0x65, 0xb5 }, /* her */ + { 0x65, 0x65, 0x55, 0xa5, 0x55, 0xa5 }, /* scy */ + { 0x55, 0x65, 0xa5, 0xb5 }, /* hrc */ + { 0x55, 0x65, 0xa5, 0xb5, 0xc5 }, /* hmd */ +}; + +/* actual fan speed */ +static const u8 FSCHMD_REG_FAN_ACT[5][6] = { + { 0x0e, 0x6b, 0xab }, /* pos */ + { 0x0e, 0x6b, 0xbb }, /* her */ + { 0x6b, 0x6c, 0x0e, 0xab, 0x5c, 0xbb }, /* scy */ + { 0x0e, 0x6b, 0xab, 0xbb }, /* hrc */ + { 0x5b, 0x6b, 0xab, 0xbb, 0xcb }, /* hmd */ +}; + +/* fan status registers */ +static const u8 FSCHMD_REG_FAN_STATE[5][6] = { + { 0x0d, 0x62, 0xa2 }, /* pos */ + { 0x0d, 0x62, 0xb2 }, /* her */ + { 0x62, 0x61, 0x0d, 0xa2, 0x52, 0xb2 }, /* scy */ + { 0x0d, 0x62, 0xa2, 0xb2 }, /* hrc */ + { 0x52, 0x62, 0xa2, 0xb2, 0xc2 }, /* hmd */ +}; + +/* fan ripple / divider registers */ +static const u8 FSCHMD_REG_FAN_RIPPLE[5][6] = { + { 0x0f, 0x6f, 0xaf }, /* pos */ + { 0x0f, 0x6f, 0xbf }, /* her */ + { 0x6f, 0x6f, 0x0f, 0xaf, 0x0f, 0xbf }, /* scy */ + { 0x0f, 0x6f, 0xaf, 0xbf }, /* hrc */ + { 0x5f, 0x6f, 0xaf, 0xbf, 0xcf }, /* hmd */ +}; + +static const int FSCHMD_NO_FAN_SENSORS[5] = { 3, 3, 6, 4, 5 }; + +/* Fan status register bitmasks */ +#define FSCHMD_FAN_ALARM_MASK 0x04 /* called fault by FSC! */ +#define FSCHMD_FAN_NOT_PRESENT_MASK 0x08 /* not documented */ + + +/* actual temperature registers */ +static const u8 FSCHMD_REG_TEMP_ACT[5][5] = { + { 0x64, 0x32, 0x35 }, /* pos */ + { 0x64, 0x32, 0x35 }, /* her */ + { 0x64, 0xD0, 0x32, 0x35 }, /* scy */ + { 0x64, 0x32, 0x35 }, /* hrc */ + { 0x70, 0x80, 0x90, 0xd0, 0xe0 }, /* hmd */ +}; + +/* temperature state registers */ +static const u8 FSCHMD_REG_TEMP_STATE[5][5] = { + { 0x71, 0x81, 0x91 }, /* pos */ + { 0x71, 0x81, 0x91 }, /* her */ + { 0x71, 0xd1, 0x81, 0x91 }, /* scy */ + { 0x71, 0x81, 0x91 }, /* hrc */ + { 0x71, 0x81, 0x91, 0xd1, 0xe1 }, /* hmd */ +}; + +/* temperature high limit registers, FSC does not document these. Proven to be + there with field testing on the fscher and fschrc, already supported / used + in the fscscy 2.4 driver. FSC has confirmed that the fschmd has registers + at these addresses, but doesn't want to confirm they are the same as with + the fscher?? */ +static const u8 FSCHMD_REG_TEMP_LIMIT[5][5] = { + { 0, 0, 0 }, /* pos */ + { 0x76, 0x86, 0x96 }, /* her */ + { 0x76, 0xd6, 0x86, 0x96 }, /* scy */ + { 0x76, 0x86, 0x96 }, /* hrc */ + { 0x76, 0x86, 0x96, 0xd6, 0xe6 }, /* hmd */ +}; + +/* These were found through experimenting with an fscher, currently they are + not used, but we keep them around for future reference. +static const u8 FSCHER_REG_TEMP_AUTOP1[] = { 0x73, 0x83, 0x93 }; +static const u8 FSCHER_REG_TEMP_AUTOP2[] = { 0x75, 0x85, 0x95 }; */ + +static const int FSCHMD_NO_TEMP_SENSORS[5] = { 3, 3, 4, 3, 5 }; + +/* temp status register bitmasks */ +#define FSCHMD_TEMP_WORKING_MASK 0x01 +#define FSCHMD_TEMP_ALERT_MASK 0x02 +/* there only really is an alarm if the sensor is working and alert == 1 */ +#define FSCHMD_TEMP_ALARM_MASK \ + (FSCHMD_TEMP_WORKING_MASK | FSCHMD_TEMP_ALERT_MASK) + +/* our driver name */ +#define FSCHMD_NAME "fschmd" + +/* + * Functions declarations + */ + +static int fschmd_attach_adapter(struct i2c_adapter *adapter); +static int fschmd_detach_client(struct i2c_client *client); +static struct fschmd_data *fschmd_update_device(struct device *dev); + +/* + * Driver data (common to all clients) + */ + +static struct i2c_driver fschmd_driver = { + .driver = { + .name = FSCHMD_NAME, + }, + .attach_adapter = fschmd_attach_adapter, + .detach_client = fschmd_detach_client, +}; + +/* + * Client data (each client gets its own) + */ + +struct fschmd_data { + struct i2c_client client; + struct device *hwmon_dev; + struct mutex update_lock; + int kind; + char valid; /* zero until following fields are valid */ + unsigned long last_updated; /* in jiffies */ + + /* register values */ + u8 global_control; /* global control register */ + u8 volt[3]; /* 12, 5, battery voltage */ + u8 temp_act[5]; /* temperature */ + u8 temp_status[5]; /* status of sensor */ + u8 temp_max[5]; /* high temp limit, notice: undocumented! */ + u8 fan_act[6]; /* fans revolutions per second */ + u8 fan_status[6]; /* fan status */ + u8 fan_min[6]; /* fan min value for rps */ + u8 fan_ripple[6]; /* divider for rps */ +}; + +/* + * Sysfs attr show / store functions + */ + +static ssize_t show_in_value(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + const int max_reading[3] = { 14200, 6600, 3300 }; + int index = to_sensor_dev_attr(devattr)->index; + struct fschmd_data *data = fschmd_update_device(dev); + + return sprintf(buf, "%d\n", (data->volt[index] * + max_reading[index] + 128) / 255); +} + + +#define TEMP_FROM_REG(val) (((val) - 128) * 1000) + +static ssize_t show_temp_value(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct fschmd_data *data = fschmd_update_device(dev); + + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_act[index])); +} + +static ssize_t show_temp_max(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct fschmd_data *data = fschmd_update_device(dev); + + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[index])); +} + +static ssize_t store_temp_max(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct fschmd_data *data = dev_get_drvdata(dev); + long v = simple_strtol(buf, NULL, 10) / 1000; + + v = SENSORS_LIMIT(v, -128, 127) + 128; + + mutex_lock(&data->update_lock); + i2c_smbus_write_byte_data(&data->client, + FSCHMD_REG_TEMP_LIMIT[data->kind][index], v); + data->temp_max[index] = v; + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_temp_fault(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct fschmd_data *data = fschmd_update_device(dev); + + /* bit 0 set means sensor working ok, so no fault! */ + if (data->temp_status[index] & FSCHMD_TEMP_WORKING_MASK) + return sprintf(buf, "0\n"); + else + return sprintf(buf, "1\n"); +} + +static ssize_t show_temp_alarm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct fschmd_data *data = fschmd_update_device(dev); + + if ((data->temp_status[index] & FSCHMD_TEMP_ALARM_MASK) == + FSCHMD_TEMP_ALARM_MASK) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + + +#define RPM_FROM_REG(val) ((val) * 60) + +static ssize_t show_fan_value(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct fschmd_data *data = fschmd_update_device(dev); + + return sprintf(buf, "%u\n", RPM_FROM_REG(data->fan_act[index])); +} + +static ssize_t show_fan_div(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct fschmd_data *data = fschmd_update_device(dev); + + /* bits 2..7 reserved => mask with 3 */ + return sprintf(buf, "%d\n", 1 << (data->fan_ripple[index] & 3)); +} + +static ssize_t store_fan_div(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count) +{ + u8 reg; + int index = to_sensor_dev_attr(devattr)->index; + struct fschmd_data *data = dev_get_drvdata(dev); + /* supported values: 2, 4, 8 */ + unsigned long v = simple_strtoul(buf, NULL, 10); + + switch (v) { + case 2: v = 1; break; + case 4: v = 2; break; + case 8: v = 3; break; + default: + dev_err(dev, "fan_div value %lu not supported. " + "Choose one of 2, 4 or 8!\n", v); + return -EINVAL; + } + + mutex_lock(&data->update_lock); + + reg = i2c_smbus_read_byte_data(&data->client, + FSCHMD_REG_FAN_RIPPLE[data->kind][index]); + + /* bits 2..7 reserved => mask with 0x03 */ + reg &= ~0x03; + reg |= v; + + i2c_smbus_write_byte_data(&data->client, + FSCHMD_REG_FAN_RIPPLE[data->kind][index], reg); + + data->fan_ripple[index] = reg; + + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_fan_alarm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct fschmd_data *data = fschmd_update_device(dev); + + if (data->fan_status[index] & FSCHMD_FAN_ALARM_MASK) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + +static ssize_t show_fan_fault(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct fschmd_data *data = fschmd_update_device(dev); + + if (data->fan_status[index] & FSCHMD_FAN_NOT_PRESENT_MASK) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + + +static ssize_t show_pwm_auto_point1_pwm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + int val = fschmd_update_device(dev)->fan_min[index]; + + /* 0 = allow turning off, 1-255 = 50-100% */ + if (val) + val = val / 2 + 128; + + return sprintf(buf, "%d\n", val); +} + +static ssize_t store_pwm_auto_point1_pwm(struct device *dev, + struct device_attribute *devattr, const char *buf, size_t count) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct fschmd_data *data = dev_get_drvdata(dev); + unsigned long v = simple_strtoul(buf, NULL, 10); + + /* register: 0 = allow turning off, 1-255 = 50-100% */ + if (v) { + v = SENSORS_LIMIT(v, 128, 255); + v = (v - 128) * 2 + 1; + } + + mutex_lock(&data->update_lock); + + i2c_smbus_write_byte_data(&data->client, + FSCHMD_REG_FAN_MIN[data->kind][index], v); + data->fan_min[index] = v; + + mutex_unlock(&data->update_lock); + + return count; +} + + +/* The FSC hwmon family has the ability to force an attached alert led to flash + from software, we export this as an alert_led sysfs attr */ +static ssize_t show_alert_led(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct fschmd_data *data = fschmd_update_device(dev); + + if (data->global_control & FSCHMD_CONTROL_ALERT_LED_MASK) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + +static ssize_t store_alert_led(struct device *dev, + struct device_attribute *devattr, const char *buf, size_t count) +{ + u8 reg; + struct fschmd_data *data = dev_get_drvdata(dev); + unsigned long v = simple_strtoul(buf, NULL, 10); + + mutex_lock(&data->update_lock); + + reg = i2c_smbus_read_byte_data(&data->client, FSCHMD_REG_CONTROL); + + if (v) + reg |= FSCHMD_CONTROL_ALERT_LED_MASK; + else + reg &= ~FSCHMD_CONTROL_ALERT_LED_MASK; + + i2c_smbus_write_byte_data(&data->client, FSCHMD_REG_CONTROL, reg); + + data->global_control = reg; + + mutex_unlock(&data->update_lock); + + return count; +} + +static struct sensor_device_attribute fschmd_attr[] = { + SENSOR_ATTR(in0_input, 0444, show_in_value, NULL, 0), + SENSOR_ATTR(in1_input, 0444, show_in_value, NULL, 1), + SENSOR_ATTR(in2_input, 0444, show_in_value, NULL, 2), + SENSOR_ATTR(alert_led, 0644, show_alert_led, store_alert_led, 0), +}; + +static struct sensor_device_attribute fschmd_temp_attr[] = { + SENSOR_ATTR(temp1_input, 0444, show_temp_value, NULL, 0), + SENSOR_ATTR(temp1_max, 0644, show_temp_max, store_temp_max, 0), + SENSOR_ATTR(temp1_fault, 0444, show_temp_fault, NULL, 0), + SENSOR_ATTR(temp1_alarm, 0444, show_temp_alarm, NULL, 0), + SENSOR_ATTR(temp2_input, 0444, show_temp_value, NULL, 1), + SENSOR_ATTR(temp2_max, 0644, show_temp_max, store_temp_max, 1), + SENSOR_ATTR(temp2_fault, 0444, show_temp_fault, NULL, 1), + SENSOR_ATTR(temp2_alarm, 0444, show_temp_alarm, NULL, 1), + SENSOR_ATTR(temp3_input, 0444, show_temp_value, NULL, 2), + SENSOR_ATTR(temp3_max, 0644, show_temp_max, store_temp_max, 2), + SENSOR_ATTR(temp3_fault, 0444, show_temp_fault, NULL, 2), + SENSOR_ATTR(temp3_alarm, 0444, show_temp_alarm, NULL, 2), + SENSOR_ATTR(temp4_input, 0444, show_temp_value, NULL, 3), + SENSOR_ATTR(temp4_max, 0644, show_temp_max, store_temp_max, 3), + SENSOR_ATTR(temp4_fault, 0444, show_temp_fault, NULL, 3), + SENSOR_ATTR(temp4_alarm, 0444, show_temp_alarm, NULL, 3), + SENSOR_ATTR(temp5_input, 0444, show_temp_value, NULL, 4), + SENSOR_ATTR(temp5_max, 0644, show_temp_max, store_temp_max, 4), + SENSOR_ATTR(temp5_fault, 0444, show_temp_fault, NULL, 4), + SENSOR_ATTR(temp5_alarm, 0444, show_temp_alarm, NULL, 4), +}; + +static struct sensor_device_attribute fschmd_fan_attr[] = { + SENSOR_ATTR(fan1_input, 0444, show_fan_value, NULL, 0), + SENSOR_ATTR(fan1_div, 0644, show_fan_div, store_fan_div, 0), + SENSOR_ATTR(fan1_alarm, 0444, show_fan_alarm, NULL, 0), + SENSOR_ATTR(fan1_fault, 0444, show_fan_fault, NULL, 0), + SENSOR_ATTR(pwm1_auto_point1_pwm, 0644, show_pwm_auto_point1_pwm, + store_pwm_auto_point1_pwm, 0), + SENSOR_ATTR(fan2_input, 0444, show_fan_value, NULL, 1), + SENSOR_ATTR(fan2_div, 0644, show_fan_div, store_fan_div, 1), + SENSOR_ATTR(fan2_alarm, 0444, show_fan_alarm, NULL, 1), + SENSOR_ATTR(fan2_fault, 0444, show_fan_fault, NULL, 1), + SENSOR_ATTR(pwm2_auto_point1_pwm, 0644, show_pwm_auto_point1_pwm, + store_pwm_auto_point1_pwm, 1), + SENSOR_ATTR(fan3_input, 0444, show_fan_value, NULL, 2), + SENSOR_ATTR(fan3_div, 0644, show_fan_div, store_fan_div, 2), + SENSOR_ATTR(fan3_alarm, 0444, show_fan_alarm, NULL, 2), + SENSOR_ATTR(fan3_fault, 0444, show_fan_fault, NULL, 2), + SENSOR_ATTR(pwm3_auto_point1_pwm, 0644, show_pwm_auto_point1_pwm, + store_pwm_auto_point1_pwm, 2), + SENSOR_ATTR(fan4_input, 0444, show_fan_value, NULL, 3), + SENSOR_ATTR(fan4_div, 0644, show_fan_div, store_fan_div, 3), + SENSOR_ATTR(fan4_alarm, 0444, show_fan_alarm, NULL, 3), + SENSOR_ATTR(fan4_fault, 0444, show_fan_fault, NULL, 3), + SENSOR_ATTR(pwm4_auto_point1_pwm, 0644, show_pwm_auto_point1_pwm, + store_pwm_auto_point1_pwm, 3), + SENSOR_ATTR(fan5_input, 0444, show_fan_value, NULL, 4), + SENSOR_ATTR(fan5_div, 0644, show_fan_div, store_fan_div, 4), + SENSOR_ATTR(fan5_alarm, 0444, show_fan_alarm, NULL, 4), + SENSOR_ATTR(fan5_fault, 0444, show_fan_fault, NULL, 4), + SENSOR_ATTR(pwm5_auto_point1_pwm, 0644, show_pwm_auto_point1_pwm, + store_pwm_auto_point1_pwm, 4), + SENSOR_ATTR(fan6_input, 0444, show_fan_value, NULL, 5), + SENSOR_ATTR(fan6_div, 0644, show_fan_div, store_fan_div, 5), + SENSOR_ATTR(fan6_alarm, 0444, show_fan_alarm, NULL, 5), + SENSOR_ATTR(fan6_fault, 0444, show_fan_fault, NULL, 5), + SENSOR_ATTR(pwm6_auto_point1_pwm, 0644, show_pwm_auto_point1_pwm, + store_pwm_auto_point1_pwm, 5), +}; + + +/* + * Real code + */ + +static int fschmd_detect(struct i2c_adapter *adapter, int address, int kind) +{ + struct i2c_client *client; + struct fschmd_data *data; + u8 revision; + const char * const names[5] = { "Poseidon", "Hermes", "Scylla", + "Heracles", "Heimdall" }; + const char * const client_names[5] = { "fscpos", "fscher", "fscscy", + "fschrc", "fschmd" }; + int i, err = 0; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return 0; + + /* OK. For now, we presume we have a valid client. We now create the + * client structure, even though we cannot fill it completely yet. + * But it allows us to access i2c_smbus_read_byte_data. */ + if (!(data = kzalloc(sizeof(struct fschmd_data), GFP_KERNEL))) + return -ENOMEM; + + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &fschmd_driver; + mutex_init(&data->update_lock); + + /* Detect & Identify the chip */ + if (kind <= 0) { + char id[4]; + + id[0] = i2c_smbus_read_byte_data(client, + FSCHMD_REG_IDENT_0); + id[1] = i2c_smbus_read_byte_data(client, + FSCHMD_REG_IDENT_1); + id[2] = i2c_smbus_read_byte_data(client, + FSCHMD_REG_IDENT_2); + id[3] = '\0'; + + if (!strcmp(id, "PEG")) + kind = fscpos; + else if (!strcmp(id, "HER")) + kind = fscher; + else if (!strcmp(id, "SCY")) + kind = fscscy; + else if (!strcmp(id, "HRC")) + kind = fschrc; + else if (!strcmp(id, "HMD")) + kind = fschmd; + else + goto exit_free; + } + + if (kind == fscpos) { + /* The Poseidon has hardwired temp limits, fill these + in for the alarm resetting code */ + data->temp_max[0] = 70 + 128; + data->temp_max[1] = 50 + 128; + data->temp_max[2] = 50 + 128; + } + + /* i2c kind goes from 1-5, we want from 0-4 to address arrays */ + data->kind = kind - 1; + strlcpy(client->name, client_names[data->kind], I2C_NAME_SIZE); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) + goto exit_free; + + for (i = 0; i < ARRAY_SIZE(fschmd_attr); i++) { + err = device_create_file(&client->dev, + &fschmd_attr[i].dev_attr); + if (err) + goto exit_detach; + } + + for (i = 0; i < (FSCHMD_NO_TEMP_SENSORS[data->kind] * 4); i++) { + /* Poseidon doesn't have TEMP_LIMIT registers */ + if (kind == fscpos && fschmd_temp_attr[i].dev_attr.show == + show_temp_max) + continue; + + err = device_create_file(&client->dev, + &fschmd_temp_attr[i].dev_attr); + if (err) + goto exit_detach; + } + + for (i = 0; i < (FSCHMD_NO_FAN_SENSORS[data->kind] * 5); i++) { + /* Poseidon doesn't have a FAN_MIN register for its 3rd fan */ + if (kind == fscpos && + !strcmp(fschmd_fan_attr[i].dev_attr.attr.name, + "pwm3_auto_point1_pwm")) + continue; + + err = device_create_file(&client->dev, + &fschmd_fan_attr[i].dev_attr); + if (err) + goto exit_detach; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); + data->hwmon_dev = NULL; + goto exit_detach; + } + + revision = i2c_smbus_read_byte_data(client, FSCHMD_REG_REVISION); + printk(KERN_INFO FSCHMD_NAME ": Detected FSC %s chip, revision: %d\n", + names[data->kind], (int) revision); + + return 0; + +exit_detach: + fschmd_detach_client(client); /* will also free data for us */ + return err; + +exit_free: + kfree(data); + return err; +} + +static int fschmd_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, fschmd_detect); +} + +static int fschmd_detach_client(struct i2c_client *client) +{ + struct fschmd_data *data = i2c_get_clientdata(client); + int i, err; + + /* Check if registered in case we're called from fschmd_detect + to cleanup after an error */ + if (data->hwmon_dev) + hwmon_device_unregister(data->hwmon_dev); + + for (i = 0; i < ARRAY_SIZE(fschmd_attr); i++) + device_remove_file(&client->dev, &fschmd_attr[i].dev_attr); + for (i = 0; i < (FSCHMD_NO_TEMP_SENSORS[data->kind] * 4); i++) + device_remove_file(&client->dev, + &fschmd_temp_attr[i].dev_attr); + for (i = 0; i < (FSCHMD_NO_FAN_SENSORS[data->kind] * 5); i++) + device_remove_file(&client->dev, + &fschmd_fan_attr[i].dev_attr); + + if ((err = i2c_detach_client(client))) + return err; + + kfree(data); + return 0; +} + +static struct fschmd_data *fschmd_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct fschmd_data *data = i2c_get_clientdata(client); + int i; + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { + + for (i = 0; i < FSCHMD_NO_TEMP_SENSORS[data->kind]; i++) { + data->temp_act[i] = i2c_smbus_read_byte_data(client, + FSCHMD_REG_TEMP_ACT[data->kind][i]); + data->temp_status[i] = i2c_smbus_read_byte_data(client, + FSCHMD_REG_TEMP_STATE[data->kind][i]); + + /* The fscpos doesn't have TEMP_LIMIT registers */ + if (FSCHMD_REG_TEMP_LIMIT[data->kind][i]) + data->temp_max[i] = i2c_smbus_read_byte_data( + client, + FSCHMD_REG_TEMP_LIMIT[data->kind][i]); + + /* reset alarm if the alarm condition is gone, + the chip doesn't do this itself */ + if ((data->temp_status[i] & FSCHMD_TEMP_ALARM_MASK) == + FSCHMD_TEMP_ALARM_MASK && + data->temp_act[i] < data->temp_max[i]) + i2c_smbus_write_byte_data(client, + FSCHMD_REG_TEMP_STATE[data->kind][i], + FSCHMD_TEMP_ALERT_MASK); + } + + for (i = 0; i < FSCHMD_NO_FAN_SENSORS[data->kind]; i++) { + data->fan_act[i] = i2c_smbus_read_byte_data(client, + FSCHMD_REG_FAN_ACT[data->kind][i]); + data->fan_status[i] = i2c_smbus_read_byte_data(client, + FSCHMD_REG_FAN_STATE[data->kind][i]); + data->fan_ripple[i] = i2c_smbus_read_byte_data(client, + FSCHMD_REG_FAN_RIPPLE[data->kind][i]); + + /* The fscpos third fan doesn't have a fan_min */ + if (FSCHMD_REG_FAN_MIN[data->kind][i]) + data->fan_min[i] = i2c_smbus_read_byte_data( + client, + FSCHMD_REG_FAN_MIN[data->kind][i]); + + /* reset fan status if speed is back to > 0 */ + if ((data->fan_status[i] & FSCHMD_FAN_ALARM_MASK) && + data->fan_act[i]) + i2c_smbus_write_byte_data(client, + FSCHMD_REG_FAN_STATE[data->kind][i], + FSCHMD_FAN_ALARM_MASK); + } + + for (i = 0; i < 3; i++) + data->volt[i] = i2c_smbus_read_byte_data(client, + FSCHMD_REG_VOLT[i]); + + data->global_control = i2c_smbus_read_byte_data(client, + FSCHMD_REG_CONTROL); + + /* To be implemented in the future + data->watchdog[0] = i2c_smbus_read_byte_data(client, + FSCHMD_REG_WDOG_PRESET); + data->watchdog[1] = i2c_smbus_read_byte_data(client, + FSCHMD_REG_WDOG_STATE); + data->watchdog[2] = i2c_smbus_read_byte_data(client, + FSCHMD_REG_WDOG_CONTROL); */ + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static int __init fschmd_init(void) +{ + return i2c_add_driver(&fschmd_driver); +} + +static void __exit fschmd_exit(void) +{ + i2c_del_driver(&fschmd_driver); +} + +MODULE_AUTHOR("Hans de Goede "); +MODULE_DESCRIPTION("FSC Poseidon, Hermes, Scylla, Heracles and " + "Heimdall driver"); +MODULE_LICENSE("GPL"); + +module_init(fschmd_init); +module_exit(fschmd_exit); -- cgit v1.2.3 From 07584c762541672e35735b52af031183ca17a5a2 Mon Sep 17 00:00:00 2001 From: Jim Cromie Date: Fri, 12 Oct 2007 21:08:00 +0200 Subject: hwmon: (w83627hf) De-macro sysfs callback functions This patch to drivers/hwmon/w83627hf converts many sysfs items from DEVICE_ATTRs to SENSOR_DEVICE_ATTRs, and replaces macros which expand to define redundant callbacks, with callbacks which use the SENSOR_DEV.nr to know what to do. Signed-off-by: Jim Cromie Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/w83627hf.c | 701 +++++++++++++++++++++++------------------------ 1 file changed, 342 insertions(+), 359 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index a2ccf93521c..996fc1ca322 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -218,7 +219,7 @@ static const u8 regpwm_627hf[] = { W83627HF_REG_PWM1, W83627HF_REG_PWM2 }; static const u8 regpwm[] = { W83627THF_REG_PWM1, W83627THF_REG_PWM2, W83627THF_REG_PWM3 }; #define W836X7HF_REG_PWM(type, nr) (((type) == w83627hf) ? \ - regpwm_627hf[(nr) - 1] : regpwm[(nr) - 1]) + regpwm_627hf[nr] : regpwm[nr]) #define W83627HF_REG_PWM_FREQ 0x5C /* Only for the 627HF */ @@ -400,72 +401,71 @@ static struct platform_driver w83627hf_driver = { .remove = __devexit_p(w83627hf_remove), }; -/* following are the sysfs callback functions */ -#define show_in_reg(reg) \ -static ssize_t show_##reg (struct device *dev, char *buf, int nr) \ -{ \ - struct w83627hf_data *data = w83627hf_update_device(dev); \ - return sprintf(buf,"%ld\n", (long)IN_FROM_REG(data->reg[nr])); \ +static ssize_t +show_in_input(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int nr = to_sensor_dev_attr(devattr)->index; + struct w83627hf_data *data = w83627hf_update_device(dev); + return sprintf(buf, "%ld\n", (long)IN_FROM_REG(data->in[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 w83627hf_data *data = dev_get_drvdata(dev); \ - u32 val; \ - \ - val = simple_strtoul(buf, NULL, 10); \ - \ - mutex_lock(&data->update_lock); \ - data->in_##reg[nr] = IN_TO_REG(val); \ - w83627hf_write_value(data, W83781D_REG_IN_##REG(nr), \ - data->in_##reg[nr]); \ - \ - mutex_unlock(&data->update_lock); \ - return count; \ +static ssize_t +show_in_min(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int nr = to_sensor_dev_attr(devattr)->index; + struct w83627hf_data *data = w83627hf_update_device(dev); + return sprintf(buf, "%ld\n", (long)IN_FROM_REG(data->in_min[nr])); +} +static ssize_t +show_in_max(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int nr = to_sensor_dev_attr(devattr)->index; + struct w83627hf_data *data = w83627hf_update_device(dev); + return sprintf(buf, "%ld\n", (long)IN_FROM_REG(data->in_max[nr])); } -store_in_reg(MIN, min) -store_in_reg(MAX, max) +static ssize_t +store_in_min(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + int nr = to_sensor_dev_attr(devattr)->index; + struct w83627hf_data *data = dev_get_drvdata(dev); + long val = simple_strtol(buf, NULL, 10); -#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); + mutex_lock(&data->update_lock); + data->in_min[nr] = IN_TO_REG(val); + w83627hf_write_value(data, W83781D_REG_IN_MIN(nr), data->in_min[nr]); + mutex_unlock(&data->update_lock); + return count; +} +static ssize_t +store_in_max(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + int nr = to_sensor_dev_attr(devattr)->index; + struct w83627hf_data *data = dev_get_drvdata(dev); + long val = simple_strtol(buf, NULL, 10); -#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(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); + mutex_lock(&data->update_lock); + data->in_max[nr] = IN_TO_REG(val); + w83627hf_write_value(data, W83781D_REG_IN_MAX(nr), data->in_max[nr]); + mutex_unlock(&data->update_lock); + return count; +} +#define sysfs_vin_decl(offset) \ +static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ + show_in_input, NULL, offset); \ +static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO|S_IWUSR, \ + show_in_min, store_in_min, offset); \ +static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO|S_IWUSR, \ + show_in_max, store_in_max, offset); + +sysfs_vin_decl(1); +sysfs_vin_decl(2); +sysfs_vin_decl(3); +sysfs_vin_decl(4); +sysfs_vin_decl(5); +sysfs_vin_decl(6); +sysfs_vin_decl(7); +sysfs_vin_decl(8); /* use a different set of functions for in0 */ static ssize_t show_in_0(struct w83627hf_data *data, char *buf, u8 reg) @@ -563,134 +563,148 @@ static DEVICE_ATTR(in0_min, S_IRUGO | S_IWUSR, static DEVICE_ATTR(in0_max, S_IRUGO | S_IWUSR, show_regs_in_max0, store_regs_in_max0); -#define show_fan_reg(reg) \ -static ssize_t show_##reg (struct device *dev, char *buf, int nr) \ -{ \ - struct w83627hf_data *data = w83627hf_update_device(dev); \ - return sprintf(buf,"%ld\n", \ - FAN_FROM_REG(data->reg[nr-1], \ - (long)DIV_FROM_REG(data->fan_div[nr-1]))); \ +static ssize_t +show_fan_input(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int nr = to_sensor_dev_attr(devattr)->index; + struct w83627hf_data *data = w83627hf_update_device(dev); + return sprintf(buf, "%ld\n", FAN_FROM_REG(data->fan[nr], + (long)DIV_FROM_REG(data->fan_div[nr]))); +} +static ssize_t +show_fan_min(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int nr = to_sensor_dev_attr(devattr)->index; + struct w83627hf_data *data = w83627hf_update_device(dev); + return sprintf(buf, "%ld\n", FAN_FROM_REG(data->fan_min[nr], + (long)DIV_FROM_REG(data->fan_div[nr]))); } -show_fan_reg(fan); -show_fan_reg(fan_min); - static ssize_t -store_fan_min(struct device *dev, const char *buf, size_t count, int nr) +store_fan_min(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) { + int nr = to_sensor_dev_attr(devattr)->index; struct w83627hf_data *data = dev_get_drvdata(dev); - u32 val; - - val = simple_strtoul(buf, NULL, 10); + u32 val = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); - data->fan_min[nr - 1] = - FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr - 1])); - w83627hf_write_value(data, W83781D_REG_FAN_MIN(nr), - data->fan_min[nr - 1]); + data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); + w83627hf_write_value(data, W83781D_REG_FAN_MIN(nr+1), + data->fan_min[nr]); mutex_unlock(&data->update_lock); return count; } +#define sysfs_fan_decl(offset) \ +static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ + show_fan_input, NULL, offset - 1); \ +static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ + show_fan_min, store_fan_min, offset - 1); -#define sysfs_fan_offset(offset) \ -static ssize_t show_regs_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_fan(dev, buf, offset); \ -} \ -static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_regs_fan_##offset, NULL); +sysfs_fan_decl(1); +sysfs_fan_decl(2); +sysfs_fan_decl(3); -#define sysfs_fan_min_offset(offset) \ -static ssize_t show_regs_fan_min##offset (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_fan_min(dev, buf, offset); \ -} \ -static ssize_t \ -store_regs_fan_min##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ -{ \ - return store_fan_min(dev, buf, count, offset); \ -} \ -static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ - show_regs_fan_min##offset, store_regs_fan_min##offset); - -sysfs_fan_offset(1); -sysfs_fan_min_offset(1); -sysfs_fan_offset(2); -sysfs_fan_min_offset(2); -sysfs_fan_offset(3); -sysfs_fan_min_offset(3); - -#define show_temp_reg(reg) \ -static ssize_t show_##reg (struct device *dev, char *buf, int nr) \ -{ \ - struct w83627hf_data *data = w83627hf_update_device(dev); \ - if (nr >= 2) { /* TEMP2 and TEMP3 */ \ - return sprintf(buf,"%ld\n", \ - (long)LM75_TEMP_FROM_REG(data->reg##_add[nr-2])); \ - } else { /* TEMP1 */ \ - return sprintf(buf,"%ld\n", (long)TEMP_FROM_REG(data->reg)); \ - } \ +static ssize_t +show_temp(struct device *dev, struct device_attribute *devattr, char *buf) +{ + int nr = to_sensor_dev_attr(devattr)->index; + struct w83627hf_data *data = w83627hf_update_device(dev); + if (nr >= 2) { /* TEMP2 and TEMP3 */ + return sprintf(buf, "%ld\n", + (long)LM75_TEMP_FROM_REG(data->temp_add[nr-2])); + } else { /* TEMP1 */ + return sprintf(buf, "%ld\n", (long)TEMP_FROM_REG(data->temp)); + } } -show_temp_reg(temp); -show_temp_reg(temp_max); -show_temp_reg(temp_max_hyst); -#define store_temp_reg(REG, reg) \ -static ssize_t \ -store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \ -{ \ - struct w83627hf_data *data = dev_get_drvdata(dev); \ - long val; \ - \ - val = simple_strtol(buf, NULL, 10); \ - \ - mutex_lock(&data->update_lock); \ - \ - if (nr >= 2) { /* TEMP2 and TEMP3 */ \ - data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \ - w83627hf_write_value(data, W83781D_REG_TEMP_##REG(nr), \ - data->temp_##reg##_add[nr-2]); \ - } else { /* TEMP1 */ \ - data->temp_##reg = TEMP_TO_REG(val); \ - w83627hf_write_value(data, W83781D_REG_TEMP_##REG(nr), \ - data->temp_##reg); \ - } \ - \ - mutex_unlock(&data->update_lock); \ - return count; \ +static ssize_t +show_temp_max(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + int nr = to_sensor_dev_attr(devattr)->index; + struct w83627hf_data *data = w83627hf_update_device(dev); + if (nr >= 2) { /* TEMP2 and TEMP3 */ + return sprintf(buf, "%ld\n", + (long)LM75_TEMP_FROM_REG(data->temp_max_add[nr-2])); + } else { /* TEMP1 */ + return sprintf(buf, "%ld\n", + (long)TEMP_FROM_REG(data->temp_max)); + } } -store_temp_reg(OVER, max); -store_temp_reg(HYST, max_hyst); -#define sysfs_temp_offset(offset) \ -static ssize_t \ -show_regs_temp_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_temp(dev, buf, offset); \ -} \ -static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_regs_temp_##offset, NULL); +static ssize_t +show_temp_max_hyst(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + int nr = to_sensor_dev_attr(devattr)->index; + struct w83627hf_data *data = w83627hf_update_device(dev); + if (nr >= 2) { /* TEMP2 and TEMP3 */ + return sprintf(buf, "%ld\n", + (long)LM75_TEMP_FROM_REG(data->temp_max_hyst_add[nr-2])); + } else { /* TEMP1 */ + return sprintf(buf, "%ld\n", + (long)TEMP_FROM_REG(data->temp_max_hyst)); + } +} -#define sysfs_temp_reg_offset(reg, offset) \ -static ssize_t show_regs_temp_##reg##offset (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_temp_##reg (dev, buf, offset); \ -} \ -static ssize_t \ -store_regs_temp_##reg##offset (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return store_temp_##reg (dev, buf, count, offset); \ -} \ -static DEVICE_ATTR(temp##offset##_##reg, S_IRUGO| S_IWUSR, \ - show_regs_temp_##reg##offset, store_regs_temp_##reg##offset); +static ssize_t +store_temp_max(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + int nr = to_sensor_dev_attr(devattr)->index; + struct w83627hf_data *data = dev_get_drvdata(dev); + long val = simple_strtol(buf, NULL, 10); -#define sysfs_temp_offsets(offset) \ -sysfs_temp_offset(offset) \ -sysfs_temp_reg_offset(max, offset) \ -sysfs_temp_reg_offset(max_hyst, offset) + mutex_lock(&data->update_lock); -sysfs_temp_offsets(1); -sysfs_temp_offsets(2); -sysfs_temp_offsets(3); + if (nr >= 2) { /* TEMP2 and TEMP3 */ + data->temp_max_add[nr-2] = LM75_TEMP_TO_REG(val); + w83627hf_write_value(data, W83781D_REG_TEMP_OVER(nr), + data->temp_max_add[nr-2]); + } else { /* TEMP1 */ + data->temp_max = TEMP_TO_REG(val); + w83627hf_write_value(data, W83781D_REG_TEMP_OVER(nr), + data->temp_max); + } + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t +store_temp_max_hyst(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + int nr = to_sensor_dev_attr(devattr)->index; + struct w83627hf_data *data = dev_get_drvdata(dev); + long val = simple_strtol(buf, NULL, 10); + + mutex_lock(&data->update_lock); + + if (nr >= 2) { /* TEMP2 and TEMP3 */ + data->temp_max_hyst_add[nr-2] = LM75_TEMP_TO_REG(val); + w83627hf_write_value(data, W83781D_REG_TEMP_HYST(nr), + data->temp_max_hyst_add[nr-2]); + } else { /* TEMP1 */ + data->temp_max_hyst = TEMP_TO_REG(val); + w83627hf_write_value(data, W83781D_REG_TEMP_HYST(nr), + data->temp_max_hyst); + } + mutex_unlock(&data->update_lock); + return count; +} + +#define sysfs_temp_decl(offset) \ +static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ + show_temp, NULL, offset); \ +static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO|S_IWUSR, \ + show_temp_max, store_temp_max, offset); \ +static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO|S_IWUSR, \ + show_temp_max_hyst, store_temp_max_hyst, offset); + +sysfs_temp_decl(1); +sysfs_temp_decl(2); +sysfs_temp_decl(3); static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf) @@ -788,20 +802,22 @@ sysfs_beep(ENABLE, enable); sysfs_beep(MASK, mask); static ssize_t -show_fan_div_reg(struct device *dev, char *buf, int nr) +show_fan_div(struct device *dev, struct device_attribute *devattr, char *buf) { + int nr = to_sensor_dev_attr(devattr)->index; struct w83627hf_data *data = w83627hf_update_device(dev); return sprintf(buf, "%ld\n", - (long) DIV_FROM_REG(data->fan_div[nr - 1])); + (long) DIV_FROM_REG(data->fan_div[nr])); } - /* Note: we save and restore the fan minimum here, because its value is determined in part by the fan divisor. This follows the principle of least surprise; the user doesn't expect the fan minimum to change just because the divisor changed. */ static ssize_t -store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr) +store_fan_div(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) { + int nr = to_sensor_dev_attr(devattr)->index; struct w83627hf_data *data = dev_get_drvdata(dev); unsigned long min; u8 reg; @@ -833,92 +849,72 @@ store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr) return count; } -#define sysfs_fan_div(offset) \ -static ssize_t show_regs_fan_div_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_fan_div_reg(dev, buf, offset); \ -} \ -static ssize_t \ -store_regs_fan_div_##offset (struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - return store_fan_div_reg(dev, buf, count, offset - 1); \ -} \ -static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ - show_regs_fan_div_##offset, store_regs_fan_div_##offset); - -sysfs_fan_div(1); -sysfs_fan_div(2); -sysfs_fan_div(3); +static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO|S_IWUSR, + show_fan_div, store_fan_div, 0); +static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO|S_IWUSR, + show_fan_div, store_fan_div, 1); +static SENSOR_DEVICE_ATTR(fan3_div, S_IRUGO|S_IWUSR, + show_fan_div, store_fan_div, 2); static ssize_t -show_pwm_reg(struct device *dev, char *buf, int nr) +show_pwm(struct device *dev, struct device_attribute *devattr, char *buf) { + int nr = to_sensor_dev_attr(devattr)->index; struct w83627hf_data *data = w83627hf_update_device(dev); - return sprintf(buf, "%ld\n", (long) data->pwm[nr - 1]); + return sprintf(buf, "%ld\n", (long) data->pwm[nr]); } static ssize_t -store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr) +store_pwm(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) { + int nr = to_sensor_dev_attr(devattr)->index; struct w83627hf_data *data = dev_get_drvdata(dev); - u32 val; - - val = simple_strtoul(buf, NULL, 10); + u32 val = simple_strtoul(buf, NULL, 10); mutex_lock(&data->update_lock); if (data->type == w83627thf) { /* bits 0-3 are reserved in 627THF */ - data->pwm[nr - 1] = PWM_TO_REG(val) & 0xf0; + data->pwm[nr] = PWM_TO_REG(val) & 0xf0; w83627hf_write_value(data, W836X7HF_REG_PWM(data->type, nr), - data->pwm[nr - 1] | + data->pwm[nr] | (w83627hf_read_value(data, W836X7HF_REG_PWM(data->type, nr)) & 0x0f)); } else { - data->pwm[nr - 1] = PWM_TO_REG(val); + data->pwm[nr] = PWM_TO_REG(val); w83627hf_write_value(data, W836X7HF_REG_PWM(data->type, nr), - data->pwm[nr - 1]); + data->pwm[nr]); } mutex_unlock(&data->update_lock); return count; } -#define sysfs_pwm(offset) \ -static ssize_t show_regs_pwm_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_pwm_reg(dev, buf, offset); \ -} \ -static ssize_t \ -store_regs_pwm_##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ -{ \ - return store_pwm_reg(dev, buf, count, offset); \ -} \ -static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ - show_regs_pwm_##offset, store_regs_pwm_##offset); - -sysfs_pwm(1); -sysfs_pwm(2); -sysfs_pwm(3); +static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0); +static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 1); +static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 2); static ssize_t -show_pwm_freq_reg(struct device *dev, char *buf, int nr) +show_pwm_freq(struct device *dev, struct device_attribute *devattr, char *buf) { + int nr = to_sensor_dev_attr(devattr)->index; struct w83627hf_data *data = w83627hf_update_device(dev); if (data->type == w83627hf) return sprintf(buf, "%ld\n", - pwm_freq_from_reg_627hf(data->pwm_freq[nr - 1])); + pwm_freq_from_reg_627hf(data->pwm_freq[nr])); else return sprintf(buf, "%ld\n", - pwm_freq_from_reg(data->pwm_freq[nr - 1])); + pwm_freq_from_reg(data->pwm_freq[nr])); } static ssize_t -store_pwm_freq_reg(struct device *dev, const char *buf, size_t count, int nr) +store_pwm_freq(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) { + int nr = to_sensor_dev_attr(devattr)->index; struct w83627hf_data *data = dev_get_drvdata(dev); static const u8 mask[]={0xF8, 0x8F}; u32 val; @@ -928,50 +924,42 @@ store_pwm_freq_reg(struct device *dev, const char *buf, size_t count, int nr) mutex_lock(&data->update_lock); if (data->type == w83627hf) { - data->pwm_freq[nr - 1] = pwm_freq_to_reg_627hf(val); + data->pwm_freq[nr] = pwm_freq_to_reg_627hf(val); w83627hf_write_value(data, W83627HF_REG_PWM_FREQ, - (data->pwm_freq[nr - 1] << ((nr - 1)*4)) | + (data->pwm_freq[nr] << (nr*4)) | (w83627hf_read_value(data, - W83627HF_REG_PWM_FREQ) & mask[nr - 1])); + W83627HF_REG_PWM_FREQ) & mask[nr])); } else { - data->pwm_freq[nr - 1] = pwm_freq_to_reg(val); - w83627hf_write_value(data, W83637HF_REG_PWM_FREQ[nr - 1], - data->pwm_freq[nr - 1]); + data->pwm_freq[nr] = pwm_freq_to_reg(val); + w83627hf_write_value(data, W83637HF_REG_PWM_FREQ[nr], + data->pwm_freq[nr]); } mutex_unlock(&data->update_lock); return count; } -#define sysfs_pwm_freq(offset) \ -static ssize_t show_regs_pwm_freq_##offset(struct device *dev, \ - struct device_attribute *attr, char *buf) \ -{ \ - return show_pwm_freq_reg(dev, buf, offset); \ -} \ -static ssize_t \ -store_regs_pwm_freq_##offset(struct device *dev, \ - struct device_attribute *attr, const char *buf, size_t count) \ -{ \ - return store_pwm_freq_reg(dev, buf, count, offset); \ -} \ -static DEVICE_ATTR(pwm##offset##_freq, S_IRUGO | S_IWUSR, \ - show_regs_pwm_freq_##offset, store_regs_pwm_freq_##offset); - -sysfs_pwm_freq(1); -sysfs_pwm_freq(2); -sysfs_pwm_freq(3); +static SENSOR_DEVICE_ATTR(pwm1_freq, S_IRUGO|S_IWUSR, + show_pwm_freq, store_pwm_freq, 0); +static SENSOR_DEVICE_ATTR(pwm2_freq, S_IRUGO|S_IWUSR, + show_pwm_freq, store_pwm_freq, 1); +static SENSOR_DEVICE_ATTR(pwm3_freq, S_IRUGO|S_IWUSR, + show_pwm_freq, store_pwm_freq, 2); static ssize_t -show_sensor_reg(struct device *dev, char *buf, int nr) +show_temp_type(struct device *dev, struct device_attribute *devattr, + char *buf) { + int nr = to_sensor_dev_attr(devattr)->index; struct w83627hf_data *data = w83627hf_update_device(dev); - return sprintf(buf, "%ld\n", (long) data->sens[nr - 1]); + return sprintf(buf, "%ld\n", (long) data->sens[nr]); } static ssize_t -store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr) +store_temp_type(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) { + int nr = to_sensor_dev_attr(devattr)->index; struct w83627hf_data *data = dev_get_drvdata(dev); u32 val, tmp; @@ -983,20 +971,20 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr) case 1: /* PII/Celeron diode */ tmp = w83627hf_read_value(data, W83781D_REG_SCFG1); w83627hf_write_value(data, W83781D_REG_SCFG1, - tmp | BIT_SCFG1[nr - 1]); + tmp | BIT_SCFG1[nr]); tmp = w83627hf_read_value(data, W83781D_REG_SCFG2); w83627hf_write_value(data, W83781D_REG_SCFG2, - tmp | BIT_SCFG2[nr - 1]); - data->sens[nr - 1] = val; + tmp | BIT_SCFG2[nr]); + data->sens[nr] = val; break; case 2: /* 3904 */ tmp = w83627hf_read_value(data, W83781D_REG_SCFG1); w83627hf_write_value(data, W83781D_REG_SCFG1, - tmp | BIT_SCFG1[nr - 1]); + tmp | BIT_SCFG1[nr]); tmp = w83627hf_read_value(data, W83781D_REG_SCFG2); w83627hf_write_value(data, W83781D_REG_SCFG2, - tmp & ~BIT_SCFG2[nr - 1]); - data->sens[nr - 1] = val; + tmp & ~BIT_SCFG2[nr]); + data->sens[nr] = val; break; case W83781D_DEFAULT_BETA: dev_warn(dev, "Sensor type %d is deprecated, please use 4 " @@ -1005,8 +993,8 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr) case 4: /* thermistor */ tmp = w83627hf_read_value(data, W83781D_REG_SCFG1); w83627hf_write_value(data, W83781D_REG_SCFG1, - tmp & ~BIT_SCFG1[nr - 1]); - data->sens[nr - 1] = val; + tmp & ~BIT_SCFG1[nr]); + data->sens[nr] = val; break; default: dev_err(dev, @@ -1019,25 +1007,16 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr) return count; } -#define sysfs_sensor(offset) \ -static ssize_t show_regs_sensor_##offset (struct device *dev, struct device_attribute *attr, char *buf) \ -{ \ - return show_sensor_reg(dev, buf, offset); \ -} \ -static ssize_t \ -store_regs_sensor_##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ -{ \ - return store_sensor_reg(dev, buf, count, offset); \ -} \ -static DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR, \ - show_regs_sensor_##offset, store_regs_sensor_##offset); +#define sysfs_temp_type(offset) \ +static SENSOR_DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR, \ + show_temp_type, store_temp_type, offset - 1); -sysfs_sensor(1); -sysfs_sensor(2); -sysfs_sensor(3); +sysfs_temp_type(1); +sysfs_temp_type(2); +sysfs_temp_type(3); -static ssize_t show_name(struct device *dev, struct device_attribute - *devattr, char *buf) +static ssize_t +show_name(struct device *dev, struct device_attribute *devattr, char *buf) { struct w83627hf_data *data = dev_get_drvdata(dev); @@ -1119,49 +1098,44 @@ static int __init w83627hf_find(int sioaddr, unsigned short *addr, return err; } +#define VIN_UNIT_ATTRS(_X_) \ + &sensor_dev_attr_in##_X_##_input.dev_attr.attr, \ + &sensor_dev_attr_in##_X_##_min.dev_attr.attr, \ + &sensor_dev_attr_in##_X_##_max.dev_attr.attr + +#define FAN_UNIT_ATTRS(_X_) \ + &sensor_dev_attr_fan##_X_##_input.dev_attr.attr, \ + &sensor_dev_attr_fan##_X_##_min.dev_attr.attr, \ + &sensor_dev_attr_fan##_X_##_div.dev_attr.attr + +#define TEMP_UNIT_ATTRS(_X_) \ + &sensor_dev_attr_temp##_X_##_input.dev_attr.attr, \ + &sensor_dev_attr_temp##_X_##_max.dev_attr.attr, \ + &sensor_dev_attr_temp##_X_##_max_hyst.dev_attr.attr, \ + &sensor_dev_attr_temp##_X_##_type.dev_attr.attr + static struct attribute *w83627hf_attributes[] = { &dev_attr_in0_input.attr, &dev_attr_in0_min.attr, &dev_attr_in0_max.attr, - &dev_attr_in2_input.attr, - &dev_attr_in2_min.attr, - &dev_attr_in2_max.attr, - &dev_attr_in3_input.attr, - &dev_attr_in3_min.attr, - &dev_attr_in3_max.attr, - &dev_attr_in4_input.attr, - &dev_attr_in4_min.attr, - &dev_attr_in4_max.attr, - &dev_attr_in7_input.attr, - &dev_attr_in7_min.attr, - &dev_attr_in7_max.attr, - &dev_attr_in8_input.attr, - &dev_attr_in8_min.attr, - &dev_attr_in8_max.attr, - - &dev_attr_fan1_input.attr, - &dev_attr_fan1_min.attr, - &dev_attr_fan1_div.attr, - &dev_attr_fan2_input.attr, - &dev_attr_fan2_min.attr, - &dev_attr_fan2_div.attr, - - &dev_attr_temp1_input.attr, - &dev_attr_temp1_max.attr, - &dev_attr_temp1_max_hyst.attr, - &dev_attr_temp1_type.attr, - &dev_attr_temp2_input.attr, - &dev_attr_temp2_max.attr, - &dev_attr_temp2_max_hyst.attr, - &dev_attr_temp2_type.attr, + VIN_UNIT_ATTRS(2), + VIN_UNIT_ATTRS(3), + VIN_UNIT_ATTRS(4), + VIN_UNIT_ATTRS(7), + VIN_UNIT_ATTRS(8), + + FAN_UNIT_ATTRS(1), + FAN_UNIT_ATTRS(2), + + TEMP_UNIT_ATTRS(1), + TEMP_UNIT_ATTRS(2), &dev_attr_alarms.attr, &dev_attr_beep_enable.attr, &dev_attr_beep_mask.attr, - &dev_attr_pwm1.attr, - &dev_attr_pwm2.attr, - + &sensor_dev_attr_pwm1.dev_attr.attr, + &sensor_dev_attr_pwm2.dev_attr.attr, &dev_attr_name.attr, NULL }; @@ -1171,30 +1145,17 @@ static const struct attribute_group w83627hf_group = { }; static struct attribute *w83627hf_attributes_opt[] = { - &dev_attr_in1_input.attr, - &dev_attr_in1_min.attr, - &dev_attr_in1_max.attr, - &dev_attr_in5_input.attr, - &dev_attr_in5_min.attr, - &dev_attr_in5_max.attr, - &dev_attr_in6_input.attr, - &dev_attr_in6_min.attr, - &dev_attr_in6_max.attr, - - &dev_attr_fan3_input.attr, - &dev_attr_fan3_min.attr, - &dev_attr_fan3_div.attr, - - &dev_attr_temp3_input.attr, - &dev_attr_temp3_max.attr, - &dev_attr_temp3_max_hyst.attr, - &dev_attr_temp3_type.attr, - - &dev_attr_pwm3.attr, - - &dev_attr_pwm1_freq.attr, - &dev_attr_pwm2_freq.attr, - &dev_attr_pwm3_freq.attr, + VIN_UNIT_ATTRS(1), + VIN_UNIT_ATTRS(5), + VIN_UNIT_ATTRS(6), + + FAN_UNIT_ATTRS(3), + TEMP_UNIT_ATTRS(3), + &sensor_dev_attr_pwm3.dev_attr.attr, + + &sensor_dev_attr_pwm1_freq.dev_attr.attr, + &sensor_dev_attr_pwm2_freq.dev_attr.attr, + &sensor_dev_attr_pwm3_freq.dev_attr.attr, NULL }; @@ -1252,27 +1213,45 @@ static int __devinit w83627hf_probe(struct platform_device *pdev) /* Register chip-specific device attributes */ if (data->type == w83627hf || data->type == w83697hf) - if ((err = device_create_file(dev, &dev_attr_in5_input)) - || (err = device_create_file(dev, &dev_attr_in5_min)) - || (err = device_create_file(dev, &dev_attr_in5_max)) - || (err = device_create_file(dev, &dev_attr_in6_input)) - || (err = device_create_file(dev, &dev_attr_in6_min)) - || (err = device_create_file(dev, &dev_attr_in6_max)) - || (err = device_create_file(dev, &dev_attr_pwm1_freq)) - || (err = device_create_file(dev, &dev_attr_pwm2_freq))) + if ((err = device_create_file(dev, + &sensor_dev_attr_in5_input.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_in5_min.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_in5_max.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_in6_input.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_in6_min.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_in6_max.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_pwm1_freq.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_pwm2_freq.dev_attr))) goto ERROR4; if (data->type != w83697hf) - if ((err = device_create_file(dev, &dev_attr_in1_input)) - || (err = device_create_file(dev, &dev_attr_in1_min)) - || (err = device_create_file(dev, &dev_attr_in1_max)) - || (err = device_create_file(dev, &dev_attr_fan3_input)) - || (err = device_create_file(dev, &dev_attr_fan3_min)) - || (err = device_create_file(dev, &dev_attr_fan3_div)) - || (err = device_create_file(dev, &dev_attr_temp3_input)) - || (err = device_create_file(dev, &dev_attr_temp3_max)) - || (err = device_create_file(dev, &dev_attr_temp3_max_hyst)) - || (err = device_create_file(dev, &dev_attr_temp3_type))) + if ((err = device_create_file(dev, + &sensor_dev_attr_in1_input.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_in1_min.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_in1_max.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_fan3_input.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_fan3_min.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_fan3_div.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_temp3_input.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_temp3_max.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_temp3_max_hyst.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_temp3_type.dev_attr))) goto ERROR4; if (data->type != w83697hf && data->vid != 0xff) { @@ -1286,13 +1265,17 @@ static int __devinit w83627hf_probe(struct platform_device *pdev) if (data->type == w83627thf || data->type == w83637hf || data->type == w83687thf) - if ((err = device_create_file(dev, &dev_attr_pwm3))) + if ((err = device_create_file(dev, + &sensor_dev_attr_pwm3.dev_attr))) goto ERROR4; if (data->type == w83637hf || data->type == w83687thf) - if ((err = device_create_file(dev, &dev_attr_pwm1_freq)) - || (err = device_create_file(dev, &dev_attr_pwm2_freq)) - || (err = device_create_file(dev, &dev_attr_pwm3_freq))) + if ((err = device_create_file(dev, + &sensor_dev_attr_pwm1_freq.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_pwm2_freq.dev_attr)) + || (err = device_create_file(dev, + &sensor_dev_attr_pwm3_freq.dev_attr))) goto ERROR4; data->hwmon_dev = hwmon_device_register(dev); @@ -1588,15 +1571,15 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev) w83627hf_read_value(data, W83781D_REG_FAN_MIN(i)); } - for (i = 1; i <= 3; i++) { + for (i = 0; i <= 2; i++) { u8 tmp = w83627hf_read_value(data, W836X7HF_REG_PWM(data->type, i)); /* bits 0-3 are reserved in 627THF */ if (data->type == w83627thf) tmp &= 0xf0; - data->pwm[i - 1] = tmp; - if(i == 2 && - (data->type == w83627hf || data->type == w83697hf)) + data->pwm[i] = tmp; + if (i == 1 && + (data->type == w83627hf || data->type == w83697hf)) break; } if (data->type == w83627hf) { -- cgit v1.2.3 From c09c5184a26158da32801e89d5849d774605f0dd Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Fri, 12 Oct 2007 21:53:07 +0200 Subject: hwmon: (w83627hf) Fix setting fan min right after driver load We need to read the fan clock dividers at initialization time, otherwise the code in store_fan_min() may use uninitialized values. That's pretty much the same bug and same fix as for the w83627ehf driver last month. Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/w83627hf.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 996fc1ca322..2169d8c8bbe 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -389,6 +389,7 @@ static int __devexit w83627hf_remove(struct platform_device *pdev); static int w83627hf_read_value(struct w83627hf_data *data, u16 reg); static int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value); +static void w83627hf_update_fan_div(struct w83627hf_data *data); static struct w83627hf_data *w83627hf_update_device(struct device *dev); static void w83627hf_init_device(struct platform_device *pdev); @@ -1206,6 +1207,7 @@ static int __devinit w83627hf_probe(struct platform_device *pdev) data->fan_min[0] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(1)); data->fan_min[1] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(2)); data->fan_min[2] = w83627hf_read_value(data, W83781D_REG_FAN_MIN(3)); + w83627hf_update_fan_div(data); /* Register common device attributes */ if ((err = sysfs_create_group(&dev->kobj, &w83627hf_group))) @@ -1540,6 +1542,24 @@ static void __devinit w83627hf_init_device(struct platform_device *pdev) | 0x01); } +static void w83627hf_update_fan_div(struct w83627hf_data *data) +{ + int reg; + + reg = w83627hf_read_value(data, W83781D_REG_VID_FANDIV); + data->fan_div[0] = (reg >> 4) & 0x03; + data->fan_div[1] = (reg >> 6) & 0x03; + if (data->type != w83697hf) { + data->fan_div[2] = (w83627hf_read_value(data, + W83781D_REG_PIN) >> 6) & 0x03; + } + reg = w83627hf_read_value(data, W83781D_REG_VBAT); + data->fan_div[0] |= (reg >> 3) & 0x04; + data->fan_div[1] |= (reg >> 4) & 0x04; + if (data->type != w83697hf) + data->fan_div[2] |= (reg >> 5) & 0x04; +} + static struct w83627hf_data *w83627hf_update_device(struct device *dev) { struct w83627hf_data *data = dev_get_drvdata(dev); @@ -1617,18 +1637,8 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev) w83627hf_read_value(data, W83781D_REG_TEMP_HYST(3)); } - i = w83627hf_read_value(data, W83781D_REG_VID_FANDIV); - data->fan_div[0] = (i >> 4) & 0x03; - data->fan_div[1] = (i >> 6) & 0x03; - if (data->type != w83697hf) { - data->fan_div[2] = (w83627hf_read_value(data, - W83781D_REG_PIN) >> 6) & 0x03; - } - i = w83627hf_read_value(data, W83781D_REG_VBAT); - data->fan_div[0] |= (i >> 3) & 0x04; - data->fan_div[1] |= (i >> 4) & 0x04; - if (data->type != w83697hf) - data->fan_div[2] |= (i >> 5) & 0x04; + w83627hf_update_fan_div(data); + data->alarms = w83627hf_read_value(data, W83781D_REG_ALARM1) | (w83627hf_read_value(data, W83781D_REG_ALARM2) << 8) | -- cgit v1.2.3 From d58df9cd788e6fb4962e1c8d5ba7b8b95d639a44 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 10 Oct 2007 16:30:23 +0200 Subject: hwmon: (w83627hf) don't assume bank 0 The bank switching code assumes that the bank selector is set to 0 when the driver is loaded. This might not be the case. This is exactly the same bug as was fixed in the w83627ehf driver two months ago: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=0956895aa6f8dc6a33210967252fd7787652537d In practice, this bug was causing the sensor thermal types to be improperly reported for my W83627THF the first time I was loading the w83627hf driver. From the driver history, I'd say that it has been broken since September 2005 (when we stopped resetting the chip by default at driver load.) Signed-off-by: Jean Delvare Signed-off-by: Mark M. Hoffman --- drivers/hwmon/w83627hf.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 2169d8c8bbe..20ae425a198 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -1319,6 +1319,24 @@ static int __devexit w83627hf_remove(struct platform_device *pdev) } +/* Registers 0x50-0x5f are banked */ +static inline void w83627hf_set_bank(struct w83627hf_data *data, u16 reg) +{ + if ((reg & 0x00f0) == 0x50) { + outb_p(W83781D_REG_BANK, data->addr + W83781D_ADDR_REG_OFFSET); + outb_p(reg >> 8, data->addr + W83781D_DATA_REG_OFFSET); + } +} + +/* Not strictly necessary, but play it safe for now */ +static inline void w83627hf_reset_bank(struct w83627hf_data *data, u16 reg) +{ + if (reg & 0xff00) { + outb_p(W83781D_REG_BANK, data->addr + W83781D_ADDR_REG_OFFSET); + outb_p(0, data->addr + W83781D_DATA_REG_OFFSET); + } +} + static int w83627hf_read_value(struct w83627hf_data *data, u16 reg) { int res, word_sized; @@ -1329,12 +1347,7 @@ static int w83627hf_read_value(struct w83627hf_data *data, u16 reg) && (((reg & 0x00ff) == 0x50) || ((reg & 0x00ff) == 0x53) || ((reg & 0x00ff) == 0x55)); - if (reg & 0xff00) { - outb_p(W83781D_REG_BANK, - data->addr + W83781D_ADDR_REG_OFFSET); - outb_p(reg >> 8, - data->addr + W83781D_DATA_REG_OFFSET); - } + w83627hf_set_bank(data, reg); outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET); res = inb_p(data->addr + W83781D_DATA_REG_OFFSET); if (word_sized) { @@ -1344,11 +1357,7 @@ static int w83627hf_read_value(struct w83627hf_data *data, u16 reg) (res << 8) + inb_p(data->addr + W83781D_DATA_REG_OFFSET); } - if (reg & 0xff00) { - outb_p(W83781D_REG_BANK, - data->addr + W83781D_ADDR_REG_OFFSET); - outb_p(0, data->addr + W83781D_DATA_REG_OFFSET); - } + w83627hf_reset_bank(data, reg); mutex_unlock(&data->lock); return res; } @@ -1419,12 +1428,7 @@ static int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value) || ((reg & 0xff00) == 0x200)) && (((reg & 0x00ff) == 0x53) || ((reg & 0x00ff) == 0x55)); - if (reg & 0xff00) { - outb_p(W83781D_REG_BANK, - data->addr + W83781D_ADDR_REG_OFFSET); - outb_p(reg >> 8, - data->addr + W83781D_DATA_REG_OFFSET); - } + w83627hf_set_bank(data, reg); outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET); if (word_sized) { outb_p(value >> 8, @@ -1434,11 +1438,7 @@ static int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value) } outb_p(value & 0xff, data->addr + W83781D_DATA_REG_OFFSET); - if (reg & 0xff00) { - outb_p(W83781D_REG_BANK, - data->addr + W83781D_ADDR_REG_OFFSET); - outb_p(0, data->addr + W83781D_DATA_REG_OFFSET); - } + w83627hf_reset_bank(data, reg); mutex_unlock(&data->lock); return 0; } -- cgit v1.2.3 From 5460a9d0ffc860a370631e096a8a6f3682f3fc94 Mon Sep 17 00:00:00 2001 From: "Mark M. Hoffman" Date: Sun, 14 Oct 2007 14:57:35 -0400 Subject: hwmon: (sis5595) fix sparse warning Signed-off-by: Mark M. Hoffman --- drivers/hwmon/sis5595.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c index 79a5376a8d8..860b71ccbb8 100644 --- a/drivers/hwmon/sis5595.c +++ b/drivers/hwmon/sis5595.c @@ -739,11 +739,10 @@ static int __devinit sis5595_pci_probe(struct pci_dev *dev, int *i; for (i = blacklist; *i != 0; i++) { - struct pci_dev *dev; - dev = pci_get_device(PCI_VENDOR_ID_SI, *i, NULL); - if (dev) { - dev_err(&dev->dev, "Looked for SIS5595 but found unsupported device %.4x\n", *i); - pci_dev_put(dev); + struct pci_dev *d; + if ((d = pci_get_device(PCI_VENDOR_ID_SI, *i, NULL))) { + dev_err(&d->dev, "Looked for SIS5595 but found unsupported device %.4x\n", *i); + pci_dev_put(d); return -ENODEV; } } -- cgit v1.2.3 From a022fef5a2b19086b329d1cc64a5d78aa83e2908 Mon Sep 17 00:00:00 2001 From: "Mark M. Hoffman" Date: Sun, 14 Oct 2007 15:00:24 -0400 Subject: hwmon: (vt8231) fix sparse warning Signed-off-by: Mark M. Hoffman --- drivers/hwmon/vt8231.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c index 8806302b5f3..2196a84603f 100644 --- a/drivers/hwmon/vt8231.c +++ b/drivers/hwmon/vt8231.c @@ -676,7 +676,7 @@ static struct pci_driver vt8231_pci_driver = { .probe = vt8231_pci_probe, }; -int vt8231_probe(struct platform_device *pdev) +static int vt8231_probe(struct platform_device *pdev) { struct resource *res; struct vt8231_data *data; -- cgit v1.2.3