diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-03 22:09:43 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-03 22:09:43 +0400 |
commit | f456205265a61f1d649f8378eceaa163850cba4e (patch) | |
tree | c974aafac8fad9bf1322f2ec66aaf01d01adfaf8 /drivers/hwmon/lm92.c | |
parent | 8f5759aeb88a47448cd92ab55a016d013b154a98 (diff) | |
parent | 9d311eddf3565ed0e05b3cb5a22db41fa74d9d86 (diff) | |
download | linux-f456205265a61f1d649f8378eceaa163850cba4e.tar.xz |
Merge tag 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging into next
Pull hwmon updates from Guenter Roeck:
"New driver for NCT6683D
New chip support to existing drivers:
- add support for STTS2004 and AT30TSE004 to jc42 driver
- add support for EMC1402/EMC1412/EMC1422 to emc1403 driver
Other notable changes:
- document hwmon kernel API
- convert jc42, lm70, lm75, lm77, lm83, lm92, max1619, tmp421, and
tmp102 drivers to use new hwmon API functions
- replace function macros in lm80, lm92, and jc42 drivers with real
code
- convert emc1403 driver to use regmap, add support for additional
attributes, and add device IDs for EMC1412, EMC1413, and EMC1414
- various additional cleanup and minor bug fixes in several drivers"
* tag 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: (60 commits)
hwmon: (nct6775) Fix probe unwind paths to properly unregister platform devices
hwmon: (nct6683) Fix probe unwind paths to properly unregister platform devices
hwmon: (ultra45_env) Introduce managed version of kzalloc
hwmon: Driver for NCT6683D
hwmon: (lm80) Rearrange code to avoid forward declarations
hwmon: (lm80) Convert fan display function macros into functions
hwmon: (lm80) Convert voltage display function macros into functions
hwmon: (lm80) Convert temperature display function macros into functions
hwmon: (lm80) Normalize all temperature values to 16 bit
hwmon: (lm80) Simplify TEMP_FROM_REG
hwmon: (lm83) Convert to use devm_hwmon_device_register_with_groups
hwmon: (lm83) Rearange code to avoid forward declarations
hwmon: (lm83) Drop FSF address
hwmon: (max1619) Convert to use devm_hwmon_device_register_with_groups
hwmon: (max1619) Drop function macros
hwmon: (max1619) Rearrange code to avoid forward declarations
hwmon: (max1619) Drop FSF address
hwmon: (max1619) Fix critical alarm display
hwmon: (jc42) Add support for STTS2004 and AT30TSE004
hwmon: (jc42) Convert function macros into functions
...
Diffstat (limited to 'drivers/hwmon/lm92.c')
-rw-r--r-- | drivers/hwmon/lm92.c | 224 |
1 files changed, 96 insertions, 128 deletions
diff --git a/drivers/hwmon/lm92.c b/drivers/hwmon/lm92.c index b9022db6511a..d2060e245ff5 100644 --- a/drivers/hwmon/lm92.c +++ b/drivers/hwmon/lm92.c @@ -34,10 +34,6 @@ * 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 <linux/module.h> @@ -93,46 +89,53 @@ static inline u8 ALARMS_FROM_REG(s16 reg) return reg & 0x0007; } -/* Driver data (common to all clients) */ -static struct i2c_driver lm92_driver; +enum temp_index { + t_input, + t_crit, + t_min, + t_max, + t_hyst, + t_num_regs +}; + +static const u8 regs[t_num_regs] = { + [t_input] = LM92_REG_TEMP, + [t_crit] = LM92_REG_TEMP_CRIT, + [t_min] = LM92_REG_TEMP_LOW, + [t_max] = LM92_REG_TEMP_HIGH, + [t_hyst] = LM92_REG_TEMP_HYST, +}; /* Client data (each client gets its own) */ struct lm92_data { - struct device *hwmon_dev; + struct i2c_client *client; struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ /* registers values */ - s16 temp1_input, temp1_crit, temp1_min, temp1_max, temp1_hyst; + s16 temp[t_num_regs]; /* index with enum temp_index */ }; - /* * Sysfs attributes and callback functions */ static struct lm92_data *lm92_update_device(struct device *dev) { - struct i2c_client *client = to_i2c_client(dev); - struct lm92_data *data = i2c_get_clientdata(client); + struct lm92_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int i; mutex_lock(&data->update_lock); if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { dev_dbg(&client->dev, "Updating lm92 data\n"); - data->temp1_input = i2c_smbus_read_word_swapped(client, - LM92_REG_TEMP); - data->temp1_hyst = i2c_smbus_read_word_swapped(client, - LM92_REG_TEMP_HYST); - data->temp1_crit = i2c_smbus_read_word_swapped(client, - LM92_REG_TEMP_CRIT); - data->temp1_min = i2c_smbus_read_word_swapped(client, - LM92_REG_TEMP_LOW); - data->temp1_max = i2c_smbus_read_word_swapped(client, - LM92_REG_TEMP_HIGH); - + for (i = 0; i < t_num_regs; i++) { + data->temp[i] = + i2c_smbus_read_word_swapped(client, regs[i]); + } data->last_updated = jiffies; data->valid = 1; } @@ -142,68 +145,60 @@ static struct lm92_data *lm92_update_device(struct device *dev) return data; } -#define show_temp(value) \ -static ssize_t show_##value(struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - struct lm92_data *data = lm92_update_device(dev); \ - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->value)); \ -} -show_temp(temp1_input); -show_temp(temp1_crit); -show_temp(temp1_min); -show_temp(temp1_max); - -#define set_temp(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 lm92_data *data = i2c_get_clientdata(client); \ - long val; \ - int err = kstrtol(buf, 10, &val); \ - if (err) \ - return err; \ -\ - mutex_lock(&data->update_lock); \ - data->value = TEMP_TO_REG(val); \ - i2c_smbus_write_word_swapped(client, reg, data->value); \ - mutex_unlock(&data->update_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 lm92_data *data = lm92_update_device(dev); + + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index])); } -set_temp(temp1_crit, LM92_REG_TEMP_CRIT); -set_temp(temp1_min, LM92_REG_TEMP_LOW); -set_temp(temp1_max, LM92_REG_TEMP_HIGH); -static ssize_t show_temp1_crit_hyst(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t set_temp(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) { - struct lm92_data *data = lm92_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp1_crit) - - TEMP_FROM_REG(data->temp1_hyst)); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct lm92_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int nr = attr->index; + long val; + int err; + + err = kstrtol(buf, 10, &val); + if (err) + return err; + + mutex_lock(&data->update_lock); + data->temp[nr] = TEMP_TO_REG(val); + i2c_smbus_write_word_swapped(client, regs[nr], data->temp[nr]); + mutex_unlock(&data->update_lock); + return count; } -static ssize_t show_temp1_max_hyst(struct device *dev, - struct device_attribute *attr, char *buf) + +static ssize_t show_temp_hyst(struct device *dev, + struct device_attribute *devattr, char *buf) { + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct lm92_data *data = lm92_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp1_max) - - TEMP_FROM_REG(data->temp1_hyst)); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index]) + - TEMP_FROM_REG(data->temp[t_hyst])); } -static ssize_t show_temp1_min_hyst(struct device *dev, - struct device_attribute *attr, char *buf) + +static ssize_t show_temp_min_hyst(struct device *dev, + struct device_attribute *attr, char *buf) { struct lm92_data *data = lm92_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp1_min) - + TEMP_FROM_REG(data->temp1_hyst)); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[t_min]) + + TEMP_FROM_REG(data->temp[t_hyst])); } -static ssize_t set_temp1_crit_hyst(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t set_temp_hyst(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct lm92_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct lm92_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -212,9 +207,9 @@ static ssize_t set_temp1_crit_hyst(struct device *dev, return err; mutex_lock(&data->update_lock); - data->temp1_hyst = TEMP_FROM_REG(data->temp1_crit) - val; + data->temp[t_hyst] = TEMP_FROM_REG(data->temp[attr->index]) - val; i2c_smbus_write_word_swapped(client, LM92_REG_TEMP_HYST, - TEMP_TO_REG(data->temp1_hyst)); + TEMP_TO_REG(data->temp[t_hyst])); mutex_unlock(&data->update_lock); return count; } @@ -223,7 +218,7 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf) { struct lm92_data *data = lm92_update_device(dev); - return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->temp1_input)); + return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->temp[t_input])); } static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, @@ -231,26 +226,25 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, { int bitnr = to_sensor_dev_attr(attr)->index; struct lm92_data *data = lm92_update_device(dev); - return sprintf(buf, "%d\n", (data->temp1_input >> bitnr) & 1); + return sprintf(buf, "%d\n", (data->temp[t_input] >> bitnr) & 1); } -static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1_input, NULL); -static DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp1_crit, - set_temp1_crit); -static DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temp1_crit_hyst, - set_temp1_crit_hyst); -static DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp1_min, - set_temp1_min); -static DEVICE_ATTR(temp1_min_hyst, S_IRUGO, show_temp1_min_hyst, NULL); -static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp1_max, - set_temp1_max); -static DEVICE_ATTR(temp1_max_hyst, S_IRUGO, show_temp1_max_hyst, NULL); +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, t_input); +static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp, set_temp, + t_crit); +static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temp_hyst, + set_temp_hyst, t_crit); +static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp, set_temp, + t_min); +static DEVICE_ATTR(temp1_min_hyst, S_IRUGO, show_temp_min_hyst, NULL); +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp, set_temp, + t_max); +static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO, show_temp_hyst, NULL, t_max); static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 2); static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 0); static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 1); - /* * Detection and registration */ @@ -322,24 +316,21 @@ static int max6635_check(struct i2c_client *client) return 1; } -static struct attribute *lm92_attributes[] = { - &dev_attr_temp1_input.attr, - &dev_attr_temp1_crit.attr, - &dev_attr_temp1_crit_hyst.attr, - &dev_attr_temp1_min.attr, +static struct attribute *lm92_attrs[] = { + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp1_crit.dev_attr.attr, + &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, + &sensor_dev_attr_temp1_min.dev_attr.attr, &dev_attr_temp1_min_hyst.attr, - &dev_attr_temp1_max.attr, - &dev_attr_temp1_max_hyst.attr, + &sensor_dev_attr_temp1_max.dev_attr.attr, + &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, &dev_attr_alarms.attr, &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, NULL }; - -static const struct attribute_group lm92_group = { - .attrs = lm92_attributes, -}; +ATTRIBUTE_GROUPS(lm92); /* Return 0 if detection is successful, -ENODEV otherwise */ static int lm92_detect(struct i2c_client *new_client, @@ -371,46 +362,24 @@ static int lm92_detect(struct i2c_client *new_client, static int lm92_probe(struct i2c_client *new_client, const struct i2c_device_id *id) { + struct device *hwmon_dev; struct lm92_data *data; - int err; data = devm_kzalloc(&new_client->dev, sizeof(struct lm92_data), GFP_KERNEL); if (!data) return -ENOMEM; - i2c_set_clientdata(new_client, data); + data->client = new_client; mutex_init(&data->update_lock); /* Initialize the chipset */ lm92_init_client(new_client); - /* Register sysfs hooks */ - err = sysfs_create_group(&new_client->dev.kobj, &lm92_group); - if (err) - return err; - - data->hwmon_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - return 0; - -exit_remove: - sysfs_remove_group(&new_client->dev.kobj, &lm92_group); - return err; -} - -static int lm92_remove(struct i2c_client *client) -{ - struct lm92_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &lm92_group); - - return 0; + hwmon_dev = devm_hwmon_device_register_with_groups(&new_client->dev, + new_client->name, + data, lm92_groups); + return PTR_ERR_OR_ZERO(hwmon_dev); } @@ -431,7 +400,6 @@ static struct i2c_driver lm92_driver = { .name = "lm92", }, .probe = lm92_probe, - .remove = lm92_remove, .id_table = lm92_id, .detect = lm92_detect, .address_list = normal_i2c, |