diff options
Diffstat (limited to 'drivers/hwmon/lm80.c')
| -rw-r--r-- | drivers/hwmon/lm80.c | 640 | 
1 files changed, 304 insertions, 336 deletions
| diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c index bd0a1ebbf867..4bcd9b882948 100644 --- a/drivers/hwmon/lm80.c +++ b/drivers/hwmon/lm80.c @@ -86,26 +86,41 @@ static inline unsigned char FAN_TO_REG(unsigned rpm, unsigned div)  #define FAN_FROM_REG(val, div)	((val) == 0 ? -1 : \  				(val) == 255 ? 0 : 1350000/((div) * (val))) -static inline long TEMP_FROM_REG(u16 temp) -{ -	long res; +#define TEMP_FROM_REG(reg)	((reg) * 125 / 32) +#define TEMP_TO_REG(temp)	(DIV_ROUND_CLOSEST(clamp_val((temp), \ +					-128000, 127000), 1000) << 8) -	temp >>= 4; -	if (temp < 0x0800) -		res = 625 * (long) temp; -	else -		res = ((long) temp - 0x01000) * 625; +#define DIV_FROM_REG(val)		(1 << (val)) -	return res / 10; -} +enum temp_index { +	t_input = 0, +	t_hot_max, +	t_hot_hyst, +	t_os_max, +	t_os_hyst, +	t_num_temp +}; -#define TEMP_LIMIT_FROM_REG(val)	(((val) > 0x80 ? \ -	(val) - 0x100 : (val)) * 1000) +static const u8 temp_regs[t_num_temp] = { +	[t_input] = LM80_REG_TEMP, +	[t_hot_max] = LM80_REG_TEMP_HOT_MAX, +	[t_hot_hyst] = LM80_REG_TEMP_HOT_HYST, +	[t_os_max] = LM80_REG_TEMP_OS_MAX, +	[t_os_hyst] = LM80_REG_TEMP_OS_HYST, +}; -#define TEMP_LIMIT_TO_REG(val)		clamp_val((val) < 0 ? \ -	((val) - 500) / 1000 : ((val) + 500) / 1000, 0, 255) +enum in_index { +	i_input = 0, +	i_max, +	i_min, +	i_num_in +}; -#define DIV_FROM_REG(val)		(1 << (val)) +enum fan_index { +	f_input, +	f_min, +	f_num_fan +};  /*   * Client data (each client gets its own) @@ -118,106 +133,187 @@ struct lm80_data {  	char valid;		/* !=0 if following fields are valid */  	unsigned long last_updated;	/* In jiffies */ -	u8 in[7];		/* Register value */ -	u8 in_max[7];		/* Register value */ -	u8 in_min[7];		/* Register value */ -	u8 fan[2];		/* Register value */ -	u8 fan_min[2];		/* Register value */ +	u8 in[i_num_in][7];	/* Register value, 1st index is enum in_index */ +	u8 fan[f_num_fan][2];	/* Register value, 1st index enum fan_index */  	u8 fan_div[2];		/* Register encoding, shifted right */ -	u16 temp;		/* Register values, shifted right */ -	u8 temp_hot_max;	/* Register value */ -	u8 temp_hot_hyst;	/* Register value */ -	u8 temp_os_max;		/* Register value */ -	u8 temp_os_hyst;	/* Register value */ +	s16 temp[t_num_temp];	/* Register values, normalized to 16 bit */  	u16 alarms;		/* Register encoding, combined */  }; -/* - * Functions declaration - */ +static int lm80_read_value(struct i2c_client *client, u8 reg) +{ +	return i2c_smbus_read_byte_data(client, reg); +} -static int lm80_probe(struct i2c_client *client, -		      const struct i2c_device_id *id); -static int lm80_detect(struct i2c_client *client, struct i2c_board_info *info); -static void lm80_init_client(struct i2c_client *client); -static struct lm80_data *lm80_update_device(struct device *dev); -static int lm80_read_value(struct i2c_client *client, u8 reg); -static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value); +static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value) +{ +	return i2c_smbus_write_byte_data(client, reg, value); +} -/* - * Driver data (common to all clients) - */ +/* Called when we have found a new LM80 and after read errors */ +static void lm80_init_client(struct i2c_client *client) +{ +	/* +	 * Reset all except Watchdog values and last conversion values +	 * This sets fan-divs to 2, among others. This makes most other +	 * initializations unnecessary +	 */ +	lm80_write_value(client, LM80_REG_CONFIG, 0x80); +	/* Set 11-bit temperature resolution */ +	lm80_write_value(client, LM80_REG_RES, 0x08); -static const struct i2c_device_id lm80_id[] = { -	{ "lm80", 0 }, -	{ "lm96080", 1 }, -	{ } -}; -MODULE_DEVICE_TABLE(i2c, lm80_id); +	/* Start monitoring */ +	lm80_write_value(client, LM80_REG_CONFIG, 0x01); +} -static struct i2c_driver lm80_driver = { -	.class		= I2C_CLASS_HWMON, -	.driver = { -		.name	= "lm80", -	}, -	.probe		= lm80_probe, -	.id_table	= lm80_id, -	.detect		= lm80_detect, -	.address_list	= normal_i2c, -}; +static struct lm80_data *lm80_update_device(struct device *dev) +{ +	struct lm80_data *data = dev_get_drvdata(dev); +	struct i2c_client *client = data->client; +	int i; +	int rv; +	int prev_rv; +	struct lm80_data *ret = data; + +	mutex_lock(&data->update_lock); + +	if (data->error) +		lm80_init_client(client); + +	if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { +		dev_dbg(dev, "Starting lm80 update\n"); +		for (i = 0; i <= 6; i++) { +			rv = lm80_read_value(client, LM80_REG_IN(i)); +			if (rv < 0) +				goto abort; +			data->in[i_input][i] = rv; + +			rv = lm80_read_value(client, LM80_REG_IN_MIN(i)); +			if (rv < 0) +				goto abort; +			data->in[i_min][i] = rv; + +			rv = lm80_read_value(client, LM80_REG_IN_MAX(i)); +			if (rv < 0) +				goto abort; +			data->in[i_max][i] = rv; +		} + +		rv = lm80_read_value(client, LM80_REG_FAN1); +		if (rv < 0) +			goto abort; +		data->fan[f_input][0] = rv; + +		rv = lm80_read_value(client, LM80_REG_FAN_MIN(1)); +		if (rv < 0) +			goto abort; +		data->fan[f_min][0] = rv; + +		rv = lm80_read_value(client, LM80_REG_FAN2); +		if (rv < 0) +			goto abort; +		data->fan[f_input][1] = rv; + +		rv = lm80_read_value(client, LM80_REG_FAN_MIN(2)); +		if (rv < 0) +			goto abort; +		data->fan[f_min][1] = rv; + +		prev_rv = rv = lm80_read_value(client, LM80_REG_TEMP); +		if (rv < 0) +			goto abort; +		rv = lm80_read_value(client, LM80_REG_RES); +		if (rv < 0) +			goto abort; +		data->temp[t_input] = (prev_rv << 8) | (rv & 0xf0); + +		for (i = t_input + 1; i < t_num_temp; i++) { +			rv = lm80_read_value(client, temp_regs[i]); +			if (rv < 0) +				goto abort; +			data->temp[i] = rv << 8; +		} + +		rv = lm80_read_value(client, LM80_REG_FANDIV); +		if (rv < 0) +			goto abort; +		data->fan_div[0] = (rv >> 2) & 0x03; +		data->fan_div[1] = (rv >> 4) & 0x03; + +		prev_rv = rv = lm80_read_value(client, LM80_REG_ALARM1); +		if (rv < 0) +			goto abort; +		rv = lm80_read_value(client, LM80_REG_ALARM2); +		if (rv < 0) +			goto abort; +		data->alarms = prev_rv + (rv << 8); + +		data->last_updated = jiffies; +		data->valid = 1; +		data->error = 0; +	} +	goto done; + +abort: +	ret = ERR_PTR(rv); +	data->valid = 0; +	data->error = 1; + +done: +	mutex_unlock(&data->update_lock); + +	return ret; +}  /*   * Sysfs stuff   */ -#define show_in(suffix, value) \ -static ssize_t show_in_##suffix(struct device *dev, \ -	struct device_attribute *attr, char *buf) \ -{ \ -	int nr = to_sensor_dev_attr(attr)->index; \ -	struct lm80_data *data = lm80_update_device(dev); \ -	if (IS_ERR(data)) \ -		return PTR_ERR(data); \ -	return sprintf(buf, "%d\n", IN_FROM_REG(data->value[nr])); \ +static ssize_t show_in(struct device *dev, struct device_attribute *attr, +		       char *buf) +{ +	struct lm80_data *data = lm80_update_device(dev); +	int index = to_sensor_dev_attr_2(attr)->index; +	int nr = to_sensor_dev_attr_2(attr)->nr; + +	if (IS_ERR(data)) +		return PTR_ERR(data); +	return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr][index]));  } -show_in(min, in_min) -show_in(max, in_max) -show_in(input, in) - -#define set_in(suffix, value, reg) \ -static ssize_t set_in_##suffix(struct device *dev, \ -	struct device_attribute *attr, const char *buf, size_t count) \ -{ \ -	int nr = to_sensor_dev_attr(attr)->index; \ -	struct lm80_data *data = dev_get_drvdata(dev); \ -	struct i2c_client *client = data->client; \ -	long val; \ -	int err = kstrtol(buf, 10, &val); \ -	if (err < 0) \ -		return err; \ -\ -	mutex_lock(&data->update_lock);\ -	data->value[nr] = IN_TO_REG(val); \ -	lm80_write_value(client, reg(nr), data->value[nr]); \ -	mutex_unlock(&data->update_lock);\ -	return count; \ + +static ssize_t set_in(struct device *dev, struct device_attribute *attr, +		      const char *buf, size_t count) +{ +	struct lm80_data *data = dev_get_drvdata(dev); +	struct i2c_client *client = data->client; +	int index = to_sensor_dev_attr_2(attr)->index; +	int nr = to_sensor_dev_attr_2(attr)->nr; +	long val; +	u8 reg; +	int err = kstrtol(buf, 10, &val); +	if (err < 0) +		return err; + +	reg = nr == i_min ? LM80_REG_IN_MIN(index) : LM80_REG_IN_MAX(index); + +	mutex_lock(&data->update_lock); +	data->in[nr][index] = IN_TO_REG(val); +	lm80_write_value(client, reg, data->in[nr][index]); +	mutex_unlock(&data->update_lock); +	return count;  } -set_in(min, in_min, LM80_REG_IN_MIN) -set_in(max, in_max, LM80_REG_IN_MAX) - -#define show_fan(suffix, value) \ -static ssize_t show_fan_##suffix(struct device *dev, \ -	struct device_attribute *attr, char *buf) \ -{ \ -	int nr = to_sensor_dev_attr(attr)->index; \ -	struct lm80_data *data = lm80_update_device(dev); \ -	if (IS_ERR(data)) \ -		return PTR_ERR(data); \ -	return sprintf(buf, "%d\n", FAN_FROM_REG(data->value[nr], \ -		       DIV_FROM_REG(data->fan_div[nr]))); \ + +static ssize_t show_fan(struct device *dev, struct device_attribute *attr, +			char *buf) +{ +	int index = to_sensor_dev_attr_2(attr)->index; +	int nr = to_sensor_dev_attr_2(attr)->nr; +	struct lm80_data *data = lm80_update_device(dev); +	if (IS_ERR(data)) +		return PTR_ERR(data); +	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr][index], +		       DIV_FROM_REG(data->fan_div[index])));  } -show_fan(min, fan_min) -show_fan(input, fan)  static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr,  	char *buf) @@ -232,7 +328,8 @@ static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr,  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; +	int index = to_sensor_dev_attr_2(attr)->index; +	int nr = to_sensor_dev_attr_2(attr)->nr;  	struct lm80_data *data = dev_get_drvdata(dev);  	struct i2c_client *client = data->client;  	unsigned long val; @@ -241,8 +338,10 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,  		return err;  	mutex_lock(&data->update_lock); -	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); -	lm80_write_value(client, LM80_REG_FAN_MIN(nr + 1), data->fan_min[nr]); +	data->fan[nr][index] = FAN_TO_REG(val, +					  DIV_FROM_REG(data->fan_div[index])); +	lm80_write_value(client, LM80_REG_FAN_MIN(index + 1), +			 data->fan[nr][index]);  	mutex_unlock(&data->update_lock);  	return count;  } @@ -267,7 +366,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,  	/* Save fan_min */  	mutex_lock(&data->update_lock); -	min = FAN_FROM_REG(data->fan_min[nr], +	min = FAN_FROM_REG(data->fan[f_min][nr],  			   DIV_FROM_REG(data->fan_div[nr]));  	switch (val) { @@ -291,62 +390,47 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,  		return -EINVAL;  	} -	reg = (lm80_read_value(client, LM80_REG_FANDIV) & ~(3 << (2 * (nr + 1)))) -	    | (data->fan_div[nr] << (2 * (nr + 1))); +	reg = (lm80_read_value(client, LM80_REG_FANDIV) & +	       ~(3 << (2 * (nr + 1)))) | (data->fan_div[nr] << (2 * (nr + 1)));  	lm80_write_value(client, LM80_REG_FANDIV, reg);  	/* Restore fan_min */ -	data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); -	lm80_write_value(client, LM80_REG_FAN_MIN(nr + 1), data->fan_min[nr]); +	data->fan[f_min][nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); +	lm80_write_value(client, LM80_REG_FAN_MIN(nr + 1), +			 data->fan[f_min][nr]);  	mutex_unlock(&data->update_lock);  	return count;  } -static ssize_t show_temp_input1(struct device *dev, -	struct device_attribute *attr, char *buf) +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 lm80_data *data = lm80_update_device(dev);  	if (IS_ERR(data))  		return PTR_ERR(data); -	return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp)); +	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index]));  } -#define show_temp(suffix, value) \ -static ssize_t show_temp_##suffix(struct device *dev, \ -	struct device_attribute *attr, char *buf) \ -{ \ -	struct lm80_data *data = lm80_update_device(dev); \ -	if (IS_ERR(data)) \ -		return PTR_ERR(data); \ -	return sprintf(buf, "%d\n", TEMP_LIMIT_FROM_REG(data->value)); \ -} -show_temp(hot_max, temp_hot_max); -show_temp(hot_hyst, temp_hot_hyst); -show_temp(os_max, temp_os_max); -show_temp(os_hyst, temp_os_hyst); - -#define set_temp(suffix, value, reg) \ -static ssize_t set_temp_##suffix(struct device *dev, \ -	struct device_attribute *attr, const char *buf, size_t count) \ -{ \ -	struct lm80_data *data = dev_get_drvdata(dev); \ -	struct i2c_client *client = data->client; \ -	long val; \ -	int err = kstrtol(buf, 10, &val); \ -	if (err < 0) \ -		return err; \ -\ -	mutex_lock(&data->update_lock); \ -	data->value = TEMP_LIMIT_TO_REG(val); \ -	lm80_write_value(client, reg, data->value); \ -	mutex_unlock(&data->update_lock); \ -	return count; \ +static ssize_t set_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 lm80_data *data = dev_get_drvdata(dev); +	struct i2c_client *client = data->client; +	int nr = attr->index; +	long val; +	int err = kstrtol(buf, 10, &val); +	if (err < 0) +		return err; + +	mutex_lock(&data->update_lock); +	data->temp[nr] = TEMP_TO_REG(val); +	lm80_write_value(client, temp_regs[nr], data->temp[nr] >> 8); +	mutex_unlock(&data->update_lock); +	return count;  } -set_temp(hot_max, temp_hot_max, LM80_REG_TEMP_HOT_MAX); -set_temp(hot_hyst, temp_hot_hyst, LM80_REG_TEMP_HOT_HYST); -set_temp(os_max, temp_os_max, LM80_REG_TEMP_OS_MAX); -set_temp(os_hyst, temp_os_hyst, LM80_REG_TEMP_OS_HYST);  static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,  			   char *buf) @@ -367,60 +451,60 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,  	return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);  } -static SENSOR_DEVICE_ATTR(in0_min, S_IWUSR | S_IRUGO, -		show_in_min, set_in_min, 0); -static SENSOR_DEVICE_ATTR(in1_min, S_IWUSR | S_IRUGO, -		show_in_min, set_in_min, 1); -static SENSOR_DEVICE_ATTR(in2_min, S_IWUSR | S_IRUGO, -		show_in_min, set_in_min, 2); -static SENSOR_DEVICE_ATTR(in3_min, S_IWUSR | S_IRUGO, -		show_in_min, set_in_min, 3); -static SENSOR_DEVICE_ATTR(in4_min, S_IWUSR | S_IRUGO, -		show_in_min, set_in_min, 4); -static SENSOR_DEVICE_ATTR(in5_min, S_IWUSR | S_IRUGO, -		show_in_min, set_in_min, 5); -static SENSOR_DEVICE_ATTR(in6_min, S_IWUSR | S_IRUGO, -		show_in_min, set_in_min, 6); -static SENSOR_DEVICE_ATTR(in0_max, S_IWUSR | S_IRUGO, -		show_in_max, set_in_max, 0); -static SENSOR_DEVICE_ATTR(in1_max, S_IWUSR | S_IRUGO, -		show_in_max, set_in_max, 1); -static SENSOR_DEVICE_ATTR(in2_max, S_IWUSR | S_IRUGO, -		show_in_max, set_in_max, 2); -static SENSOR_DEVICE_ATTR(in3_max, S_IWUSR | S_IRUGO, -		show_in_max, set_in_max, 3); -static SENSOR_DEVICE_ATTR(in4_max, S_IWUSR | S_IRUGO, -		show_in_max, set_in_max, 4); -static SENSOR_DEVICE_ATTR(in5_max, S_IWUSR | S_IRUGO, -		show_in_max, set_in_max, 5); -static SENSOR_DEVICE_ATTR(in6_max, S_IWUSR | S_IRUGO, -		show_in_max, set_in_max, 6); -static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_in_input, NULL, 0); -static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in_input, NULL, 1); -static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in_input, NULL, 2); -static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in_input, NULL, 3); -static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in_input, NULL, 4); -static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_in_input, NULL, 5); -static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_in_input, NULL, 6); -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(fan1_input, S_IRUGO, show_fan_input, NULL, 0); -static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1); +static SENSOR_DEVICE_ATTR_2(in0_min, S_IWUSR | S_IRUGO, +		show_in, set_in, i_min, 0); +static SENSOR_DEVICE_ATTR_2(in1_min, S_IWUSR | S_IRUGO, +		show_in, set_in, i_min, 1); +static SENSOR_DEVICE_ATTR_2(in2_min, S_IWUSR | S_IRUGO, +		show_in, set_in, i_min, 2); +static SENSOR_DEVICE_ATTR_2(in3_min, S_IWUSR | S_IRUGO, +		show_in, set_in, i_min, 3); +static SENSOR_DEVICE_ATTR_2(in4_min, S_IWUSR | S_IRUGO, +		show_in, set_in, i_min, 4); +static SENSOR_DEVICE_ATTR_2(in5_min, S_IWUSR | S_IRUGO, +		show_in, set_in, i_min, 5); +static SENSOR_DEVICE_ATTR_2(in6_min, S_IWUSR | S_IRUGO, +		show_in, set_in, i_min, 6); +static SENSOR_DEVICE_ATTR_2(in0_max, S_IWUSR | S_IRUGO, +		show_in, set_in, i_max, 0); +static SENSOR_DEVICE_ATTR_2(in1_max, S_IWUSR | S_IRUGO, +		show_in, set_in, i_max, 1); +static SENSOR_DEVICE_ATTR_2(in2_max, S_IWUSR | S_IRUGO, +		show_in, set_in, i_max, 2); +static SENSOR_DEVICE_ATTR_2(in3_max, S_IWUSR | S_IRUGO, +		show_in, set_in, i_max, 3); +static SENSOR_DEVICE_ATTR_2(in4_max, S_IWUSR | S_IRUGO, +		show_in, set_in, i_max, 4); +static SENSOR_DEVICE_ATTR_2(in5_max, S_IWUSR | S_IRUGO, +		show_in, set_in, i_max, 5); +static SENSOR_DEVICE_ATTR_2(in6_max, S_IWUSR | S_IRUGO, +		show_in, set_in, i_max, 6); +static SENSOR_DEVICE_ATTR_2(in0_input, S_IRUGO, show_in, NULL, i_input, 0); +static SENSOR_DEVICE_ATTR_2(in1_input, S_IRUGO, show_in, NULL, i_input, 1); +static SENSOR_DEVICE_ATTR_2(in2_input, S_IRUGO, show_in, NULL, i_input, 2); +static SENSOR_DEVICE_ATTR_2(in3_input, S_IRUGO, show_in, NULL, i_input, 3); +static SENSOR_DEVICE_ATTR_2(in4_input, S_IRUGO, show_in, NULL, i_input, 4); +static SENSOR_DEVICE_ATTR_2(in5_input, S_IRUGO, show_in, NULL, i_input, 5); +static SENSOR_DEVICE_ATTR_2(in6_input, S_IRUGO, show_in, NULL, i_input, 6); +static SENSOR_DEVICE_ATTR_2(fan1_min, S_IWUSR | S_IRUGO, +		show_fan, set_fan_min, f_min, 0); +static SENSOR_DEVICE_ATTR_2(fan2_min, S_IWUSR | S_IRUGO, +		show_fan, set_fan_min, f_min, 1); +static SENSOR_DEVICE_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, f_input, 0); +static SENSOR_DEVICE_ATTR_2(fan2_input, S_IRUGO, show_fan, NULL, f_input, 1);  static SENSOR_DEVICE_ATTR(fan1_div, S_IWUSR | S_IRUGO,  		show_fan_div, set_fan_div, 0);  static SENSOR_DEVICE_ATTR(fan2_div, S_IWUSR | S_IRUGO,  		show_fan_div, set_fan_div, 1); -static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input1, NULL); -static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_hot_max, -	set_temp_hot_max); -static DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_temp_hot_hyst, -	set_temp_hot_hyst); -static DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp_os_max, -	set_temp_os_max); -static DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temp_os_hyst, -	set_temp_os_hyst); +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, t_input); +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp, +		set_temp, t_hot_max); +static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_temp, +		set_temp, t_hot_hyst); +static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp, +		set_temp, t_os_max); +static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temp, +		set_temp, t_os_hyst);  static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, 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); @@ -466,11 +550,11 @@ static struct attribute *lm80_attrs[] = {  	&sensor_dev_attr_fan2_input.dev_attr.attr,  	&sensor_dev_attr_fan1_div.dev_attr.attr,  	&sensor_dev_attr_fan2_div.dev_attr.attr, -	&dev_attr_temp1_input.attr, -	&dev_attr_temp1_max.attr, -	&dev_attr_temp1_max_hyst.attr, -	&dev_attr_temp1_crit.attr, -	&dev_attr_temp1_crit_hyst.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, +	&sensor_dev_attr_temp1_crit.dev_attr.attr, +	&sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,  	&dev_attr_alarms.attr,  	&sensor_dev_attr_in0_alarm.dev_attr.attr,  	&sensor_dev_attr_in1_alarm.dev_attr.attr, @@ -551,8 +635,8 @@ static int lm80_probe(struct i2c_client *client,  	lm80_init_client(client);  	/* A few vars need to be filled upon startup */ -	data->fan_min[0] = lm80_read_value(client, LM80_REG_FAN_MIN(1)); -	data->fan_min[1] = lm80_read_value(client, LM80_REG_FAN_MIN(2)); +	data->fan[f_min][0] = lm80_read_value(client, LM80_REG_FAN_MIN(1)); +	data->fan[f_min][1] = lm80_read_value(client, LM80_REG_FAN_MIN(2));  	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,  							   data, lm80_groups); @@ -560,143 +644,27 @@ static int lm80_probe(struct i2c_client *client,  	return PTR_ERR_OR_ZERO(hwmon_dev);  } -static int lm80_read_value(struct i2c_client *client, u8 reg) -{ -	return i2c_smbus_read_byte_data(client, reg); -} - -static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value) -{ -	return i2c_smbus_write_byte_data(client, reg, value); -} - -/* Called when we have found a new LM80. */ -static void lm80_init_client(struct i2c_client *client) -{ -	/* -	 * Reset all except Watchdog values and last conversion values -	 * This sets fan-divs to 2, among others. This makes most other -	 * initializations unnecessary -	 */ -	lm80_write_value(client, LM80_REG_CONFIG, 0x80); -	/* Set 11-bit temperature resolution */ -	lm80_write_value(client, LM80_REG_RES, 0x08); - -	/* Start monitoring */ -	lm80_write_value(client, LM80_REG_CONFIG, 0x01); -} - -static struct lm80_data *lm80_update_device(struct device *dev) -{ -	struct lm80_data *data = dev_get_drvdata(dev); -	struct i2c_client *client = data->client; -	int i; -	int rv; -	int prev_rv; -	struct lm80_data *ret = data; - -	mutex_lock(&data->update_lock); - -	if (data->error) -		lm80_init_client(client); - -	if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { -		dev_dbg(dev, "Starting lm80 update\n"); -		for (i = 0; i <= 6; i++) { -			rv = lm80_read_value(client, LM80_REG_IN(i)); -			if (rv < 0) -				goto abort; -			data->in[i] = rv; - -			rv = lm80_read_value(client, LM80_REG_IN_MIN(i)); -			if (rv < 0) -				goto abort; -			data->in_min[i] = rv; - -			rv = lm80_read_value(client, LM80_REG_IN_MAX(i)); -			if (rv < 0) -				goto abort; -			data->in_max[i] = rv; -		} - -		rv = lm80_read_value(client, LM80_REG_FAN1); -		if (rv < 0) -			goto abort; -		data->fan[0] = rv; - -		rv = lm80_read_value(client, LM80_REG_FAN_MIN(1)); -		if (rv < 0) -			goto abort; -		data->fan_min[0] = rv; - -		rv = lm80_read_value(client, LM80_REG_FAN2); -		if (rv < 0) -			goto abort; -		data->fan[1] = rv; - -		rv = lm80_read_value(client, LM80_REG_FAN_MIN(2)); -		if (rv < 0) -			goto abort; -		data->fan_min[1] = rv; - -		prev_rv = rv = lm80_read_value(client, LM80_REG_TEMP); -		if (rv < 0) -			goto abort; -		rv = lm80_read_value(client, LM80_REG_RES); -		if (rv < 0) -			goto abort; -		data->temp = (prev_rv << 8) | (rv & 0xf0); - -		rv = lm80_read_value(client, LM80_REG_TEMP_OS_MAX); -		if (rv < 0) -			goto abort; -		data->temp_os_max = rv; - -		rv = lm80_read_value(client, LM80_REG_TEMP_OS_HYST); -		if (rv < 0) -			goto abort; -		data->temp_os_hyst = rv; - -		rv = lm80_read_value(client, LM80_REG_TEMP_HOT_MAX); -		if (rv < 0) -			goto abort; -		data->temp_hot_max = rv; - -		rv = lm80_read_value(client, LM80_REG_TEMP_HOT_HYST); -		if (rv < 0) -			goto abort; -		data->temp_hot_hyst = rv; - -		rv = lm80_read_value(client, LM80_REG_FANDIV); -		if (rv < 0) -			goto abort; -		data->fan_div[0] = (rv >> 2) & 0x03; -		data->fan_div[1] = (rv >> 4) & 0x03; - -		prev_rv = rv = lm80_read_value(client, LM80_REG_ALARM1); -		if (rv < 0) -			goto abort; -		rv = lm80_read_value(client, LM80_REG_ALARM2); -		if (rv < 0) -			goto abort; -		data->alarms = prev_rv + (rv << 8); - -		data->last_updated = jiffies; -		data->valid = 1; -		data->error = 0; -	} -	goto done; - -abort: -	ret = ERR_PTR(rv); -	data->valid = 0; -	data->error = 1; +/* + * Driver data (common to all clients) + */ -done: -	mutex_unlock(&data->update_lock); +static const struct i2c_device_id lm80_id[] = { +	{ "lm80", 0 }, +	{ "lm96080", 1 }, +	{ } +}; +MODULE_DEVICE_TABLE(i2c, lm80_id); -	return ret; -} +static struct i2c_driver lm80_driver = { +	.class		= I2C_CLASS_HWMON, +	.driver = { +		.name	= "lm80", +	}, +	.probe		= lm80_probe, +	.id_table	= lm80_id, +	.detect		= lm80_detect, +	.address_list	= normal_i2c, +};  module_i2c_driver(lm80_driver); | 
