diff options
Diffstat (limited to 'drivers/hwmon/lm85.c')
| -rw-r--r-- | drivers/hwmon/lm85.c | 1179 |
1 files changed, 585 insertions, 594 deletions
diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index 3894c408fda3..1c244ed75122 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * lm85.c - Part of lm_sensors, Linux kernel modules for hardware * monitoring @@ -5,26 +6,13 @@ * Copyright (c) 2002, 2003 Philip Pokorny <ppokorny@penguincomputing.com> * Copyright (c) 2003 Margit Schubert-While <margitsw@t-online.de> * Copyright (c) 2004 Justin Thiessen <jthiessen@penguincomputing.com> - * Copyright (C) 2007--2009 Jean Delvare <khali@linux-fr.org> + * Copyright (C) 2007--2014 Jean Delvare <jdelvare@suse.de> * * Chip details at <http://www.national.com/ds/LM/LM85.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 <linux/module.h> +#include <linux/of.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/jiffies.h> @@ -34,12 +22,13 @@ #include <linux/hwmon-sysfs.h> #include <linux/err.h> #include <linux/mutex.h> +#include <linux/util_macros.h> /* Addresses to scan */ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; enum chips { - any_chip, lm85b, lm85c, + lm85, lm96000, adm1027, adt7463, adt7468, emc6d100, emc6d102, emc6d103, emc6d103s }; @@ -75,9 +64,6 @@ enum chips { #define LM85_COMPANY_NATIONAL 0x01 #define LM85_COMPANY_ANALOG_DEV 0x41 #define LM85_COMPANY_SMSC 0x5c -#define LM85_VERSTEP_VMASK 0xf0 -#define LM85_VERSTEP_GENERIC 0x60 -#define LM85_VERSTEP_GENERIC2 0x70 #define LM85_VERSTEP_LM85C 0x60 #define LM85_VERSTEP_LM85B 0x62 #define LM85_VERSTEP_LM96000_1 0x68 @@ -124,7 +110,6 @@ enum chips { #define EMC6D102_REG_EXTEND_ADC3 0x87 #define EMC6D102_REG_EXTEND_ADC4 0x88 - /* * Conversions. Rounding and limit checking is only done on the TO_REG * variants. Note that you should be a bit careful with which arguments @@ -139,7 +124,8 @@ static const int lm85_scaling[] = { /* .001 Volts */ #define SCALE(val, from, to) (((val) * (to) + ((from) / 2)) / (from)) #define INS_TO_REG(n, val) \ - clamp_val(SCALE(val, lm85_scaling[n], 192), 0, 255) + SCALE(clamp_val(val, 0, 255 * lm85_scaling[n] / 192), \ + lm85_scaling[n], 192) #define INSEXT_FROM_REG(n, val, ext) \ SCALE(((val) << 4) + (ext), 192 << 4, lm85_scaling[n]) @@ -158,7 +144,7 @@ static inline u16 FAN_TO_REG(unsigned long val) /* Temperature is reported in .001 degC increments */ #define TEMP_TO_REG(val) \ - clamp_val(SCALE(val, 1000, 1), -127, 127) + DIV_ROUND_CLOSEST(clamp_val((val), -127000, 127000), 1000) #define TEMPEXT_FROM_REG(val, ext) \ SCALE(((val) << 4) + (ext), 16, 1000) #define TEMP_FROM_REG(val) ((val) * 1000) @@ -166,7 +152,6 @@ static inline u16 FAN_TO_REG(unsigned long val) #define PWM_TO_REG(val) clamp_val(val, 0, 255) #define PWM_FROM_REG(val) (val) - /* * ZONEs have the following parameters: * Limit (low) temp, 1. degC @@ -192,42 +177,35 @@ static const int lm85_range_map[] = { 13300, 16000, 20000, 26600, 32000, 40000, 53300, 80000 }; -static int RANGE_TO_REG(int range) +static int RANGE_TO_REG(long range) { - int i; - - /* Find the closest match */ - for (i = 0; i < 15; ++i) { - if (range <= (lm85_range_map[i] + lm85_range_map[i + 1]) / 2) - break; - } - - return i; + return find_closest(range, lm85_range_map, ARRAY_SIZE(lm85_range_map)); } #define RANGE_FROM_REG(val) lm85_range_map[(val) & 0x0f] /* These are the PWM frequency encodings */ -static const int lm85_freq_map[8] = { /* 1 Hz */ +static const int lm85_freq_map[] = { /* 1 Hz */ 10, 15, 23, 30, 38, 47, 61, 94 }; -static const int adm1027_freq_map[8] = { /* 1 Hz */ + +static const int lm96000_freq_map[] = { /* 1 Hz */ + 10, 15, 23, 30, 38, 47, 61, 94, + 22500, 24000, 25700, 25700, 27700, 27700, 30000, 30000 +}; + +static const int adm1027_freq_map[] = { /* 1 Hz */ 11, 15, 22, 29, 35, 44, 59, 88 }; -static int FREQ_TO_REG(const int *map, int freq) +static int FREQ_TO_REG(const int *map, + unsigned int map_size, unsigned long freq) { - int i; - - /* Find the closest match */ - for (i = 0; i < 7; ++i) - if (freq <= (map[i] + map[i + 1]) / 2) - break; - return i; + return find_closest(freq, map, map_size); } -static int FREQ_FROM_REG(const int *map, u8 reg) +static int FREQ_FROM_REG(const int *map, unsigned int map_size, u8 reg) { - return map[reg & 0x07]; + return map[reg % map_size]; } /* @@ -306,14 +284,17 @@ struct lm85_autofan { * The structure is dynamically allocated. */ struct lm85_data { - struct device *hwmon_dev; + struct i2c_client *client; + const struct attribute_group *groups[6]; const int *freq_map; + unsigned int freq_map_size; + enum chips type; bool has_vid5; /* true if VID5 is configured for ADT7463 or ADT7468 */ struct mutex update_lock; - int valid; /* !=0 if following fields are valid */ + bool valid; /* true if following fields are valid */ unsigned long last_reading; /* In jiffies */ unsigned long last_config; /* In jiffies */ @@ -337,68 +318,260 @@ struct lm85_data { struct lm85_zone zone[3]; }; -static int lm85_detect(struct i2c_client *client, struct i2c_board_info *info); -static int lm85_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int lm85_remove(struct i2c_client *client); +static int lm85_read_value(struct i2c_client *client, u8 reg) +{ + int res; -static int lm85_read_value(struct i2c_client *client, u8 reg); -static void lm85_write_value(struct i2c_client *client, u8 reg, int value); -static struct lm85_data *lm85_update_device(struct device *dev); + /* What size location is it? */ + switch (reg) { + case LM85_REG_FAN(0): /* Read WORD data */ + case LM85_REG_FAN(1): + case LM85_REG_FAN(2): + case LM85_REG_FAN(3): + case LM85_REG_FAN_MIN(0): + case LM85_REG_FAN_MIN(1): + case LM85_REG_FAN_MIN(2): + case LM85_REG_FAN_MIN(3): + case LM85_REG_ALARM1: /* Read both bytes at once */ + res = i2c_smbus_read_byte_data(client, reg) & 0xff; + res |= i2c_smbus_read_byte_data(client, reg + 1) << 8; + break; + default: /* Read BYTE data */ + res = i2c_smbus_read_byte_data(client, reg); + break; + } + return res; +} -static const struct i2c_device_id lm85_id[] = { - { "adm1027", adm1027 }, - { "adt7463", adt7463 }, - { "adt7468", adt7468 }, - { "lm85", any_chip }, - { "lm85b", lm85b }, - { "lm85c", lm85c }, - { "emc6d100", emc6d100 }, - { "emc6d101", emc6d100 }, - { "emc6d102", emc6d102 }, - { "emc6d103", emc6d103 }, - { "emc6d103s", emc6d103s }, - { } -}; -MODULE_DEVICE_TABLE(i2c, lm85_id); +static void lm85_write_value(struct i2c_client *client, u8 reg, int value) +{ + switch (reg) { + case LM85_REG_FAN(0): /* Write WORD data */ + case LM85_REG_FAN(1): + case LM85_REG_FAN(2): + case LM85_REG_FAN(3): + case LM85_REG_FAN_MIN(0): + case LM85_REG_FAN_MIN(1): + case LM85_REG_FAN_MIN(2): + case LM85_REG_FAN_MIN(3): + /* NOTE: ALARM is read only, so not included here */ + i2c_smbus_write_byte_data(client, reg, value & 0xff); + i2c_smbus_write_byte_data(client, reg + 1, value >> 8); + break; + default: /* Write BYTE data */ + i2c_smbus_write_byte_data(client, reg, value); + break; + } +} -static struct i2c_driver lm85_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "lm85", - }, - .probe = lm85_probe, - .remove = lm85_remove, - .id_table = lm85_id, - .detect = lm85_detect, - .address_list = normal_i2c, -}; +static struct lm85_data *lm85_update_device(struct device *dev) +{ + struct lm85_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int i; + + mutex_lock(&data->update_lock); + + if (!data->valid || + time_after(jiffies, data->last_reading + LM85_DATA_INTERVAL)) { + /* Things that change quickly */ + dev_dbg(&client->dev, "Reading sensor values\n"); + + /* + * 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 || + data->type == adt7468) { + int ext1 = lm85_read_value(client, + ADM1027_REG_EXTEND_ADC1); + int ext2 = lm85_read_value(client, + ADM1027_REG_EXTEND_ADC2); + int val = (ext1 << 8) + ext2; + + for (i = 0; i <= 4; i++) + data->in_ext[i] = + ((val >> (i * 2)) & 0x03) << 2; + + for (i = 0; i <= 2; i++) + data->temp_ext[i] = + (val >> ((i + 4) * 2)) & 0x0c; + } + + data->vid = lm85_read_value(client, LM85_REG_VID); + + for (i = 0; i <= 3; ++i) { + data->in[i] = + lm85_read_value(client, LM85_REG_IN(i)); + data->fan[i] = + lm85_read_value(client, LM85_REG_FAN(i)); + } + + if (!data->has_vid5) + data->in[4] = lm85_read_value(client, LM85_REG_IN(4)); + + if (data->type == adt7468) + data->cfg5 = lm85_read_value(client, ADT7468_REG_CFG5); + + for (i = 0; i <= 2; ++i) { + data->temp[i] = + lm85_read_value(client, LM85_REG_TEMP(i)); + data->pwm[i] = + lm85_read_value(client, LM85_REG_PWM(i)); + + if (IS_ADT7468_OFF64(data)) + data->temp[i] -= 64; + } + + data->alarms = lm85_read_value(client, LM85_REG_ALARM1); + + if (data->type == emc6d100) { + /* Three more voltage sensors */ + for (i = 5; i <= 7; ++i) { + data->in[i] = lm85_read_value(client, + EMC6D100_REG_IN(i)); + } + /* More alarm bits */ + data->alarms |= lm85_read_value(client, + EMC6D100_REG_ALARM3) << 16; + } else if (data->type == emc6d102 || data->type == emc6d103 || + data->type == emc6d103s) { + /* + * Have to read LSB bits after the MSB ones because + * the reading of the MSB bits has frozen the + * LSBs (backward from the ADM1027). + */ + int ext1 = lm85_read_value(client, + EMC6D102_REG_EXTEND_ADC1); + int ext2 = lm85_read_value(client, + EMC6D102_REG_EXTEND_ADC2); + int ext3 = lm85_read_value(client, + EMC6D102_REG_EXTEND_ADC3); + int ext4 = lm85_read_value(client, + EMC6D102_REG_EXTEND_ADC4); + data->in_ext[0] = ext3 & 0x0f; + data->in_ext[1] = ext4 & 0x0f; + data->in_ext[2] = ext4 >> 4; + data->in_ext[3] = ext3 >> 4; + data->in_ext[4] = ext2 >> 4; + + data->temp_ext[0] = ext1 & 0x0f; + data->temp_ext[1] = ext2 & 0x0f; + data->temp_ext[2] = ext1 >> 4; + } + data->last_reading = jiffies; + } /* last_reading */ + + if (!data->valid || + time_after(jiffies, data->last_config + LM85_CONFIG_INTERVAL)) { + /* Things that don't change often */ + dev_dbg(&client->dev, "Reading config values\n"); + + for (i = 0; i <= 3; ++i) { + data->in_min[i] = + lm85_read_value(client, LM85_REG_IN_MIN(i)); + data->in_max[i] = + lm85_read_value(client, LM85_REG_IN_MAX(i)); + data->fan_min[i] = + lm85_read_value(client, LM85_REG_FAN_MIN(i)); + } + + if (!data->has_vid5) { + data->in_min[4] = lm85_read_value(client, + LM85_REG_IN_MIN(4)); + data->in_max[4] = lm85_read_value(client, + LM85_REG_IN_MAX(4)); + } + + if (data->type == emc6d100) { + for (i = 5; i <= 7; ++i) { + data->in_min[i] = lm85_read_value(client, + EMC6D100_REG_IN_MIN(i)); + data->in_max[i] = lm85_read_value(client, + EMC6D100_REG_IN_MAX(i)); + } + } + + for (i = 0; i <= 2; ++i) { + int val; + + data->temp_min[i] = + lm85_read_value(client, LM85_REG_TEMP_MIN(i)); + data->temp_max[i] = + lm85_read_value(client, LM85_REG_TEMP_MAX(i)); + + data->autofan[i].config = + lm85_read_value(client, LM85_REG_AFAN_CONFIG(i)); + val = lm85_read_value(client, LM85_REG_AFAN_RANGE(i)); + data->pwm_freq[i] = val % data->freq_map_size; + data->zone[i].range = val >> 4; + data->autofan[i].min_pwm = + lm85_read_value(client, LM85_REG_AFAN_MINPWM(i)); + data->zone[i].limit = + lm85_read_value(client, LM85_REG_AFAN_LIMIT(i)); + data->zone[i].critical = + lm85_read_value(client, LM85_REG_AFAN_CRITICAL(i)); + + if (IS_ADT7468_OFF64(data)) { + data->temp_min[i] -= 64; + data->temp_max[i] -= 64; + data->zone[i].limit -= 64; + data->zone[i].critical -= 64; + } + } + + if (data->type != emc6d103s) { + i = lm85_read_value(client, LM85_REG_AFAN_SPIKE1); + data->autofan[0].min_off = (i & 0x20) != 0; + data->autofan[1].min_off = (i & 0x40) != 0; + data->autofan[2].min_off = (i & 0x80) != 0; + + i = lm85_read_value(client, LM85_REG_AFAN_HYST1); + data->zone[0].hyst = i >> 4; + data->zone[1].hyst = i & 0x0f; + + i = lm85_read_value(client, LM85_REG_AFAN_HYST2); + data->zone[2].hyst = i >> 4; + } + + data->last_config = jiffies; + } /* last_config */ + + data->valid = true; + + mutex_unlock(&data->update_lock); + + return data; +} /* 4 Fans */ -static ssize_t show_fan(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t fan_show(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, struct device_attribute *attr, - char *buf) +static ssize_t fan_min_show(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, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t fan_min_store(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); + struct lm85_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; unsigned long val; int err; @@ -413,21 +586,19 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, return count; } -#define show_fan_offset(offset) \ -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); -show_fan_offset(3); -show_fan_offset(4); +static SENSOR_DEVICE_ATTR_RO(fan1_input, fan, 0); +static SENSOR_DEVICE_ATTR_RW(fan1_min, fan_min, 0); +static SENSOR_DEVICE_ATTR_RO(fan2_input, fan, 1); +static SENSOR_DEVICE_ATTR_RW(fan2_min, fan_min, 1); +static SENSOR_DEVICE_ATTR_RO(fan3_input, fan, 2); +static SENSOR_DEVICE_ATTR_RW(fan3_min, fan_min, 2); +static SENSOR_DEVICE_ATTR_RO(fan4_input, fan, 3); +static SENSOR_DEVICE_ATTR_RW(fan4_min, fan_min, 3); /* vid, vrm, alarms */ -static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t cpu0_vid_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct lm85_data *data = lm85_update_device(dev); int vid; @@ -443,17 +614,17 @@ static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%d\n", vid); } -static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); +static DEVICE_ATTR_RO(cpu0_vid); -static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t vrm_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct lm85_data *data = dev_get_drvdata(dev); return sprintf(buf, "%ld\n", (long) data->vrm); } -static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t vrm_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct lm85_data *data = dev_get_drvdata(dev); unsigned long val; @@ -463,63 +634,66 @@ static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr, if (err) return err; + if (val > 255) + return -EINVAL; + data->vrm = val; return count; } -static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); +static DEVICE_ATTR_RW(vrm); -static ssize_t show_alarms_reg(struct device *dev, struct device_attribute - *attr, char *buf) +static ssize_t alarms_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct lm85_data *data = lm85_update_device(dev); return sprintf(buf, "%u\n", data->alarms); } -static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); +static DEVICE_ATTR_RO(alarms); -static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t alarm_show(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); +static SENSOR_DEVICE_ATTR_RO(in0_alarm, alarm, 0); +static SENSOR_DEVICE_ATTR_RO(in1_alarm, alarm, 1); +static SENSOR_DEVICE_ATTR_RO(in2_alarm, alarm, 2); +static SENSOR_DEVICE_ATTR_RO(in3_alarm, alarm, 3); +static SENSOR_DEVICE_ATTR_RO(in4_alarm, alarm, 8); +static SENSOR_DEVICE_ATTR_RO(in5_alarm, alarm, 18); +static SENSOR_DEVICE_ATTR_RO(in6_alarm, alarm, 16); +static SENSOR_DEVICE_ATTR_RO(in7_alarm, alarm, 17); +static SENSOR_DEVICE_ATTR_RO(temp1_alarm, alarm, 4); +static SENSOR_DEVICE_ATTR_RO(temp1_fault, alarm, 14); +static SENSOR_DEVICE_ATTR_RO(temp2_alarm, alarm, 5); +static SENSOR_DEVICE_ATTR_RO(temp3_alarm, alarm, 6); +static SENSOR_DEVICE_ATTR_RO(temp3_fault, alarm, 15); +static SENSOR_DEVICE_ATTR_RO(fan1_alarm, alarm, 10); +static SENSOR_DEVICE_ATTR_RO(fan2_alarm, alarm, 11); +static SENSOR_DEVICE_ATTR_RO(fan3_alarm, alarm, 12); +static SENSOR_DEVICE_ATTR_RO(fan4_alarm, alarm, 13); /* pwm */ -static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t pwm_show(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, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t pwm_store(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); + struct lm85_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; unsigned long val; int err; @@ -534,8 +708,8 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, return count; } -static ssize_t show_pwm_enable(struct device *dev, struct device_attribute - *attr, char *buf) +static ssize_t pwm_enable_show(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); @@ -556,12 +730,13 @@ static ssize_t show_pwm_enable(struct device *dev, struct device_attribute return sprintf(buf, "%d\n", enable); } -static ssize_t set_pwm_enable(struct device *dev, struct device_attribute - *attr, const char *buf, size_t count) +static ssize_t pwm_enable_store(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); + struct lm85_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; u8 config; unsigned long val; int err; @@ -599,8 +774,8 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute return count; } -static ssize_t show_pwm_freq(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t pwm_freq_show(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); @@ -609,17 +784,19 @@ static ssize_t show_pwm_freq(struct device *dev, if (IS_ADT7468_HFPWM(data)) freq = 22500; else - freq = FREQ_FROM_REG(data->freq_map, data->pwm_freq[nr]); + freq = FREQ_FROM_REG(data->freq_map, data->freq_map_size, + data->pwm_freq[nr]); return sprintf(buf, "%d\n", freq); } -static ssize_t set_pwm_freq(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) +static ssize_t pwm_freq_store(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); + struct lm85_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; unsigned long val; int err; @@ -637,7 +814,8 @@ static ssize_t set_pwm_freq(struct device *dev, data->cfg5 &= ~ADT7468_HFPWM; lm85_write_value(client, ADT7468_REG_CFG5, data->cfg5); } else { /* Low freq. mode */ - data->pwm_freq[nr] = FREQ_TO_REG(data->freq_map, val); + data->pwm_freq[nr] = FREQ_TO_REG(data->freq_map, + data->freq_map_size, val); lm85_write_value(client, LM85_REG_AFAN_RANGE(nr), (data->zone[nr].range << 4) | data->pwm_freq[nr]); @@ -650,22 +828,20 @@ static ssize_t set_pwm_freq(struct device *dev, return count; } -#define show_pwm_reg(offset) \ -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 | S_IWUSR, \ - show_pwm_enable, set_pwm_enable, offset - 1); \ -static SENSOR_DEVICE_ATTR(pwm##offset##_freq, S_IRUGO | S_IWUSR, \ - show_pwm_freq, set_pwm_freq, offset - 1) - -show_pwm_reg(1); -show_pwm_reg(2); -show_pwm_reg(3); +static SENSOR_DEVICE_ATTR_RW(pwm1, pwm, 0); +static SENSOR_DEVICE_ATTR_RW(pwm1_enable, pwm_enable, 0); +static SENSOR_DEVICE_ATTR_RW(pwm1_freq, pwm_freq, 0); +static SENSOR_DEVICE_ATTR_RW(pwm2, pwm, 1); +static SENSOR_DEVICE_ATTR_RW(pwm2_enable, pwm_enable, 1); +static SENSOR_DEVICE_ATTR_RW(pwm2_freq, pwm_freq, 1); +static SENSOR_DEVICE_ATTR_RW(pwm3, pwm, 2); +static SENSOR_DEVICE_ATTR_RW(pwm3_enable, pwm_enable, 2); +static SENSOR_DEVICE_ATTR_RW(pwm3_freq, pwm_freq, 2); /* Voltages */ -static ssize_t show_in(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t in_show(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); @@ -673,20 +849,20 @@ static ssize_t show_in(struct device *dev, struct device_attribute *attr, data->in_ext[nr])); } -static ssize_t show_in_min(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t in_min_show(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, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t in_min_store(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); + struct lm85_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -701,20 +877,20 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, return count; } -static ssize_t show_in_max(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t in_max_show(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, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t in_max_store(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); + struct lm85_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -729,27 +905,35 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, return count; } -#define show_in_reg(offset) \ -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); -show_in_reg(2); -show_in_reg(3); -show_in_reg(4); -show_in_reg(5); -show_in_reg(6); -show_in_reg(7); +static SENSOR_DEVICE_ATTR_RO(in0_input, in, 0); +static SENSOR_DEVICE_ATTR_RW(in0_min, in_min, 0); +static SENSOR_DEVICE_ATTR_RW(in0_max, in_max, 0); +static SENSOR_DEVICE_ATTR_RO(in1_input, in, 1); +static SENSOR_DEVICE_ATTR_RW(in1_min, in_min, 1); +static SENSOR_DEVICE_ATTR_RW(in1_max, in_max, 1); +static SENSOR_DEVICE_ATTR_RO(in2_input, in, 2); +static SENSOR_DEVICE_ATTR_RW(in2_min, in_min, 2); +static SENSOR_DEVICE_ATTR_RW(in2_max, in_max, 2); +static SENSOR_DEVICE_ATTR_RO(in3_input, in, 3); +static SENSOR_DEVICE_ATTR_RW(in3_min, in_min, 3); +static SENSOR_DEVICE_ATTR_RW(in3_max, in_max, 3); +static SENSOR_DEVICE_ATTR_RO(in4_input, in, 4); +static SENSOR_DEVICE_ATTR_RW(in4_min, in_min, 4); +static SENSOR_DEVICE_ATTR_RW(in4_max, in_max, 4); +static SENSOR_DEVICE_ATTR_RO(in5_input, in, 5); +static SENSOR_DEVICE_ATTR_RW(in5_min, in_min, 5); +static SENSOR_DEVICE_ATTR_RW(in5_max, in_max, 5); +static SENSOR_DEVICE_ATTR_RO(in6_input, in, 6); +static SENSOR_DEVICE_ATTR_RW(in6_min, in_min, 6); +static SENSOR_DEVICE_ATTR_RW(in6_max, in_max, 6); +static SENSOR_DEVICE_ATTR_RO(in7_input, in, 7); +static SENSOR_DEVICE_ATTR_RW(in7_min, in_min, 7); +static SENSOR_DEVICE_ATTR_RW(in7_max, in_max, 7); /* Temps */ -static ssize_t show_temp(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t temp_show(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); @@ -757,20 +941,21 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *attr, data->temp_ext[nr])); } -static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t temp_min_show(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, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t temp_min_store(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); + struct lm85_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -788,20 +973,21 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, return count; } -static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t temp_max_show(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, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t temp_max_store(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); + struct lm85_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -819,35 +1005,34 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, return count; } -#define show_temp_reg(offset) \ -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); -show_temp_reg(3); - +static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, 0); +static SENSOR_DEVICE_ATTR_RW(temp1_min, temp_min, 0); +static SENSOR_DEVICE_ATTR_RW(temp1_max, temp_max, 0); +static SENSOR_DEVICE_ATTR_RO(temp2_input, temp, 1); +static SENSOR_DEVICE_ATTR_RW(temp2_min, temp_min, 1); +static SENSOR_DEVICE_ATTR_RW(temp2_max, temp_max, 1); +static SENSOR_DEVICE_ATTR_RO(temp3_input, temp, 2); +static SENSOR_DEVICE_ATTR_RW(temp3_min, temp_min, 2); +static SENSOR_DEVICE_ATTR_RW(temp3_max, temp_max, 2); /* Automatic PWM control */ -static ssize_t show_pwm_auto_channels(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t pwm_auto_channels_show(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, - struct device_attribute *attr, const char *buf, size_t count) +static ssize_t pwm_auto_channels_store(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); + struct lm85_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -864,20 +1049,21 @@ static ssize_t set_pwm_auto_channels(struct device *dev, return count; } -static ssize_t show_pwm_auto_pwm_min(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t pwm_auto_pwm_min_show(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, - struct device_attribute *attr, const char *buf, size_t count) +static ssize_t pwm_auto_pwm_min_store(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); + struct lm85_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; unsigned long val; int err; @@ -893,20 +1079,22 @@ static ssize_t set_pwm_auto_pwm_min(struct device *dev, return count; } -static ssize_t show_pwm_auto_pwm_minctl(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t pwm_auto_pwm_minctl_show(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, - struct device_attribute *attr, const char *buf, size_t count) +static ssize_t pwm_auto_pwm_minctl_store(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); + struct lm85_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; u8 tmp; long val; int err; @@ -926,25 +1114,21 @@ static ssize_t set_pwm_auto_pwm_minctl(struct device *dev, return count; } -#define pwm_auto(offset) \ -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) - -pwm_auto(1); -pwm_auto(2); -pwm_auto(3); +static SENSOR_DEVICE_ATTR_RW(pwm1_auto_channels, pwm_auto_channels, 0); +static SENSOR_DEVICE_ATTR_RW(pwm1_auto_pwm_min, pwm_auto_pwm_min, 0); +static SENSOR_DEVICE_ATTR_RW(pwm1_auto_pwm_minctl, pwm_auto_pwm_minctl, 0); +static SENSOR_DEVICE_ATTR_RW(pwm2_auto_channels, pwm_auto_channels, 1); +static SENSOR_DEVICE_ATTR_RW(pwm2_auto_pwm_min, pwm_auto_pwm_min, 1); +static SENSOR_DEVICE_ATTR_RW(pwm2_auto_pwm_minctl, pwm_auto_pwm_minctl, 1); +static SENSOR_DEVICE_ATTR_RW(pwm3_auto_channels, pwm_auto_channels, 2); +static SENSOR_DEVICE_ATTR_RW(pwm3_auto_pwm_min, pwm_auto_pwm_min, 2); +static SENSOR_DEVICE_ATTR_RW(pwm3_auto_pwm_minctl, pwm_auto_pwm_minctl, 2); /* Temperature settings for automatic PWM control */ -static ssize_t show_temp_auto_temp_off(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t temp_auto_temp_off_show(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); @@ -952,12 +1136,13 @@ static ssize_t show_temp_auto_temp_off(struct device *dev, HYST_FROM_REG(data->zone[nr].hyst)); } -static ssize_t set_temp_auto_temp_off(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) +static ssize_t temp_auto_temp_off_store(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); + struct lm85_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int min; long val; int err; @@ -981,20 +1166,22 @@ static ssize_t set_temp_auto_temp_off(struct device *dev, return count; } -static ssize_t show_temp_auto_temp_min(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t temp_auto_temp_min_show(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, - struct device_attribute *attr, const char *buf, size_t count) +static ssize_t temp_auto_temp_min_store(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); + struct lm85_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -1013,14 +1200,15 @@ static ssize_t set_temp_auto_temp_min(struct device *dev, TEMP_FROM_REG(data->zone[nr].limit)); lm85_write_value(client, LM85_REG_AFAN_RANGE(nr), ((data->zone[nr].range & 0x0f) << 4) - | (data->pwm_freq[nr] & 0x07)); + | data->pwm_freq[nr]); mutex_unlock(&data->update_lock); return count; } -static ssize_t show_temp_auto_temp_max(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t temp_auto_temp_max_show(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); @@ -1028,12 +1216,13 @@ static ssize_t show_temp_auto_temp_max(struct device *dev, RANGE_FROM_REG(data->zone[nr].range)); } -static ssize_t set_temp_auto_temp_max(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) +static ssize_t temp_auto_temp_max_store(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); + struct lm85_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int min; long val; int err; @@ -1049,25 +1238,27 @@ static ssize_t set_temp_auto_temp_max(struct device *dev, val - min); lm85_write_value(client, LM85_REG_AFAN_RANGE(nr), ((data->zone[nr].range & 0x0f) << 4) - | (data->pwm_freq[nr] & 0x07)); + | data->pwm_freq[nr]); mutex_unlock(&data->update_lock); return count; } -static ssize_t show_temp_auto_temp_crit(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t temp_auto_temp_crit_show(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, - struct device_attribute *attr, const char *buf, size_t count) +static ssize_t temp_auto_temp_crit_store(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); + struct lm85_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -1083,23 +1274,18 @@ static ssize_t set_temp_auto_temp_crit(struct device *dev, return count; } -#define temp_auto(offset) \ -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); +static SENSOR_DEVICE_ATTR_RW(temp1_auto_temp_off, temp_auto_temp_off, 0); +static SENSOR_DEVICE_ATTR_RW(temp1_auto_temp_min, temp_auto_temp_min, 0); +static SENSOR_DEVICE_ATTR_RW(temp1_auto_temp_max, temp_auto_temp_max, 0); +static SENSOR_DEVICE_ATTR_RW(temp1_auto_temp_crit, temp_auto_temp_crit, 0); +static SENSOR_DEVICE_ATTR_RW(temp2_auto_temp_off, temp_auto_temp_off, 1); +static SENSOR_DEVICE_ATTR_RW(temp2_auto_temp_min, temp_auto_temp_min, 1); +static SENSOR_DEVICE_ATTR_RW(temp2_auto_temp_max, temp_auto_temp_max, 1); +static SENSOR_DEVICE_ATTR_RW(temp2_auto_temp_crit, temp_auto_temp_crit, 1); +static SENSOR_DEVICE_ATTR_RW(temp3_auto_temp_off, temp_auto_temp_off, 2); +static SENSOR_DEVICE_ATTR_RW(temp3_auto_temp_min, temp_auto_temp_min, 2); +static SENSOR_DEVICE_ATTR_RW(temp3_auto_temp_max, temp_auto_temp_max, 2); +static SENSOR_DEVICE_ATTR_RW(temp3_auto_temp_crit, temp_auto_temp_crit, 2); static struct attribute *lm85_attributes[] = { &sensor_dev_attr_fan1_input.dev_attr.attr, @@ -1281,7 +1467,7 @@ static int lm85_detect(struct i2c_client *client, struct i2c_board_info *info) { struct i2c_adapter *adapter = client->adapter; int address = client->addr; - const char *type_name; + const char *type_name = NULL; int company, verstep; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { @@ -1297,16 +1483,6 @@ static int lm85_detect(struct i2c_client *client, struct i2c_board_info *info) "Detecting device at 0x%02x with COMPANY: 0x%02x and VERSTEP: 0x%02x\n", address, company, verstep); - /* All supported chips have the version in common */ - if ((verstep & LM85_VERSTEP_VMASK) != LM85_VERSTEP_GENERIC && - (verstep & LM85_VERSTEP_VMASK) != LM85_VERSTEP_GENERIC2) { - dev_dbg(&adapter->dev, - "Autodetection failed: unsupported version\n"); - return -ENODEV; - } - type_name = "lm85"; - - /* Now, refine the detection */ if (company == LM85_COMPANY_NATIONAL) { switch (verstep) { case LM85_VERSTEP_LM85C: @@ -1323,6 +1499,7 @@ static int lm85_detect(struct i2c_client *client, struct i2c_board_info *info) "Found Winbond WPCD377I, ignoring\n"); return -ENODEV; } + type_name = "lm96000"; break; } } else if (company == LM85_COMPANY_ANALOG_DEV) { @@ -1357,42 +1534,29 @@ static int lm85_detect(struct i2c_client *client, struct i2c_board_info *info) type_name = "emc6d103s"; break; } - } else { - dev_dbg(&adapter->dev, - "Autodetection failed: unknown vendor\n"); - return -ENODEV; } - strlcpy(info->type, type_name, I2C_NAME_SIZE); + if (!type_name) + return -ENODEV; - return 0; -} + strscpy(info->type, type_name, I2C_NAME_SIZE); -static void lm85_remove_files(struct i2c_client *client, struct lm85_data *data) -{ - sysfs_remove_group(&client->dev.kobj, &lm85_group); - if (data->type != emc6d103s) { - sysfs_remove_group(&client->dev.kobj, &lm85_group_minctl); - sysfs_remove_group(&client->dev.kobj, &lm85_group_temp_off); - } - if (!data->has_vid5) - sysfs_remove_group(&client->dev.kobj, &lm85_group_in4); - if (data->type == emc6d100) - sysfs_remove_group(&client->dev.kobj, &lm85_group_in567); + return 0; } -static int lm85_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int lm85_probe(struct i2c_client *client) { + struct device *dev = &client->dev; + struct device *hwmon_dev; struct lm85_data *data; - int err; + int idx = 0; - data = devm_kzalloc(&client->dev, sizeof(struct lm85_data), GFP_KERNEL); + data = devm_kzalloc(dev, sizeof(struct lm85_data), GFP_KERNEL); if (!data) return -ENOMEM; - i2c_set_clientdata(client, data); - data->type = id->driver_data; + data->client = client; + data->type = (uintptr_t)i2c_get_match_data(client); mutex_init(&data->update_lock); /* Fill in the chip specific driver values */ @@ -1405,9 +1569,15 @@ static int lm85_probe(struct i2c_client *client, case emc6d103: case emc6d103s: data->freq_map = adm1027_freq_map; + data->freq_map_size = ARRAY_SIZE(adm1027_freq_map); + break; + case lm96000: + data->freq_map = lm96000_freq_map; + data->freq_map_size = ARRAY_SIZE(lm96000_freq_map); break; default: data->freq_map = lm85_freq_map; + data->freq_map_size = ARRAY_SIZE(lm85_freq_map); } /* Set the VRM version */ @@ -1416,20 +1586,13 @@ static int lm85_probe(struct i2c_client *client, /* Initialize the LM85 chip */ lm85_init_client(client); - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &lm85_group); - if (err) - return err; + /* sysfs hooks */ + data->groups[idx++] = &lm85_group; /* minctl and temp_off exist on all chips except emc6d103s */ if (data->type != emc6d103s) { - err = sysfs_create_group(&client->dev.kobj, &lm85_group_minctl); - if (err) - goto err_remove_files; - err = sysfs_create_group(&client->dev.kobj, - &lm85_group_temp_off); - if (err) - goto err_remove_files; + data->groups[idx++] = &lm85_group_minctl; + data->groups[idx++] = &lm85_group_temp_off; } /* @@ -1442,271 +1605,99 @@ static int lm85_probe(struct i2c_client *client, data->has_vid5 = true; } - if (!data->has_vid5) { - err = sysfs_create_group(&client->dev.kobj, &lm85_group_in4); - if (err) - goto err_remove_files; - } + if (!data->has_vid5) + data->groups[idx++] = &lm85_group_in4; /* The EMC6D100 has 3 additional voltage inputs */ - if (data->type == emc6d100) { - err = sysfs_create_group(&client->dev.kobj, &lm85_group_in567); - if (err) - goto err_remove_files; - } - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto err_remove_files; - } - - return 0; - - /* Error out and cleanup code */ - err_remove_files: - lm85_remove_files(client, data); - return err; -} - -static int lm85_remove(struct i2c_client *client) -{ - struct lm85_data *data = i2c_get_clientdata(client); - hwmon_device_unregister(data->hwmon_dev); - lm85_remove_files(client, data); - return 0; -} - - -static int lm85_read_value(struct i2c_client *client, u8 reg) -{ - int res; - - /* What size location is it? */ - switch (reg) { - case LM85_REG_FAN(0): /* Read WORD data */ - case LM85_REG_FAN(1): - case LM85_REG_FAN(2): - case LM85_REG_FAN(3): - case LM85_REG_FAN_MIN(0): - case LM85_REG_FAN_MIN(1): - case LM85_REG_FAN_MIN(2): - case LM85_REG_FAN_MIN(3): - case LM85_REG_ALARM1: /* Read both bytes at once */ - res = i2c_smbus_read_byte_data(client, reg) & 0xff; - res |= i2c_smbus_read_byte_data(client, reg + 1) << 8; - break; - default: /* Read BYTE data */ - res = i2c_smbus_read_byte_data(client, reg); - break; - } + if (data->type == emc6d100) + data->groups[idx++] = &lm85_group_in567; - return res; + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, + data, data->groups); + return PTR_ERR_OR_ZERO(hwmon_dev); } -static void lm85_write_value(struct i2c_client *client, u8 reg, int value) -{ - switch (reg) { - case LM85_REG_FAN(0): /* Write WORD data */ - case LM85_REG_FAN(1): - case LM85_REG_FAN(2): - case LM85_REG_FAN(3): - case LM85_REG_FAN_MIN(0): - case LM85_REG_FAN_MIN(1): - case LM85_REG_FAN_MIN(2): - case LM85_REG_FAN_MIN(3): - /* NOTE: ALARM is read only, so not included here */ - i2c_smbus_write_byte_data(client, reg, value & 0xff); - i2c_smbus_write_byte_data(client, reg + 1, value >> 8); - break; - default: /* Write BYTE data */ - i2c_smbus_write_byte_data(client, reg, value); - break; - } -} - -static struct lm85_data *lm85_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); - int i; - - mutex_lock(&data->update_lock); - - if (!data->valid || - time_after(jiffies, data->last_reading + LM85_DATA_INTERVAL)) { - /* Things that change quickly */ - dev_dbg(&client->dev, "Reading sensor values\n"); - - /* - * 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 || - data->type == adt7468) { - int ext1 = lm85_read_value(client, - ADM1027_REG_EXTEND_ADC1); - int ext2 = lm85_read_value(client, - ADM1027_REG_EXTEND_ADC2); - int val = (ext1 << 8) + ext2; - - for (i = 0; i <= 4; i++) - data->in_ext[i] = - ((val >> (i * 2)) & 0x03) << 2; - - for (i = 0; i <= 2; i++) - data->temp_ext[i] = - (val >> ((i + 4) * 2)) & 0x0c; - } - - data->vid = lm85_read_value(client, LM85_REG_VID); - - for (i = 0; i <= 3; ++i) { - data->in[i] = - lm85_read_value(client, LM85_REG_IN(i)); - data->fan[i] = - lm85_read_value(client, LM85_REG_FAN(i)); - } - - if (!data->has_vid5) - data->in[4] = lm85_read_value(client, LM85_REG_IN(4)); - - if (data->type == adt7468) - data->cfg5 = lm85_read_value(client, ADT7468_REG_CFG5); - - for (i = 0; i <= 2; ++i) { - data->temp[i] = - lm85_read_value(client, LM85_REG_TEMP(i)); - data->pwm[i] = - lm85_read_value(client, LM85_REG_PWM(i)); - - if (IS_ADT7468_OFF64(data)) - data->temp[i] -= 64; - } - - data->alarms = lm85_read_value(client, LM85_REG_ALARM1); - - if (data->type == emc6d100) { - /* Three more voltage sensors */ - for (i = 5; i <= 7; ++i) { - data->in[i] = lm85_read_value(client, - EMC6D100_REG_IN(i)); - } - /* More alarm bits */ - data->alarms |= lm85_read_value(client, - EMC6D100_REG_ALARM3) << 16; - } else if (data->type == emc6d102 || data->type == emc6d103 || - data->type == emc6d103s) { - /* - * Have to read LSB bits after the MSB ones because - * the reading of the MSB bits has frozen the - * LSBs (backward from the ADM1027). - */ - int ext1 = lm85_read_value(client, - EMC6D102_REG_EXTEND_ADC1); - int ext2 = lm85_read_value(client, - EMC6D102_REG_EXTEND_ADC2); - int ext3 = lm85_read_value(client, - EMC6D102_REG_EXTEND_ADC3); - int ext4 = lm85_read_value(client, - EMC6D102_REG_EXTEND_ADC4); - data->in_ext[0] = ext3 & 0x0f; - data->in_ext[1] = ext4 & 0x0f; - data->in_ext[2] = ext4 >> 4; - data->in_ext[3] = ext3 >> 4; - data->in_ext[4] = ext2 >> 4; - - data->temp_ext[0] = ext1 & 0x0f; - data->temp_ext[1] = ext2 & 0x0f; - data->temp_ext[2] = ext1 >> 4; - } - - data->last_reading = jiffies; - } /* last_reading */ - - if (!data->valid || - time_after(jiffies, data->last_config + LM85_CONFIG_INTERVAL)) { - /* Things that don't change often */ - dev_dbg(&client->dev, "Reading config values\n"); - - for (i = 0; i <= 3; ++i) { - data->in_min[i] = - lm85_read_value(client, LM85_REG_IN_MIN(i)); - data->in_max[i] = - lm85_read_value(client, LM85_REG_IN_MAX(i)); - data->fan_min[i] = - lm85_read_value(client, LM85_REG_FAN_MIN(i)); - } - - if (!data->has_vid5) { - data->in_min[4] = lm85_read_value(client, - LM85_REG_IN_MIN(4)); - data->in_max[4] = lm85_read_value(client, - LM85_REG_IN_MAX(4)); - } - - if (data->type == emc6d100) { - for (i = 5; i <= 7; ++i) { - data->in_min[i] = lm85_read_value(client, - EMC6D100_REG_IN_MIN(i)); - data->in_max[i] = lm85_read_value(client, - EMC6D100_REG_IN_MAX(i)); - } - } - - for (i = 0; i <= 2; ++i) { - int val; - - data->temp_min[i] = - lm85_read_value(client, LM85_REG_TEMP_MIN(i)); - data->temp_max[i] = - lm85_read_value(client, LM85_REG_TEMP_MAX(i)); - - data->autofan[i].config = - lm85_read_value(client, LM85_REG_AFAN_CONFIG(i)); - val = lm85_read_value(client, LM85_REG_AFAN_RANGE(i)); - data->pwm_freq[i] = val & 0x07; - data->zone[i].range = val >> 4; - data->autofan[i].min_pwm = - lm85_read_value(client, LM85_REG_AFAN_MINPWM(i)); - data->zone[i].limit = - lm85_read_value(client, LM85_REG_AFAN_LIMIT(i)); - data->zone[i].critical = - lm85_read_value(client, LM85_REG_AFAN_CRITICAL(i)); - - if (IS_ADT7468_OFF64(data)) { - data->temp_min[i] -= 64; - data->temp_max[i] -= 64; - data->zone[i].limit -= 64; - data->zone[i].critical -= 64; - } - } - - if (data->type != emc6d103s) { - i = lm85_read_value(client, LM85_REG_AFAN_SPIKE1); - data->autofan[0].min_off = (i & 0x20) != 0; - data->autofan[1].min_off = (i & 0x40) != 0; - data->autofan[2].min_off = (i & 0x80) != 0; - - i = lm85_read_value(client, LM85_REG_AFAN_HYST1); - data->zone[0].hyst = i >> 4; - data->zone[1].hyst = i & 0x0f; - - i = lm85_read_value(client, LM85_REG_AFAN_HYST2); - data->zone[2].hyst = i >> 4; - } - - data->last_config = jiffies; - } /* last_config */ - - data->valid = 1; +static const struct i2c_device_id lm85_id[] = { + { "adm1027", adm1027 }, + { "adt7463", adt7463 }, + { "adt7468", adt7468 }, + { "lm85", lm85 }, + { "lm85b", lm85 }, + { "lm85c", lm85 }, + { "lm96000", lm96000 }, + { "emc6d100", emc6d100 }, + { "emc6d101", emc6d100 }, + { "emc6d102", emc6d102 }, + { "emc6d103", emc6d103 }, + { "emc6d103s", emc6d103s }, + { } +}; +MODULE_DEVICE_TABLE(i2c, lm85_id); - mutex_unlock(&data->update_lock); +static const struct of_device_id __maybe_unused lm85_of_match[] = { + { + .compatible = "adi,adm1027", + .data = (void *)adm1027 + }, + { + .compatible = "adi,adt7463", + .data = (void *)adt7463 + }, + { + .compatible = "adi,adt7468", + .data = (void *)adt7468 + }, + { + .compatible = "national,lm85", + .data = (void *)lm85 + }, + { + .compatible = "national,lm85b", + .data = (void *)lm85 + }, + { + .compatible = "national,lm85c", + .data = (void *)lm85 + }, + { + .compatible = "ti,lm96000", + .data = (void *)lm96000 + }, + { + .compatible = "smsc,emc6d100", + .data = (void *)emc6d100 + }, + { + .compatible = "smsc,emc6d101", + .data = (void *)emc6d100 + }, + { + .compatible = "smsc,emc6d102", + .data = (void *)emc6d102 + }, + { + .compatible = "smsc,emc6d103", + .data = (void *)emc6d103 + }, + { + .compatible = "smsc,emc6d103s", + .data = (void *)emc6d103s + }, + { }, +}; +MODULE_DEVICE_TABLE(of, lm85_of_match); - return data; -} +static struct i2c_driver lm85_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "lm85", + .of_match_table = of_match_ptr(lm85_of_match), + }, + .probe = lm85_probe, + .id_table = lm85_id, + .detect = lm85_detect, + .address_list = normal_i2c, +}; module_i2c_driver(lm85_driver); |
