xref: /openbmc/linux/drivers/hwmon/adm1031.c (revision 49dc9efed05ad3e49000097ce1ec31cd3bbc909b)
18d5d45fbSJean Delvare /*
28d5d45fbSJean Delvare   adm1031.c - Part of lm_sensors, Linux kernel modules for hardware
38d5d45fbSJean Delvare   monitoring
48d5d45fbSJean Delvare   Based on lm75.c and lm85.c
58d5d45fbSJean Delvare   Supports adm1030 / adm1031
68d5d45fbSJean Delvare   Copyright (C) 2004 Alexandre d'Alton <alex@alexdalton.org>
78d5d45fbSJean Delvare   Reworked by Jean Delvare <khali@linux-fr.org>
88d5d45fbSJean Delvare 
98d5d45fbSJean Delvare   This program is free software; you can redistribute it and/or modify
108d5d45fbSJean Delvare   it under the terms of the GNU General Public License as published by
118d5d45fbSJean Delvare   the Free Software Foundation; either version 2 of the License, or
128d5d45fbSJean Delvare   (at your option) any later version.
138d5d45fbSJean Delvare 
148d5d45fbSJean Delvare   This program is distributed in the hope that it will be useful,
158d5d45fbSJean Delvare   but WITHOUT ANY WARRANTY; without even the implied warranty of
168d5d45fbSJean Delvare   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
178d5d45fbSJean Delvare   GNU General Public License for more details.
188d5d45fbSJean Delvare 
198d5d45fbSJean Delvare   You should have received a copy of the GNU General Public License
208d5d45fbSJean Delvare   along with this program; if not, write to the Free Software
218d5d45fbSJean Delvare   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
228d5d45fbSJean Delvare */
238d5d45fbSJean Delvare 
248d5d45fbSJean Delvare #include <linux/module.h>
258d5d45fbSJean Delvare #include <linux/init.h>
268d5d45fbSJean Delvare #include <linux/slab.h>
278d5d45fbSJean Delvare #include <linux/jiffies.h>
288d5d45fbSJean Delvare #include <linux/i2c.h>
29943b0830SMark M. Hoffman #include <linux/hwmon.h>
30c801082dSJean Delvare #include <linux/hwmon-sysfs.h>
31943b0830SMark M. Hoffman #include <linux/err.h>
329a61bf63SIngo Molnar #include <linux/mutex.h>
338d5d45fbSJean Delvare 
348d5d45fbSJean Delvare /* Following macros takes channel parameter starting from 0 to 2 */
358d5d45fbSJean Delvare #define ADM1031_REG_FAN_SPEED(nr)	(0x08 + (nr))
368d5d45fbSJean Delvare #define ADM1031_REG_FAN_DIV(nr)		(0x20 + (nr))
378d5d45fbSJean Delvare #define ADM1031_REG_PWM			(0x22)
388d5d45fbSJean Delvare #define ADM1031_REG_FAN_MIN(nr)		(0x10 + (nr))
398d5d45fbSJean Delvare 
40*49dc9efeSIra Snyder #define ADM1031_REG_TEMP_OFFSET(nr)	(0x0d + (nr))
418d5d45fbSJean Delvare #define ADM1031_REG_TEMP_MAX(nr)	(0x14 + 4 * (nr))
428d5d45fbSJean Delvare #define ADM1031_REG_TEMP_MIN(nr)	(0x15 + 4 * (nr))
438d5d45fbSJean Delvare #define ADM1031_REG_TEMP_CRIT(nr)	(0x16 + 4 * (nr))
448d5d45fbSJean Delvare 
456d6006b8SJean Delvare #define ADM1031_REG_TEMP(nr)		(0x0a + (nr))
468d5d45fbSJean Delvare #define ADM1031_REG_AUTO_TEMP(nr)	(0x24 + (nr))
478d5d45fbSJean Delvare 
488d5d45fbSJean Delvare #define ADM1031_REG_STATUS(nr)		(0x2 + (nr))
498d5d45fbSJean Delvare 
506d6006b8SJean Delvare #define ADM1031_REG_CONF1		0x00
516d6006b8SJean Delvare #define ADM1031_REG_CONF2		0x01
526d6006b8SJean Delvare #define ADM1031_REG_EXT_TEMP		0x06
538d5d45fbSJean Delvare 
548d5d45fbSJean Delvare #define ADM1031_CONF1_MONITOR_ENABLE	0x01	/* Monitoring enable */
558d5d45fbSJean Delvare #define ADM1031_CONF1_PWM_INVERT	0x08	/* PWM Invert */
568d5d45fbSJean Delvare #define ADM1031_CONF1_AUTO_MODE		0x80	/* Auto FAN */
578d5d45fbSJean Delvare 
588d5d45fbSJean Delvare #define ADM1031_CONF2_PWM1_ENABLE	0x01
598d5d45fbSJean Delvare #define ADM1031_CONF2_PWM2_ENABLE	0x02
608d5d45fbSJean Delvare #define ADM1031_CONF2_TACH1_ENABLE	0x04
618d5d45fbSJean Delvare #define ADM1031_CONF2_TACH2_ENABLE	0x08
628d5d45fbSJean Delvare #define ADM1031_CONF2_TEMP_ENABLE(chan)	(0x10 << (chan))
638d5d45fbSJean Delvare 
648d5d45fbSJean Delvare /* Addresses to scan */
6525e9c86dSMark M. Hoffman static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
668d5d45fbSJean Delvare 
678d5d45fbSJean Delvare /* Insmod parameters */
68f4b50261SJean Delvare I2C_CLIENT_INSMOD_2(adm1030, adm1031);
698d5d45fbSJean Delvare 
708d5d45fbSJean Delvare typedef u8 auto_chan_table_t[8][2];
718d5d45fbSJean Delvare 
728d5d45fbSJean Delvare /* Each client has this additional data */
738d5d45fbSJean Delvare struct adm1031_data {
741beeffe4STony Jones 	struct device *hwmon_dev;
759a61bf63SIngo Molnar 	struct mutex update_lock;
768d5d45fbSJean Delvare 	int chip_type;
778d5d45fbSJean Delvare 	char valid;		/* !=0 if following fields are valid */
788d5d45fbSJean Delvare 	unsigned long last_updated;	/* In jiffies */
798d5d45fbSJean Delvare 	/* The chan_select_table contains the possible configurations for
808d5d45fbSJean Delvare 	 * auto fan control.
818d5d45fbSJean Delvare 	 */
826d6006b8SJean Delvare 	const auto_chan_table_t *chan_select_table;
838d5d45fbSJean Delvare 	u16 alarm;
848d5d45fbSJean Delvare 	u8 conf1;
858d5d45fbSJean Delvare 	u8 conf2;
868d5d45fbSJean Delvare 	u8 fan[2];
878d5d45fbSJean Delvare 	u8 fan_div[2];
888d5d45fbSJean Delvare 	u8 fan_min[2];
898d5d45fbSJean Delvare 	u8 pwm[2];
908d5d45fbSJean Delvare 	u8 old_pwm[2];
918d5d45fbSJean Delvare 	s8 temp[3];
928d5d45fbSJean Delvare 	u8 ext_temp[3];
938d5d45fbSJean Delvare 	u8 auto_temp[3];
948d5d45fbSJean Delvare 	u8 auto_temp_min[3];
958d5d45fbSJean Delvare 	u8 auto_temp_off[3];
968d5d45fbSJean Delvare 	u8 auto_temp_max[3];
97*49dc9efeSIra Snyder 	s8 temp_offset[3];
988d5d45fbSJean Delvare 	s8 temp_min[3];
998d5d45fbSJean Delvare 	s8 temp_max[3];
1008d5d45fbSJean Delvare 	s8 temp_crit[3];
1018d5d45fbSJean Delvare };
1028d5d45fbSJean Delvare 
103af200f88SJean Delvare static int adm1031_probe(struct i2c_client *client,
104af200f88SJean Delvare 			 const struct i2c_device_id *id);
105af200f88SJean Delvare static int adm1031_detect(struct i2c_client *client, int kind,
106af200f88SJean Delvare 			  struct i2c_board_info *info);
1078d5d45fbSJean Delvare static void adm1031_init_client(struct i2c_client *client);
108af200f88SJean Delvare static int adm1031_remove(struct i2c_client *client);
1098d5d45fbSJean Delvare static struct adm1031_data *adm1031_update_device(struct device *dev);
1108d5d45fbSJean Delvare 
111af200f88SJean Delvare static const struct i2c_device_id adm1031_id[] = {
112af200f88SJean Delvare 	{ "adm1030", adm1030 },
113af200f88SJean Delvare 	{ "adm1031", adm1031 },
114af200f88SJean Delvare 	{ }
115af200f88SJean Delvare };
116af200f88SJean Delvare MODULE_DEVICE_TABLE(i2c, adm1031_id);
117af200f88SJean Delvare 
1188d5d45fbSJean Delvare /* This is the driver that will be inserted */
1198d5d45fbSJean Delvare static struct i2c_driver adm1031_driver = {
120af200f88SJean Delvare 	.class		= I2C_CLASS_HWMON,
121cdaf7934SLaurent Riffard 	.driver = {
1228d5d45fbSJean Delvare 		.name = "adm1031",
123cdaf7934SLaurent Riffard 	},
124af200f88SJean Delvare 	.probe		= adm1031_probe,
125af200f88SJean Delvare 	.remove		= adm1031_remove,
126af200f88SJean Delvare 	.id_table	= adm1031_id,
127af200f88SJean Delvare 	.detect		= adm1031_detect,
128af200f88SJean Delvare 	.address_data	= &addr_data,
1298d5d45fbSJean Delvare };
1308d5d45fbSJean Delvare 
1318d5d45fbSJean Delvare static inline u8 adm1031_read_value(struct i2c_client *client, u8 reg)
1328d5d45fbSJean Delvare {
1338d5d45fbSJean Delvare 	return i2c_smbus_read_byte_data(client, reg);
1348d5d45fbSJean Delvare }
1358d5d45fbSJean Delvare 
1368d5d45fbSJean Delvare static inline int
1378d5d45fbSJean Delvare adm1031_write_value(struct i2c_client *client, u8 reg, unsigned int value)
1388d5d45fbSJean Delvare {
1398d5d45fbSJean Delvare 	return i2c_smbus_write_byte_data(client, reg, value);
1408d5d45fbSJean Delvare }
1418d5d45fbSJean Delvare 
1428d5d45fbSJean Delvare 
1438d5d45fbSJean Delvare #define TEMP_TO_REG(val)		(((val) < 0 ? ((val - 500) / 1000) : \
1448d5d45fbSJean Delvare 					((val + 500) / 1000)))
1458d5d45fbSJean Delvare 
1468d5d45fbSJean Delvare #define TEMP_FROM_REG(val)		((val) * 1000)
1478d5d45fbSJean Delvare 
1488d5d45fbSJean Delvare #define TEMP_FROM_REG_EXT(val, ext)	(TEMP_FROM_REG(val) + (ext) * 125)
1498d5d45fbSJean Delvare 
150*49dc9efeSIra Snyder #define TEMP_OFFSET_TO_REG(val)		(TEMP_TO_REG(val) & 0x8f)
151*49dc9efeSIra Snyder #define TEMP_OFFSET_FROM_REG(val)	TEMP_FROM_REG((val) < 0 ? \
152*49dc9efeSIra Snyder 						      (val) | 0x70 : (val))
153*49dc9efeSIra Snyder 
1548d5d45fbSJean Delvare #define FAN_FROM_REG(reg, div)		((reg) ? (11250 * 60) / ((reg) * (div)) : 0)
1558d5d45fbSJean Delvare 
1568d5d45fbSJean Delvare static int FAN_TO_REG(int reg, int div)
1578d5d45fbSJean Delvare {
1588d5d45fbSJean Delvare 	int tmp;
1598d5d45fbSJean Delvare 	tmp = FAN_FROM_REG(SENSORS_LIMIT(reg, 0, 65535), div);
1608d5d45fbSJean Delvare 	return tmp > 255 ? 255 : tmp;
1618d5d45fbSJean Delvare }
1628d5d45fbSJean Delvare 
1638d5d45fbSJean Delvare #define FAN_DIV_FROM_REG(reg)		(1<<(((reg)&0xc0)>>6))
1648d5d45fbSJean Delvare 
1658d5d45fbSJean Delvare #define PWM_TO_REG(val)			(SENSORS_LIMIT((val), 0, 255) >> 4)
1668d5d45fbSJean Delvare #define PWM_FROM_REG(val)		((val) << 4)
1678d5d45fbSJean Delvare 
1688d5d45fbSJean Delvare #define FAN_CHAN_FROM_REG(reg)		(((reg) >> 5) & 7)
1698d5d45fbSJean Delvare #define FAN_CHAN_TO_REG(val, reg)	\
1708d5d45fbSJean Delvare 	(((reg) & 0x1F) | (((val) << 5) & 0xe0))
1718d5d45fbSJean Delvare 
1728d5d45fbSJean Delvare #define AUTO_TEMP_MIN_TO_REG(val, reg)	\
1738d5d45fbSJean Delvare 	((((val)/500) & 0xf8)|((reg) & 0x7))
1748d5d45fbSJean Delvare #define AUTO_TEMP_RANGE_FROM_REG(reg)	(5000 * (1<< ((reg)&0x7)))
1758d5d45fbSJean Delvare #define AUTO_TEMP_MIN_FROM_REG(reg)	(1000 * ((((reg) >> 3) & 0x1f) << 2))
1768d5d45fbSJean Delvare 
1778d5d45fbSJean Delvare #define AUTO_TEMP_MIN_FROM_REG_DEG(reg)	((((reg) >> 3) & 0x1f) << 2)
1788d5d45fbSJean Delvare 
1798d5d45fbSJean Delvare #define AUTO_TEMP_OFF_FROM_REG(reg)		\
1808d5d45fbSJean Delvare 	(AUTO_TEMP_MIN_FROM_REG(reg) - 5000)
1818d5d45fbSJean Delvare 
1828d5d45fbSJean Delvare #define AUTO_TEMP_MAX_FROM_REG(reg)		\
1838d5d45fbSJean Delvare 	(AUTO_TEMP_RANGE_FROM_REG(reg) +	\
1848d5d45fbSJean Delvare 	AUTO_TEMP_MIN_FROM_REG(reg))
1858d5d45fbSJean Delvare 
1868d5d45fbSJean Delvare static int AUTO_TEMP_MAX_TO_REG(int val, int reg, int pwm)
1878d5d45fbSJean Delvare {
1888d5d45fbSJean Delvare 	int ret;
1898d5d45fbSJean Delvare 	int range = val - AUTO_TEMP_MIN_FROM_REG(reg);
1908d5d45fbSJean Delvare 
1918d5d45fbSJean Delvare 	range = ((val - AUTO_TEMP_MIN_FROM_REG(reg))*10)/(16 - pwm);
1928d5d45fbSJean Delvare 	ret = ((reg & 0xf8) |
1938d5d45fbSJean Delvare 	       (range < 10000 ? 0 :
1948d5d45fbSJean Delvare 		range < 20000 ? 1 :
1958d5d45fbSJean Delvare 		range < 40000 ? 2 : range < 80000 ? 3 : 4));
1968d5d45fbSJean Delvare 	return ret;
1978d5d45fbSJean Delvare }
1988d5d45fbSJean Delvare 
1998d5d45fbSJean Delvare /* FAN auto control */
2008d5d45fbSJean Delvare #define GET_FAN_AUTO_BITFIELD(data, idx)	\
2018d5d45fbSJean Delvare 	(*(data)->chan_select_table)[FAN_CHAN_FROM_REG((data)->conf1)][idx%2]
2028d5d45fbSJean Delvare 
2038d5d45fbSJean Delvare /* The tables below contains the possible values for the auto fan
2048d5d45fbSJean Delvare  * control bitfields. the index in the table is the register value.
2058d5d45fbSJean Delvare  * MSb is the auto fan control enable bit, so the four first entries
2068d5d45fbSJean Delvare  * in the table disables auto fan control when both bitfields are zero.
2078d5d45fbSJean Delvare  */
2086d6006b8SJean Delvare static const auto_chan_table_t auto_channel_select_table_adm1031 = {
2098d5d45fbSJean Delvare 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2108d5d45fbSJean Delvare 	{ 2 /* 0b010 */ , 4 /* 0b100 */ },
2118d5d45fbSJean Delvare 	{ 2 /* 0b010 */ , 2 /* 0b010 */ },
2128d5d45fbSJean Delvare 	{ 4 /* 0b100 */ , 4 /* 0b100 */ },
2138d5d45fbSJean Delvare 	{ 7 /* 0b111 */ , 7 /* 0b111 */ },
2148d5d45fbSJean Delvare };
2158d5d45fbSJean Delvare 
2166d6006b8SJean Delvare static const auto_chan_table_t auto_channel_select_table_adm1030 = {
2178d5d45fbSJean Delvare 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2188d5d45fbSJean Delvare 	{ 2 /* 0b10 */		, 0 },
2198d5d45fbSJean Delvare 	{ 0xff /* invalid */	, 0 },
2208d5d45fbSJean Delvare 	{ 0xff /* invalid */	, 0 },
2218d5d45fbSJean Delvare 	{ 3 /* 0b11 */		, 0 },
2228d5d45fbSJean Delvare };
2238d5d45fbSJean Delvare 
2248d5d45fbSJean Delvare /* That function checks if a bitfield is valid and returns the other bitfield
2258d5d45fbSJean Delvare  * nearest match if no exact match where found.
2268d5d45fbSJean Delvare  */
2278d5d45fbSJean Delvare static int
2288d5d45fbSJean Delvare get_fan_auto_nearest(struct adm1031_data *data,
2298d5d45fbSJean Delvare 		     int chan, u8 val, u8 reg, u8 * new_reg)
2308d5d45fbSJean Delvare {
2318d5d45fbSJean Delvare 	int i;
2328d5d45fbSJean Delvare 	int first_match = -1, exact_match = -1;
2338d5d45fbSJean Delvare 	u8 other_reg_val =
2348d5d45fbSJean Delvare 	    (*data->chan_select_table)[FAN_CHAN_FROM_REG(reg)][chan ? 0 : 1];
2358d5d45fbSJean Delvare 
2368d5d45fbSJean Delvare 	if (val == 0) {
2378d5d45fbSJean Delvare 		*new_reg = 0;
2388d5d45fbSJean Delvare 		return 0;
2398d5d45fbSJean Delvare 	}
2408d5d45fbSJean Delvare 
2418d5d45fbSJean Delvare 	for (i = 0; i < 8; i++) {
2428d5d45fbSJean Delvare 		if ((val == (*data->chan_select_table)[i][chan]) &&
2438d5d45fbSJean Delvare 		    ((*data->chan_select_table)[i][chan ? 0 : 1] ==
2448d5d45fbSJean Delvare 		     other_reg_val)) {
2458d5d45fbSJean Delvare 			/* We found an exact match */
2468d5d45fbSJean Delvare 			exact_match = i;
2478d5d45fbSJean Delvare 			break;
2488d5d45fbSJean Delvare 		} else if (val == (*data->chan_select_table)[i][chan] &&
2498d5d45fbSJean Delvare 			   first_match == -1) {
2506d6006b8SJean Delvare 			/* Save the first match in case of an exact match has
2516d6006b8SJean Delvare 			 * not been found
2528d5d45fbSJean Delvare 			 */
2538d5d45fbSJean Delvare 			first_match = i;
2548d5d45fbSJean Delvare 		}
2558d5d45fbSJean Delvare 	}
2568d5d45fbSJean Delvare 
2578d5d45fbSJean Delvare 	if (exact_match >= 0) {
2588d5d45fbSJean Delvare 		*new_reg = exact_match;
2598d5d45fbSJean Delvare 	} else if (first_match >= 0) {
2608d5d45fbSJean Delvare 		*new_reg = first_match;
2618d5d45fbSJean Delvare 	} else {
2628d5d45fbSJean Delvare 		return -EINVAL;
2638d5d45fbSJean Delvare 	}
2648d5d45fbSJean Delvare 	return 0;
2658d5d45fbSJean Delvare }
2668d5d45fbSJean Delvare 
267c801082dSJean Delvare static ssize_t show_fan_auto_channel(struct device *dev,
268c801082dSJean Delvare 				     struct device_attribute *attr, char *buf)
2698d5d45fbSJean Delvare {
270c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
2718d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
2728d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", GET_FAN_AUTO_BITFIELD(data, nr));
2738d5d45fbSJean Delvare }
2748d5d45fbSJean Delvare 
2758d5d45fbSJean Delvare static ssize_t
276c801082dSJean Delvare set_fan_auto_channel(struct device *dev, struct device_attribute *attr,
277c801082dSJean Delvare 		     const char *buf, size_t count)
2788d5d45fbSJean Delvare {
2798d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
2808d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
281c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
2828d5d45fbSJean Delvare 	int val = simple_strtol(buf, NULL, 10);
2838d5d45fbSJean Delvare 	u8 reg;
2848d5d45fbSJean Delvare 	int ret;
2858d5d45fbSJean Delvare 	u8 old_fan_mode;
2868d5d45fbSJean Delvare 
2878d5d45fbSJean Delvare 	old_fan_mode = data->conf1;
2888d5d45fbSJean Delvare 
2899a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
2908d5d45fbSJean Delvare 
2918d5d45fbSJean Delvare 	if ((ret = get_fan_auto_nearest(data, nr, val, data->conf1, &reg))) {
2929a61bf63SIngo Molnar 		mutex_unlock(&data->update_lock);
2938d5d45fbSJean Delvare 		return ret;
2948d5d45fbSJean Delvare 	}
2956d6006b8SJean Delvare 	data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1);
2966d6006b8SJean Delvare 	if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) ^
2978d5d45fbSJean Delvare 	    (old_fan_mode & ADM1031_CONF1_AUTO_MODE)) {
2988d5d45fbSJean Delvare 		if (data->conf1 & ADM1031_CONF1_AUTO_MODE){
2998d5d45fbSJean Delvare 			/* Switch to Auto Fan Mode
3008d5d45fbSJean Delvare 			 * Save PWM registers
3018d5d45fbSJean Delvare 			 * Set PWM registers to 33% Both */
3028d5d45fbSJean Delvare 			data->old_pwm[0] = data->pwm[0];
3038d5d45fbSJean Delvare 			data->old_pwm[1] = data->pwm[1];
3048d5d45fbSJean Delvare 			adm1031_write_value(client, ADM1031_REG_PWM, 0x55);
3058d5d45fbSJean Delvare 		} else {
3068d5d45fbSJean Delvare 			/* Switch to Manual Mode */
3078d5d45fbSJean Delvare 			data->pwm[0] = data->old_pwm[0];
3088d5d45fbSJean Delvare 			data->pwm[1] = data->old_pwm[1];
3098d5d45fbSJean Delvare 			/* Restore PWM registers */
3108d5d45fbSJean Delvare 			adm1031_write_value(client, ADM1031_REG_PWM,
3118d5d45fbSJean Delvare 					    data->pwm[0] | (data->pwm[1] << 4));
3128d5d45fbSJean Delvare 		}
3138d5d45fbSJean Delvare 	}
3148d5d45fbSJean Delvare 	data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1);
3158d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_CONF1, data->conf1);
3169a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
3178d5d45fbSJean Delvare 	return count;
3188d5d45fbSJean Delvare }
3198d5d45fbSJean Delvare 
320c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_fan1_channel, S_IRUGO | S_IWUSR,
321c801082dSJean Delvare 		show_fan_auto_channel, set_fan_auto_channel, 0);
322c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_fan2_channel, S_IRUGO | S_IWUSR,
323c801082dSJean Delvare 		show_fan_auto_channel, set_fan_auto_channel, 1);
3248d5d45fbSJean Delvare 
3258d5d45fbSJean Delvare /* Auto Temps */
326c801082dSJean Delvare static ssize_t show_auto_temp_off(struct device *dev,
327c801082dSJean Delvare 				  struct device_attribute *attr, char *buf)
3288d5d45fbSJean Delvare {
329c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
3308d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
3318d5d45fbSJean Delvare 	return sprintf(buf, "%d\n",
3328d5d45fbSJean Delvare 		       AUTO_TEMP_OFF_FROM_REG(data->auto_temp[nr]));
3338d5d45fbSJean Delvare }
334c801082dSJean Delvare static ssize_t show_auto_temp_min(struct device *dev,
335c801082dSJean Delvare 				  struct device_attribute *attr, char *buf)
3368d5d45fbSJean Delvare {
337c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
3388d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
3398d5d45fbSJean Delvare 	return sprintf(buf, "%d\n",
3408d5d45fbSJean Delvare 		       AUTO_TEMP_MIN_FROM_REG(data->auto_temp[nr]));
3418d5d45fbSJean Delvare }
3428d5d45fbSJean Delvare static ssize_t
343c801082dSJean Delvare set_auto_temp_min(struct device *dev, struct device_attribute *attr,
344c801082dSJean Delvare 		  const char *buf, size_t count)
3458d5d45fbSJean Delvare {
3468d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
3478d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
348c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
3498d5d45fbSJean Delvare 	int val = simple_strtol(buf, NULL, 10);
3508d5d45fbSJean Delvare 
3519a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
3528d5d45fbSJean Delvare 	data->auto_temp[nr] = AUTO_TEMP_MIN_TO_REG(val, data->auto_temp[nr]);
3538d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr),
3548d5d45fbSJean Delvare 			    data->auto_temp[nr]);
3559a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
3568d5d45fbSJean Delvare 	return count;
3578d5d45fbSJean Delvare }
358c801082dSJean Delvare static ssize_t show_auto_temp_max(struct device *dev,
359c801082dSJean Delvare 				  struct device_attribute *attr, char *buf)
3608d5d45fbSJean Delvare {
361c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
3628d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
3638d5d45fbSJean Delvare 	return sprintf(buf, "%d\n",
3648d5d45fbSJean Delvare 		       AUTO_TEMP_MAX_FROM_REG(data->auto_temp[nr]));
3658d5d45fbSJean Delvare }
3668d5d45fbSJean Delvare static ssize_t
367c801082dSJean Delvare set_auto_temp_max(struct device *dev, struct device_attribute *attr,
368c801082dSJean Delvare 		  const char *buf, size_t count)
3698d5d45fbSJean Delvare {
3708d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
3718d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
372c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
3738d5d45fbSJean Delvare 	int val = simple_strtol(buf, NULL, 10);
3748d5d45fbSJean Delvare 
3759a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
3768d5d45fbSJean Delvare 	data->temp_max[nr] = AUTO_TEMP_MAX_TO_REG(val, data->auto_temp[nr], data->pwm[nr]);
3778d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr),
3788d5d45fbSJean Delvare 			    data->temp_max[nr]);
3799a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
3808d5d45fbSJean Delvare 	return count;
3818d5d45fbSJean Delvare }
3828d5d45fbSJean Delvare 
3838d5d45fbSJean Delvare #define auto_temp_reg(offset)						\
384c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_temp##offset##_off, S_IRUGO,		\
385c801082dSJean Delvare 		show_auto_temp_off, NULL, offset - 1);			\
386c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_temp##offset##_min, S_IRUGO | S_IWUSR,	\
387c801082dSJean Delvare 		show_auto_temp_min, set_auto_temp_min, offset - 1);	\
388c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_temp##offset##_max, S_IRUGO | S_IWUSR,	\
389c801082dSJean Delvare 		show_auto_temp_max, set_auto_temp_max, offset - 1)
3908d5d45fbSJean Delvare 
3918d5d45fbSJean Delvare auto_temp_reg(1);
3928d5d45fbSJean Delvare auto_temp_reg(2);
3938d5d45fbSJean Delvare auto_temp_reg(3);
3948d5d45fbSJean Delvare 
3958d5d45fbSJean Delvare /* pwm */
396c801082dSJean Delvare static ssize_t show_pwm(struct device *dev,
397c801082dSJean Delvare 			struct device_attribute *attr, char *buf)
3988d5d45fbSJean Delvare {
399c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4008d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
4018d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm[nr]));
4028d5d45fbSJean Delvare }
403c801082dSJean Delvare static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
404c801082dSJean Delvare 		       const char *buf, size_t count)
4058d5d45fbSJean Delvare {
4068d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
4078d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
408c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4098d5d45fbSJean Delvare 	int val = simple_strtol(buf, NULL, 10);
4108d5d45fbSJean Delvare 	int reg;
4118d5d45fbSJean Delvare 
4129a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
4138d5d45fbSJean Delvare 	if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) &&
4148d5d45fbSJean Delvare 	    (((val>>4) & 0xf) != 5)) {
4158d5d45fbSJean Delvare 		/* In automatic mode, the only PWM accepted is 33% */
4169a61bf63SIngo Molnar 		mutex_unlock(&data->update_lock);
4178d5d45fbSJean Delvare 		return -EINVAL;
4188d5d45fbSJean Delvare 	}
4198d5d45fbSJean Delvare 	data->pwm[nr] = PWM_TO_REG(val);
4208d5d45fbSJean Delvare 	reg = adm1031_read_value(client, ADM1031_REG_PWM);
4218d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_PWM,
4228d5d45fbSJean Delvare 			    nr ? ((data->pwm[nr] << 4) & 0xf0) | (reg & 0xf)
4238d5d45fbSJean Delvare 			    : (data->pwm[nr] & 0xf) | (reg & 0xf0));
4249a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
4258d5d45fbSJean Delvare 	return count;
4268d5d45fbSJean Delvare }
4278d5d45fbSJean Delvare 
428c801082dSJean Delvare static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 0);
429c801082dSJean Delvare static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 1);
430c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_fan1_min_pwm, S_IRUGO | S_IWUSR,
431c801082dSJean Delvare 		show_pwm, set_pwm, 0);
432c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_fan2_min_pwm, S_IRUGO | S_IWUSR,
433c801082dSJean Delvare 		show_pwm, set_pwm, 1);
4348d5d45fbSJean Delvare 
4358d5d45fbSJean Delvare /* Fans */
4368d5d45fbSJean Delvare 
4378d5d45fbSJean Delvare /*
4388d5d45fbSJean Delvare  * That function checks the cases where the fan reading is not
4398d5d45fbSJean Delvare  * relevant.  It is used to provide 0 as fan reading when the fan is
4408d5d45fbSJean Delvare  * not supposed to run
4418d5d45fbSJean Delvare  */
4428d5d45fbSJean Delvare static int trust_fan_readings(struct adm1031_data *data, int chan)
4438d5d45fbSJean Delvare {
4448d5d45fbSJean Delvare 	int res = 0;
4458d5d45fbSJean Delvare 
4468d5d45fbSJean Delvare 	if (data->conf1 & ADM1031_CONF1_AUTO_MODE) {
4478d5d45fbSJean Delvare 		switch (data->conf1 & 0x60) {
4488d5d45fbSJean Delvare 		case 0x00:	/* remote temp1 controls fan1 remote temp2 controls fan2 */
4498d5d45fbSJean Delvare 			res = data->temp[chan+1] >=
4508d5d45fbSJean Delvare 			      AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[chan+1]);
4518d5d45fbSJean Delvare 			break;
4528d5d45fbSJean Delvare 		case 0x20:	/* remote temp1 controls both fans */
4538d5d45fbSJean Delvare 			res =
4548d5d45fbSJean Delvare 			    data->temp[1] >=
4558d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[1]);
4568d5d45fbSJean Delvare 			break;
4578d5d45fbSJean Delvare 		case 0x40:	/* remote temp2 controls both fans */
4588d5d45fbSJean Delvare 			res =
4598d5d45fbSJean Delvare 			    data->temp[2] >=
4608d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[2]);
4618d5d45fbSJean Delvare 			break;
4628d5d45fbSJean Delvare 		case 0x60:	/* max controls both fans */
4638d5d45fbSJean Delvare 			res =
4648d5d45fbSJean Delvare 			    data->temp[0] >=
4658d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[0])
4668d5d45fbSJean Delvare 			    || data->temp[1] >=
4678d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[1])
4688d5d45fbSJean Delvare 			    || (data->chip_type == adm1031
4698d5d45fbSJean Delvare 				&& data->temp[2] >=
4708d5d45fbSJean Delvare 				AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[2]));
4718d5d45fbSJean Delvare 			break;
4728d5d45fbSJean Delvare 		}
4738d5d45fbSJean Delvare 	} else {
4748d5d45fbSJean Delvare 		res = data->pwm[chan] > 0;
4758d5d45fbSJean Delvare 	}
4768d5d45fbSJean Delvare 	return res;
4778d5d45fbSJean Delvare }
4788d5d45fbSJean Delvare 
4798d5d45fbSJean Delvare 
480c801082dSJean Delvare static ssize_t show_fan(struct device *dev,
481c801082dSJean Delvare 			struct device_attribute *attr, char *buf)
4828d5d45fbSJean Delvare {
483c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4848d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
4858d5d45fbSJean Delvare 	int value;
4868d5d45fbSJean Delvare 
4878d5d45fbSJean Delvare 	value = trust_fan_readings(data, nr) ? FAN_FROM_REG(data->fan[nr],
4888d5d45fbSJean Delvare 				 FAN_DIV_FROM_REG(data->fan_div[nr])) : 0;
4898d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", value);
4908d5d45fbSJean Delvare }
4918d5d45fbSJean Delvare 
492c801082dSJean Delvare static ssize_t show_fan_div(struct device *dev,
493c801082dSJean Delvare 			    struct device_attribute *attr, char *buf)
4948d5d45fbSJean Delvare {
495c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4968d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
4978d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", FAN_DIV_FROM_REG(data->fan_div[nr]));
4988d5d45fbSJean Delvare }
499c801082dSJean Delvare static ssize_t show_fan_min(struct device *dev,
500c801082dSJean Delvare 			    struct device_attribute *attr, char *buf)
5018d5d45fbSJean Delvare {
502c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
5038d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
5048d5d45fbSJean Delvare 	return sprintf(buf, "%d\n",
5058d5d45fbSJean Delvare 		       FAN_FROM_REG(data->fan_min[nr],
5068d5d45fbSJean Delvare 				    FAN_DIV_FROM_REG(data->fan_div[nr])));
5078d5d45fbSJean Delvare }
508c801082dSJean Delvare static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
509c801082dSJean Delvare 			   const char *buf, size_t count)
5108d5d45fbSJean Delvare {
5118d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
5128d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
513c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
5148d5d45fbSJean Delvare 	int val = simple_strtol(buf, NULL, 10);
5158d5d45fbSJean Delvare 
5169a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
5178d5d45fbSJean Delvare 	if (val) {
5188d5d45fbSJean Delvare 		data->fan_min[nr] =
5198d5d45fbSJean Delvare 			FAN_TO_REG(val, FAN_DIV_FROM_REG(data->fan_div[nr]));
5208d5d45fbSJean Delvare 	} else {
5218d5d45fbSJean Delvare 		data->fan_min[nr] = 0xff;
5228d5d45fbSJean Delvare 	}
5238d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), data->fan_min[nr]);
5249a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
5258d5d45fbSJean Delvare 	return count;
5268d5d45fbSJean Delvare }
527c801082dSJean Delvare static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
528c801082dSJean Delvare 			   const char *buf, size_t count)
5298d5d45fbSJean Delvare {
5308d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
5318d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
532c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
5338d5d45fbSJean Delvare 	int val = simple_strtol(buf, NULL, 10);
5348d5d45fbSJean Delvare 	u8 tmp;
5358d5d45fbSJean Delvare 	int old_div;
5368d5d45fbSJean Delvare 	int new_min;
5378d5d45fbSJean Delvare 
5388d5d45fbSJean Delvare 	tmp = val == 8 ? 0xc0 :
5398d5d45fbSJean Delvare 	      val == 4 ? 0x80 :
5408d5d45fbSJean Delvare 	      val == 2 ? 0x40 :
5418d5d45fbSJean Delvare 	      val == 1 ? 0x00 :
5428d5d45fbSJean Delvare 	      0xff;
5438d5d45fbSJean Delvare 	if (tmp == 0xff)
5448d5d45fbSJean Delvare 		return -EINVAL;
5458d5d45fbSJean Delvare 
5469a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
54738a1f0e9SJean Delvare 	/* Get fresh readings */
54838a1f0e9SJean Delvare 	data->fan_div[nr] = adm1031_read_value(client,
54938a1f0e9SJean Delvare 					       ADM1031_REG_FAN_DIV(nr));
55038a1f0e9SJean Delvare 	data->fan_min[nr] = adm1031_read_value(client,
55138a1f0e9SJean Delvare 					       ADM1031_REG_FAN_MIN(nr));
55238a1f0e9SJean Delvare 
55338a1f0e9SJean Delvare 	/* Write the new clock divider and fan min */
5548d5d45fbSJean Delvare 	old_div = FAN_DIV_FROM_REG(data->fan_div[nr]);
5556d6006b8SJean Delvare 	data->fan_div[nr] = tmp | (0x3f & data->fan_div[nr]);
5566d6006b8SJean Delvare 	new_min = data->fan_min[nr] * old_div / val;
5578d5d45fbSJean Delvare 	data->fan_min[nr] = new_min > 0xff ? 0xff : new_min;
5588d5d45fbSJean Delvare 
5598d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_FAN_DIV(nr),
5608d5d45fbSJean Delvare 			    data->fan_div[nr]);
5618d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr),
5628d5d45fbSJean Delvare 			    data->fan_min[nr]);
56338a1f0e9SJean Delvare 
56438a1f0e9SJean Delvare 	/* Invalidate the cache: fan speed is no longer valid */
56538a1f0e9SJean Delvare 	data->valid = 0;
5669a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
5678d5d45fbSJean Delvare 	return count;
5688d5d45fbSJean Delvare }
5698d5d45fbSJean Delvare 
5708d5d45fbSJean Delvare #define fan_offset(offset)						\
571c801082dSJean Delvare static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO,			\
572c801082dSJean Delvare 		show_fan, NULL, offset - 1);				\
573c801082dSJean Delvare static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,		\
574c801082dSJean Delvare 		show_fan_min, set_fan_min, offset - 1);			\
575c801082dSJean Delvare static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR,		\
576c801082dSJean Delvare 		show_fan_div, set_fan_div, offset - 1)
5778d5d45fbSJean Delvare 
5788d5d45fbSJean Delvare fan_offset(1);
5798d5d45fbSJean Delvare fan_offset(2);
5808d5d45fbSJean Delvare 
5818d5d45fbSJean Delvare 
5828d5d45fbSJean Delvare /* Temps */
583c801082dSJean Delvare static ssize_t show_temp(struct device *dev,
584c801082dSJean Delvare 			 struct device_attribute *attr, char *buf)
5858d5d45fbSJean Delvare {
586c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
5878d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
5888d5d45fbSJean Delvare 	int ext;
5898d5d45fbSJean Delvare 	ext = nr == 0 ?
5908d5d45fbSJean Delvare 	    ((data->ext_temp[nr] >> 6) & 0x3) * 2 :
5918d5d45fbSJean Delvare 	    (((data->ext_temp[nr] >> ((nr - 1) * 3)) & 7));
5928d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG_EXT(data->temp[nr], ext));
5938d5d45fbSJean Delvare }
594*49dc9efeSIra Snyder static ssize_t show_temp_offset(struct device *dev,
595*49dc9efeSIra Snyder 				struct device_attribute *attr, char *buf)
596*49dc9efeSIra Snyder {
597*49dc9efeSIra Snyder 	int nr = to_sensor_dev_attr(attr)->index;
598*49dc9efeSIra Snyder 	struct adm1031_data *data = adm1031_update_device(dev);
599*49dc9efeSIra Snyder 	return sprintf(buf, "%d\n",
600*49dc9efeSIra Snyder 		       TEMP_OFFSET_FROM_REG(data->temp_offset[nr]));
601*49dc9efeSIra Snyder }
602c801082dSJean Delvare static ssize_t show_temp_min(struct device *dev,
603c801082dSJean Delvare 			     struct device_attribute *attr, char *buf)
6048d5d45fbSJean Delvare {
605c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
6068d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
6078d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr]));
6088d5d45fbSJean Delvare }
609c801082dSJean Delvare static ssize_t show_temp_max(struct device *dev,
610c801082dSJean Delvare 			     struct device_attribute *attr, char *buf)
6118d5d45fbSJean Delvare {
612c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
6138d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
6148d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr]));
6158d5d45fbSJean Delvare }
616c801082dSJean Delvare static ssize_t show_temp_crit(struct device *dev,
617c801082dSJean Delvare 			      struct device_attribute *attr, char *buf)
6188d5d45fbSJean Delvare {
619c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
6208d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
6218d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[nr]));
6228d5d45fbSJean Delvare }
623*49dc9efeSIra Snyder static ssize_t set_temp_offset(struct device *dev,
624*49dc9efeSIra Snyder 			       struct device_attribute *attr, const char *buf,
625*49dc9efeSIra Snyder 			       size_t count)
626*49dc9efeSIra Snyder {
627*49dc9efeSIra Snyder 	struct i2c_client *client = to_i2c_client(dev);
628*49dc9efeSIra Snyder 	struct adm1031_data *data = i2c_get_clientdata(client);
629*49dc9efeSIra Snyder 	int nr = to_sensor_dev_attr(attr)->index;
630*49dc9efeSIra Snyder 	int val;
631*49dc9efeSIra Snyder 
632*49dc9efeSIra Snyder 	val = simple_strtol(buf, NULL, 10);
633*49dc9efeSIra Snyder 	val = SENSORS_LIMIT(val, -15000, 15000);
634*49dc9efeSIra Snyder 	mutex_lock(&data->update_lock);
635*49dc9efeSIra Snyder 	data->temp_offset[nr] = TEMP_OFFSET_TO_REG(val);
636*49dc9efeSIra Snyder 	adm1031_write_value(client, ADM1031_REG_TEMP_OFFSET(nr),
637*49dc9efeSIra Snyder 			    data->temp_offset[nr]);
638*49dc9efeSIra Snyder 	mutex_unlock(&data->update_lock);
639*49dc9efeSIra Snyder 	return count;
640*49dc9efeSIra Snyder }
641c801082dSJean Delvare static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
642c801082dSJean Delvare 			    const char *buf, size_t count)
6438d5d45fbSJean Delvare {
6448d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
6458d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
646c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
6478d5d45fbSJean Delvare 	int val;
6488d5d45fbSJean Delvare 
6498d5d45fbSJean Delvare 	val = simple_strtol(buf, NULL, 10);
6508d5d45fbSJean Delvare 	val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875);
6519a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
6528d5d45fbSJean Delvare 	data->temp_min[nr] = TEMP_TO_REG(val);
6538d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_TEMP_MIN(nr),
6548d5d45fbSJean Delvare 			    data->temp_min[nr]);
6559a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
6568d5d45fbSJean Delvare 	return count;
6578d5d45fbSJean Delvare }
658c801082dSJean Delvare static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
659c801082dSJean Delvare 			    const char *buf, size_t count)
6608d5d45fbSJean Delvare {
6618d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
6628d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
663c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
6648d5d45fbSJean Delvare 	int val;
6658d5d45fbSJean Delvare 
6668d5d45fbSJean Delvare 	val = simple_strtol(buf, NULL, 10);
6678d5d45fbSJean Delvare 	val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875);
6689a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
6698d5d45fbSJean Delvare 	data->temp_max[nr] = TEMP_TO_REG(val);
6708d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_TEMP_MAX(nr),
6718d5d45fbSJean Delvare 			    data->temp_max[nr]);
6729a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
6738d5d45fbSJean Delvare 	return count;
6748d5d45fbSJean Delvare }
675c801082dSJean Delvare static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr,
676c801082dSJean Delvare 			     const char *buf, size_t count)
6778d5d45fbSJean Delvare {
6788d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
6798d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
680c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
6818d5d45fbSJean Delvare 	int val;
6828d5d45fbSJean Delvare 
6838d5d45fbSJean Delvare 	val = simple_strtol(buf, NULL, 10);
6848d5d45fbSJean Delvare 	val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875);
6859a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
6868d5d45fbSJean Delvare 	data->temp_crit[nr] = TEMP_TO_REG(val);
6878d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_TEMP_CRIT(nr),
6888d5d45fbSJean Delvare 			    data->temp_crit[nr]);
6899a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
6908d5d45fbSJean Delvare 	return count;
6918d5d45fbSJean Delvare }
6928d5d45fbSJean Delvare 
6938d5d45fbSJean Delvare #define temp_reg(offset)						\
694c801082dSJean Delvare static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO,		\
695c801082dSJean Delvare 		show_temp, NULL, offset - 1);				\
696*49dc9efeSIra Snyder static SENSOR_DEVICE_ATTR(temp##offset##_offset, S_IRUGO | S_IWUSR,	\
697*49dc9efeSIra Snyder 		show_temp_offset, set_temp_offset, offset - 1);		\
698c801082dSJean Delvare static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR,	\
699c801082dSJean Delvare 		show_temp_min, set_temp_min, offset - 1);		\
700c801082dSJean Delvare static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR,	\
701c801082dSJean Delvare 		show_temp_max, set_temp_max, offset - 1);		\
702c801082dSJean Delvare static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IRUGO | S_IWUSR,	\
703c801082dSJean Delvare 		show_temp_crit, set_temp_crit, offset - 1)
7048d5d45fbSJean Delvare 
7058d5d45fbSJean Delvare temp_reg(1);
7068d5d45fbSJean Delvare temp_reg(2);
7078d5d45fbSJean Delvare temp_reg(3);
7088d5d45fbSJean Delvare 
7098d5d45fbSJean Delvare /* Alarms */
7108d5d45fbSJean Delvare static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
7118d5d45fbSJean Delvare {
7128d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
7138d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", data->alarm);
7148d5d45fbSJean Delvare }
7158d5d45fbSJean Delvare 
7168d5d45fbSJean Delvare static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
7178d5d45fbSJean Delvare 
718050ab878SJean Delvare static ssize_t show_alarm(struct device *dev,
719050ab878SJean Delvare 			  struct device_attribute *attr, char *buf)
720050ab878SJean Delvare {
721050ab878SJean Delvare 	int bitnr = to_sensor_dev_attr(attr)->index;
722050ab878SJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
723050ab878SJean Delvare 	return sprintf(buf, "%d\n", (data->alarm >> bitnr) & 1);
724050ab878SJean Delvare }
725050ab878SJean Delvare 
726050ab878SJean Delvare static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 0);
727050ab878SJean Delvare static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_alarm, NULL, 1);
728050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 2);
729050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 3);
730050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 4);
731050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 5);
732050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6);
733050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 7);
734050ab878SJean Delvare static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 8);
735050ab878SJean Delvare static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_alarm, NULL, 9);
736050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL, 10);
737050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp3_min_alarm, S_IRUGO, show_alarm, NULL, 11);
738050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 12);
739050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 13);
740050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 14);
7418d5d45fbSJean Delvare 
742681c6f7aSMark M. Hoffman static struct attribute *adm1031_attributes[] = {
743c801082dSJean Delvare 	&sensor_dev_attr_fan1_input.dev_attr.attr,
744c801082dSJean Delvare 	&sensor_dev_attr_fan1_div.dev_attr.attr,
745c801082dSJean Delvare 	&sensor_dev_attr_fan1_min.dev_attr.attr,
746050ab878SJean Delvare 	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
747050ab878SJean Delvare 	&sensor_dev_attr_fan1_fault.dev_attr.attr,
748c801082dSJean Delvare 	&sensor_dev_attr_pwm1.dev_attr.attr,
749c801082dSJean Delvare 	&sensor_dev_attr_auto_fan1_channel.dev_attr.attr,
750c801082dSJean Delvare 	&sensor_dev_attr_temp1_input.dev_attr.attr,
751*49dc9efeSIra Snyder 	&sensor_dev_attr_temp1_offset.dev_attr.attr,
752c801082dSJean Delvare 	&sensor_dev_attr_temp1_min.dev_attr.attr,
753050ab878SJean Delvare 	&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
754c801082dSJean Delvare 	&sensor_dev_attr_temp1_max.dev_attr.attr,
755050ab878SJean Delvare 	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
756c801082dSJean Delvare 	&sensor_dev_attr_temp1_crit.dev_attr.attr,
757050ab878SJean Delvare 	&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
758c801082dSJean Delvare 	&sensor_dev_attr_temp2_input.dev_attr.attr,
759*49dc9efeSIra Snyder 	&sensor_dev_attr_temp2_offset.dev_attr.attr,
760c801082dSJean Delvare 	&sensor_dev_attr_temp2_min.dev_attr.attr,
761050ab878SJean Delvare 	&sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
762c801082dSJean Delvare 	&sensor_dev_attr_temp2_max.dev_attr.attr,
763050ab878SJean Delvare 	&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
764c801082dSJean Delvare 	&sensor_dev_attr_temp2_crit.dev_attr.attr,
765050ab878SJean Delvare 	&sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
766050ab878SJean Delvare 	&sensor_dev_attr_temp2_fault.dev_attr.attr,
767681c6f7aSMark M. Hoffman 
768c801082dSJean Delvare 	&sensor_dev_attr_auto_temp1_off.dev_attr.attr,
769c801082dSJean Delvare 	&sensor_dev_attr_auto_temp1_min.dev_attr.attr,
770c801082dSJean Delvare 	&sensor_dev_attr_auto_temp1_max.dev_attr.attr,
771681c6f7aSMark M. Hoffman 
772c801082dSJean Delvare 	&sensor_dev_attr_auto_temp2_off.dev_attr.attr,
773c801082dSJean Delvare 	&sensor_dev_attr_auto_temp2_min.dev_attr.attr,
774c801082dSJean Delvare 	&sensor_dev_attr_auto_temp2_max.dev_attr.attr,
775681c6f7aSMark M. Hoffman 
776c801082dSJean Delvare 	&sensor_dev_attr_auto_fan1_min_pwm.dev_attr.attr,
777681c6f7aSMark M. Hoffman 
778681c6f7aSMark M. Hoffman 	&dev_attr_alarms.attr,
779681c6f7aSMark M. Hoffman 
780681c6f7aSMark M. Hoffman 	NULL
781681c6f7aSMark M. Hoffman };
782681c6f7aSMark M. Hoffman 
783681c6f7aSMark M. Hoffman static const struct attribute_group adm1031_group = {
784681c6f7aSMark M. Hoffman 	.attrs = adm1031_attributes,
785681c6f7aSMark M. Hoffman };
786681c6f7aSMark M. Hoffman 
787681c6f7aSMark M. Hoffman static struct attribute *adm1031_attributes_opt[] = {
788c801082dSJean Delvare 	&sensor_dev_attr_fan2_input.dev_attr.attr,
789c801082dSJean Delvare 	&sensor_dev_attr_fan2_div.dev_attr.attr,
790c801082dSJean Delvare 	&sensor_dev_attr_fan2_min.dev_attr.attr,
791050ab878SJean Delvare 	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
792050ab878SJean Delvare 	&sensor_dev_attr_fan2_fault.dev_attr.attr,
793c801082dSJean Delvare 	&sensor_dev_attr_pwm2.dev_attr.attr,
794c801082dSJean Delvare 	&sensor_dev_attr_auto_fan2_channel.dev_attr.attr,
795c801082dSJean Delvare 	&sensor_dev_attr_temp3_input.dev_attr.attr,
796*49dc9efeSIra Snyder 	&sensor_dev_attr_temp3_offset.dev_attr.attr,
797c801082dSJean Delvare 	&sensor_dev_attr_temp3_min.dev_attr.attr,
798050ab878SJean Delvare 	&sensor_dev_attr_temp3_min_alarm.dev_attr.attr,
799c801082dSJean Delvare 	&sensor_dev_attr_temp3_max.dev_attr.attr,
800050ab878SJean Delvare 	&sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
801c801082dSJean Delvare 	&sensor_dev_attr_temp3_crit.dev_attr.attr,
802050ab878SJean Delvare 	&sensor_dev_attr_temp3_crit_alarm.dev_attr.attr,
803050ab878SJean Delvare 	&sensor_dev_attr_temp3_fault.dev_attr.attr,
804c801082dSJean Delvare 	&sensor_dev_attr_auto_temp3_off.dev_attr.attr,
805c801082dSJean Delvare 	&sensor_dev_attr_auto_temp3_min.dev_attr.attr,
806c801082dSJean Delvare 	&sensor_dev_attr_auto_temp3_max.dev_attr.attr,
807c801082dSJean Delvare 	&sensor_dev_attr_auto_fan2_min_pwm.dev_attr.attr,
808681c6f7aSMark M. Hoffman 	NULL
809681c6f7aSMark M. Hoffman };
810681c6f7aSMark M. Hoffman 
811681c6f7aSMark M. Hoffman static const struct attribute_group adm1031_group_opt = {
812681c6f7aSMark M. Hoffman 	.attrs = adm1031_attributes_opt,
813681c6f7aSMark M. Hoffman };
814681c6f7aSMark M. Hoffman 
815af200f88SJean Delvare /* Return 0 if detection is successful, -ENODEV otherwise */
816af200f88SJean Delvare static int adm1031_detect(struct i2c_client *client, int kind,
817af200f88SJean Delvare 			  struct i2c_board_info *info)
8188d5d45fbSJean Delvare {
819af200f88SJean Delvare 	struct i2c_adapter *adapter = client->adapter;
8208d5d45fbSJean Delvare 	const char *name = "";
8218d5d45fbSJean Delvare 
8228d5d45fbSJean Delvare 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
823af200f88SJean Delvare 		return -ENODEV;
8248d5d45fbSJean Delvare 
8258d5d45fbSJean Delvare 	if (kind < 0) {
8268d5d45fbSJean Delvare 		int id, co;
8276d6006b8SJean Delvare 		id = i2c_smbus_read_byte_data(client, 0x3d);
8286d6006b8SJean Delvare 		co = i2c_smbus_read_byte_data(client, 0x3e);
8298d5d45fbSJean Delvare 
8308d5d45fbSJean Delvare 		if (!((id == 0x31 || id == 0x30) && co == 0x41))
831af200f88SJean Delvare 			return -ENODEV;
8328d5d45fbSJean Delvare 		kind = (id == 0x30) ? adm1030 : adm1031;
8338d5d45fbSJean Delvare 	}
8348d5d45fbSJean Delvare 
8358d5d45fbSJean Delvare 	if (kind <= 0)
8368d5d45fbSJean Delvare 		kind = adm1031;
8378d5d45fbSJean Delvare 
8388d5d45fbSJean Delvare 	/* Given the detected chip type, set the chip name and the
8398d5d45fbSJean Delvare 	 * auto fan control helper table. */
8408d5d45fbSJean Delvare 	if (kind == adm1030) {
8418d5d45fbSJean Delvare 		name = "adm1030";
8428d5d45fbSJean Delvare 	} else if (kind == adm1031) {
8438d5d45fbSJean Delvare 		name = "adm1031";
8448d5d45fbSJean Delvare 	}
845af200f88SJean Delvare 	strlcpy(info->type, name, I2C_NAME_SIZE);
8468d5d45fbSJean Delvare 
847af200f88SJean Delvare 	return 0;
848af200f88SJean Delvare }
849af200f88SJean Delvare 
850af200f88SJean Delvare static int adm1031_probe(struct i2c_client *client,
851af200f88SJean Delvare 			 const struct i2c_device_id *id)
852af200f88SJean Delvare {
853af200f88SJean Delvare 	struct adm1031_data *data;
854af200f88SJean Delvare 	int err;
855af200f88SJean Delvare 
856af200f88SJean Delvare 	data = kzalloc(sizeof(struct adm1031_data), GFP_KERNEL);
857af200f88SJean Delvare 	if (!data) {
858af200f88SJean Delvare 		err = -ENOMEM;
859af200f88SJean Delvare 		goto exit;
860af200f88SJean Delvare 	}
861af200f88SJean Delvare 
862af200f88SJean Delvare 	i2c_set_clientdata(client, data);
863af200f88SJean Delvare 	data->chip_type = id->driver_data;
8649a61bf63SIngo Molnar 	mutex_init(&data->update_lock);
8658d5d45fbSJean Delvare 
866af200f88SJean Delvare 	if (data->chip_type == adm1030)
867af200f88SJean Delvare 		data->chan_select_table = &auto_channel_select_table_adm1030;
868af200f88SJean Delvare 	else
869af200f88SJean Delvare 		data->chan_select_table = &auto_channel_select_table_adm1031;
8708d5d45fbSJean Delvare 
8718d5d45fbSJean Delvare 	/* Initialize the ADM1031 chip */
8726d6006b8SJean Delvare 	adm1031_init_client(client);
8738d5d45fbSJean Delvare 
8748d5d45fbSJean Delvare 	/* Register sysfs hooks */
8756d6006b8SJean Delvare 	if ((err = sysfs_create_group(&client->dev.kobj, &adm1031_group)))
876af200f88SJean Delvare 		goto exit_free;
877681c6f7aSMark M. Hoffman 
878af200f88SJean Delvare 	if (data->chip_type == adm1031) {
8796d6006b8SJean Delvare 		if ((err = sysfs_create_group(&client->dev.kobj,
880681c6f7aSMark M. Hoffman 						&adm1031_group_opt)))
881681c6f7aSMark M. Hoffman 			goto exit_remove;
882681c6f7aSMark M. Hoffman 	}
883681c6f7aSMark M. Hoffman 
8846d6006b8SJean Delvare 	data->hwmon_dev = hwmon_device_register(&client->dev);
8851beeffe4STony Jones 	if (IS_ERR(data->hwmon_dev)) {
8861beeffe4STony Jones 		err = PTR_ERR(data->hwmon_dev);
887681c6f7aSMark M. Hoffman 		goto exit_remove;
8888d5d45fbSJean Delvare 	}
8898d5d45fbSJean Delvare 
8908d5d45fbSJean Delvare 	return 0;
8918d5d45fbSJean Delvare 
892681c6f7aSMark M. Hoffman exit_remove:
8936d6006b8SJean Delvare 	sysfs_remove_group(&client->dev.kobj, &adm1031_group);
8946d6006b8SJean Delvare 	sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt);
8958d5d45fbSJean Delvare exit_free:
8961f57ff89SAlexey Dobriyan 	kfree(data);
8978d5d45fbSJean Delvare exit:
8988d5d45fbSJean Delvare 	return err;
8998d5d45fbSJean Delvare }
9008d5d45fbSJean Delvare 
901af200f88SJean Delvare static int adm1031_remove(struct i2c_client *client)
9028d5d45fbSJean Delvare {
903943b0830SMark M. Hoffman 	struct adm1031_data *data = i2c_get_clientdata(client);
904943b0830SMark M. Hoffman 
9051beeffe4STony Jones 	hwmon_device_unregister(data->hwmon_dev);
906681c6f7aSMark M. Hoffman 	sysfs_remove_group(&client->dev.kobj, &adm1031_group);
907681c6f7aSMark M. Hoffman 	sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt);
908943b0830SMark M. Hoffman 	kfree(data);
9098d5d45fbSJean Delvare 	return 0;
9108d5d45fbSJean Delvare }
9118d5d45fbSJean Delvare 
9128d5d45fbSJean Delvare static void adm1031_init_client(struct i2c_client *client)
9138d5d45fbSJean Delvare {
9148d5d45fbSJean Delvare 	unsigned int read_val;
9158d5d45fbSJean Delvare 	unsigned int mask;
9168d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
9178d5d45fbSJean Delvare 
9188d5d45fbSJean Delvare 	mask = (ADM1031_CONF2_PWM1_ENABLE | ADM1031_CONF2_TACH1_ENABLE);
9198d5d45fbSJean Delvare 	if (data->chip_type == adm1031) {
9208d5d45fbSJean Delvare 		mask |= (ADM1031_CONF2_PWM2_ENABLE |
9218d5d45fbSJean Delvare 			ADM1031_CONF2_TACH2_ENABLE);
9228d5d45fbSJean Delvare 	}
9238d5d45fbSJean Delvare 	/* Initialize the ADM1031 chip (enables fan speed reading ) */
9248d5d45fbSJean Delvare 	read_val = adm1031_read_value(client, ADM1031_REG_CONF2);
9258d5d45fbSJean Delvare 	if ((read_val | mask) != read_val) {
9268d5d45fbSJean Delvare 	    adm1031_write_value(client, ADM1031_REG_CONF2, read_val | mask);
9278d5d45fbSJean Delvare 	}
9288d5d45fbSJean Delvare 
9298d5d45fbSJean Delvare 	read_val = adm1031_read_value(client, ADM1031_REG_CONF1);
9308d5d45fbSJean Delvare 	if ((read_val | ADM1031_CONF1_MONITOR_ENABLE) != read_val) {
9318d5d45fbSJean Delvare 	    adm1031_write_value(client, ADM1031_REG_CONF1, read_val |
9328d5d45fbSJean Delvare 				ADM1031_CONF1_MONITOR_ENABLE);
9338d5d45fbSJean Delvare 	}
9348d5d45fbSJean Delvare 
9358d5d45fbSJean Delvare }
9368d5d45fbSJean Delvare 
9378d5d45fbSJean Delvare static struct adm1031_data *adm1031_update_device(struct device *dev)
9388d5d45fbSJean Delvare {
9398d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
9408d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
9418d5d45fbSJean Delvare 	int chan;
9428d5d45fbSJean Delvare 
9439a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
9448d5d45fbSJean Delvare 
9458d5d45fbSJean Delvare 	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
9468d5d45fbSJean Delvare 	    || !data->valid) {
9478d5d45fbSJean Delvare 
9488d5d45fbSJean Delvare 		dev_dbg(&client->dev, "Starting adm1031 update\n");
9498d5d45fbSJean Delvare 		for (chan = 0;
9508d5d45fbSJean Delvare 		     chan < ((data->chip_type == adm1031) ? 3 : 2); chan++) {
9518d5d45fbSJean Delvare 			u8 oldh, newh;
9528d5d45fbSJean Delvare 
9538d5d45fbSJean Delvare 			oldh =
9548d5d45fbSJean Delvare 			    adm1031_read_value(client, ADM1031_REG_TEMP(chan));
9558d5d45fbSJean Delvare 			data->ext_temp[chan] =
9568d5d45fbSJean Delvare 			    adm1031_read_value(client, ADM1031_REG_EXT_TEMP);
9578d5d45fbSJean Delvare 			newh =
9588d5d45fbSJean Delvare 			    adm1031_read_value(client, ADM1031_REG_TEMP(chan));
9598d5d45fbSJean Delvare 			if (newh != oldh) {
9608d5d45fbSJean Delvare 				data->ext_temp[chan] =
9618d5d45fbSJean Delvare 				    adm1031_read_value(client,
9628d5d45fbSJean Delvare 						       ADM1031_REG_EXT_TEMP);
9638d5d45fbSJean Delvare #ifdef DEBUG
9648d5d45fbSJean Delvare 				oldh =
9658d5d45fbSJean Delvare 				    adm1031_read_value(client,
9668d5d45fbSJean Delvare 						       ADM1031_REG_TEMP(chan));
9678d5d45fbSJean Delvare 
9688d5d45fbSJean Delvare 				/* oldh is actually newer */
9698d5d45fbSJean Delvare 				if (newh != oldh)
9708d5d45fbSJean Delvare 					dev_warn(&client->dev,
9718d5d45fbSJean Delvare 						 "Remote temperature may be "
9728d5d45fbSJean Delvare 						 "wrong.\n");
9738d5d45fbSJean Delvare #endif
9748d5d45fbSJean Delvare 			}
9758d5d45fbSJean Delvare 			data->temp[chan] = newh;
9768d5d45fbSJean Delvare 
977*49dc9efeSIra Snyder 			data->temp_offset[chan] =
978*49dc9efeSIra Snyder 			    adm1031_read_value(client,
979*49dc9efeSIra Snyder 					       ADM1031_REG_TEMP_OFFSET(chan));
9808d5d45fbSJean Delvare 			data->temp_min[chan] =
9818d5d45fbSJean Delvare 			    adm1031_read_value(client,
9828d5d45fbSJean Delvare 					       ADM1031_REG_TEMP_MIN(chan));
9838d5d45fbSJean Delvare 			data->temp_max[chan] =
9848d5d45fbSJean Delvare 			    adm1031_read_value(client,
9858d5d45fbSJean Delvare 					       ADM1031_REG_TEMP_MAX(chan));
9868d5d45fbSJean Delvare 			data->temp_crit[chan] =
9878d5d45fbSJean Delvare 			    adm1031_read_value(client,
9888d5d45fbSJean Delvare 					       ADM1031_REG_TEMP_CRIT(chan));
9898d5d45fbSJean Delvare 			data->auto_temp[chan] =
9908d5d45fbSJean Delvare 			    adm1031_read_value(client,
9918d5d45fbSJean Delvare 					       ADM1031_REG_AUTO_TEMP(chan));
9928d5d45fbSJean Delvare 
9938d5d45fbSJean Delvare 		}
9948d5d45fbSJean Delvare 
9958d5d45fbSJean Delvare 		data->conf1 = adm1031_read_value(client, ADM1031_REG_CONF1);
9968d5d45fbSJean Delvare 		data->conf2 = adm1031_read_value(client, ADM1031_REG_CONF2);
9978d5d45fbSJean Delvare 
9988d5d45fbSJean Delvare 		data->alarm = adm1031_read_value(client, ADM1031_REG_STATUS(0))
9998d5d45fbSJean Delvare 			     | (adm1031_read_value(client, ADM1031_REG_STATUS(1))
10008d5d45fbSJean Delvare 				<< 8);
10018d5d45fbSJean Delvare 		if (data->chip_type == adm1030) {
10028d5d45fbSJean Delvare 			data->alarm &= 0xc0ff;
10038d5d45fbSJean Delvare 		}
10048d5d45fbSJean Delvare 
10058d5d45fbSJean Delvare 		for (chan=0; chan<(data->chip_type == adm1030 ? 1 : 2); chan++) {
10068d5d45fbSJean Delvare 			data->fan_div[chan] =
10078d5d45fbSJean Delvare 			    adm1031_read_value(client, ADM1031_REG_FAN_DIV(chan));
10088d5d45fbSJean Delvare 			data->fan_min[chan] =
10098d5d45fbSJean Delvare 			    adm1031_read_value(client, ADM1031_REG_FAN_MIN(chan));
10108d5d45fbSJean Delvare 			data->fan[chan] =
10118d5d45fbSJean Delvare 			    adm1031_read_value(client, ADM1031_REG_FAN_SPEED(chan));
10128d5d45fbSJean Delvare 			data->pwm[chan] =
10138d5d45fbSJean Delvare 			    0xf & (adm1031_read_value(client, ADM1031_REG_PWM) >>
10148d5d45fbSJean Delvare 				   (4*chan));
10158d5d45fbSJean Delvare 		}
10168d5d45fbSJean Delvare 		data->last_updated = jiffies;
10178d5d45fbSJean Delvare 		data->valid = 1;
10188d5d45fbSJean Delvare 	}
10198d5d45fbSJean Delvare 
10209a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
10218d5d45fbSJean Delvare 
10228d5d45fbSJean Delvare 	return data;
10238d5d45fbSJean Delvare }
10248d5d45fbSJean Delvare 
10258d5d45fbSJean Delvare static int __init sensors_adm1031_init(void)
10268d5d45fbSJean Delvare {
10278d5d45fbSJean Delvare 	return i2c_add_driver(&adm1031_driver);
10288d5d45fbSJean Delvare }
10298d5d45fbSJean Delvare 
10308d5d45fbSJean Delvare static void __exit sensors_adm1031_exit(void)
10318d5d45fbSJean Delvare {
10328d5d45fbSJean Delvare 	i2c_del_driver(&adm1031_driver);
10338d5d45fbSJean Delvare }
10348d5d45fbSJean Delvare 
10358d5d45fbSJean Delvare MODULE_AUTHOR("Alexandre d'Alton <alex@alexdalton.org>");
10368d5d45fbSJean Delvare MODULE_DESCRIPTION("ADM1031/ADM1030 driver");
10378d5d45fbSJean Delvare MODULE_LICENSE("GPL");
10388d5d45fbSJean Delvare 
10398d5d45fbSJean Delvare module_init(sensors_adm1031_init);
10408d5d45fbSJean Delvare module_exit(sensors_adm1031_exit);
1041