Please note that most of the function declarations cannot be omitted.
--
All difficult problems have a simple solution. That is wrong. [A. Einstein]
Signed-off-by: Davide Rizzo <elpa.rizzo@xxxxxxxxx> --- Rewritten without macro-generated functions --- linux-2.6.37-rc1/drivers/hwmon/lm95241.c 2010-11-01 12:54:12.000000000 +0100 +++ linux-2.6.37-rc1.elpa/drivers/hwmon/lm95241.c 2010-11-08 19:16:35.873755269 +0100 @@ -1,13 +1,9 @@ /* - * lm95241.c - Part of lm_sensors, Linux kernel modules for hardware - * monitoring - * Copyright (C) 2008 Davide Rizzo <elpa-rizzo@xxxxxxxxx> + * Copyright (C) 2008, 2010 Davide Rizzo <elpa.rizzo@xxxxxxxxx> * - * Based on the max1619 driver. The LM95241 is a sensor chip made by National - * Semiconductors. - * It reports up to three temperatures (its own plus up to - * two external ones). Complete datasheet can be - * obtained from National's website at: + * The LM95241 is a sensor chip made by National Semiconductors. + * It reports up to three temperatures (its own plus up to two external ones). + * Complete datasheet can be obtained from National's website at: * http://www.national.com/ds.cgi/LM/LM95241.pdf * * This program is free software; you can redistribute it and/or modify @@ -36,6 +32,8 @@ #include <linux/mutex.h> #include <linux/sysfs.h> +#define DEVNAME "lm95241" + static const unsigned short normal_i2c[] = { 0x19, 0x2a, 0x2b, I2C_CLIENT_END}; @@ -83,10 +81,6 @@ static const unsigned short normal_i2c[] #define TEMP_FROM_REG(val_h, val_l) (((val_h) & 0x80 ? (val_h) - 0x100 : \ (val_h)) * 1000 + (val_l) * 1000 / 256) -/* Functions declaration */ -static void lm95241_init_client(struct i2c_client *client); -static struct lm95241_data *lm95241_update_device(struct device *dev); - /* Client data (each client gets its own) */ struct lm95241_data { struct device *hwmon_dev; @@ -100,23 +94,254 @@ struct lm95241_data { u8 config, model, trutherm; }; +/* Conversions */ +static int TempFromReg(u8 val_h, u8 val_l) +{ + if (val_h & 0x80) + return val_h - 0x100; + return val_h * 1000 + val_l * 1000 / 256; +} + +static struct lm95241_data *lm95241_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct lm95241_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + data->interval) || + !data->valid) { + dev_dbg(&client->dev, "Updating lm95241 data.\n"); + data->local_h = + i2c_smbus_read_byte_data(client, + LM95241_REG_R_LOCAL_TEMPH); + data->local_l = + i2c_smbus_read_byte_data(client, + LM95241_REG_R_LOCAL_TEMPL); + data->remote1_h = + i2c_smbus_read_byte_data(client, + LM95241_REG_R_REMOTE1_TEMPH); + data->remote1_l = + i2c_smbus_read_byte_data(client, + LM95241_REG_R_REMOTE1_TEMPL); + data->remote2_h = + i2c_smbus_read_byte_data(client, + LM95241_REG_R_REMOTE2_TEMPH); + data->remote2_l = + i2c_smbus_read_byte_data(client, + LM95241_REG_R_REMOTE2_TEMPL); + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static ssize_t show_input(struct device *dev, struct device_attribute *attr, + char *buf); + +static DEVICE_ATTR(temp1_input, S_IRUGO, show_input, NULL); +static DEVICE_ATTR(temp2_input, S_IRUGO, show_input, NULL); +static DEVICE_ATTR(temp3_input, S_IRUGO, show_input, NULL); + /* Sysfs stuff */ -#define show_temp(value) \ -static ssize_t show_##value(struct device *dev, \ - struct device_attribute *attr, char *buf) \ -{ \ - struct lm95241_data *data = lm95241_update_device(dev); \ - snprintf(buf, PAGE_SIZE - 1, "%d\n", \ - TEMP_FROM_REG(data->value##_h, data->value##_l)); \ - return strlen(buf); \ -} -show_temp(local); -show_temp(remote1); -show_temp(remote2); +static ssize_t show_input(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct lm95241_data *data = lm95241_update_device(dev); + int value; -static ssize_t show_interval(struct device *dev, struct device_attribute *attr, + if (attr == &dev_attr_temp1_input) + value = TempFromReg(data->local_h, data->local_l); + else if (attr == &dev_attr_temp2_input) + value = TempFromReg(data->remote1_h, data->remote1_l); + else + value = TempFromReg(data->remote2_h, data->remote2_l); + snprintf(buf, PAGE_SIZE - 1, "%d\n", value); + return strlen(buf); +} + +static ssize_t show_type(struct device *dev, struct device_attribute *attr, + char *buf); +static ssize_t set_type(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count); + +static DEVICE_ATTR(temp2_type, S_IWUSR | S_IRUGO, show_type, set_type); +static DEVICE_ATTR(temp3_type, S_IWUSR | S_IRUGO, show_type, set_type); + +static ssize_t show_type(struct device *dev, struct device_attribute *attr, char *buf) { + struct i2c_client *client = to_i2c_client(dev); + struct lm95241_data *data = i2c_get_clientdata(client); + + if (attr == &dev_attr_temp2_type) + snprintf(buf, PAGE_SIZE - 1, + data->model & R1MS_MASK ? "1\n" : "2\n"); + else + snprintf(buf, PAGE_SIZE - 1, + data->model & R2MS_MASK ? "1\n" : "2\n"); + return strlen(buf); +} + +static ssize_t set_type(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct lm95241_data *data = i2c_get_clientdata(client); + unsigned long val; + + if (strict_strtoul(buf, 10, &val) < 0) + return -EINVAL; + + if (val == 1 || val == 2) { + int shift; + u8 mask; + if (attr == &dev_attr_temp2_type) { + shift = TT1_SHIFT; + mask = R1MS_MASK; + } else { + shift = TT2_SHIFT; + mask = R2MS_MASK; + } + + mutex_lock(&data->update_lock); + + data->trutherm &= ~(TT_MASK << shift); + if (val == 1) { + data->model |= mask; + data->trutherm |= (TT_ON << shift); + } else { + data->model &= ~mask; + data->trutherm |= (TT_OFF << shift); + } + + data->valid = 0; + + i2c_smbus_write_byte_data(client, LM95241_REG_RW_REMOTE_MODEL, + data->model); + i2c_smbus_write_byte_data(client, LM95241_REG_RW_TRUTHERM, + data->trutherm); + + mutex_unlock(&data->update_lock); + + } + return count; +} + +static ssize_t show_min(struct device *dev, struct device_attribute *attr, + char *buf); +static ssize_t set_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count); + +static DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_min, set_min); +static DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_min, set_min); + +static ssize_t show_min(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct lm95241_data *data = i2c_get_clientdata(client); + + if (attr == &dev_attr_temp2_min) + snprintf(buf, PAGE_SIZE - 1, + data->config & R1DF_MASK ? "-127000\n" : "0\n"); + else + snprintf(buf, PAGE_SIZE - 1, + data->config & R2DF_MASK ? "-127000\n" : "0\n"); + return strlen(buf); +} + +static ssize_t set_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct lm95241_data *data = i2c_get_clientdata(client); + long val; + u8 mask; + + if (strict_strtol(buf, 10, &val) < 0) + return -EINVAL; + + if (attr == &dev_attr_temp2_min) + mask = R1DF_MASK; + else + mask = R2DF_MASK; + + mutex_lock(&data->update_lock); + + if (val < 0) + data->config |= mask; + else + data->config &= mask; + data->valid = 0; + + i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, data->config); + + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_max(struct device *dev, struct device_attribute *attr, + char *buf); +static ssize_t set_max(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count); + +static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_max, set_max); +static DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_max, set_max); + +static ssize_t show_max(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct lm95241_data *data = i2c_get_clientdata(client); + + if (attr == &dev_attr_temp2_max) + snprintf(buf, PAGE_SIZE - 1, + data->config & R1DF_MASK ? "127000\n" : "255000\n"); + else + snprintf(buf, PAGE_SIZE - 1, + data->config & R2DF_MASK ? "127000\n" : "255000\n"); + return strlen(buf); +} + +static ssize_t set_max(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct lm95241_data *data = i2c_get_clientdata(client); + long val; + u8 mask; + + if (strict_strtol(buf, 10, &val) < 0) + return -EINVAL; + + if (attr == &dev_attr_temp2_max) + mask = R1DF_MASK; + else + mask = R2DF_MASK; + + mutex_lock(&data->update_lock); + + if (val <= 127000) + data->config |= R1DF_MASK; + else + data->config &= ~R2DF_MASK; + data->valid = 0; + + i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, data->config); + + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_interval(struct device *dev, struct device_attribute *attr, + char *buf) +{ struct lm95241_data *data = lm95241_update_device(dev); snprintf(buf, PAGE_SIZE - 1, "%lu\n", 1000 * data->interval / HZ); @@ -124,168 +349,20 @@ static ssize_t show_interval(struct devi } static ssize_t set_interval(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) + const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); struct lm95241_data *data = i2c_get_clientdata(client); + unsigned long val; + + if (strict_strtoul(buf, 10, &val) < 0) + return -EINVAL; - strict_strtol(buf, 10, &data->interval); - data->interval = data->interval * HZ / 1000; + data->interval = val * HZ / 1000; return count; } -#define show_type(flag) \ -static ssize_t show_type##flag(struct device *dev, \ - struct device_attribute *attr, char *buf) \ -{ \ - struct i2c_client *client = to_i2c_client(dev); \ - struct lm95241_data *data = i2c_get_clientdata(client); \ -\ - snprintf(buf, PAGE_SIZE - 1, \ - data->model & R##flag##MS_MASK ? "1\n" : "2\n"); \ - return strlen(buf); \ -} -show_type(1); -show_type(2); - -#define show_min(flag) \ -static ssize_t show_min##flag(struct device *dev, \ - struct device_attribute *attr, char *buf) \ -{ \ - struct i2c_client *client = to_i2c_client(dev); \ - struct lm95241_data *data = i2c_get_clientdata(client); \ -\ - snprintf(buf, PAGE_SIZE - 1, \ - data->config & R##flag##DF_MASK ? \ - "-127000\n" : "0\n"); \ - return strlen(buf); \ -} -show_min(1); -show_min(2); - -#define show_max(flag) \ -static ssize_t show_max##flag(struct device *dev, \ - struct device_attribute *attr, char *buf) \ -{ \ - struct i2c_client *client = to_i2c_client(dev); \ - struct lm95241_data *data = i2c_get_clientdata(client); \ -\ - snprintf(buf, PAGE_SIZE - 1, \ - data->config & R##flag##DF_MASK ? \ - "127000\n" : "255000\n"); \ - return strlen(buf); \ -} -show_max(1); -show_max(2); - -#define set_type(flag) \ -static ssize_t set_type##flag(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct i2c_client *client = to_i2c_client(dev); \ - struct lm95241_data *data = i2c_get_clientdata(client); \ -\ - long val; \ - strict_strtol(buf, 10, &val); \ -\ - if ((val == 1) || (val == 2)) { \ -\ - mutex_lock(&data->update_lock); \ -\ - data->trutherm &= ~(TT_MASK << TT##flag##_SHIFT); \ - if (val == 1) { \ - data->model |= R##flag##MS_MASK; \ - data->trutherm |= (TT_ON << TT##flag##_SHIFT); \ - } \ - else { \ - data->model &= ~R##flag##MS_MASK; \ - data->trutherm |= (TT_OFF << TT##flag##_SHIFT); \ - } \ -\ - data->valid = 0; \ -\ - i2c_smbus_write_byte_data(client, LM95241_REG_RW_REMOTE_MODEL, \ - data->model); \ - i2c_smbus_write_byte_data(client, LM95241_REG_RW_TRUTHERM, \ - data->trutherm); \ -\ - mutex_unlock(&data->update_lock); \ -\ - } \ - return count; \ -} -set_type(1); -set_type(2); - -#define set_min(flag) \ -static ssize_t set_min##flag(struct device *dev, \ - struct device_attribute *devattr, const char *buf, size_t count) \ -{ \ - struct i2c_client *client = to_i2c_client(dev); \ - struct lm95241_data *data = i2c_get_clientdata(client); \ -\ - long val; \ - strict_strtol(buf, 10, &val); \ -\ - mutex_lock(&data->update_lock); \ -\ - if (val < 0) \ - data->config |= R##flag##DF_MASK; \ - else \ - data->config &= ~R##flag##DF_MASK; \ -\ - data->valid = 0; \ -\ - i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, \ - data->config); \ -\ - mutex_unlock(&data->update_lock); \ -\ - return count; \ -} -set_min(1); -set_min(2); - -#define set_max(flag) \ -static ssize_t set_max##flag(struct device *dev, \ - struct device_attribute *devattr, const char *buf, size_t count) \ -{ \ - struct i2c_client *client = to_i2c_client(dev); \ - struct lm95241_data *data = i2c_get_clientdata(client); \ -\ - long val; \ - strict_strtol(buf, 10, &val); \ -\ - mutex_lock(&data->update_lock); \ -\ - if (val <= 127000) \ - data->config |= R##flag##DF_MASK; \ - else \ - data->config &= ~R##flag##DF_MASK; \ -\ - data->valid = 0; \ -\ - i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, \ - data->config); \ -\ - mutex_unlock(&data->update_lock); \ -\ - return count; \ -} -set_max(1); -set_max(2); - -static DEVICE_ATTR(temp1_input, S_IRUGO, show_local, NULL); -static DEVICE_ATTR(temp2_input, S_IRUGO, show_remote1, NULL); -static DEVICE_ATTR(temp3_input, S_IRUGO, show_remote2, NULL); -static DEVICE_ATTR(temp2_type, S_IWUSR | S_IRUGO, show_type1, set_type1); -static DEVICE_ATTR(temp3_type, S_IWUSR | S_IRUGO, show_type2, set_type2); -static DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_min1, set_min1); -static DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_min2, set_min2); -static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_max1, set_max1); -static DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_max2, set_max2); static DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO, show_interval, set_interval); @@ -322,7 +399,7 @@ static int lm95241_detect(struct i2c_cli == MANUFACTURER_ID) && (i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID) >= DEFAULT_REVISION)) { - name = "lm95241"; + name = DEVNAME; } else { dev_dbg(&adapter->dev, "LM95241 detection failed at 0x%02x\n", address); @@ -334,6 +411,26 @@ static int lm95241_detect(struct i2c_cli return 0; } +static void lm95241_init_client(struct i2c_client *client) +{ + struct lm95241_data *data = i2c_get_clientdata(client); + + data->interval = HZ; /* 1 sec default */ + data->valid = 0; + data->config = CFG_CR0076; + data->model = 0; + data->trutherm = (TT_OFF << TT1_SHIFT) | (TT_OFF << TT2_SHIFT); + + i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, + data->config); + i2c_smbus_write_byte_data(client, LM95241_REG_RW_REM_FILTER, + R1FE_MASK | R2FE_MASK); + i2c_smbus_write_byte_data(client, LM95241_REG_RW_TRUTHERM, + data->trutherm); + i2c_smbus_write_byte_data(client, LM95241_REG_RW_REMOTE_MODEL, + data->model); +} + static int lm95241_probe(struct i2c_client *new_client, const struct i2c_device_id *id) { @@ -373,26 +470,6 @@ exit: return err; } -static void lm95241_init_client(struct i2c_client *client) -{ - struct lm95241_data *data = i2c_get_clientdata(client); - - data->interval = HZ; /* 1 sec default */ - data->valid = 0; - data->config = CFG_CR0076; - data->model = 0; - data->trutherm = (TT_OFF << TT1_SHIFT) | (TT_OFF << TT2_SHIFT); - - i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, - data->config); - i2c_smbus_write_byte_data(client, LM95241_REG_RW_REM_FILTER, - R1FE_MASK | R2FE_MASK); - i2c_smbus_write_byte_data(client, LM95241_REG_RW_TRUTHERM, - data->trutherm); - i2c_smbus_write_byte_data(client, LM95241_REG_RW_REMOTE_MODEL, - data->model); -} - static int lm95241_remove(struct i2c_client *client) { struct lm95241_data *data = i2c_get_clientdata(client); @@ -404,46 +481,9 @@ static int lm95241_remove(struct i2c_cli return 0; } -static struct lm95241_data *lm95241_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm95241_data *data = i2c_get_clientdata(client); - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + data->interval) || - !data->valid) { - dev_dbg(&client->dev, "Updating lm95241 data.\n"); - data->local_h = - i2c_smbus_read_byte_data(client, - LM95241_REG_R_LOCAL_TEMPH); - data->local_l = - i2c_smbus_read_byte_data(client, - LM95241_REG_R_LOCAL_TEMPL); - data->remote1_h = - i2c_smbus_read_byte_data(client, - LM95241_REG_R_REMOTE1_TEMPH); - data->remote1_l = - i2c_smbus_read_byte_data(client, - LM95241_REG_R_REMOTE1_TEMPL); - data->remote2_h = - i2c_smbus_read_byte_data(client, - LM95241_REG_R_REMOTE2_TEMPH); - data->remote2_l = - i2c_smbus_read_byte_data(client, - LM95241_REG_R_REMOTE2_TEMPL); - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - /* Driver data (common to all clients) */ static const struct i2c_device_id lm95241_id[] = { - { "lm95241", 0 }, + { DEVNAME, 0 }, { } }; MODULE_DEVICE_TABLE(i2c, lm95241_id); @@ -451,7 +491,7 @@ MODULE_DEVICE_TABLE(i2c, lm95241_id); static struct i2c_driver lm95241_driver = { .class = I2C_CLASS_HWMON, .driver = { - .name = "lm95241", + .name = DEVNAME, }, .probe = lm95241_probe, .remove = lm95241_remove, @@ -470,9 +510,10 @@ static void __exit sensors_lm95241_exit( i2c_del_driver(&lm95241_driver); } -MODULE_AUTHOR("Davide Rizzo <elpa-rizzo@xxxxxxxxx>"); +MODULE_AUTHOR("Davide Rizzo <elpa.rizzo@xxxxxxxxx>"); MODULE_DESCRIPTION("LM95241 sensor driver"); MODULE_LICENSE("GPL"); module_init(sensors_lm95241_init); module_exit(sensors_lm95241_exit); +
_______________________________________________ lm-sensors mailing list lm-sensors@xxxxxxxxxxxxxx http://lists.lm-sensors.org/mailman/listinfo/lm-sensors