xref: /openbmc/linux/drivers/hwmon/adm1031.c (revision 179c4fdb565dd2157e5dfe89318b74868e3b523d)
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))
3987c33daaSJean Delvare #define ADM1031_REG_FAN_FILTER		(0x23)
408d5d45fbSJean Delvare 
4149dc9efeSIra Snyder #define ADM1031_REG_TEMP_OFFSET(nr)	(0x0d + (nr))
428d5d45fbSJean Delvare #define ADM1031_REG_TEMP_MAX(nr)	(0x14 + 4 * (nr))
438d5d45fbSJean Delvare #define ADM1031_REG_TEMP_MIN(nr)	(0x15 + 4 * (nr))
448d5d45fbSJean Delvare #define ADM1031_REG_TEMP_CRIT(nr)	(0x16 + 4 * (nr))
458d5d45fbSJean Delvare 
466d6006b8SJean Delvare #define ADM1031_REG_TEMP(nr)		(0x0a + (nr))
478d5d45fbSJean Delvare #define ADM1031_REG_AUTO_TEMP(nr)	(0x24 + (nr))
488d5d45fbSJean Delvare 
498d5d45fbSJean Delvare #define ADM1031_REG_STATUS(nr)		(0x2 + (nr))
508d5d45fbSJean Delvare 
516d6006b8SJean Delvare #define ADM1031_REG_CONF1		0x00
526d6006b8SJean Delvare #define ADM1031_REG_CONF2		0x01
536d6006b8SJean Delvare #define ADM1031_REG_EXT_TEMP		0x06
548d5d45fbSJean Delvare 
558d5d45fbSJean Delvare #define ADM1031_CONF1_MONITOR_ENABLE	0x01	/* Monitoring enable */
568d5d45fbSJean Delvare #define ADM1031_CONF1_PWM_INVERT	0x08	/* PWM Invert */
578d5d45fbSJean Delvare #define ADM1031_CONF1_AUTO_MODE		0x80	/* Auto FAN */
588d5d45fbSJean Delvare 
598d5d45fbSJean Delvare #define ADM1031_CONF2_PWM1_ENABLE	0x01
608d5d45fbSJean Delvare #define ADM1031_CONF2_PWM2_ENABLE	0x02
618d5d45fbSJean Delvare #define ADM1031_CONF2_TACH1_ENABLE	0x04
628d5d45fbSJean Delvare #define ADM1031_CONF2_TACH2_ENABLE	0x08
638d5d45fbSJean Delvare #define ADM1031_CONF2_TEMP_ENABLE(chan)	(0x10 << (chan))
648d5d45fbSJean Delvare 
6587c33daaSJean Delvare #define ADM1031_UPDATE_RATE_MASK	0x1c
6687c33daaSJean Delvare #define ADM1031_UPDATE_RATE_SHIFT	2
6787c33daaSJean Delvare 
688d5d45fbSJean Delvare /* Addresses to scan */
6925e9c86dSMark M. Hoffman static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
708d5d45fbSJean Delvare 
71e5e9f44cSJean Delvare enum chips { adm1030, adm1031 };
728d5d45fbSJean Delvare 
738d5d45fbSJean Delvare typedef u8 auto_chan_table_t[8][2];
748d5d45fbSJean Delvare 
758d5d45fbSJean Delvare /* Each client has this additional data */
768d5d45fbSJean Delvare struct adm1031_data {
771beeffe4STony Jones 	struct device *hwmon_dev;
789a61bf63SIngo Molnar 	struct mutex update_lock;
798d5d45fbSJean Delvare 	int chip_type;
808d5d45fbSJean Delvare 	char valid;		/* !=0 if following fields are valid */
818d5d45fbSJean Delvare 	unsigned long last_updated;	/* In jiffies */
82a51b9944SGuenter Roeck 	unsigned int update_interval;	/* In milliseconds */
838d5d45fbSJean Delvare 	/* The chan_select_table contains the possible configurations for
848d5d45fbSJean Delvare 	 * auto fan control.
858d5d45fbSJean Delvare 	 */
866d6006b8SJean Delvare 	const auto_chan_table_t *chan_select_table;
878d5d45fbSJean Delvare 	u16 alarm;
888d5d45fbSJean Delvare 	u8 conf1;
898d5d45fbSJean Delvare 	u8 conf2;
908d5d45fbSJean Delvare 	u8 fan[2];
918d5d45fbSJean Delvare 	u8 fan_div[2];
928d5d45fbSJean Delvare 	u8 fan_min[2];
938d5d45fbSJean Delvare 	u8 pwm[2];
948d5d45fbSJean Delvare 	u8 old_pwm[2];
958d5d45fbSJean Delvare 	s8 temp[3];
968d5d45fbSJean Delvare 	u8 ext_temp[3];
978d5d45fbSJean Delvare 	u8 auto_temp[3];
988d5d45fbSJean Delvare 	u8 auto_temp_min[3];
998d5d45fbSJean Delvare 	u8 auto_temp_off[3];
1008d5d45fbSJean Delvare 	u8 auto_temp_max[3];
10149dc9efeSIra Snyder 	s8 temp_offset[3];
1028d5d45fbSJean Delvare 	s8 temp_min[3];
1038d5d45fbSJean Delvare 	s8 temp_max[3];
1048d5d45fbSJean Delvare 	s8 temp_crit[3];
1058d5d45fbSJean Delvare };
1068d5d45fbSJean Delvare 
107af200f88SJean Delvare static int adm1031_probe(struct i2c_client *client,
108af200f88SJean Delvare 			 const struct i2c_device_id *id);
109310ec792SJean Delvare static int adm1031_detect(struct i2c_client *client,
110af200f88SJean Delvare 			  struct i2c_board_info *info);
1118d5d45fbSJean Delvare static void adm1031_init_client(struct i2c_client *client);
112af200f88SJean Delvare static int adm1031_remove(struct i2c_client *client);
1138d5d45fbSJean Delvare static struct adm1031_data *adm1031_update_device(struct device *dev);
1148d5d45fbSJean Delvare 
115af200f88SJean Delvare static const struct i2c_device_id adm1031_id[] = {
116af200f88SJean Delvare 	{ "adm1030", adm1030 },
117af200f88SJean Delvare 	{ "adm1031", adm1031 },
118af200f88SJean Delvare 	{ }
119af200f88SJean Delvare };
120af200f88SJean Delvare MODULE_DEVICE_TABLE(i2c, adm1031_id);
121af200f88SJean Delvare 
1228d5d45fbSJean Delvare /* This is the driver that will be inserted */
1238d5d45fbSJean Delvare static struct i2c_driver adm1031_driver = {
124af200f88SJean Delvare 	.class		= I2C_CLASS_HWMON,
125cdaf7934SLaurent Riffard 	.driver = {
1268d5d45fbSJean Delvare 		.name = "adm1031",
127cdaf7934SLaurent Riffard 	},
128af200f88SJean Delvare 	.probe		= adm1031_probe,
129af200f88SJean Delvare 	.remove		= adm1031_remove,
130af200f88SJean Delvare 	.id_table	= adm1031_id,
131af200f88SJean Delvare 	.detect		= adm1031_detect,
132c3813d6aSJean Delvare 	.address_list	= normal_i2c,
1338d5d45fbSJean Delvare };
1348d5d45fbSJean Delvare 
1358d5d45fbSJean Delvare static inline u8 adm1031_read_value(struct i2c_client *client, u8 reg)
1368d5d45fbSJean Delvare {
1378d5d45fbSJean Delvare 	return i2c_smbus_read_byte_data(client, reg);
1388d5d45fbSJean Delvare }
1398d5d45fbSJean Delvare 
1408d5d45fbSJean Delvare static inline int
1418d5d45fbSJean Delvare adm1031_write_value(struct i2c_client *client, u8 reg, unsigned int value)
1428d5d45fbSJean Delvare {
1438d5d45fbSJean Delvare 	return i2c_smbus_write_byte_data(client, reg, value);
1448d5d45fbSJean Delvare }
1458d5d45fbSJean Delvare 
1468d5d45fbSJean Delvare 
1478d5d45fbSJean Delvare #define TEMP_TO_REG(val)		(((val) < 0 ? ((val - 500) / 1000) : \
1488d5d45fbSJean Delvare 					((val + 500) / 1000)))
1498d5d45fbSJean Delvare 
1508d5d45fbSJean Delvare #define TEMP_FROM_REG(val)		((val) * 1000)
1518d5d45fbSJean Delvare 
1528d5d45fbSJean Delvare #define TEMP_FROM_REG_EXT(val, ext)	(TEMP_FROM_REG(val) + (ext) * 125)
1538d5d45fbSJean Delvare 
15449dc9efeSIra Snyder #define TEMP_OFFSET_TO_REG(val)		(TEMP_TO_REG(val) & 0x8f)
15549dc9efeSIra Snyder #define TEMP_OFFSET_FROM_REG(val)	TEMP_FROM_REG((val) < 0 ? \
15649dc9efeSIra Snyder 						      (val) | 0x70 : (val))
15749dc9efeSIra Snyder 
1588d5d45fbSJean Delvare #define FAN_FROM_REG(reg, div)		((reg) ? (11250 * 60) / ((reg) * (div)) : 0)
1598d5d45fbSJean Delvare 
1608d5d45fbSJean Delvare static int FAN_TO_REG(int reg, int div)
1618d5d45fbSJean Delvare {
1628d5d45fbSJean Delvare 	int tmp;
1638d5d45fbSJean Delvare 	tmp = FAN_FROM_REG(SENSORS_LIMIT(reg, 0, 65535), div);
1648d5d45fbSJean Delvare 	return tmp > 255 ? 255 : tmp;
1658d5d45fbSJean Delvare }
1668d5d45fbSJean Delvare 
1678d5d45fbSJean Delvare #define FAN_DIV_FROM_REG(reg)		(1<<(((reg)&0xc0)>>6))
1688d5d45fbSJean Delvare 
1698d5d45fbSJean Delvare #define PWM_TO_REG(val)			(SENSORS_LIMIT((val), 0, 255) >> 4)
1708d5d45fbSJean Delvare #define PWM_FROM_REG(val)		((val) << 4)
1718d5d45fbSJean Delvare 
1728d5d45fbSJean Delvare #define FAN_CHAN_FROM_REG(reg)		(((reg) >> 5) & 7)
1738d5d45fbSJean Delvare #define FAN_CHAN_TO_REG(val, reg)	\
1748d5d45fbSJean Delvare 	(((reg) & 0x1F) | (((val) << 5) & 0xe0))
1758d5d45fbSJean Delvare 
1768d5d45fbSJean Delvare #define AUTO_TEMP_MIN_TO_REG(val, reg)	\
1778d5d45fbSJean Delvare 	((((val)/500) & 0xf8)|((reg) & 0x7))
1788d5d45fbSJean Delvare #define AUTO_TEMP_RANGE_FROM_REG(reg)	(5000 * (1<< ((reg)&0x7)))
1798d5d45fbSJean Delvare #define AUTO_TEMP_MIN_FROM_REG(reg)	(1000 * ((((reg) >> 3) & 0x1f) << 2))
1808d5d45fbSJean Delvare 
1818d5d45fbSJean Delvare #define AUTO_TEMP_MIN_FROM_REG_DEG(reg)	((((reg) >> 3) & 0x1f) << 2)
1828d5d45fbSJean Delvare 
1838d5d45fbSJean Delvare #define AUTO_TEMP_OFF_FROM_REG(reg)		\
1848d5d45fbSJean Delvare 	(AUTO_TEMP_MIN_FROM_REG(reg) - 5000)
1858d5d45fbSJean Delvare 
1868d5d45fbSJean Delvare #define AUTO_TEMP_MAX_FROM_REG(reg)		\
1878d5d45fbSJean Delvare 	(AUTO_TEMP_RANGE_FROM_REG(reg) +	\
1888d5d45fbSJean Delvare 	AUTO_TEMP_MIN_FROM_REG(reg))
1898d5d45fbSJean Delvare 
1908d5d45fbSJean Delvare static int AUTO_TEMP_MAX_TO_REG(int val, int reg, int pwm)
1918d5d45fbSJean Delvare {
1928d5d45fbSJean Delvare 	int ret;
1938d5d45fbSJean Delvare 	int range = val - AUTO_TEMP_MIN_FROM_REG(reg);
1948d5d45fbSJean Delvare 
1958d5d45fbSJean Delvare 	range = ((val - AUTO_TEMP_MIN_FROM_REG(reg))*10)/(16 - pwm);
1968d5d45fbSJean Delvare 	ret = ((reg & 0xf8) |
1978d5d45fbSJean Delvare 	       (range < 10000 ? 0 :
1988d5d45fbSJean Delvare 		range < 20000 ? 1 :
1998d5d45fbSJean Delvare 		range < 40000 ? 2 : range < 80000 ? 3 : 4));
2008d5d45fbSJean Delvare 	return ret;
2018d5d45fbSJean Delvare }
2028d5d45fbSJean Delvare 
2038d5d45fbSJean Delvare /* FAN auto control */
2048d5d45fbSJean Delvare #define GET_FAN_AUTO_BITFIELD(data, idx)	\
2058d5d45fbSJean Delvare 	(*(data)->chan_select_table)[FAN_CHAN_FROM_REG((data)->conf1)][idx%2]
2068d5d45fbSJean Delvare 
2078d5d45fbSJean Delvare /* The tables below contains the possible values for the auto fan
2088d5d45fbSJean Delvare  * control bitfields. the index in the table is the register value.
2098d5d45fbSJean Delvare  * MSb is the auto fan control enable bit, so the four first entries
2108d5d45fbSJean Delvare  * in the table disables auto fan control when both bitfields are zero.
2118d5d45fbSJean Delvare  */
2126d6006b8SJean Delvare static const auto_chan_table_t auto_channel_select_table_adm1031 = {
2138d5d45fbSJean Delvare 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2148d5d45fbSJean Delvare 	{ 2 /* 0b010 */ , 4 /* 0b100 */ },
2158d5d45fbSJean Delvare 	{ 2 /* 0b010 */ , 2 /* 0b010 */ },
2168d5d45fbSJean Delvare 	{ 4 /* 0b100 */ , 4 /* 0b100 */ },
2178d5d45fbSJean Delvare 	{ 7 /* 0b111 */ , 7 /* 0b111 */ },
2188d5d45fbSJean Delvare };
2198d5d45fbSJean Delvare 
2206d6006b8SJean Delvare static const auto_chan_table_t auto_channel_select_table_adm1030 = {
2218d5d45fbSJean Delvare 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2228d5d45fbSJean Delvare 	{ 2 /* 0b10 */		, 0 },
2238d5d45fbSJean Delvare 	{ 0xff /* invalid */	, 0 },
2248d5d45fbSJean Delvare 	{ 0xff /* invalid */	, 0 },
2258d5d45fbSJean Delvare 	{ 3 /* 0b11 */		, 0 },
2268d5d45fbSJean Delvare };
2278d5d45fbSJean Delvare 
2288d5d45fbSJean Delvare /* That function checks if a bitfield is valid and returns the other bitfield
2298d5d45fbSJean Delvare  * nearest match if no exact match where found.
2308d5d45fbSJean Delvare  */
2318d5d45fbSJean Delvare static int
2328d5d45fbSJean Delvare get_fan_auto_nearest(struct adm1031_data *data,
2338d5d45fbSJean Delvare 		     int chan, u8 val, u8 reg, u8 * new_reg)
2348d5d45fbSJean Delvare {
2358d5d45fbSJean Delvare 	int i;
2368d5d45fbSJean Delvare 	int first_match = -1, exact_match = -1;
2378d5d45fbSJean Delvare 	u8 other_reg_val =
2388d5d45fbSJean Delvare 	    (*data->chan_select_table)[FAN_CHAN_FROM_REG(reg)][chan ? 0 : 1];
2398d5d45fbSJean Delvare 
2408d5d45fbSJean Delvare 	if (val == 0) {
2418d5d45fbSJean Delvare 		*new_reg = 0;
2428d5d45fbSJean Delvare 		return 0;
2438d5d45fbSJean Delvare 	}
2448d5d45fbSJean Delvare 
2458d5d45fbSJean Delvare 	for (i = 0; i < 8; i++) {
2468d5d45fbSJean Delvare 		if ((val == (*data->chan_select_table)[i][chan]) &&
2478d5d45fbSJean Delvare 		    ((*data->chan_select_table)[i][chan ? 0 : 1] ==
2488d5d45fbSJean Delvare 		     other_reg_val)) {
2498d5d45fbSJean Delvare 			/* We found an exact match */
2508d5d45fbSJean Delvare 			exact_match = i;
2518d5d45fbSJean Delvare 			break;
2528d5d45fbSJean Delvare 		} else if (val == (*data->chan_select_table)[i][chan] &&
2538d5d45fbSJean Delvare 			   first_match == -1) {
2546d6006b8SJean Delvare 			/* Save the first match in case of an exact match has
2556d6006b8SJean Delvare 			 * not been found
2568d5d45fbSJean Delvare 			 */
2578d5d45fbSJean Delvare 			first_match = i;
2588d5d45fbSJean Delvare 		}
2598d5d45fbSJean Delvare 	}
2608d5d45fbSJean Delvare 
2618d5d45fbSJean Delvare 	if (exact_match >= 0) {
2628d5d45fbSJean Delvare 		*new_reg = exact_match;
2638d5d45fbSJean Delvare 	} else if (first_match >= 0) {
2648d5d45fbSJean Delvare 		*new_reg = first_match;
2658d5d45fbSJean Delvare 	} else {
2668d5d45fbSJean Delvare 		return -EINVAL;
2678d5d45fbSJean Delvare 	}
2688d5d45fbSJean Delvare 	return 0;
2698d5d45fbSJean Delvare }
2708d5d45fbSJean Delvare 
271c801082dSJean Delvare static ssize_t show_fan_auto_channel(struct device *dev,
272c801082dSJean Delvare 				     struct device_attribute *attr, char *buf)
2738d5d45fbSJean Delvare {
274c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
2758d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
2768d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", GET_FAN_AUTO_BITFIELD(data, nr));
2778d5d45fbSJean Delvare }
2788d5d45fbSJean Delvare 
2798d5d45fbSJean Delvare static ssize_t
280c801082dSJean Delvare set_fan_auto_channel(struct device *dev, struct device_attribute *attr,
281c801082dSJean Delvare 		     const char *buf, size_t count)
2828d5d45fbSJean Delvare {
2838d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
2848d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
285c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
2868d5d45fbSJean Delvare 	int val = simple_strtol(buf, NULL, 10);
2878d5d45fbSJean Delvare 	u8 reg;
2888d5d45fbSJean Delvare 	int ret;
2898d5d45fbSJean Delvare 	u8 old_fan_mode;
2908d5d45fbSJean Delvare 
2918d5d45fbSJean Delvare 	old_fan_mode = data->conf1;
2928d5d45fbSJean Delvare 
2939a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
2948d5d45fbSJean Delvare 
2958d5d45fbSJean Delvare 	if ((ret = get_fan_auto_nearest(data, nr, val, data->conf1, &reg))) {
2969a61bf63SIngo Molnar 		mutex_unlock(&data->update_lock);
2978d5d45fbSJean Delvare 		return ret;
2988d5d45fbSJean Delvare 	}
2996d6006b8SJean Delvare 	data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1);
3006d6006b8SJean Delvare 	if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) ^
3018d5d45fbSJean Delvare 	    (old_fan_mode & ADM1031_CONF1_AUTO_MODE)) {
3028d5d45fbSJean Delvare 		if (data->conf1 & ADM1031_CONF1_AUTO_MODE){
3038d5d45fbSJean Delvare 			/* Switch to Auto Fan Mode
3048d5d45fbSJean Delvare 			 * Save PWM registers
3058d5d45fbSJean Delvare 			 * Set PWM registers to 33% Both */
3068d5d45fbSJean Delvare 			data->old_pwm[0] = data->pwm[0];
3078d5d45fbSJean Delvare 			data->old_pwm[1] = data->pwm[1];
3088d5d45fbSJean Delvare 			adm1031_write_value(client, ADM1031_REG_PWM, 0x55);
3098d5d45fbSJean Delvare 		} else {
3108d5d45fbSJean Delvare 			/* Switch to Manual Mode */
3118d5d45fbSJean Delvare 			data->pwm[0] = data->old_pwm[0];
3128d5d45fbSJean Delvare 			data->pwm[1] = data->old_pwm[1];
3138d5d45fbSJean Delvare 			/* Restore PWM registers */
3148d5d45fbSJean Delvare 			adm1031_write_value(client, ADM1031_REG_PWM,
3158d5d45fbSJean Delvare 					    data->pwm[0] | (data->pwm[1] << 4));
3168d5d45fbSJean Delvare 		}
3178d5d45fbSJean Delvare 	}
3188d5d45fbSJean Delvare 	data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1);
3198d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_CONF1, data->conf1);
3209a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
3218d5d45fbSJean Delvare 	return count;
3228d5d45fbSJean Delvare }
3238d5d45fbSJean Delvare 
324c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_fan1_channel, S_IRUGO | S_IWUSR,
325c801082dSJean Delvare 		show_fan_auto_channel, set_fan_auto_channel, 0);
326c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_fan2_channel, S_IRUGO | S_IWUSR,
327c801082dSJean Delvare 		show_fan_auto_channel, set_fan_auto_channel, 1);
3288d5d45fbSJean Delvare 
3298d5d45fbSJean Delvare /* Auto Temps */
330c801082dSJean Delvare static ssize_t show_auto_temp_off(struct device *dev,
331c801082dSJean Delvare 				  struct device_attribute *attr, char *buf)
3328d5d45fbSJean Delvare {
333c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
3348d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
3358d5d45fbSJean Delvare 	return sprintf(buf, "%d\n",
3368d5d45fbSJean Delvare 		       AUTO_TEMP_OFF_FROM_REG(data->auto_temp[nr]));
3378d5d45fbSJean Delvare }
338c801082dSJean Delvare static ssize_t show_auto_temp_min(struct device *dev,
339c801082dSJean Delvare 				  struct device_attribute *attr, char *buf)
3408d5d45fbSJean Delvare {
341c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
3428d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
3438d5d45fbSJean Delvare 	return sprintf(buf, "%d\n",
3448d5d45fbSJean Delvare 		       AUTO_TEMP_MIN_FROM_REG(data->auto_temp[nr]));
3458d5d45fbSJean Delvare }
3468d5d45fbSJean Delvare static ssize_t
347c801082dSJean Delvare set_auto_temp_min(struct device *dev, struct device_attribute *attr,
348c801082dSJean Delvare 		  const char *buf, size_t count)
3498d5d45fbSJean Delvare {
3508d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
3518d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
352c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
3538d5d45fbSJean Delvare 	int val = simple_strtol(buf, NULL, 10);
3548d5d45fbSJean Delvare 
3559a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
3568d5d45fbSJean Delvare 	data->auto_temp[nr] = AUTO_TEMP_MIN_TO_REG(val, data->auto_temp[nr]);
3578d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr),
3588d5d45fbSJean Delvare 			    data->auto_temp[nr]);
3599a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
3608d5d45fbSJean Delvare 	return count;
3618d5d45fbSJean Delvare }
362c801082dSJean Delvare static ssize_t show_auto_temp_max(struct device *dev,
363c801082dSJean Delvare 				  struct device_attribute *attr, char *buf)
3648d5d45fbSJean Delvare {
365c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
3668d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
3678d5d45fbSJean Delvare 	return sprintf(buf, "%d\n",
3688d5d45fbSJean Delvare 		       AUTO_TEMP_MAX_FROM_REG(data->auto_temp[nr]));
3698d5d45fbSJean Delvare }
3708d5d45fbSJean Delvare static ssize_t
371c801082dSJean Delvare set_auto_temp_max(struct device *dev, struct device_attribute *attr,
372c801082dSJean Delvare 		  const char *buf, size_t count)
3738d5d45fbSJean Delvare {
3748d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
3758d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
376c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
3778d5d45fbSJean Delvare 	int val = simple_strtol(buf, NULL, 10);
3788d5d45fbSJean Delvare 
3799a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
3808d5d45fbSJean Delvare 	data->temp_max[nr] = AUTO_TEMP_MAX_TO_REG(val, data->auto_temp[nr], data->pwm[nr]);
3818d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr),
3828d5d45fbSJean Delvare 			    data->temp_max[nr]);
3839a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
3848d5d45fbSJean Delvare 	return count;
3858d5d45fbSJean Delvare }
3868d5d45fbSJean Delvare 
3878d5d45fbSJean Delvare #define auto_temp_reg(offset)						\
388c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_temp##offset##_off, S_IRUGO,		\
389c801082dSJean Delvare 		show_auto_temp_off, NULL, offset - 1);			\
390c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_temp##offset##_min, S_IRUGO | S_IWUSR,	\
391c801082dSJean Delvare 		show_auto_temp_min, set_auto_temp_min, offset - 1);	\
392c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_temp##offset##_max, S_IRUGO | S_IWUSR,	\
393c801082dSJean Delvare 		show_auto_temp_max, set_auto_temp_max, offset - 1)
3948d5d45fbSJean Delvare 
3958d5d45fbSJean Delvare auto_temp_reg(1);
3968d5d45fbSJean Delvare auto_temp_reg(2);
3978d5d45fbSJean Delvare auto_temp_reg(3);
3988d5d45fbSJean Delvare 
3998d5d45fbSJean Delvare /* pwm */
400c801082dSJean Delvare static ssize_t show_pwm(struct device *dev,
401c801082dSJean Delvare 			struct device_attribute *attr, char *buf)
4028d5d45fbSJean Delvare {
403c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4048d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
4058d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm[nr]));
4068d5d45fbSJean Delvare }
407c801082dSJean Delvare static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
408c801082dSJean Delvare 		       const char *buf, size_t count)
4098d5d45fbSJean Delvare {
4108d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
4118d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
412c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4138d5d45fbSJean Delvare 	int val = simple_strtol(buf, NULL, 10);
4148d5d45fbSJean Delvare 	int reg;
4158d5d45fbSJean Delvare 
4169a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
4178d5d45fbSJean Delvare 	if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) &&
4188d5d45fbSJean Delvare 	    (((val>>4) & 0xf) != 5)) {
4198d5d45fbSJean Delvare 		/* In automatic mode, the only PWM accepted is 33% */
4209a61bf63SIngo Molnar 		mutex_unlock(&data->update_lock);
4218d5d45fbSJean Delvare 		return -EINVAL;
4228d5d45fbSJean Delvare 	}
4238d5d45fbSJean Delvare 	data->pwm[nr] = PWM_TO_REG(val);
4248d5d45fbSJean Delvare 	reg = adm1031_read_value(client, ADM1031_REG_PWM);
4258d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_PWM,
4268d5d45fbSJean Delvare 			    nr ? ((data->pwm[nr] << 4) & 0xf0) | (reg & 0xf)
4278d5d45fbSJean Delvare 			    : (data->pwm[nr] & 0xf) | (reg & 0xf0));
4289a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
4298d5d45fbSJean Delvare 	return count;
4308d5d45fbSJean Delvare }
4318d5d45fbSJean Delvare 
432c801082dSJean Delvare static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 0);
433c801082dSJean Delvare static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 1);
434c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_fan1_min_pwm, S_IRUGO | S_IWUSR,
435c801082dSJean Delvare 		show_pwm, set_pwm, 0);
436c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_fan2_min_pwm, S_IRUGO | S_IWUSR,
437c801082dSJean Delvare 		show_pwm, set_pwm, 1);
4388d5d45fbSJean Delvare 
4398d5d45fbSJean Delvare /* Fans */
4408d5d45fbSJean Delvare 
4418d5d45fbSJean Delvare /*
4428d5d45fbSJean Delvare  * That function checks the cases where the fan reading is not
4438d5d45fbSJean Delvare  * relevant.  It is used to provide 0 as fan reading when the fan is
4448d5d45fbSJean Delvare  * not supposed to run
4458d5d45fbSJean Delvare  */
4468d5d45fbSJean Delvare static int trust_fan_readings(struct adm1031_data *data, int chan)
4478d5d45fbSJean Delvare {
4488d5d45fbSJean Delvare 	int res = 0;
4498d5d45fbSJean Delvare 
4508d5d45fbSJean Delvare 	if (data->conf1 & ADM1031_CONF1_AUTO_MODE) {
4518d5d45fbSJean Delvare 		switch (data->conf1 & 0x60) {
4528d5d45fbSJean Delvare 		case 0x00:	/* remote temp1 controls fan1 remote temp2 controls fan2 */
4538d5d45fbSJean Delvare 			res = data->temp[chan+1] >=
4548d5d45fbSJean Delvare 			      AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[chan+1]);
4558d5d45fbSJean Delvare 			break;
4568d5d45fbSJean Delvare 		case 0x20:	/* remote temp1 controls both fans */
4578d5d45fbSJean Delvare 			res =
4588d5d45fbSJean Delvare 			    data->temp[1] >=
4598d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[1]);
4608d5d45fbSJean Delvare 			break;
4618d5d45fbSJean Delvare 		case 0x40:	/* remote temp2 controls both fans */
4628d5d45fbSJean Delvare 			res =
4638d5d45fbSJean Delvare 			    data->temp[2] >=
4648d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[2]);
4658d5d45fbSJean Delvare 			break;
4668d5d45fbSJean Delvare 		case 0x60:	/* max controls both fans */
4678d5d45fbSJean Delvare 			res =
4688d5d45fbSJean Delvare 			    data->temp[0] >=
4698d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[0])
4708d5d45fbSJean Delvare 			    || data->temp[1] >=
4718d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[1])
4728d5d45fbSJean Delvare 			    || (data->chip_type == adm1031
4738d5d45fbSJean Delvare 				&& data->temp[2] >=
4748d5d45fbSJean Delvare 				AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[2]));
4758d5d45fbSJean Delvare 			break;
4768d5d45fbSJean Delvare 		}
4778d5d45fbSJean Delvare 	} else {
4788d5d45fbSJean Delvare 		res = data->pwm[chan] > 0;
4798d5d45fbSJean Delvare 	}
4808d5d45fbSJean Delvare 	return res;
4818d5d45fbSJean Delvare }
4828d5d45fbSJean Delvare 
4838d5d45fbSJean Delvare 
484c801082dSJean Delvare static ssize_t show_fan(struct device *dev,
485c801082dSJean Delvare 			struct device_attribute *attr, char *buf)
4868d5d45fbSJean Delvare {
487c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4888d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
4898d5d45fbSJean Delvare 	int value;
4908d5d45fbSJean Delvare 
4918d5d45fbSJean Delvare 	value = trust_fan_readings(data, nr) ? FAN_FROM_REG(data->fan[nr],
4928d5d45fbSJean Delvare 				 FAN_DIV_FROM_REG(data->fan_div[nr])) : 0;
4938d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", value);
4948d5d45fbSJean Delvare }
4958d5d45fbSJean Delvare 
496c801082dSJean Delvare static ssize_t show_fan_div(struct device *dev,
497c801082dSJean Delvare 			    struct device_attribute *attr, char *buf)
4988d5d45fbSJean Delvare {
499c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
5008d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
5018d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", FAN_DIV_FROM_REG(data->fan_div[nr]));
5028d5d45fbSJean Delvare }
503c801082dSJean Delvare static ssize_t show_fan_min(struct device *dev,
504c801082dSJean Delvare 			    struct device_attribute *attr, char *buf)
5058d5d45fbSJean Delvare {
506c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
5078d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
5088d5d45fbSJean Delvare 	return sprintf(buf, "%d\n",
5098d5d45fbSJean Delvare 		       FAN_FROM_REG(data->fan_min[nr],
5108d5d45fbSJean Delvare 				    FAN_DIV_FROM_REG(data->fan_div[nr])));
5118d5d45fbSJean Delvare }
512c801082dSJean Delvare static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
513c801082dSJean Delvare 			   const char *buf, size_t count)
5148d5d45fbSJean Delvare {
5158d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
5168d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
517c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
5188d5d45fbSJean Delvare 	int val = simple_strtol(buf, NULL, 10);
5198d5d45fbSJean Delvare 
5209a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
5218d5d45fbSJean Delvare 	if (val) {
5228d5d45fbSJean Delvare 		data->fan_min[nr] =
5238d5d45fbSJean Delvare 			FAN_TO_REG(val, FAN_DIV_FROM_REG(data->fan_div[nr]));
5248d5d45fbSJean Delvare 	} else {
5258d5d45fbSJean Delvare 		data->fan_min[nr] = 0xff;
5268d5d45fbSJean Delvare 	}
5278d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), data->fan_min[nr]);
5289a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
5298d5d45fbSJean Delvare 	return count;
5308d5d45fbSJean Delvare }
531c801082dSJean Delvare static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
532c801082dSJean Delvare 			   const char *buf, size_t count)
5338d5d45fbSJean Delvare {
5348d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
5358d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
536c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
5378d5d45fbSJean Delvare 	int val = simple_strtol(buf, NULL, 10);
5388d5d45fbSJean Delvare 	u8 tmp;
5398d5d45fbSJean Delvare 	int old_div;
5408d5d45fbSJean Delvare 	int new_min;
5418d5d45fbSJean Delvare 
5428d5d45fbSJean Delvare 	tmp = val == 8 ? 0xc0 :
5438d5d45fbSJean Delvare 	      val == 4 ? 0x80 :
5448d5d45fbSJean Delvare 	      val == 2 ? 0x40 :
5458d5d45fbSJean Delvare 	      val == 1 ? 0x00 :
5468d5d45fbSJean Delvare 	      0xff;
5478d5d45fbSJean Delvare 	if (tmp == 0xff)
5488d5d45fbSJean Delvare 		return -EINVAL;
5498d5d45fbSJean Delvare 
5509a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
55138a1f0e9SJean Delvare 	/* Get fresh readings */
55238a1f0e9SJean Delvare 	data->fan_div[nr] = adm1031_read_value(client,
55338a1f0e9SJean Delvare 					       ADM1031_REG_FAN_DIV(nr));
55438a1f0e9SJean Delvare 	data->fan_min[nr] = adm1031_read_value(client,
55538a1f0e9SJean Delvare 					       ADM1031_REG_FAN_MIN(nr));
55638a1f0e9SJean Delvare 
55738a1f0e9SJean Delvare 	/* Write the new clock divider and fan min */
5588d5d45fbSJean Delvare 	old_div = FAN_DIV_FROM_REG(data->fan_div[nr]);
5596d6006b8SJean Delvare 	data->fan_div[nr] = tmp | (0x3f & data->fan_div[nr]);
5606d6006b8SJean Delvare 	new_min = data->fan_min[nr] * old_div / val;
5618d5d45fbSJean Delvare 	data->fan_min[nr] = new_min > 0xff ? 0xff : new_min;
5628d5d45fbSJean Delvare 
5638d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_FAN_DIV(nr),
5648d5d45fbSJean Delvare 			    data->fan_div[nr]);
5658d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr),
5668d5d45fbSJean Delvare 			    data->fan_min[nr]);
56738a1f0e9SJean Delvare 
56838a1f0e9SJean Delvare 	/* Invalidate the cache: fan speed is no longer valid */
56938a1f0e9SJean Delvare 	data->valid = 0;
5709a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
5718d5d45fbSJean Delvare 	return count;
5728d5d45fbSJean Delvare }
5738d5d45fbSJean Delvare 
5748d5d45fbSJean Delvare #define fan_offset(offset)						\
575c801082dSJean Delvare static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO,			\
576c801082dSJean Delvare 		show_fan, NULL, offset - 1);				\
577c801082dSJean Delvare static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,		\
578c801082dSJean Delvare 		show_fan_min, set_fan_min, offset - 1);			\
579c801082dSJean Delvare static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR,		\
580c801082dSJean Delvare 		show_fan_div, set_fan_div, offset - 1)
5818d5d45fbSJean Delvare 
5828d5d45fbSJean Delvare fan_offset(1);
5838d5d45fbSJean Delvare fan_offset(2);
5848d5d45fbSJean Delvare 
5858d5d45fbSJean Delvare 
5868d5d45fbSJean Delvare /* Temps */
587c801082dSJean Delvare static ssize_t show_temp(struct device *dev,
588c801082dSJean Delvare 			 struct device_attribute *attr, char *buf)
5898d5d45fbSJean Delvare {
590c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
5918d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
5928d5d45fbSJean Delvare 	int ext;
5938d5d45fbSJean Delvare 	ext = nr == 0 ?
5948d5d45fbSJean Delvare 	    ((data->ext_temp[nr] >> 6) & 0x3) * 2 :
5958d5d45fbSJean Delvare 	    (((data->ext_temp[nr] >> ((nr - 1) * 3)) & 7));
5968d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG_EXT(data->temp[nr], ext));
5978d5d45fbSJean Delvare }
59849dc9efeSIra Snyder static ssize_t show_temp_offset(struct device *dev,
59949dc9efeSIra Snyder 				struct device_attribute *attr, char *buf)
60049dc9efeSIra Snyder {
60149dc9efeSIra Snyder 	int nr = to_sensor_dev_attr(attr)->index;
60249dc9efeSIra Snyder 	struct adm1031_data *data = adm1031_update_device(dev);
60349dc9efeSIra Snyder 	return sprintf(buf, "%d\n",
60449dc9efeSIra Snyder 		       TEMP_OFFSET_FROM_REG(data->temp_offset[nr]));
60549dc9efeSIra Snyder }
606c801082dSJean Delvare static ssize_t show_temp_min(struct device *dev,
607c801082dSJean Delvare 			     struct device_attribute *attr, char *buf)
6088d5d45fbSJean Delvare {
609c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
6108d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
6118d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr]));
6128d5d45fbSJean Delvare }
613c801082dSJean Delvare static ssize_t show_temp_max(struct device *dev,
614c801082dSJean Delvare 			     struct device_attribute *attr, char *buf)
6158d5d45fbSJean Delvare {
616c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
6178d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
6188d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr]));
6198d5d45fbSJean Delvare }
620c801082dSJean Delvare static ssize_t show_temp_crit(struct device *dev,
621c801082dSJean Delvare 			      struct device_attribute *attr, char *buf)
6228d5d45fbSJean Delvare {
623c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
6248d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
6258d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[nr]));
6268d5d45fbSJean Delvare }
62749dc9efeSIra Snyder static ssize_t set_temp_offset(struct device *dev,
62849dc9efeSIra Snyder 			       struct device_attribute *attr, const char *buf,
62949dc9efeSIra Snyder 			       size_t count)
63049dc9efeSIra Snyder {
63149dc9efeSIra Snyder 	struct i2c_client *client = to_i2c_client(dev);
63249dc9efeSIra Snyder 	struct adm1031_data *data = i2c_get_clientdata(client);
63349dc9efeSIra Snyder 	int nr = to_sensor_dev_attr(attr)->index;
63449dc9efeSIra Snyder 	int val;
63549dc9efeSIra Snyder 
63649dc9efeSIra Snyder 	val = simple_strtol(buf, NULL, 10);
63749dc9efeSIra Snyder 	val = SENSORS_LIMIT(val, -15000, 15000);
63849dc9efeSIra Snyder 	mutex_lock(&data->update_lock);
63949dc9efeSIra Snyder 	data->temp_offset[nr] = TEMP_OFFSET_TO_REG(val);
64049dc9efeSIra Snyder 	adm1031_write_value(client, ADM1031_REG_TEMP_OFFSET(nr),
64149dc9efeSIra Snyder 			    data->temp_offset[nr]);
64249dc9efeSIra Snyder 	mutex_unlock(&data->update_lock);
64349dc9efeSIra Snyder 	return count;
64449dc9efeSIra Snyder }
645c801082dSJean Delvare static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
646c801082dSJean Delvare 			    const char *buf, size_t count)
6478d5d45fbSJean Delvare {
6488d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
6498d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
650c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
6518d5d45fbSJean Delvare 	int val;
6528d5d45fbSJean Delvare 
6538d5d45fbSJean Delvare 	val = simple_strtol(buf, NULL, 10);
6548d5d45fbSJean Delvare 	val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875);
6559a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
6568d5d45fbSJean Delvare 	data->temp_min[nr] = TEMP_TO_REG(val);
6578d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_TEMP_MIN(nr),
6588d5d45fbSJean Delvare 			    data->temp_min[nr]);
6599a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
6608d5d45fbSJean Delvare 	return count;
6618d5d45fbSJean Delvare }
662c801082dSJean Delvare static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
663c801082dSJean Delvare 			    const char *buf, size_t count)
6648d5d45fbSJean Delvare {
6658d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
6668d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
667c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
6688d5d45fbSJean Delvare 	int val;
6698d5d45fbSJean Delvare 
6708d5d45fbSJean Delvare 	val = simple_strtol(buf, NULL, 10);
6718d5d45fbSJean Delvare 	val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875);
6729a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
6738d5d45fbSJean Delvare 	data->temp_max[nr] = TEMP_TO_REG(val);
6748d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_TEMP_MAX(nr),
6758d5d45fbSJean Delvare 			    data->temp_max[nr]);
6769a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
6778d5d45fbSJean Delvare 	return count;
6788d5d45fbSJean Delvare }
679c801082dSJean Delvare static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr,
680c801082dSJean Delvare 			     const char *buf, size_t count)
6818d5d45fbSJean Delvare {
6828d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
6838d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
684c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
6858d5d45fbSJean Delvare 	int val;
6868d5d45fbSJean Delvare 
6878d5d45fbSJean Delvare 	val = simple_strtol(buf, NULL, 10);
6888d5d45fbSJean Delvare 	val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875);
6899a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
6908d5d45fbSJean Delvare 	data->temp_crit[nr] = TEMP_TO_REG(val);
6918d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_TEMP_CRIT(nr),
6928d5d45fbSJean Delvare 			    data->temp_crit[nr]);
6939a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
6948d5d45fbSJean Delvare 	return count;
6958d5d45fbSJean Delvare }
6968d5d45fbSJean Delvare 
6978d5d45fbSJean Delvare #define temp_reg(offset)						\
698c801082dSJean Delvare static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO,		\
699c801082dSJean Delvare 		show_temp, NULL, offset - 1);				\
70049dc9efeSIra Snyder static SENSOR_DEVICE_ATTR(temp##offset##_offset, S_IRUGO | S_IWUSR,	\
70149dc9efeSIra Snyder 		show_temp_offset, set_temp_offset, offset - 1);		\
702c801082dSJean Delvare static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR,	\
703c801082dSJean Delvare 		show_temp_min, set_temp_min, offset - 1);		\
704c801082dSJean Delvare static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR,	\
705c801082dSJean Delvare 		show_temp_max, set_temp_max, offset - 1);		\
706c801082dSJean Delvare static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IRUGO | S_IWUSR,	\
707c801082dSJean Delvare 		show_temp_crit, set_temp_crit, offset - 1)
7088d5d45fbSJean Delvare 
7098d5d45fbSJean Delvare temp_reg(1);
7108d5d45fbSJean Delvare temp_reg(2);
7118d5d45fbSJean Delvare temp_reg(3);
7128d5d45fbSJean Delvare 
7138d5d45fbSJean Delvare /* Alarms */
7148d5d45fbSJean Delvare static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
7158d5d45fbSJean Delvare {
7168d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
7178d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", data->alarm);
7188d5d45fbSJean Delvare }
7198d5d45fbSJean Delvare 
7208d5d45fbSJean Delvare static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
7218d5d45fbSJean Delvare 
722050ab878SJean Delvare static ssize_t show_alarm(struct device *dev,
723050ab878SJean Delvare 			  struct device_attribute *attr, char *buf)
724050ab878SJean Delvare {
725050ab878SJean Delvare 	int bitnr = to_sensor_dev_attr(attr)->index;
726050ab878SJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
727050ab878SJean Delvare 	return sprintf(buf, "%d\n", (data->alarm >> bitnr) & 1);
728050ab878SJean Delvare }
729050ab878SJean Delvare 
730050ab878SJean Delvare static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 0);
731050ab878SJean Delvare static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_alarm, NULL, 1);
732050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 2);
733050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 3);
734050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 4);
735050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 5);
736050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6);
737050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 7);
738050ab878SJean Delvare static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 8);
739050ab878SJean Delvare static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_alarm, NULL, 9);
740050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL, 10);
741050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp3_min_alarm, S_IRUGO, show_alarm, NULL, 11);
742050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 12);
743050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 13);
744050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 14);
7458d5d45fbSJean Delvare 
746a51b9944SGuenter Roeck /* Update Interval */
747a51b9944SGuenter Roeck static const unsigned int update_intervals[] = {
74887c33daaSJean Delvare 	16000, 8000, 4000, 2000, 1000, 500, 250, 125,
74987c33daaSJean Delvare };
75087c33daaSJean Delvare 
751a51b9944SGuenter Roeck static ssize_t show_update_interval(struct device *dev,
75287c33daaSJean Delvare 				    struct device_attribute *attr, char *buf)
75387c33daaSJean Delvare {
75487c33daaSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
75587c33daaSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
75687c33daaSJean Delvare 
757a51b9944SGuenter Roeck 	return sprintf(buf, "%u\n", data->update_interval);
75887c33daaSJean Delvare }
75987c33daaSJean Delvare 
760a51b9944SGuenter Roeck static ssize_t set_update_interval(struct device *dev,
76187c33daaSJean Delvare 				   struct device_attribute *attr,
76287c33daaSJean Delvare 				   const char *buf, size_t count)
76387c33daaSJean Delvare {
76487c33daaSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
76587c33daaSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
76687c33daaSJean Delvare 	unsigned long val;
76787c33daaSJean Delvare 	int i, err;
76887c33daaSJean Delvare 	u8 reg;
76987c33daaSJean Delvare 
770*179c4fdbSFrans Meulenbroeks 	err = kstrtoul(buf, 10, &val);
77187c33daaSJean Delvare 	if (err)
77287c33daaSJean Delvare 		return err;
77387c33daaSJean Delvare 
774a51b9944SGuenter Roeck 	/*
775a51b9944SGuenter Roeck 	 * Find the nearest update interval from the table.
776a51b9944SGuenter Roeck 	 * Use it to determine the matching update rate.
777a51b9944SGuenter Roeck 	 */
778a51b9944SGuenter Roeck 	for (i = 0; i < ARRAY_SIZE(update_intervals) - 1; i++) {
779a51b9944SGuenter Roeck 		if (val >= update_intervals[i])
78087c33daaSJean Delvare 			break;
78187c33daaSJean Delvare 	}
782a51b9944SGuenter Roeck 	/* if not found, we point to the last entry (lowest update interval) */
78387c33daaSJean Delvare 
78487c33daaSJean Delvare 	/* set the new update rate while preserving other settings */
78587c33daaSJean Delvare 	reg = adm1031_read_value(client, ADM1031_REG_FAN_FILTER);
78687c33daaSJean Delvare 	reg &= ~ADM1031_UPDATE_RATE_MASK;
78787c33daaSJean Delvare 	reg |= i << ADM1031_UPDATE_RATE_SHIFT;
78887c33daaSJean Delvare 	adm1031_write_value(client, ADM1031_REG_FAN_FILTER, reg);
78987c33daaSJean Delvare 
79087c33daaSJean Delvare 	mutex_lock(&data->update_lock);
791a51b9944SGuenter Roeck 	data->update_interval = update_intervals[i];
79287c33daaSJean Delvare 	mutex_unlock(&data->update_lock);
79387c33daaSJean Delvare 
79487c33daaSJean Delvare 	return count;
79587c33daaSJean Delvare }
79687c33daaSJean Delvare 
797a51b9944SGuenter Roeck static DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR, show_update_interval,
798a51b9944SGuenter Roeck 		   set_update_interval);
79987c33daaSJean Delvare 
800681c6f7aSMark M. Hoffman static struct attribute *adm1031_attributes[] = {
801c801082dSJean Delvare 	&sensor_dev_attr_fan1_input.dev_attr.attr,
802c801082dSJean Delvare 	&sensor_dev_attr_fan1_div.dev_attr.attr,
803c801082dSJean Delvare 	&sensor_dev_attr_fan1_min.dev_attr.attr,
804050ab878SJean Delvare 	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
805050ab878SJean Delvare 	&sensor_dev_attr_fan1_fault.dev_attr.attr,
806c801082dSJean Delvare 	&sensor_dev_attr_pwm1.dev_attr.attr,
807c801082dSJean Delvare 	&sensor_dev_attr_auto_fan1_channel.dev_attr.attr,
808c801082dSJean Delvare 	&sensor_dev_attr_temp1_input.dev_attr.attr,
80949dc9efeSIra Snyder 	&sensor_dev_attr_temp1_offset.dev_attr.attr,
810c801082dSJean Delvare 	&sensor_dev_attr_temp1_min.dev_attr.attr,
811050ab878SJean Delvare 	&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
812c801082dSJean Delvare 	&sensor_dev_attr_temp1_max.dev_attr.attr,
813050ab878SJean Delvare 	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
814c801082dSJean Delvare 	&sensor_dev_attr_temp1_crit.dev_attr.attr,
815050ab878SJean Delvare 	&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
816c801082dSJean Delvare 	&sensor_dev_attr_temp2_input.dev_attr.attr,
81749dc9efeSIra Snyder 	&sensor_dev_attr_temp2_offset.dev_attr.attr,
818c801082dSJean Delvare 	&sensor_dev_attr_temp2_min.dev_attr.attr,
819050ab878SJean Delvare 	&sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
820c801082dSJean Delvare 	&sensor_dev_attr_temp2_max.dev_attr.attr,
821050ab878SJean Delvare 	&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
822c801082dSJean Delvare 	&sensor_dev_attr_temp2_crit.dev_attr.attr,
823050ab878SJean Delvare 	&sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
824050ab878SJean Delvare 	&sensor_dev_attr_temp2_fault.dev_attr.attr,
825681c6f7aSMark M. Hoffman 
826c801082dSJean Delvare 	&sensor_dev_attr_auto_temp1_off.dev_attr.attr,
827c801082dSJean Delvare 	&sensor_dev_attr_auto_temp1_min.dev_attr.attr,
828c801082dSJean Delvare 	&sensor_dev_attr_auto_temp1_max.dev_attr.attr,
829681c6f7aSMark M. Hoffman 
830c801082dSJean Delvare 	&sensor_dev_attr_auto_temp2_off.dev_attr.attr,
831c801082dSJean Delvare 	&sensor_dev_attr_auto_temp2_min.dev_attr.attr,
832c801082dSJean Delvare 	&sensor_dev_attr_auto_temp2_max.dev_attr.attr,
833681c6f7aSMark M. Hoffman 
834c801082dSJean Delvare 	&sensor_dev_attr_auto_fan1_min_pwm.dev_attr.attr,
835681c6f7aSMark M. Hoffman 
836a51b9944SGuenter Roeck 	&dev_attr_update_interval.attr,
837681c6f7aSMark M. Hoffman 	&dev_attr_alarms.attr,
838681c6f7aSMark M. Hoffman 
839681c6f7aSMark M. Hoffman 	NULL
840681c6f7aSMark M. Hoffman };
841681c6f7aSMark M. Hoffman 
842681c6f7aSMark M. Hoffman static const struct attribute_group adm1031_group = {
843681c6f7aSMark M. Hoffman 	.attrs = adm1031_attributes,
844681c6f7aSMark M. Hoffman };
845681c6f7aSMark M. Hoffman 
846681c6f7aSMark M. Hoffman static struct attribute *adm1031_attributes_opt[] = {
847c801082dSJean Delvare 	&sensor_dev_attr_fan2_input.dev_attr.attr,
848c801082dSJean Delvare 	&sensor_dev_attr_fan2_div.dev_attr.attr,
849c801082dSJean Delvare 	&sensor_dev_attr_fan2_min.dev_attr.attr,
850050ab878SJean Delvare 	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
851050ab878SJean Delvare 	&sensor_dev_attr_fan2_fault.dev_attr.attr,
852c801082dSJean Delvare 	&sensor_dev_attr_pwm2.dev_attr.attr,
853c801082dSJean Delvare 	&sensor_dev_attr_auto_fan2_channel.dev_attr.attr,
854c801082dSJean Delvare 	&sensor_dev_attr_temp3_input.dev_attr.attr,
85549dc9efeSIra Snyder 	&sensor_dev_attr_temp3_offset.dev_attr.attr,
856c801082dSJean Delvare 	&sensor_dev_attr_temp3_min.dev_attr.attr,
857050ab878SJean Delvare 	&sensor_dev_attr_temp3_min_alarm.dev_attr.attr,
858c801082dSJean Delvare 	&sensor_dev_attr_temp3_max.dev_attr.attr,
859050ab878SJean Delvare 	&sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
860c801082dSJean Delvare 	&sensor_dev_attr_temp3_crit.dev_attr.attr,
861050ab878SJean Delvare 	&sensor_dev_attr_temp3_crit_alarm.dev_attr.attr,
862050ab878SJean Delvare 	&sensor_dev_attr_temp3_fault.dev_attr.attr,
863c801082dSJean Delvare 	&sensor_dev_attr_auto_temp3_off.dev_attr.attr,
864c801082dSJean Delvare 	&sensor_dev_attr_auto_temp3_min.dev_attr.attr,
865c801082dSJean Delvare 	&sensor_dev_attr_auto_temp3_max.dev_attr.attr,
866c801082dSJean Delvare 	&sensor_dev_attr_auto_fan2_min_pwm.dev_attr.attr,
867681c6f7aSMark M. Hoffman 	NULL
868681c6f7aSMark M. Hoffman };
869681c6f7aSMark M. Hoffman 
870681c6f7aSMark M. Hoffman static const struct attribute_group adm1031_group_opt = {
871681c6f7aSMark M. Hoffman 	.attrs = adm1031_attributes_opt,
872681c6f7aSMark M. Hoffman };
873681c6f7aSMark M. Hoffman 
874af200f88SJean Delvare /* Return 0 if detection is successful, -ENODEV otherwise */
875310ec792SJean Delvare static int adm1031_detect(struct i2c_client *client,
876af200f88SJean Delvare 			  struct i2c_board_info *info)
8778d5d45fbSJean Delvare {
878af200f88SJean Delvare 	struct i2c_adapter *adapter = client->adapter;
87952df6440SJean Delvare 	const char *name;
88052df6440SJean Delvare 	int id, co;
8818d5d45fbSJean Delvare 
8828d5d45fbSJean Delvare 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
883af200f88SJean Delvare 		return -ENODEV;
8848d5d45fbSJean Delvare 
8856d6006b8SJean Delvare 	id = i2c_smbus_read_byte_data(client, 0x3d);
8866d6006b8SJean Delvare 	co = i2c_smbus_read_byte_data(client, 0x3e);
8878d5d45fbSJean Delvare 
8888d5d45fbSJean Delvare 	if (!((id == 0x31 || id == 0x30) && co == 0x41))
889af200f88SJean Delvare 		return -ENODEV;
89052df6440SJean Delvare 	name = (id == 0x30) ? "adm1030" : "adm1031";
8918d5d45fbSJean Delvare 
892af200f88SJean Delvare 	strlcpy(info->type, name, I2C_NAME_SIZE);
8938d5d45fbSJean Delvare 
894af200f88SJean Delvare 	return 0;
895af200f88SJean Delvare }
896af200f88SJean Delvare 
897af200f88SJean Delvare static int adm1031_probe(struct i2c_client *client,
898af200f88SJean Delvare 			 const struct i2c_device_id *id)
899af200f88SJean Delvare {
900af200f88SJean Delvare 	struct adm1031_data *data;
901af200f88SJean Delvare 	int err;
902af200f88SJean Delvare 
903af200f88SJean Delvare 	data = kzalloc(sizeof(struct adm1031_data), GFP_KERNEL);
904af200f88SJean Delvare 	if (!data) {
905af200f88SJean Delvare 		err = -ENOMEM;
906af200f88SJean Delvare 		goto exit;
907af200f88SJean Delvare 	}
908af200f88SJean Delvare 
909af200f88SJean Delvare 	i2c_set_clientdata(client, data);
910af200f88SJean Delvare 	data->chip_type = id->driver_data;
9119a61bf63SIngo Molnar 	mutex_init(&data->update_lock);
9128d5d45fbSJean Delvare 
913af200f88SJean Delvare 	if (data->chip_type == adm1030)
914af200f88SJean Delvare 		data->chan_select_table = &auto_channel_select_table_adm1030;
915af200f88SJean Delvare 	else
916af200f88SJean Delvare 		data->chan_select_table = &auto_channel_select_table_adm1031;
9178d5d45fbSJean Delvare 
9188d5d45fbSJean Delvare 	/* Initialize the ADM1031 chip */
9196d6006b8SJean Delvare 	adm1031_init_client(client);
9208d5d45fbSJean Delvare 
9218d5d45fbSJean Delvare 	/* Register sysfs hooks */
9226d6006b8SJean Delvare 	if ((err = sysfs_create_group(&client->dev.kobj, &adm1031_group)))
923af200f88SJean Delvare 		goto exit_free;
924681c6f7aSMark M. Hoffman 
925af200f88SJean Delvare 	if (data->chip_type == adm1031) {
9266d6006b8SJean Delvare 		if ((err = sysfs_create_group(&client->dev.kobj,
927681c6f7aSMark M. Hoffman 						&adm1031_group_opt)))
928681c6f7aSMark M. Hoffman 			goto exit_remove;
929681c6f7aSMark M. Hoffman 	}
930681c6f7aSMark M. Hoffman 
9316d6006b8SJean Delvare 	data->hwmon_dev = hwmon_device_register(&client->dev);
9321beeffe4STony Jones 	if (IS_ERR(data->hwmon_dev)) {
9331beeffe4STony Jones 		err = PTR_ERR(data->hwmon_dev);
934681c6f7aSMark M. Hoffman 		goto exit_remove;
9358d5d45fbSJean Delvare 	}
9368d5d45fbSJean Delvare 
9378d5d45fbSJean Delvare 	return 0;
9388d5d45fbSJean Delvare 
939681c6f7aSMark M. Hoffman exit_remove:
9406d6006b8SJean Delvare 	sysfs_remove_group(&client->dev.kobj, &adm1031_group);
9416d6006b8SJean Delvare 	sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt);
9428d5d45fbSJean Delvare exit_free:
9431f57ff89SAlexey Dobriyan 	kfree(data);
9448d5d45fbSJean Delvare exit:
9458d5d45fbSJean Delvare 	return err;
9468d5d45fbSJean Delvare }
9478d5d45fbSJean Delvare 
948af200f88SJean Delvare static int adm1031_remove(struct i2c_client *client)
9498d5d45fbSJean Delvare {
950943b0830SMark M. Hoffman 	struct adm1031_data *data = i2c_get_clientdata(client);
951943b0830SMark M. Hoffman 
9521beeffe4STony Jones 	hwmon_device_unregister(data->hwmon_dev);
953681c6f7aSMark M. Hoffman 	sysfs_remove_group(&client->dev.kobj, &adm1031_group);
954681c6f7aSMark M. Hoffman 	sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt);
955943b0830SMark M. Hoffman 	kfree(data);
9568d5d45fbSJean Delvare 	return 0;
9578d5d45fbSJean Delvare }
9588d5d45fbSJean Delvare 
9598d5d45fbSJean Delvare static void adm1031_init_client(struct i2c_client *client)
9608d5d45fbSJean Delvare {
9618d5d45fbSJean Delvare 	unsigned int read_val;
9628d5d45fbSJean Delvare 	unsigned int mask;
96387c33daaSJean Delvare 	int i;
9648d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
9658d5d45fbSJean Delvare 
9668d5d45fbSJean Delvare 	mask = (ADM1031_CONF2_PWM1_ENABLE | ADM1031_CONF2_TACH1_ENABLE);
9678d5d45fbSJean Delvare 	if (data->chip_type == adm1031) {
9688d5d45fbSJean Delvare 		mask |= (ADM1031_CONF2_PWM2_ENABLE |
9698d5d45fbSJean Delvare 			ADM1031_CONF2_TACH2_ENABLE);
9708d5d45fbSJean Delvare 	}
9718d5d45fbSJean Delvare 	/* Initialize the ADM1031 chip (enables fan speed reading ) */
9728d5d45fbSJean Delvare 	read_val = adm1031_read_value(client, ADM1031_REG_CONF2);
9738d5d45fbSJean Delvare 	if ((read_val | mask) != read_val) {
9748d5d45fbSJean Delvare 	    adm1031_write_value(client, ADM1031_REG_CONF2, read_val | mask);
9758d5d45fbSJean Delvare 	}
9768d5d45fbSJean Delvare 
9778d5d45fbSJean Delvare 	read_val = adm1031_read_value(client, ADM1031_REG_CONF1);
9788d5d45fbSJean Delvare 	if ((read_val | ADM1031_CONF1_MONITOR_ENABLE) != read_val) {
9798d5d45fbSJean Delvare 	    adm1031_write_value(client, ADM1031_REG_CONF1, read_val |
9808d5d45fbSJean Delvare 				ADM1031_CONF1_MONITOR_ENABLE);
9818d5d45fbSJean Delvare 	}
9828d5d45fbSJean Delvare 
98387c33daaSJean Delvare 	/* Read the chip's update rate */
98487c33daaSJean Delvare 	mask = ADM1031_UPDATE_RATE_MASK;
98587c33daaSJean Delvare 	read_val = adm1031_read_value(client, ADM1031_REG_FAN_FILTER);
98687c33daaSJean Delvare 	i = (read_val & mask) >> ADM1031_UPDATE_RATE_SHIFT;
987a51b9944SGuenter Roeck 	/* Save it as update interval */
988a51b9944SGuenter Roeck 	data->update_interval = update_intervals[i];
9898d5d45fbSJean Delvare }
9908d5d45fbSJean Delvare 
9918d5d45fbSJean Delvare static struct adm1031_data *adm1031_update_device(struct device *dev)
9928d5d45fbSJean Delvare {
9938d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
9948d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
99587c33daaSJean Delvare 	unsigned long next_update;
9968d5d45fbSJean Delvare 	int chan;
9978d5d45fbSJean Delvare 
9989a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
9998d5d45fbSJean Delvare 
1000a51b9944SGuenter Roeck 	next_update = data->last_updated
1001a51b9944SGuenter Roeck 	  + msecs_to_jiffies(data->update_interval);
100287c33daaSJean Delvare 	if (time_after(jiffies, next_update) || !data->valid) {
10038d5d45fbSJean Delvare 
10048d5d45fbSJean Delvare 		dev_dbg(&client->dev, "Starting adm1031 update\n");
10058d5d45fbSJean Delvare 		for (chan = 0;
10068d5d45fbSJean Delvare 		     chan < ((data->chip_type == adm1031) ? 3 : 2); chan++) {
10078d5d45fbSJean Delvare 			u8 oldh, newh;
10088d5d45fbSJean Delvare 
10098d5d45fbSJean Delvare 			oldh =
10108d5d45fbSJean Delvare 			    adm1031_read_value(client, ADM1031_REG_TEMP(chan));
10118d5d45fbSJean Delvare 			data->ext_temp[chan] =
10128d5d45fbSJean Delvare 			    adm1031_read_value(client, ADM1031_REG_EXT_TEMP);
10138d5d45fbSJean Delvare 			newh =
10148d5d45fbSJean Delvare 			    adm1031_read_value(client, ADM1031_REG_TEMP(chan));
10158d5d45fbSJean Delvare 			if (newh != oldh) {
10168d5d45fbSJean Delvare 				data->ext_temp[chan] =
10178d5d45fbSJean Delvare 				    adm1031_read_value(client,
10188d5d45fbSJean Delvare 						       ADM1031_REG_EXT_TEMP);
10198d5d45fbSJean Delvare #ifdef DEBUG
10208d5d45fbSJean Delvare 				oldh =
10218d5d45fbSJean Delvare 				    adm1031_read_value(client,
10228d5d45fbSJean Delvare 						       ADM1031_REG_TEMP(chan));
10238d5d45fbSJean Delvare 
10248d5d45fbSJean Delvare 				/* oldh is actually newer */
10258d5d45fbSJean Delvare 				if (newh != oldh)
10268d5d45fbSJean Delvare 					dev_warn(&client->dev,
10278d5d45fbSJean Delvare 						 "Remote temperature may be "
10288d5d45fbSJean Delvare 						 "wrong.\n");
10298d5d45fbSJean Delvare #endif
10308d5d45fbSJean Delvare 			}
10318d5d45fbSJean Delvare 			data->temp[chan] = newh;
10328d5d45fbSJean Delvare 
103349dc9efeSIra Snyder 			data->temp_offset[chan] =
103449dc9efeSIra Snyder 			    adm1031_read_value(client,
103549dc9efeSIra Snyder 					       ADM1031_REG_TEMP_OFFSET(chan));
10368d5d45fbSJean Delvare 			data->temp_min[chan] =
10378d5d45fbSJean Delvare 			    adm1031_read_value(client,
10388d5d45fbSJean Delvare 					       ADM1031_REG_TEMP_MIN(chan));
10398d5d45fbSJean Delvare 			data->temp_max[chan] =
10408d5d45fbSJean Delvare 			    adm1031_read_value(client,
10418d5d45fbSJean Delvare 					       ADM1031_REG_TEMP_MAX(chan));
10428d5d45fbSJean Delvare 			data->temp_crit[chan] =
10438d5d45fbSJean Delvare 			    adm1031_read_value(client,
10448d5d45fbSJean Delvare 					       ADM1031_REG_TEMP_CRIT(chan));
10458d5d45fbSJean Delvare 			data->auto_temp[chan] =
10468d5d45fbSJean Delvare 			    adm1031_read_value(client,
10478d5d45fbSJean Delvare 					       ADM1031_REG_AUTO_TEMP(chan));
10488d5d45fbSJean Delvare 
10498d5d45fbSJean Delvare 		}
10508d5d45fbSJean Delvare 
10518d5d45fbSJean Delvare 		data->conf1 = adm1031_read_value(client, ADM1031_REG_CONF1);
10528d5d45fbSJean Delvare 		data->conf2 = adm1031_read_value(client, ADM1031_REG_CONF2);
10538d5d45fbSJean Delvare 
10548d5d45fbSJean Delvare 		data->alarm = adm1031_read_value(client, ADM1031_REG_STATUS(0))
10558d5d45fbSJean Delvare 			     | (adm1031_read_value(client, ADM1031_REG_STATUS(1))
10568d5d45fbSJean Delvare 				<< 8);
10578d5d45fbSJean Delvare 		if (data->chip_type == adm1030) {
10588d5d45fbSJean Delvare 			data->alarm &= 0xc0ff;
10598d5d45fbSJean Delvare 		}
10608d5d45fbSJean Delvare 
10618d5d45fbSJean Delvare 		for (chan=0; chan<(data->chip_type == adm1030 ? 1 : 2); chan++) {
10628d5d45fbSJean Delvare 			data->fan_div[chan] =
10638d5d45fbSJean Delvare 			    adm1031_read_value(client, ADM1031_REG_FAN_DIV(chan));
10648d5d45fbSJean Delvare 			data->fan_min[chan] =
10658d5d45fbSJean Delvare 			    adm1031_read_value(client, ADM1031_REG_FAN_MIN(chan));
10668d5d45fbSJean Delvare 			data->fan[chan] =
10678d5d45fbSJean Delvare 			    adm1031_read_value(client, ADM1031_REG_FAN_SPEED(chan));
10688d5d45fbSJean Delvare 			data->pwm[chan] =
10698d5d45fbSJean Delvare 			    0xf & (adm1031_read_value(client, ADM1031_REG_PWM) >>
10708d5d45fbSJean Delvare 				   (4*chan));
10718d5d45fbSJean Delvare 		}
10728d5d45fbSJean Delvare 		data->last_updated = jiffies;
10738d5d45fbSJean Delvare 		data->valid = 1;
10748d5d45fbSJean Delvare 	}
10758d5d45fbSJean Delvare 
10769a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
10778d5d45fbSJean Delvare 
10788d5d45fbSJean Delvare 	return data;
10798d5d45fbSJean Delvare }
10808d5d45fbSJean Delvare 
10818d5d45fbSJean Delvare static int __init sensors_adm1031_init(void)
10828d5d45fbSJean Delvare {
10838d5d45fbSJean Delvare 	return i2c_add_driver(&adm1031_driver);
10848d5d45fbSJean Delvare }
10858d5d45fbSJean Delvare 
10868d5d45fbSJean Delvare static void __exit sensors_adm1031_exit(void)
10878d5d45fbSJean Delvare {
10888d5d45fbSJean Delvare 	i2c_del_driver(&adm1031_driver);
10898d5d45fbSJean Delvare }
10908d5d45fbSJean Delvare 
10918d5d45fbSJean Delvare MODULE_AUTHOR("Alexandre d'Alton <alex@alexdalton.org>");
10928d5d45fbSJean Delvare MODULE_DESCRIPTION("ADM1031/ADM1030 driver");
10938d5d45fbSJean Delvare MODULE_LICENSE("GPL");
10948d5d45fbSJean Delvare 
10958d5d45fbSJean Delvare module_init(sensors_adm1031_init);
10968d5d45fbSJean Delvare module_exit(sensors_adm1031_exit);
1097