xref: /openbmc/linux/drivers/hwmon/adm1031.c (revision af200f881d2cbf3ba2f4c505fa1ae5cfef36f46a)
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 
408d5d45fbSJean Delvare #define ADM1031_REG_TEMP_MAX(nr)	(0x14 + 4 * (nr))
418d5d45fbSJean Delvare #define ADM1031_REG_TEMP_MIN(nr)	(0x15 + 4 * (nr))
428d5d45fbSJean Delvare #define ADM1031_REG_TEMP_CRIT(nr)	(0x16 + 4 * (nr))
438d5d45fbSJean Delvare 
446d6006b8SJean Delvare #define ADM1031_REG_TEMP(nr)		(0x0a + (nr))
458d5d45fbSJean Delvare #define ADM1031_REG_AUTO_TEMP(nr)	(0x24 + (nr))
468d5d45fbSJean Delvare 
478d5d45fbSJean Delvare #define ADM1031_REG_STATUS(nr)		(0x2 + (nr))
488d5d45fbSJean Delvare 
496d6006b8SJean Delvare #define ADM1031_REG_CONF1		0x00
506d6006b8SJean Delvare #define ADM1031_REG_CONF2		0x01
516d6006b8SJean Delvare #define ADM1031_REG_EXT_TEMP		0x06
528d5d45fbSJean Delvare 
538d5d45fbSJean Delvare #define ADM1031_CONF1_MONITOR_ENABLE	0x01	/* Monitoring enable */
548d5d45fbSJean Delvare #define ADM1031_CONF1_PWM_INVERT	0x08	/* PWM Invert */
558d5d45fbSJean Delvare #define ADM1031_CONF1_AUTO_MODE		0x80	/* Auto FAN */
568d5d45fbSJean Delvare 
578d5d45fbSJean Delvare #define ADM1031_CONF2_PWM1_ENABLE	0x01
588d5d45fbSJean Delvare #define ADM1031_CONF2_PWM2_ENABLE	0x02
598d5d45fbSJean Delvare #define ADM1031_CONF2_TACH1_ENABLE	0x04
608d5d45fbSJean Delvare #define ADM1031_CONF2_TACH2_ENABLE	0x08
618d5d45fbSJean Delvare #define ADM1031_CONF2_TEMP_ENABLE(chan)	(0x10 << (chan))
628d5d45fbSJean Delvare 
638d5d45fbSJean Delvare /* Addresses to scan */
6425e9c86dSMark M. Hoffman static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
658d5d45fbSJean Delvare 
668d5d45fbSJean Delvare /* Insmod parameters */
67f4b50261SJean Delvare I2C_CLIENT_INSMOD_2(adm1030, adm1031);
688d5d45fbSJean Delvare 
698d5d45fbSJean Delvare typedef u8 auto_chan_table_t[8][2];
708d5d45fbSJean Delvare 
718d5d45fbSJean Delvare /* Each client has this additional data */
728d5d45fbSJean Delvare struct adm1031_data {
731beeffe4STony Jones 	struct device *hwmon_dev;
749a61bf63SIngo Molnar 	struct mutex update_lock;
758d5d45fbSJean Delvare 	int chip_type;
768d5d45fbSJean Delvare 	char valid;		/* !=0 if following fields are valid */
778d5d45fbSJean Delvare 	unsigned long last_updated;	/* In jiffies */
788d5d45fbSJean Delvare 	/* The chan_select_table contains the possible configurations for
798d5d45fbSJean Delvare 	 * auto fan control.
808d5d45fbSJean Delvare 	 */
816d6006b8SJean Delvare 	const auto_chan_table_t *chan_select_table;
828d5d45fbSJean Delvare 	u16 alarm;
838d5d45fbSJean Delvare 	u8 conf1;
848d5d45fbSJean Delvare 	u8 conf2;
858d5d45fbSJean Delvare 	u8 fan[2];
868d5d45fbSJean Delvare 	u8 fan_div[2];
878d5d45fbSJean Delvare 	u8 fan_min[2];
888d5d45fbSJean Delvare 	u8 pwm[2];
898d5d45fbSJean Delvare 	u8 old_pwm[2];
908d5d45fbSJean Delvare 	s8 temp[3];
918d5d45fbSJean Delvare 	u8 ext_temp[3];
928d5d45fbSJean Delvare 	u8 auto_temp[3];
938d5d45fbSJean Delvare 	u8 auto_temp_min[3];
948d5d45fbSJean Delvare 	u8 auto_temp_off[3];
958d5d45fbSJean Delvare 	u8 auto_temp_max[3];
968d5d45fbSJean Delvare 	s8 temp_min[3];
978d5d45fbSJean Delvare 	s8 temp_max[3];
988d5d45fbSJean Delvare 	s8 temp_crit[3];
998d5d45fbSJean Delvare };
1008d5d45fbSJean Delvare 
101*af200f88SJean Delvare static int adm1031_probe(struct i2c_client *client,
102*af200f88SJean Delvare 			 const struct i2c_device_id *id);
103*af200f88SJean Delvare static int adm1031_detect(struct i2c_client *client, int kind,
104*af200f88SJean Delvare 			  struct i2c_board_info *info);
1058d5d45fbSJean Delvare static void adm1031_init_client(struct i2c_client *client);
106*af200f88SJean Delvare static int adm1031_remove(struct i2c_client *client);
1078d5d45fbSJean Delvare static struct adm1031_data *adm1031_update_device(struct device *dev);
1088d5d45fbSJean Delvare 
109*af200f88SJean Delvare static const struct i2c_device_id adm1031_id[] = {
110*af200f88SJean Delvare 	{ "adm1030", adm1030 },
111*af200f88SJean Delvare 	{ "adm1031", adm1031 },
112*af200f88SJean Delvare 	{ }
113*af200f88SJean Delvare };
114*af200f88SJean Delvare MODULE_DEVICE_TABLE(i2c, adm1031_id);
115*af200f88SJean Delvare 
1168d5d45fbSJean Delvare /* This is the driver that will be inserted */
1178d5d45fbSJean Delvare static struct i2c_driver adm1031_driver = {
118*af200f88SJean Delvare 	.class		= I2C_CLASS_HWMON,
119cdaf7934SLaurent Riffard 	.driver = {
1208d5d45fbSJean Delvare 		.name = "adm1031",
121cdaf7934SLaurent Riffard 	},
122*af200f88SJean Delvare 	.probe		= adm1031_probe,
123*af200f88SJean Delvare 	.remove		= adm1031_remove,
124*af200f88SJean Delvare 	.id_table	= adm1031_id,
125*af200f88SJean Delvare 	.detect		= adm1031_detect,
126*af200f88SJean Delvare 	.address_data	= &addr_data,
1278d5d45fbSJean Delvare };
1288d5d45fbSJean Delvare 
1298d5d45fbSJean Delvare static inline u8 adm1031_read_value(struct i2c_client *client, u8 reg)
1308d5d45fbSJean Delvare {
1318d5d45fbSJean Delvare 	return i2c_smbus_read_byte_data(client, reg);
1328d5d45fbSJean Delvare }
1338d5d45fbSJean Delvare 
1348d5d45fbSJean Delvare static inline int
1358d5d45fbSJean Delvare adm1031_write_value(struct i2c_client *client, u8 reg, unsigned int value)
1368d5d45fbSJean Delvare {
1378d5d45fbSJean Delvare 	return i2c_smbus_write_byte_data(client, reg, value);
1388d5d45fbSJean Delvare }
1398d5d45fbSJean Delvare 
1408d5d45fbSJean Delvare 
1418d5d45fbSJean Delvare #define TEMP_TO_REG(val)		(((val) < 0 ? ((val - 500) / 1000) : \
1428d5d45fbSJean Delvare 					((val + 500) / 1000)))
1438d5d45fbSJean Delvare 
1448d5d45fbSJean Delvare #define TEMP_FROM_REG(val)		((val) * 1000)
1458d5d45fbSJean Delvare 
1468d5d45fbSJean Delvare #define TEMP_FROM_REG_EXT(val, ext)	(TEMP_FROM_REG(val) + (ext) * 125)
1478d5d45fbSJean Delvare 
1488d5d45fbSJean Delvare #define FAN_FROM_REG(reg, div)		((reg) ? (11250 * 60) / ((reg) * (div)) : 0)
1498d5d45fbSJean Delvare 
1508d5d45fbSJean Delvare static int FAN_TO_REG(int reg, int div)
1518d5d45fbSJean Delvare {
1528d5d45fbSJean Delvare 	int tmp;
1538d5d45fbSJean Delvare 	tmp = FAN_FROM_REG(SENSORS_LIMIT(reg, 0, 65535), div);
1548d5d45fbSJean Delvare 	return tmp > 255 ? 255 : tmp;
1558d5d45fbSJean Delvare }
1568d5d45fbSJean Delvare 
1578d5d45fbSJean Delvare #define FAN_DIV_FROM_REG(reg)		(1<<(((reg)&0xc0)>>6))
1588d5d45fbSJean Delvare 
1598d5d45fbSJean Delvare #define PWM_TO_REG(val)			(SENSORS_LIMIT((val), 0, 255) >> 4)
1608d5d45fbSJean Delvare #define PWM_FROM_REG(val)		((val) << 4)
1618d5d45fbSJean Delvare 
1628d5d45fbSJean Delvare #define FAN_CHAN_FROM_REG(reg)		(((reg) >> 5) & 7)
1638d5d45fbSJean Delvare #define FAN_CHAN_TO_REG(val, reg)	\
1648d5d45fbSJean Delvare 	(((reg) & 0x1F) | (((val) << 5) & 0xe0))
1658d5d45fbSJean Delvare 
1668d5d45fbSJean Delvare #define AUTO_TEMP_MIN_TO_REG(val, reg)	\
1678d5d45fbSJean Delvare 	((((val)/500) & 0xf8)|((reg) & 0x7))
1688d5d45fbSJean Delvare #define AUTO_TEMP_RANGE_FROM_REG(reg)	(5000 * (1<< ((reg)&0x7)))
1698d5d45fbSJean Delvare #define AUTO_TEMP_MIN_FROM_REG(reg)	(1000 * ((((reg) >> 3) & 0x1f) << 2))
1708d5d45fbSJean Delvare 
1718d5d45fbSJean Delvare #define AUTO_TEMP_MIN_FROM_REG_DEG(reg)	((((reg) >> 3) & 0x1f) << 2)
1728d5d45fbSJean Delvare 
1738d5d45fbSJean Delvare #define AUTO_TEMP_OFF_FROM_REG(reg)		\
1748d5d45fbSJean Delvare 	(AUTO_TEMP_MIN_FROM_REG(reg) - 5000)
1758d5d45fbSJean Delvare 
1768d5d45fbSJean Delvare #define AUTO_TEMP_MAX_FROM_REG(reg)		\
1778d5d45fbSJean Delvare 	(AUTO_TEMP_RANGE_FROM_REG(reg) +	\
1788d5d45fbSJean Delvare 	AUTO_TEMP_MIN_FROM_REG(reg))
1798d5d45fbSJean Delvare 
1808d5d45fbSJean Delvare static int AUTO_TEMP_MAX_TO_REG(int val, int reg, int pwm)
1818d5d45fbSJean Delvare {
1828d5d45fbSJean Delvare 	int ret;
1838d5d45fbSJean Delvare 	int range = val - AUTO_TEMP_MIN_FROM_REG(reg);
1848d5d45fbSJean Delvare 
1858d5d45fbSJean Delvare 	range = ((val - AUTO_TEMP_MIN_FROM_REG(reg))*10)/(16 - pwm);
1868d5d45fbSJean Delvare 	ret = ((reg & 0xf8) |
1878d5d45fbSJean Delvare 	       (range < 10000 ? 0 :
1888d5d45fbSJean Delvare 		range < 20000 ? 1 :
1898d5d45fbSJean Delvare 		range < 40000 ? 2 : range < 80000 ? 3 : 4));
1908d5d45fbSJean Delvare 	return ret;
1918d5d45fbSJean Delvare }
1928d5d45fbSJean Delvare 
1938d5d45fbSJean Delvare /* FAN auto control */
1948d5d45fbSJean Delvare #define GET_FAN_AUTO_BITFIELD(data, idx)	\
1958d5d45fbSJean Delvare 	(*(data)->chan_select_table)[FAN_CHAN_FROM_REG((data)->conf1)][idx%2]
1968d5d45fbSJean Delvare 
1978d5d45fbSJean Delvare /* The tables below contains the possible values for the auto fan
1988d5d45fbSJean Delvare  * control bitfields. the index in the table is the register value.
1998d5d45fbSJean Delvare  * MSb is the auto fan control enable bit, so the four first entries
2008d5d45fbSJean Delvare  * in the table disables auto fan control when both bitfields are zero.
2018d5d45fbSJean Delvare  */
2026d6006b8SJean Delvare static const auto_chan_table_t auto_channel_select_table_adm1031 = {
2038d5d45fbSJean Delvare 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2048d5d45fbSJean Delvare 	{ 2 /* 0b010 */ , 4 /* 0b100 */ },
2058d5d45fbSJean Delvare 	{ 2 /* 0b010 */ , 2 /* 0b010 */ },
2068d5d45fbSJean Delvare 	{ 4 /* 0b100 */ , 4 /* 0b100 */ },
2078d5d45fbSJean Delvare 	{ 7 /* 0b111 */ , 7 /* 0b111 */ },
2088d5d45fbSJean Delvare };
2098d5d45fbSJean Delvare 
2106d6006b8SJean Delvare static const auto_chan_table_t auto_channel_select_table_adm1030 = {
2118d5d45fbSJean Delvare 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2128d5d45fbSJean Delvare 	{ 2 /* 0b10 */		, 0 },
2138d5d45fbSJean Delvare 	{ 0xff /* invalid */	, 0 },
2148d5d45fbSJean Delvare 	{ 0xff /* invalid */	, 0 },
2158d5d45fbSJean Delvare 	{ 3 /* 0b11 */		, 0 },
2168d5d45fbSJean Delvare };
2178d5d45fbSJean Delvare 
2188d5d45fbSJean Delvare /* That function checks if a bitfield is valid and returns the other bitfield
2198d5d45fbSJean Delvare  * nearest match if no exact match where found.
2208d5d45fbSJean Delvare  */
2218d5d45fbSJean Delvare static int
2228d5d45fbSJean Delvare get_fan_auto_nearest(struct adm1031_data *data,
2238d5d45fbSJean Delvare 		     int chan, u8 val, u8 reg, u8 * new_reg)
2248d5d45fbSJean Delvare {
2258d5d45fbSJean Delvare 	int i;
2268d5d45fbSJean Delvare 	int first_match = -1, exact_match = -1;
2278d5d45fbSJean Delvare 	u8 other_reg_val =
2288d5d45fbSJean Delvare 	    (*data->chan_select_table)[FAN_CHAN_FROM_REG(reg)][chan ? 0 : 1];
2298d5d45fbSJean Delvare 
2308d5d45fbSJean Delvare 	if (val == 0) {
2318d5d45fbSJean Delvare 		*new_reg = 0;
2328d5d45fbSJean Delvare 		return 0;
2338d5d45fbSJean Delvare 	}
2348d5d45fbSJean Delvare 
2358d5d45fbSJean Delvare 	for (i = 0; i < 8; i++) {
2368d5d45fbSJean Delvare 		if ((val == (*data->chan_select_table)[i][chan]) &&
2378d5d45fbSJean Delvare 		    ((*data->chan_select_table)[i][chan ? 0 : 1] ==
2388d5d45fbSJean Delvare 		     other_reg_val)) {
2398d5d45fbSJean Delvare 			/* We found an exact match */
2408d5d45fbSJean Delvare 			exact_match = i;
2418d5d45fbSJean Delvare 			break;
2428d5d45fbSJean Delvare 		} else if (val == (*data->chan_select_table)[i][chan] &&
2438d5d45fbSJean Delvare 			   first_match == -1) {
2446d6006b8SJean Delvare 			/* Save the first match in case of an exact match has
2456d6006b8SJean Delvare 			 * not been found
2468d5d45fbSJean Delvare 			 */
2478d5d45fbSJean Delvare 			first_match = i;
2488d5d45fbSJean Delvare 		}
2498d5d45fbSJean Delvare 	}
2508d5d45fbSJean Delvare 
2518d5d45fbSJean Delvare 	if (exact_match >= 0) {
2528d5d45fbSJean Delvare 		*new_reg = exact_match;
2538d5d45fbSJean Delvare 	} else if (first_match >= 0) {
2548d5d45fbSJean Delvare 		*new_reg = first_match;
2558d5d45fbSJean Delvare 	} else {
2568d5d45fbSJean Delvare 		return -EINVAL;
2578d5d45fbSJean Delvare 	}
2588d5d45fbSJean Delvare 	return 0;
2598d5d45fbSJean Delvare }
2608d5d45fbSJean Delvare 
261c801082dSJean Delvare static ssize_t show_fan_auto_channel(struct device *dev,
262c801082dSJean Delvare 				     struct device_attribute *attr, char *buf)
2638d5d45fbSJean Delvare {
264c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
2658d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
2668d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", GET_FAN_AUTO_BITFIELD(data, nr));
2678d5d45fbSJean Delvare }
2688d5d45fbSJean Delvare 
2698d5d45fbSJean Delvare static ssize_t
270c801082dSJean Delvare set_fan_auto_channel(struct device *dev, struct device_attribute *attr,
271c801082dSJean Delvare 		     const char *buf, size_t count)
2728d5d45fbSJean Delvare {
2738d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
2748d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
275c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
2768d5d45fbSJean Delvare 	int val = simple_strtol(buf, NULL, 10);
2778d5d45fbSJean Delvare 	u8 reg;
2788d5d45fbSJean Delvare 	int ret;
2798d5d45fbSJean Delvare 	u8 old_fan_mode;
2808d5d45fbSJean Delvare 
2818d5d45fbSJean Delvare 	old_fan_mode = data->conf1;
2828d5d45fbSJean Delvare 
2839a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
2848d5d45fbSJean Delvare 
2858d5d45fbSJean Delvare 	if ((ret = get_fan_auto_nearest(data, nr, val, data->conf1, &reg))) {
2869a61bf63SIngo Molnar 		mutex_unlock(&data->update_lock);
2878d5d45fbSJean Delvare 		return ret;
2888d5d45fbSJean Delvare 	}
2896d6006b8SJean Delvare 	data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1);
2906d6006b8SJean Delvare 	if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) ^
2918d5d45fbSJean Delvare 	    (old_fan_mode & ADM1031_CONF1_AUTO_MODE)) {
2928d5d45fbSJean Delvare 		if (data->conf1 & ADM1031_CONF1_AUTO_MODE){
2938d5d45fbSJean Delvare 			/* Switch to Auto Fan Mode
2948d5d45fbSJean Delvare 			 * Save PWM registers
2958d5d45fbSJean Delvare 			 * Set PWM registers to 33% Both */
2968d5d45fbSJean Delvare 			data->old_pwm[0] = data->pwm[0];
2978d5d45fbSJean Delvare 			data->old_pwm[1] = data->pwm[1];
2988d5d45fbSJean Delvare 			adm1031_write_value(client, ADM1031_REG_PWM, 0x55);
2998d5d45fbSJean Delvare 		} else {
3008d5d45fbSJean Delvare 			/* Switch to Manual Mode */
3018d5d45fbSJean Delvare 			data->pwm[0] = data->old_pwm[0];
3028d5d45fbSJean Delvare 			data->pwm[1] = data->old_pwm[1];
3038d5d45fbSJean Delvare 			/* Restore PWM registers */
3048d5d45fbSJean Delvare 			adm1031_write_value(client, ADM1031_REG_PWM,
3058d5d45fbSJean Delvare 					    data->pwm[0] | (data->pwm[1] << 4));
3068d5d45fbSJean Delvare 		}
3078d5d45fbSJean Delvare 	}
3088d5d45fbSJean Delvare 	data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1);
3098d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_CONF1, data->conf1);
3109a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
3118d5d45fbSJean Delvare 	return count;
3128d5d45fbSJean Delvare }
3138d5d45fbSJean Delvare 
314c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_fan1_channel, S_IRUGO | S_IWUSR,
315c801082dSJean Delvare 		show_fan_auto_channel, set_fan_auto_channel, 0);
316c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_fan2_channel, S_IRUGO | S_IWUSR,
317c801082dSJean Delvare 		show_fan_auto_channel, set_fan_auto_channel, 1);
3188d5d45fbSJean Delvare 
3198d5d45fbSJean Delvare /* Auto Temps */
320c801082dSJean Delvare static ssize_t show_auto_temp_off(struct device *dev,
321c801082dSJean Delvare 				  struct device_attribute *attr, char *buf)
3228d5d45fbSJean Delvare {
323c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
3248d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
3258d5d45fbSJean Delvare 	return sprintf(buf, "%d\n",
3268d5d45fbSJean Delvare 		       AUTO_TEMP_OFF_FROM_REG(data->auto_temp[nr]));
3278d5d45fbSJean Delvare }
328c801082dSJean Delvare static ssize_t show_auto_temp_min(struct device *dev,
329c801082dSJean Delvare 				  struct device_attribute *attr, char *buf)
3308d5d45fbSJean Delvare {
331c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
3328d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
3338d5d45fbSJean Delvare 	return sprintf(buf, "%d\n",
3348d5d45fbSJean Delvare 		       AUTO_TEMP_MIN_FROM_REG(data->auto_temp[nr]));
3358d5d45fbSJean Delvare }
3368d5d45fbSJean Delvare static ssize_t
337c801082dSJean Delvare set_auto_temp_min(struct device *dev, struct device_attribute *attr,
338c801082dSJean Delvare 		  const char *buf, size_t count)
3398d5d45fbSJean Delvare {
3408d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
3418d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
342c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
3438d5d45fbSJean Delvare 	int val = simple_strtol(buf, NULL, 10);
3448d5d45fbSJean Delvare 
3459a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
3468d5d45fbSJean Delvare 	data->auto_temp[nr] = AUTO_TEMP_MIN_TO_REG(val, data->auto_temp[nr]);
3478d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr),
3488d5d45fbSJean Delvare 			    data->auto_temp[nr]);
3499a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
3508d5d45fbSJean Delvare 	return count;
3518d5d45fbSJean Delvare }
352c801082dSJean Delvare static ssize_t show_auto_temp_max(struct device *dev,
353c801082dSJean Delvare 				  struct device_attribute *attr, char *buf)
3548d5d45fbSJean Delvare {
355c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
3568d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
3578d5d45fbSJean Delvare 	return sprintf(buf, "%d\n",
3588d5d45fbSJean Delvare 		       AUTO_TEMP_MAX_FROM_REG(data->auto_temp[nr]));
3598d5d45fbSJean Delvare }
3608d5d45fbSJean Delvare static ssize_t
361c801082dSJean Delvare set_auto_temp_max(struct device *dev, struct device_attribute *attr,
362c801082dSJean Delvare 		  const char *buf, size_t count)
3638d5d45fbSJean Delvare {
3648d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
3658d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
366c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
3678d5d45fbSJean Delvare 	int val = simple_strtol(buf, NULL, 10);
3688d5d45fbSJean Delvare 
3699a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
3708d5d45fbSJean Delvare 	data->temp_max[nr] = AUTO_TEMP_MAX_TO_REG(val, data->auto_temp[nr], data->pwm[nr]);
3718d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr),
3728d5d45fbSJean Delvare 			    data->temp_max[nr]);
3739a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
3748d5d45fbSJean Delvare 	return count;
3758d5d45fbSJean Delvare }
3768d5d45fbSJean Delvare 
3778d5d45fbSJean Delvare #define auto_temp_reg(offset)						\
378c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_temp##offset##_off, S_IRUGO,		\
379c801082dSJean Delvare 		show_auto_temp_off, NULL, offset - 1);			\
380c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_temp##offset##_min, S_IRUGO | S_IWUSR,	\
381c801082dSJean Delvare 		show_auto_temp_min, set_auto_temp_min, offset - 1);	\
382c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_temp##offset##_max, S_IRUGO | S_IWUSR,	\
383c801082dSJean Delvare 		show_auto_temp_max, set_auto_temp_max, offset - 1)
3848d5d45fbSJean Delvare 
3858d5d45fbSJean Delvare auto_temp_reg(1);
3868d5d45fbSJean Delvare auto_temp_reg(2);
3878d5d45fbSJean Delvare auto_temp_reg(3);
3888d5d45fbSJean Delvare 
3898d5d45fbSJean Delvare /* pwm */
390c801082dSJean Delvare static ssize_t show_pwm(struct device *dev,
391c801082dSJean Delvare 			struct device_attribute *attr, char *buf)
3928d5d45fbSJean Delvare {
393c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
3948d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
3958d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm[nr]));
3968d5d45fbSJean Delvare }
397c801082dSJean Delvare static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
398c801082dSJean Delvare 		       const char *buf, size_t count)
3998d5d45fbSJean Delvare {
4008d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
4018d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
402c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4038d5d45fbSJean Delvare 	int val = simple_strtol(buf, NULL, 10);
4048d5d45fbSJean Delvare 	int reg;
4058d5d45fbSJean Delvare 
4069a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
4078d5d45fbSJean Delvare 	if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) &&
4088d5d45fbSJean Delvare 	    (((val>>4) & 0xf) != 5)) {
4098d5d45fbSJean Delvare 		/* In automatic mode, the only PWM accepted is 33% */
4109a61bf63SIngo Molnar 		mutex_unlock(&data->update_lock);
4118d5d45fbSJean Delvare 		return -EINVAL;
4128d5d45fbSJean Delvare 	}
4138d5d45fbSJean Delvare 	data->pwm[nr] = PWM_TO_REG(val);
4148d5d45fbSJean Delvare 	reg = adm1031_read_value(client, ADM1031_REG_PWM);
4158d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_PWM,
4168d5d45fbSJean Delvare 			    nr ? ((data->pwm[nr] << 4) & 0xf0) | (reg & 0xf)
4178d5d45fbSJean Delvare 			    : (data->pwm[nr] & 0xf) | (reg & 0xf0));
4189a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
4198d5d45fbSJean Delvare 	return count;
4208d5d45fbSJean Delvare }
4218d5d45fbSJean Delvare 
422c801082dSJean Delvare static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 0);
423c801082dSJean Delvare static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 1);
424c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_fan1_min_pwm, S_IRUGO | S_IWUSR,
425c801082dSJean Delvare 		show_pwm, set_pwm, 0);
426c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_fan2_min_pwm, S_IRUGO | S_IWUSR,
427c801082dSJean Delvare 		show_pwm, set_pwm, 1);
4288d5d45fbSJean Delvare 
4298d5d45fbSJean Delvare /* Fans */
4308d5d45fbSJean Delvare 
4318d5d45fbSJean Delvare /*
4328d5d45fbSJean Delvare  * That function checks the cases where the fan reading is not
4338d5d45fbSJean Delvare  * relevant.  It is used to provide 0 as fan reading when the fan is
4348d5d45fbSJean Delvare  * not supposed to run
4358d5d45fbSJean Delvare  */
4368d5d45fbSJean Delvare static int trust_fan_readings(struct adm1031_data *data, int chan)
4378d5d45fbSJean Delvare {
4388d5d45fbSJean Delvare 	int res = 0;
4398d5d45fbSJean Delvare 
4408d5d45fbSJean Delvare 	if (data->conf1 & ADM1031_CONF1_AUTO_MODE) {
4418d5d45fbSJean Delvare 		switch (data->conf1 & 0x60) {
4428d5d45fbSJean Delvare 		case 0x00:	/* remote temp1 controls fan1 remote temp2 controls fan2 */
4438d5d45fbSJean Delvare 			res = data->temp[chan+1] >=
4448d5d45fbSJean Delvare 			      AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[chan+1]);
4458d5d45fbSJean Delvare 			break;
4468d5d45fbSJean Delvare 		case 0x20:	/* remote temp1 controls both fans */
4478d5d45fbSJean Delvare 			res =
4488d5d45fbSJean Delvare 			    data->temp[1] >=
4498d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[1]);
4508d5d45fbSJean Delvare 			break;
4518d5d45fbSJean Delvare 		case 0x40:	/* remote temp2 controls both fans */
4528d5d45fbSJean Delvare 			res =
4538d5d45fbSJean Delvare 			    data->temp[2] >=
4548d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[2]);
4558d5d45fbSJean Delvare 			break;
4568d5d45fbSJean Delvare 		case 0x60:	/* max controls both fans */
4578d5d45fbSJean Delvare 			res =
4588d5d45fbSJean Delvare 			    data->temp[0] >=
4598d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[0])
4608d5d45fbSJean Delvare 			    || data->temp[1] >=
4618d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[1])
4628d5d45fbSJean Delvare 			    || (data->chip_type == adm1031
4638d5d45fbSJean Delvare 				&& data->temp[2] >=
4648d5d45fbSJean Delvare 				AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[2]));
4658d5d45fbSJean Delvare 			break;
4668d5d45fbSJean Delvare 		}
4678d5d45fbSJean Delvare 	} else {
4688d5d45fbSJean Delvare 		res = data->pwm[chan] > 0;
4698d5d45fbSJean Delvare 	}
4708d5d45fbSJean Delvare 	return res;
4718d5d45fbSJean Delvare }
4728d5d45fbSJean Delvare 
4738d5d45fbSJean Delvare 
474c801082dSJean Delvare static ssize_t show_fan(struct device *dev,
475c801082dSJean Delvare 			struct device_attribute *attr, char *buf)
4768d5d45fbSJean Delvare {
477c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4788d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
4798d5d45fbSJean Delvare 	int value;
4808d5d45fbSJean Delvare 
4818d5d45fbSJean Delvare 	value = trust_fan_readings(data, nr) ? FAN_FROM_REG(data->fan[nr],
4828d5d45fbSJean Delvare 				 FAN_DIV_FROM_REG(data->fan_div[nr])) : 0;
4838d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", value);
4848d5d45fbSJean Delvare }
4858d5d45fbSJean Delvare 
486c801082dSJean Delvare static ssize_t show_fan_div(struct device *dev,
487c801082dSJean Delvare 			    struct device_attribute *attr, char *buf)
4888d5d45fbSJean Delvare {
489c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4908d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
4918d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", FAN_DIV_FROM_REG(data->fan_div[nr]));
4928d5d45fbSJean Delvare }
493c801082dSJean Delvare static ssize_t show_fan_min(struct device *dev,
494c801082dSJean Delvare 			    struct device_attribute *attr, char *buf)
4958d5d45fbSJean Delvare {
496c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4978d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
4988d5d45fbSJean Delvare 	return sprintf(buf, "%d\n",
4998d5d45fbSJean Delvare 		       FAN_FROM_REG(data->fan_min[nr],
5008d5d45fbSJean Delvare 				    FAN_DIV_FROM_REG(data->fan_div[nr])));
5018d5d45fbSJean Delvare }
502c801082dSJean Delvare static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
503c801082dSJean Delvare 			   const char *buf, size_t count)
5048d5d45fbSJean Delvare {
5058d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
5068d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
507c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
5088d5d45fbSJean Delvare 	int val = simple_strtol(buf, NULL, 10);
5098d5d45fbSJean Delvare 
5109a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
5118d5d45fbSJean Delvare 	if (val) {
5128d5d45fbSJean Delvare 		data->fan_min[nr] =
5138d5d45fbSJean Delvare 			FAN_TO_REG(val, FAN_DIV_FROM_REG(data->fan_div[nr]));
5148d5d45fbSJean Delvare 	} else {
5158d5d45fbSJean Delvare 		data->fan_min[nr] = 0xff;
5168d5d45fbSJean Delvare 	}
5178d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), data->fan_min[nr]);
5189a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
5198d5d45fbSJean Delvare 	return count;
5208d5d45fbSJean Delvare }
521c801082dSJean Delvare static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
522c801082dSJean Delvare 			   const char *buf, size_t count)
5238d5d45fbSJean Delvare {
5248d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
5258d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
526c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
5278d5d45fbSJean Delvare 	int val = simple_strtol(buf, NULL, 10);
5288d5d45fbSJean Delvare 	u8 tmp;
5298d5d45fbSJean Delvare 	int old_div;
5308d5d45fbSJean Delvare 	int new_min;
5318d5d45fbSJean Delvare 
5328d5d45fbSJean Delvare 	tmp = val == 8 ? 0xc0 :
5338d5d45fbSJean Delvare 	      val == 4 ? 0x80 :
5348d5d45fbSJean Delvare 	      val == 2 ? 0x40 :
5358d5d45fbSJean Delvare 	      val == 1 ? 0x00 :
5368d5d45fbSJean Delvare 	      0xff;
5378d5d45fbSJean Delvare 	if (tmp == 0xff)
5388d5d45fbSJean Delvare 		return -EINVAL;
5398d5d45fbSJean Delvare 
5409a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
54138a1f0e9SJean Delvare 	/* Get fresh readings */
54238a1f0e9SJean Delvare 	data->fan_div[nr] = adm1031_read_value(client,
54338a1f0e9SJean Delvare 					       ADM1031_REG_FAN_DIV(nr));
54438a1f0e9SJean Delvare 	data->fan_min[nr] = adm1031_read_value(client,
54538a1f0e9SJean Delvare 					       ADM1031_REG_FAN_MIN(nr));
54638a1f0e9SJean Delvare 
54738a1f0e9SJean Delvare 	/* Write the new clock divider and fan min */
5488d5d45fbSJean Delvare 	old_div = FAN_DIV_FROM_REG(data->fan_div[nr]);
5496d6006b8SJean Delvare 	data->fan_div[nr] = tmp | (0x3f & data->fan_div[nr]);
5506d6006b8SJean Delvare 	new_min = data->fan_min[nr] * old_div / val;
5518d5d45fbSJean Delvare 	data->fan_min[nr] = new_min > 0xff ? 0xff : new_min;
5528d5d45fbSJean Delvare 
5538d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_FAN_DIV(nr),
5548d5d45fbSJean Delvare 			    data->fan_div[nr]);
5558d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr),
5568d5d45fbSJean Delvare 			    data->fan_min[nr]);
55738a1f0e9SJean Delvare 
55838a1f0e9SJean Delvare 	/* Invalidate the cache: fan speed is no longer valid */
55938a1f0e9SJean Delvare 	data->valid = 0;
5609a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
5618d5d45fbSJean Delvare 	return count;
5628d5d45fbSJean Delvare }
5638d5d45fbSJean Delvare 
5648d5d45fbSJean Delvare #define fan_offset(offset)						\
565c801082dSJean Delvare static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO,			\
566c801082dSJean Delvare 		show_fan, NULL, offset - 1);				\
567c801082dSJean Delvare static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,		\
568c801082dSJean Delvare 		show_fan_min, set_fan_min, offset - 1);			\
569c801082dSJean Delvare static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR,		\
570c801082dSJean Delvare 		show_fan_div, set_fan_div, offset - 1)
5718d5d45fbSJean Delvare 
5728d5d45fbSJean Delvare fan_offset(1);
5738d5d45fbSJean Delvare fan_offset(2);
5748d5d45fbSJean Delvare 
5758d5d45fbSJean Delvare 
5768d5d45fbSJean Delvare /* Temps */
577c801082dSJean Delvare static ssize_t show_temp(struct device *dev,
578c801082dSJean Delvare 			 struct device_attribute *attr, char *buf)
5798d5d45fbSJean Delvare {
580c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
5818d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
5828d5d45fbSJean Delvare 	int ext;
5838d5d45fbSJean Delvare 	ext = nr == 0 ?
5848d5d45fbSJean Delvare 	    ((data->ext_temp[nr] >> 6) & 0x3) * 2 :
5858d5d45fbSJean Delvare 	    (((data->ext_temp[nr] >> ((nr - 1) * 3)) & 7));
5868d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG_EXT(data->temp[nr], ext));
5878d5d45fbSJean Delvare }
588c801082dSJean Delvare static ssize_t show_temp_min(struct device *dev,
589c801082dSJean Delvare 			     struct device_attribute *attr, char *buf)
5908d5d45fbSJean Delvare {
591c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
5928d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
5938d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr]));
5948d5d45fbSJean Delvare }
595c801082dSJean Delvare static ssize_t show_temp_max(struct device *dev,
596c801082dSJean Delvare 			     struct device_attribute *attr, char *buf)
5978d5d45fbSJean Delvare {
598c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
5998d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
6008d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr]));
6018d5d45fbSJean Delvare }
602c801082dSJean Delvare static ssize_t show_temp_crit(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_crit[nr]));
6088d5d45fbSJean Delvare }
609c801082dSJean Delvare static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
610c801082dSJean Delvare 			    const char *buf, size_t count)
6118d5d45fbSJean Delvare {
6128d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
6138d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
614c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
6158d5d45fbSJean Delvare 	int val;
6168d5d45fbSJean Delvare 
6178d5d45fbSJean Delvare 	val = simple_strtol(buf, NULL, 10);
6188d5d45fbSJean Delvare 	val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875);
6199a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
6208d5d45fbSJean Delvare 	data->temp_min[nr] = TEMP_TO_REG(val);
6218d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_TEMP_MIN(nr),
6228d5d45fbSJean Delvare 			    data->temp_min[nr]);
6239a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
6248d5d45fbSJean Delvare 	return count;
6258d5d45fbSJean Delvare }
626c801082dSJean Delvare static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
627c801082dSJean Delvare 			    const char *buf, size_t count)
6288d5d45fbSJean Delvare {
6298d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
6308d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
631c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
6328d5d45fbSJean Delvare 	int val;
6338d5d45fbSJean Delvare 
6348d5d45fbSJean Delvare 	val = simple_strtol(buf, NULL, 10);
6358d5d45fbSJean Delvare 	val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875);
6369a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
6378d5d45fbSJean Delvare 	data->temp_max[nr] = TEMP_TO_REG(val);
6388d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_TEMP_MAX(nr),
6398d5d45fbSJean Delvare 			    data->temp_max[nr]);
6409a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
6418d5d45fbSJean Delvare 	return count;
6428d5d45fbSJean Delvare }
643c801082dSJean Delvare static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr,
644c801082dSJean Delvare 			     const char *buf, size_t count)
6458d5d45fbSJean Delvare {
6468d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
6478d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
648c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
6498d5d45fbSJean Delvare 	int val;
6508d5d45fbSJean Delvare 
6518d5d45fbSJean Delvare 	val = simple_strtol(buf, NULL, 10);
6528d5d45fbSJean Delvare 	val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875);
6539a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
6548d5d45fbSJean Delvare 	data->temp_crit[nr] = TEMP_TO_REG(val);
6558d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_TEMP_CRIT(nr),
6568d5d45fbSJean Delvare 			    data->temp_crit[nr]);
6579a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
6588d5d45fbSJean Delvare 	return count;
6598d5d45fbSJean Delvare }
6608d5d45fbSJean Delvare 
6618d5d45fbSJean Delvare #define temp_reg(offset)						\
662c801082dSJean Delvare static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO,		\
663c801082dSJean Delvare 		show_temp, NULL, offset - 1);				\
664c801082dSJean Delvare static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR,	\
665c801082dSJean Delvare 		show_temp_min, set_temp_min, offset - 1);		\
666c801082dSJean Delvare static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR,	\
667c801082dSJean Delvare 		show_temp_max, set_temp_max, offset - 1);		\
668c801082dSJean Delvare static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IRUGO | S_IWUSR,	\
669c801082dSJean Delvare 		show_temp_crit, set_temp_crit, offset - 1)
6708d5d45fbSJean Delvare 
6718d5d45fbSJean Delvare temp_reg(1);
6728d5d45fbSJean Delvare temp_reg(2);
6738d5d45fbSJean Delvare temp_reg(3);
6748d5d45fbSJean Delvare 
6758d5d45fbSJean Delvare /* Alarms */
6768d5d45fbSJean Delvare static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
6778d5d45fbSJean Delvare {
6788d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
6798d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", data->alarm);
6808d5d45fbSJean Delvare }
6818d5d45fbSJean Delvare 
6828d5d45fbSJean Delvare static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
6838d5d45fbSJean Delvare 
684050ab878SJean Delvare static ssize_t show_alarm(struct device *dev,
685050ab878SJean Delvare 			  struct device_attribute *attr, char *buf)
686050ab878SJean Delvare {
687050ab878SJean Delvare 	int bitnr = to_sensor_dev_attr(attr)->index;
688050ab878SJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
689050ab878SJean Delvare 	return sprintf(buf, "%d\n", (data->alarm >> bitnr) & 1);
690050ab878SJean Delvare }
691050ab878SJean Delvare 
692050ab878SJean Delvare static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 0);
693050ab878SJean Delvare static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_alarm, NULL, 1);
694050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 2);
695050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 3);
696050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 4);
697050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 5);
698050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6);
699050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 7);
700050ab878SJean Delvare static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 8);
701050ab878SJean Delvare static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_alarm, NULL, 9);
702050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL, 10);
703050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp3_min_alarm, S_IRUGO, show_alarm, NULL, 11);
704050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 12);
705050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 13);
706050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 14);
7078d5d45fbSJean Delvare 
708681c6f7aSMark M. Hoffman static struct attribute *adm1031_attributes[] = {
709c801082dSJean Delvare 	&sensor_dev_attr_fan1_input.dev_attr.attr,
710c801082dSJean Delvare 	&sensor_dev_attr_fan1_div.dev_attr.attr,
711c801082dSJean Delvare 	&sensor_dev_attr_fan1_min.dev_attr.attr,
712050ab878SJean Delvare 	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
713050ab878SJean Delvare 	&sensor_dev_attr_fan1_fault.dev_attr.attr,
714c801082dSJean Delvare 	&sensor_dev_attr_pwm1.dev_attr.attr,
715c801082dSJean Delvare 	&sensor_dev_attr_auto_fan1_channel.dev_attr.attr,
716c801082dSJean Delvare 	&sensor_dev_attr_temp1_input.dev_attr.attr,
717c801082dSJean Delvare 	&sensor_dev_attr_temp1_min.dev_attr.attr,
718050ab878SJean Delvare 	&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
719c801082dSJean Delvare 	&sensor_dev_attr_temp1_max.dev_attr.attr,
720050ab878SJean Delvare 	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
721c801082dSJean Delvare 	&sensor_dev_attr_temp1_crit.dev_attr.attr,
722050ab878SJean Delvare 	&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
723c801082dSJean Delvare 	&sensor_dev_attr_temp2_input.dev_attr.attr,
724c801082dSJean Delvare 	&sensor_dev_attr_temp2_min.dev_attr.attr,
725050ab878SJean Delvare 	&sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
726c801082dSJean Delvare 	&sensor_dev_attr_temp2_max.dev_attr.attr,
727050ab878SJean Delvare 	&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
728c801082dSJean Delvare 	&sensor_dev_attr_temp2_crit.dev_attr.attr,
729050ab878SJean Delvare 	&sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
730050ab878SJean Delvare 	&sensor_dev_attr_temp2_fault.dev_attr.attr,
731681c6f7aSMark M. Hoffman 
732c801082dSJean Delvare 	&sensor_dev_attr_auto_temp1_off.dev_attr.attr,
733c801082dSJean Delvare 	&sensor_dev_attr_auto_temp1_min.dev_attr.attr,
734c801082dSJean Delvare 	&sensor_dev_attr_auto_temp1_max.dev_attr.attr,
735681c6f7aSMark M. Hoffman 
736c801082dSJean Delvare 	&sensor_dev_attr_auto_temp2_off.dev_attr.attr,
737c801082dSJean Delvare 	&sensor_dev_attr_auto_temp2_min.dev_attr.attr,
738c801082dSJean Delvare 	&sensor_dev_attr_auto_temp2_max.dev_attr.attr,
739681c6f7aSMark M. Hoffman 
740c801082dSJean Delvare 	&sensor_dev_attr_auto_fan1_min_pwm.dev_attr.attr,
741681c6f7aSMark M. Hoffman 
742681c6f7aSMark M. Hoffman 	&dev_attr_alarms.attr,
743681c6f7aSMark M. Hoffman 
744681c6f7aSMark M. Hoffman 	NULL
745681c6f7aSMark M. Hoffman };
746681c6f7aSMark M. Hoffman 
747681c6f7aSMark M. Hoffman static const struct attribute_group adm1031_group = {
748681c6f7aSMark M. Hoffman 	.attrs = adm1031_attributes,
749681c6f7aSMark M. Hoffman };
750681c6f7aSMark M. Hoffman 
751681c6f7aSMark M. Hoffman static struct attribute *adm1031_attributes_opt[] = {
752c801082dSJean Delvare 	&sensor_dev_attr_fan2_input.dev_attr.attr,
753c801082dSJean Delvare 	&sensor_dev_attr_fan2_div.dev_attr.attr,
754c801082dSJean Delvare 	&sensor_dev_attr_fan2_min.dev_attr.attr,
755050ab878SJean Delvare 	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
756050ab878SJean Delvare 	&sensor_dev_attr_fan2_fault.dev_attr.attr,
757c801082dSJean Delvare 	&sensor_dev_attr_pwm2.dev_attr.attr,
758c801082dSJean Delvare 	&sensor_dev_attr_auto_fan2_channel.dev_attr.attr,
759c801082dSJean Delvare 	&sensor_dev_attr_temp3_input.dev_attr.attr,
760c801082dSJean Delvare 	&sensor_dev_attr_temp3_min.dev_attr.attr,
761050ab878SJean Delvare 	&sensor_dev_attr_temp3_min_alarm.dev_attr.attr,
762c801082dSJean Delvare 	&sensor_dev_attr_temp3_max.dev_attr.attr,
763050ab878SJean Delvare 	&sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
764c801082dSJean Delvare 	&sensor_dev_attr_temp3_crit.dev_attr.attr,
765050ab878SJean Delvare 	&sensor_dev_attr_temp3_crit_alarm.dev_attr.attr,
766050ab878SJean Delvare 	&sensor_dev_attr_temp3_fault.dev_attr.attr,
767c801082dSJean Delvare 	&sensor_dev_attr_auto_temp3_off.dev_attr.attr,
768c801082dSJean Delvare 	&sensor_dev_attr_auto_temp3_min.dev_attr.attr,
769c801082dSJean Delvare 	&sensor_dev_attr_auto_temp3_max.dev_attr.attr,
770c801082dSJean Delvare 	&sensor_dev_attr_auto_fan2_min_pwm.dev_attr.attr,
771681c6f7aSMark M. Hoffman 	NULL
772681c6f7aSMark M. Hoffman };
773681c6f7aSMark M. Hoffman 
774681c6f7aSMark M. Hoffman static const struct attribute_group adm1031_group_opt = {
775681c6f7aSMark M. Hoffman 	.attrs = adm1031_attributes_opt,
776681c6f7aSMark M. Hoffman };
777681c6f7aSMark M. Hoffman 
778*af200f88SJean Delvare /* Return 0 if detection is successful, -ENODEV otherwise */
779*af200f88SJean Delvare static int adm1031_detect(struct i2c_client *client, int kind,
780*af200f88SJean Delvare 			  struct i2c_board_info *info)
7818d5d45fbSJean Delvare {
782*af200f88SJean Delvare 	struct i2c_adapter *adapter = client->adapter;
7838d5d45fbSJean Delvare 	const char *name = "";
7848d5d45fbSJean Delvare 
7858d5d45fbSJean Delvare 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
786*af200f88SJean Delvare 		return -ENODEV;
7878d5d45fbSJean Delvare 
7888d5d45fbSJean Delvare 	if (kind < 0) {
7898d5d45fbSJean Delvare 		int id, co;
7906d6006b8SJean Delvare 		id = i2c_smbus_read_byte_data(client, 0x3d);
7916d6006b8SJean Delvare 		co = i2c_smbus_read_byte_data(client, 0x3e);
7928d5d45fbSJean Delvare 
7938d5d45fbSJean Delvare 		if (!((id == 0x31 || id == 0x30) && co == 0x41))
794*af200f88SJean Delvare 			return -ENODEV;
7958d5d45fbSJean Delvare 		kind = (id == 0x30) ? adm1030 : adm1031;
7968d5d45fbSJean Delvare 	}
7978d5d45fbSJean Delvare 
7988d5d45fbSJean Delvare 	if (kind <= 0)
7998d5d45fbSJean Delvare 		kind = adm1031;
8008d5d45fbSJean Delvare 
8018d5d45fbSJean Delvare 	/* Given the detected chip type, set the chip name and the
8028d5d45fbSJean Delvare 	 * auto fan control helper table. */
8038d5d45fbSJean Delvare 	if (kind == adm1030) {
8048d5d45fbSJean Delvare 		name = "adm1030";
8058d5d45fbSJean Delvare 	} else if (kind == adm1031) {
8068d5d45fbSJean Delvare 		name = "adm1031";
8078d5d45fbSJean Delvare 	}
808*af200f88SJean Delvare 	strlcpy(info->type, name, I2C_NAME_SIZE);
8098d5d45fbSJean Delvare 
810*af200f88SJean Delvare 	return 0;
811*af200f88SJean Delvare }
812*af200f88SJean Delvare 
813*af200f88SJean Delvare static int adm1031_probe(struct i2c_client *client,
814*af200f88SJean Delvare 			 const struct i2c_device_id *id)
815*af200f88SJean Delvare {
816*af200f88SJean Delvare 	struct adm1031_data *data;
817*af200f88SJean Delvare 	int err;
818*af200f88SJean Delvare 
819*af200f88SJean Delvare 	data = kzalloc(sizeof(struct adm1031_data), GFP_KERNEL);
820*af200f88SJean Delvare 	if (!data) {
821*af200f88SJean Delvare 		err = -ENOMEM;
822*af200f88SJean Delvare 		goto exit;
823*af200f88SJean Delvare 	}
824*af200f88SJean Delvare 
825*af200f88SJean Delvare 	i2c_set_clientdata(client, data);
826*af200f88SJean Delvare 	data->chip_type = id->driver_data;
8279a61bf63SIngo Molnar 	mutex_init(&data->update_lock);
8288d5d45fbSJean Delvare 
829*af200f88SJean Delvare 	if (data->chip_type == adm1030)
830*af200f88SJean Delvare 		data->chan_select_table = &auto_channel_select_table_adm1030;
831*af200f88SJean Delvare 	else
832*af200f88SJean Delvare 		data->chan_select_table = &auto_channel_select_table_adm1031;
8338d5d45fbSJean Delvare 
8348d5d45fbSJean Delvare 	/* Initialize the ADM1031 chip */
8356d6006b8SJean Delvare 	adm1031_init_client(client);
8368d5d45fbSJean Delvare 
8378d5d45fbSJean Delvare 	/* Register sysfs hooks */
8386d6006b8SJean Delvare 	if ((err = sysfs_create_group(&client->dev.kobj, &adm1031_group)))
839*af200f88SJean Delvare 		goto exit_free;
840681c6f7aSMark M. Hoffman 
841*af200f88SJean Delvare 	if (data->chip_type == adm1031) {
8426d6006b8SJean Delvare 		if ((err = sysfs_create_group(&client->dev.kobj,
843681c6f7aSMark M. Hoffman 						&adm1031_group_opt)))
844681c6f7aSMark M. Hoffman 			goto exit_remove;
845681c6f7aSMark M. Hoffman 	}
846681c6f7aSMark M. Hoffman 
8476d6006b8SJean Delvare 	data->hwmon_dev = hwmon_device_register(&client->dev);
8481beeffe4STony Jones 	if (IS_ERR(data->hwmon_dev)) {
8491beeffe4STony Jones 		err = PTR_ERR(data->hwmon_dev);
850681c6f7aSMark M. Hoffman 		goto exit_remove;
8518d5d45fbSJean Delvare 	}
8528d5d45fbSJean Delvare 
8538d5d45fbSJean Delvare 	return 0;
8548d5d45fbSJean Delvare 
855681c6f7aSMark M. Hoffman exit_remove:
8566d6006b8SJean Delvare 	sysfs_remove_group(&client->dev.kobj, &adm1031_group);
8576d6006b8SJean Delvare 	sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt);
8588d5d45fbSJean Delvare exit_free:
8591f57ff89SAlexey Dobriyan 	kfree(data);
8608d5d45fbSJean Delvare exit:
8618d5d45fbSJean Delvare 	return err;
8628d5d45fbSJean Delvare }
8638d5d45fbSJean Delvare 
864*af200f88SJean Delvare static int adm1031_remove(struct i2c_client *client)
8658d5d45fbSJean Delvare {
866943b0830SMark M. Hoffman 	struct adm1031_data *data = i2c_get_clientdata(client);
867943b0830SMark M. Hoffman 
8681beeffe4STony Jones 	hwmon_device_unregister(data->hwmon_dev);
869681c6f7aSMark M. Hoffman 	sysfs_remove_group(&client->dev.kobj, &adm1031_group);
870681c6f7aSMark M. Hoffman 	sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt);
871943b0830SMark M. Hoffman 	kfree(data);
8728d5d45fbSJean Delvare 	return 0;
8738d5d45fbSJean Delvare }
8748d5d45fbSJean Delvare 
8758d5d45fbSJean Delvare static void adm1031_init_client(struct i2c_client *client)
8768d5d45fbSJean Delvare {
8778d5d45fbSJean Delvare 	unsigned int read_val;
8788d5d45fbSJean Delvare 	unsigned int mask;
8798d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
8808d5d45fbSJean Delvare 
8818d5d45fbSJean Delvare 	mask = (ADM1031_CONF2_PWM1_ENABLE | ADM1031_CONF2_TACH1_ENABLE);
8828d5d45fbSJean Delvare 	if (data->chip_type == adm1031) {
8838d5d45fbSJean Delvare 		mask |= (ADM1031_CONF2_PWM2_ENABLE |
8848d5d45fbSJean Delvare 			ADM1031_CONF2_TACH2_ENABLE);
8858d5d45fbSJean Delvare 	}
8868d5d45fbSJean Delvare 	/* Initialize the ADM1031 chip (enables fan speed reading ) */
8878d5d45fbSJean Delvare 	read_val = adm1031_read_value(client, ADM1031_REG_CONF2);
8888d5d45fbSJean Delvare 	if ((read_val | mask) != read_val) {
8898d5d45fbSJean Delvare 	    adm1031_write_value(client, ADM1031_REG_CONF2, read_val | mask);
8908d5d45fbSJean Delvare 	}
8918d5d45fbSJean Delvare 
8928d5d45fbSJean Delvare 	read_val = adm1031_read_value(client, ADM1031_REG_CONF1);
8938d5d45fbSJean Delvare 	if ((read_val | ADM1031_CONF1_MONITOR_ENABLE) != read_val) {
8948d5d45fbSJean Delvare 	    adm1031_write_value(client, ADM1031_REG_CONF1, read_val |
8958d5d45fbSJean Delvare 				ADM1031_CONF1_MONITOR_ENABLE);
8968d5d45fbSJean Delvare 	}
8978d5d45fbSJean Delvare 
8988d5d45fbSJean Delvare }
8998d5d45fbSJean Delvare 
9008d5d45fbSJean Delvare static struct adm1031_data *adm1031_update_device(struct device *dev)
9018d5d45fbSJean Delvare {
9028d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
9038d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
9048d5d45fbSJean Delvare 	int chan;
9058d5d45fbSJean Delvare 
9069a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
9078d5d45fbSJean Delvare 
9088d5d45fbSJean Delvare 	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
9098d5d45fbSJean Delvare 	    || !data->valid) {
9108d5d45fbSJean Delvare 
9118d5d45fbSJean Delvare 		dev_dbg(&client->dev, "Starting adm1031 update\n");
9128d5d45fbSJean Delvare 		for (chan = 0;
9138d5d45fbSJean Delvare 		     chan < ((data->chip_type == adm1031) ? 3 : 2); chan++) {
9148d5d45fbSJean Delvare 			u8 oldh, newh;
9158d5d45fbSJean Delvare 
9168d5d45fbSJean Delvare 			oldh =
9178d5d45fbSJean Delvare 			    adm1031_read_value(client, ADM1031_REG_TEMP(chan));
9188d5d45fbSJean Delvare 			data->ext_temp[chan] =
9198d5d45fbSJean Delvare 			    adm1031_read_value(client, ADM1031_REG_EXT_TEMP);
9208d5d45fbSJean Delvare 			newh =
9218d5d45fbSJean Delvare 			    adm1031_read_value(client, ADM1031_REG_TEMP(chan));
9228d5d45fbSJean Delvare 			if (newh != oldh) {
9238d5d45fbSJean Delvare 				data->ext_temp[chan] =
9248d5d45fbSJean Delvare 				    adm1031_read_value(client,
9258d5d45fbSJean Delvare 						       ADM1031_REG_EXT_TEMP);
9268d5d45fbSJean Delvare #ifdef DEBUG
9278d5d45fbSJean Delvare 				oldh =
9288d5d45fbSJean Delvare 				    adm1031_read_value(client,
9298d5d45fbSJean Delvare 						       ADM1031_REG_TEMP(chan));
9308d5d45fbSJean Delvare 
9318d5d45fbSJean Delvare 				/* oldh is actually newer */
9328d5d45fbSJean Delvare 				if (newh != oldh)
9338d5d45fbSJean Delvare 					dev_warn(&client->dev,
9348d5d45fbSJean Delvare 						 "Remote temperature may be "
9358d5d45fbSJean Delvare 						 "wrong.\n");
9368d5d45fbSJean Delvare #endif
9378d5d45fbSJean Delvare 			}
9388d5d45fbSJean Delvare 			data->temp[chan] = newh;
9398d5d45fbSJean Delvare 
9408d5d45fbSJean Delvare 			data->temp_min[chan] =
9418d5d45fbSJean Delvare 			    adm1031_read_value(client,
9428d5d45fbSJean Delvare 					       ADM1031_REG_TEMP_MIN(chan));
9438d5d45fbSJean Delvare 			data->temp_max[chan] =
9448d5d45fbSJean Delvare 			    adm1031_read_value(client,
9458d5d45fbSJean Delvare 					       ADM1031_REG_TEMP_MAX(chan));
9468d5d45fbSJean Delvare 			data->temp_crit[chan] =
9478d5d45fbSJean Delvare 			    adm1031_read_value(client,
9488d5d45fbSJean Delvare 					       ADM1031_REG_TEMP_CRIT(chan));
9498d5d45fbSJean Delvare 			data->auto_temp[chan] =
9508d5d45fbSJean Delvare 			    adm1031_read_value(client,
9518d5d45fbSJean Delvare 					       ADM1031_REG_AUTO_TEMP(chan));
9528d5d45fbSJean Delvare 
9538d5d45fbSJean Delvare 		}
9548d5d45fbSJean Delvare 
9558d5d45fbSJean Delvare 		data->conf1 = adm1031_read_value(client, ADM1031_REG_CONF1);
9568d5d45fbSJean Delvare 		data->conf2 = adm1031_read_value(client, ADM1031_REG_CONF2);
9578d5d45fbSJean Delvare 
9588d5d45fbSJean Delvare 		data->alarm = adm1031_read_value(client, ADM1031_REG_STATUS(0))
9598d5d45fbSJean Delvare 			     | (adm1031_read_value(client, ADM1031_REG_STATUS(1))
9608d5d45fbSJean Delvare 				<< 8);
9618d5d45fbSJean Delvare 		if (data->chip_type == adm1030) {
9628d5d45fbSJean Delvare 			data->alarm &= 0xc0ff;
9638d5d45fbSJean Delvare 		}
9648d5d45fbSJean Delvare 
9658d5d45fbSJean Delvare 		for (chan=0; chan<(data->chip_type == adm1030 ? 1 : 2); chan++) {
9668d5d45fbSJean Delvare 			data->fan_div[chan] =
9678d5d45fbSJean Delvare 			    adm1031_read_value(client, ADM1031_REG_FAN_DIV(chan));
9688d5d45fbSJean Delvare 			data->fan_min[chan] =
9698d5d45fbSJean Delvare 			    adm1031_read_value(client, ADM1031_REG_FAN_MIN(chan));
9708d5d45fbSJean Delvare 			data->fan[chan] =
9718d5d45fbSJean Delvare 			    adm1031_read_value(client, ADM1031_REG_FAN_SPEED(chan));
9728d5d45fbSJean Delvare 			data->pwm[chan] =
9738d5d45fbSJean Delvare 			    0xf & (adm1031_read_value(client, ADM1031_REG_PWM) >>
9748d5d45fbSJean Delvare 				   (4*chan));
9758d5d45fbSJean Delvare 		}
9768d5d45fbSJean Delvare 		data->last_updated = jiffies;
9778d5d45fbSJean Delvare 		data->valid = 1;
9788d5d45fbSJean Delvare 	}
9798d5d45fbSJean Delvare 
9809a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
9818d5d45fbSJean Delvare 
9828d5d45fbSJean Delvare 	return data;
9838d5d45fbSJean Delvare }
9848d5d45fbSJean Delvare 
9858d5d45fbSJean Delvare static int __init sensors_adm1031_init(void)
9868d5d45fbSJean Delvare {
9878d5d45fbSJean Delvare 	return i2c_add_driver(&adm1031_driver);
9888d5d45fbSJean Delvare }
9898d5d45fbSJean Delvare 
9908d5d45fbSJean Delvare static void __exit sensors_adm1031_exit(void)
9918d5d45fbSJean Delvare {
9928d5d45fbSJean Delvare 	i2c_del_driver(&adm1031_driver);
9938d5d45fbSJean Delvare }
9948d5d45fbSJean Delvare 
9958d5d45fbSJean Delvare MODULE_AUTHOR("Alexandre d'Alton <alex@alexdalton.org>");
9968d5d45fbSJean Delvare MODULE_DESCRIPTION("ADM1031/ADM1030 driver");
9978d5d45fbSJean Delvare MODULE_LICENSE("GPL");
9988d5d45fbSJean Delvare 
9998d5d45fbSJean Delvare module_init(sensors_adm1031_init);
10008d5d45fbSJean Delvare module_exit(sensors_adm1031_exit);
1001