xref: /openbmc/linux/drivers/hwmon/adm1031.c (revision 6d6006b8db5ead05053ccfbc45ab7e5c600a81b1)
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>
30943b0830SMark M. Hoffman #include <linux/err.h>
319a61bf63SIngo Molnar #include <linux/mutex.h>
328d5d45fbSJean Delvare 
338d5d45fbSJean Delvare /* Following macros takes channel parameter starting from 0 to 2 */
348d5d45fbSJean Delvare #define ADM1031_REG_FAN_SPEED(nr)	(0x08 + (nr))
358d5d45fbSJean Delvare #define ADM1031_REG_FAN_DIV(nr)		(0x20 + (nr))
368d5d45fbSJean Delvare #define ADM1031_REG_PWM			(0x22)
378d5d45fbSJean Delvare #define ADM1031_REG_FAN_MIN(nr)		(0x10 + (nr))
388d5d45fbSJean Delvare 
398d5d45fbSJean Delvare #define ADM1031_REG_TEMP_MAX(nr)	(0x14 + 4 * (nr))
408d5d45fbSJean Delvare #define ADM1031_REG_TEMP_MIN(nr)	(0x15 + 4 * (nr))
418d5d45fbSJean Delvare #define ADM1031_REG_TEMP_CRIT(nr)	(0x16 + 4 * (nr))
428d5d45fbSJean Delvare 
43*6d6006b8SJean Delvare #define ADM1031_REG_TEMP(nr)		(0x0a + (nr))
448d5d45fbSJean Delvare #define ADM1031_REG_AUTO_TEMP(nr)	(0x24 + (nr))
458d5d45fbSJean Delvare 
468d5d45fbSJean Delvare #define ADM1031_REG_STATUS(nr)		(0x2 + (nr))
478d5d45fbSJean Delvare 
48*6d6006b8SJean Delvare #define ADM1031_REG_CONF1		0x00
49*6d6006b8SJean Delvare #define ADM1031_REG_CONF2		0x01
50*6d6006b8SJean Delvare #define ADM1031_REG_EXT_TEMP		0x06
518d5d45fbSJean Delvare 
528d5d45fbSJean Delvare #define ADM1031_CONF1_MONITOR_ENABLE	0x01	/* Monitoring enable */
538d5d45fbSJean Delvare #define ADM1031_CONF1_PWM_INVERT	0x08	/* PWM Invert */
548d5d45fbSJean Delvare #define ADM1031_CONF1_AUTO_MODE		0x80	/* Auto FAN */
558d5d45fbSJean Delvare 
568d5d45fbSJean Delvare #define ADM1031_CONF2_PWM1_ENABLE	0x01
578d5d45fbSJean Delvare #define ADM1031_CONF2_PWM2_ENABLE	0x02
588d5d45fbSJean Delvare #define ADM1031_CONF2_TACH1_ENABLE	0x04
598d5d45fbSJean Delvare #define ADM1031_CONF2_TACH2_ENABLE	0x08
608d5d45fbSJean Delvare #define ADM1031_CONF2_TEMP_ENABLE(chan)	(0x10 << (chan))
618d5d45fbSJean Delvare 
628d5d45fbSJean Delvare /* Addresses to scan */
638d5d45fbSJean Delvare static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
648d5d45fbSJean Delvare 
658d5d45fbSJean Delvare /* Insmod parameters */
66f4b50261SJean Delvare I2C_CLIENT_INSMOD_2(adm1030, adm1031);
678d5d45fbSJean Delvare 
688d5d45fbSJean Delvare typedef u8 auto_chan_table_t[8][2];
698d5d45fbSJean Delvare 
708d5d45fbSJean Delvare /* Each client has this additional data */
718d5d45fbSJean Delvare struct adm1031_data {
728d5d45fbSJean Delvare 	struct i2c_client client;
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 	 */
81*6d6006b8SJean 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 
1018d5d45fbSJean Delvare static int adm1031_attach_adapter(struct i2c_adapter *adapter);
1028d5d45fbSJean Delvare static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind);
1038d5d45fbSJean Delvare static void adm1031_init_client(struct i2c_client *client);
1048d5d45fbSJean Delvare static int adm1031_detach_client(struct i2c_client *client);
1058d5d45fbSJean Delvare static struct adm1031_data *adm1031_update_device(struct device *dev);
1068d5d45fbSJean Delvare 
1078d5d45fbSJean Delvare /* This is the driver that will be inserted */
1088d5d45fbSJean Delvare static struct i2c_driver adm1031_driver = {
109cdaf7934SLaurent Riffard 	.driver = {
1108d5d45fbSJean Delvare 		.name = "adm1031",
111cdaf7934SLaurent Riffard 	},
1128d5d45fbSJean Delvare 	.attach_adapter = adm1031_attach_adapter,
1138d5d45fbSJean Delvare 	.detach_client = adm1031_detach_client,
1148d5d45fbSJean Delvare };
1158d5d45fbSJean Delvare 
1168d5d45fbSJean Delvare static inline u8 adm1031_read_value(struct i2c_client *client, u8 reg)
1178d5d45fbSJean Delvare {
1188d5d45fbSJean Delvare 	return i2c_smbus_read_byte_data(client, reg);
1198d5d45fbSJean Delvare }
1208d5d45fbSJean Delvare 
1218d5d45fbSJean Delvare static inline int
1228d5d45fbSJean Delvare adm1031_write_value(struct i2c_client *client, u8 reg, unsigned int value)
1238d5d45fbSJean Delvare {
1248d5d45fbSJean Delvare 	return i2c_smbus_write_byte_data(client, reg, value);
1258d5d45fbSJean Delvare }
1268d5d45fbSJean Delvare 
1278d5d45fbSJean Delvare 
1288d5d45fbSJean Delvare #define TEMP_TO_REG(val)		(((val) < 0 ? ((val - 500) / 1000) : \
1298d5d45fbSJean Delvare 					((val + 500) / 1000)))
1308d5d45fbSJean Delvare 
1318d5d45fbSJean Delvare #define TEMP_FROM_REG(val)		((val) * 1000)
1328d5d45fbSJean Delvare 
1338d5d45fbSJean Delvare #define TEMP_FROM_REG_EXT(val, ext)	(TEMP_FROM_REG(val) + (ext) * 125)
1348d5d45fbSJean Delvare 
1358d5d45fbSJean Delvare #define FAN_FROM_REG(reg, div)		((reg) ? (11250 * 60) / ((reg) * (div)) : 0)
1368d5d45fbSJean Delvare 
1378d5d45fbSJean Delvare static int FAN_TO_REG(int reg, int div)
1388d5d45fbSJean Delvare {
1398d5d45fbSJean Delvare 	int tmp;
1408d5d45fbSJean Delvare 	tmp = FAN_FROM_REG(SENSORS_LIMIT(reg, 0, 65535), div);
1418d5d45fbSJean Delvare 	return tmp > 255 ? 255 : tmp;
1428d5d45fbSJean Delvare }
1438d5d45fbSJean Delvare 
1448d5d45fbSJean Delvare #define FAN_DIV_FROM_REG(reg)		(1<<(((reg)&0xc0)>>6))
1458d5d45fbSJean Delvare 
1468d5d45fbSJean Delvare #define PWM_TO_REG(val)			(SENSORS_LIMIT((val), 0, 255) >> 4)
1478d5d45fbSJean Delvare #define PWM_FROM_REG(val)		((val) << 4)
1488d5d45fbSJean Delvare 
1498d5d45fbSJean Delvare #define FAN_CHAN_FROM_REG(reg)		(((reg) >> 5) & 7)
1508d5d45fbSJean Delvare #define FAN_CHAN_TO_REG(val, reg)	\
1518d5d45fbSJean Delvare 	(((reg) & 0x1F) | (((val) << 5) & 0xe0))
1528d5d45fbSJean Delvare 
1538d5d45fbSJean Delvare #define AUTO_TEMP_MIN_TO_REG(val, reg)	\
1548d5d45fbSJean Delvare 	((((val)/500) & 0xf8)|((reg) & 0x7))
1558d5d45fbSJean Delvare #define AUTO_TEMP_RANGE_FROM_REG(reg)	(5000 * (1<< ((reg)&0x7)))
1568d5d45fbSJean Delvare #define AUTO_TEMP_MIN_FROM_REG(reg)	(1000 * ((((reg) >> 3) & 0x1f) << 2))
1578d5d45fbSJean Delvare 
1588d5d45fbSJean Delvare #define AUTO_TEMP_MIN_FROM_REG_DEG(reg)	((((reg) >> 3) & 0x1f) << 2)
1598d5d45fbSJean Delvare 
1608d5d45fbSJean Delvare #define AUTO_TEMP_OFF_FROM_REG(reg)		\
1618d5d45fbSJean Delvare 	(AUTO_TEMP_MIN_FROM_REG(reg) - 5000)
1628d5d45fbSJean Delvare 
1638d5d45fbSJean Delvare #define AUTO_TEMP_MAX_FROM_REG(reg)		\
1648d5d45fbSJean Delvare 	(AUTO_TEMP_RANGE_FROM_REG(reg) +	\
1658d5d45fbSJean Delvare 	AUTO_TEMP_MIN_FROM_REG(reg))
1668d5d45fbSJean Delvare 
1678d5d45fbSJean Delvare static int AUTO_TEMP_MAX_TO_REG(int val, int reg, int pwm)
1688d5d45fbSJean Delvare {
1698d5d45fbSJean Delvare 	int ret;
1708d5d45fbSJean Delvare 	int range = val - AUTO_TEMP_MIN_FROM_REG(reg);
1718d5d45fbSJean Delvare 
1728d5d45fbSJean Delvare 	range = ((val - AUTO_TEMP_MIN_FROM_REG(reg))*10)/(16 - pwm);
1738d5d45fbSJean Delvare 	ret = ((reg & 0xf8) |
1748d5d45fbSJean Delvare 	       (range < 10000 ? 0 :
1758d5d45fbSJean Delvare 		range < 20000 ? 1 :
1768d5d45fbSJean Delvare 		range < 40000 ? 2 : range < 80000 ? 3 : 4));
1778d5d45fbSJean Delvare 	return ret;
1788d5d45fbSJean Delvare }
1798d5d45fbSJean Delvare 
1808d5d45fbSJean Delvare /* FAN auto control */
1818d5d45fbSJean Delvare #define GET_FAN_AUTO_BITFIELD(data, idx)	\
1828d5d45fbSJean Delvare 	(*(data)->chan_select_table)[FAN_CHAN_FROM_REG((data)->conf1)][idx%2]
1838d5d45fbSJean Delvare 
1848d5d45fbSJean Delvare /* The tables below contains the possible values for the auto fan
1858d5d45fbSJean Delvare  * control bitfields. the index in the table is the register value.
1868d5d45fbSJean Delvare  * MSb is the auto fan control enable bit, so the four first entries
1878d5d45fbSJean Delvare  * in the table disables auto fan control when both bitfields are zero.
1888d5d45fbSJean Delvare  */
189*6d6006b8SJean Delvare static const auto_chan_table_t auto_channel_select_table_adm1031 = {
1908d5d45fbSJean Delvare 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1918d5d45fbSJean Delvare 	{ 2 /* 0b010 */ , 4 /* 0b100 */ },
1928d5d45fbSJean Delvare 	{ 2 /* 0b010 */ , 2 /* 0b010 */ },
1938d5d45fbSJean Delvare 	{ 4 /* 0b100 */ , 4 /* 0b100 */ },
1948d5d45fbSJean Delvare 	{ 7 /* 0b111 */ , 7 /* 0b111 */ },
1958d5d45fbSJean Delvare };
1968d5d45fbSJean Delvare 
197*6d6006b8SJean Delvare static const auto_chan_table_t auto_channel_select_table_adm1030 = {
1988d5d45fbSJean Delvare 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1998d5d45fbSJean Delvare 	{ 2 /* 0b10 */		, 0 },
2008d5d45fbSJean Delvare 	{ 0xff /* invalid */	, 0 },
2018d5d45fbSJean Delvare 	{ 0xff /* invalid */	, 0 },
2028d5d45fbSJean Delvare 	{ 3 /* 0b11 */		, 0 },
2038d5d45fbSJean Delvare };
2048d5d45fbSJean Delvare 
2058d5d45fbSJean Delvare /* That function checks if a bitfield is valid and returns the other bitfield
2068d5d45fbSJean Delvare  * nearest match if no exact match where found.
2078d5d45fbSJean Delvare  */
2088d5d45fbSJean Delvare static int
2098d5d45fbSJean Delvare get_fan_auto_nearest(struct adm1031_data *data,
2108d5d45fbSJean Delvare 		     int chan, u8 val, u8 reg, u8 * new_reg)
2118d5d45fbSJean Delvare {
2128d5d45fbSJean Delvare 	int i;
2138d5d45fbSJean Delvare 	int first_match = -1, exact_match = -1;
2148d5d45fbSJean Delvare 	u8 other_reg_val =
2158d5d45fbSJean Delvare 	    (*data->chan_select_table)[FAN_CHAN_FROM_REG(reg)][chan ? 0 : 1];
2168d5d45fbSJean Delvare 
2178d5d45fbSJean Delvare 	if (val == 0) {
2188d5d45fbSJean Delvare 		*new_reg = 0;
2198d5d45fbSJean Delvare 		return 0;
2208d5d45fbSJean Delvare 	}
2218d5d45fbSJean Delvare 
2228d5d45fbSJean Delvare 	for (i = 0; i < 8; i++) {
2238d5d45fbSJean Delvare 		if ((val == (*data->chan_select_table)[i][chan]) &&
2248d5d45fbSJean Delvare 		    ((*data->chan_select_table)[i][chan ? 0 : 1] ==
2258d5d45fbSJean Delvare 		     other_reg_val)) {
2268d5d45fbSJean Delvare 			/* We found an exact match */
2278d5d45fbSJean Delvare 			exact_match = i;
2288d5d45fbSJean Delvare 			break;
2298d5d45fbSJean Delvare 		} else if (val == (*data->chan_select_table)[i][chan] &&
2308d5d45fbSJean Delvare 			   first_match == -1) {
231*6d6006b8SJean Delvare 			/* Save the first match in case of an exact match has
232*6d6006b8SJean Delvare 			 * not been found
2338d5d45fbSJean Delvare 			 */
2348d5d45fbSJean Delvare 			first_match = i;
2358d5d45fbSJean Delvare 		}
2368d5d45fbSJean Delvare 	}
2378d5d45fbSJean Delvare 
2388d5d45fbSJean Delvare 	if (exact_match >= 0) {
2398d5d45fbSJean Delvare 		*new_reg = exact_match;
2408d5d45fbSJean Delvare 	} else if (first_match >= 0) {
2418d5d45fbSJean Delvare 		*new_reg = first_match;
2428d5d45fbSJean Delvare 	} else {
2438d5d45fbSJean Delvare 		return -EINVAL;
2448d5d45fbSJean Delvare 	}
2458d5d45fbSJean Delvare 	return 0;
2468d5d45fbSJean Delvare }
2478d5d45fbSJean Delvare 
2488d5d45fbSJean Delvare static ssize_t show_fan_auto_channel(struct device *dev, char *buf, int nr)
2498d5d45fbSJean Delvare {
2508d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
2518d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", GET_FAN_AUTO_BITFIELD(data, nr));
2528d5d45fbSJean Delvare }
2538d5d45fbSJean Delvare 
2548d5d45fbSJean Delvare static ssize_t
2558d5d45fbSJean Delvare set_fan_auto_channel(struct device *dev, const char *buf, size_t count, int nr)
2568d5d45fbSJean Delvare {
2578d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
2588d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
2598d5d45fbSJean Delvare 	int val = simple_strtol(buf, NULL, 10);
2608d5d45fbSJean Delvare 	u8 reg;
2618d5d45fbSJean Delvare 	int ret;
2628d5d45fbSJean Delvare 	u8 old_fan_mode;
2638d5d45fbSJean Delvare 
2648d5d45fbSJean Delvare 	old_fan_mode = data->conf1;
2658d5d45fbSJean Delvare 
2669a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
2678d5d45fbSJean Delvare 
2688d5d45fbSJean Delvare 	if ((ret = get_fan_auto_nearest(data, nr, val, data->conf1, &reg))) {
2699a61bf63SIngo Molnar 		mutex_unlock(&data->update_lock);
2708d5d45fbSJean Delvare 		return ret;
2718d5d45fbSJean Delvare 	}
272*6d6006b8SJean Delvare 	data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1);
273*6d6006b8SJean Delvare 	if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) ^
2748d5d45fbSJean Delvare 	    (old_fan_mode & ADM1031_CONF1_AUTO_MODE)) {
2758d5d45fbSJean Delvare 		if (data->conf1 & ADM1031_CONF1_AUTO_MODE){
2768d5d45fbSJean Delvare 			/* Switch to Auto Fan Mode
2778d5d45fbSJean Delvare 			 * Save PWM registers
2788d5d45fbSJean Delvare 			 * Set PWM registers to 33% Both */
2798d5d45fbSJean Delvare 			data->old_pwm[0] = data->pwm[0];
2808d5d45fbSJean Delvare 			data->old_pwm[1] = data->pwm[1];
2818d5d45fbSJean Delvare 			adm1031_write_value(client, ADM1031_REG_PWM, 0x55);
2828d5d45fbSJean Delvare 		} else {
2838d5d45fbSJean Delvare 			/* Switch to Manual Mode */
2848d5d45fbSJean Delvare 			data->pwm[0] = data->old_pwm[0];
2858d5d45fbSJean Delvare 			data->pwm[1] = data->old_pwm[1];
2868d5d45fbSJean Delvare 			/* Restore PWM registers */
2878d5d45fbSJean Delvare 			adm1031_write_value(client, ADM1031_REG_PWM,
2888d5d45fbSJean Delvare 					    data->pwm[0] | (data->pwm[1] << 4));
2898d5d45fbSJean Delvare 		}
2908d5d45fbSJean Delvare 	}
2918d5d45fbSJean Delvare 	data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1);
2928d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_CONF1, data->conf1);
2939a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
2948d5d45fbSJean Delvare 	return count;
2958d5d45fbSJean Delvare }
2968d5d45fbSJean Delvare 
2978d5d45fbSJean Delvare #define fan_auto_channel_offset(offset)						\
2988d5d45fbSJean Delvare static ssize_t show_fan_auto_channel_##offset (struct device *dev, struct device_attribute *attr, char *buf)	\
2998d5d45fbSJean Delvare {										\
3008d5d45fbSJean Delvare 	return show_fan_auto_channel(dev, buf, offset - 1);			\
3018d5d45fbSJean Delvare }										\
3028d5d45fbSJean Delvare static ssize_t set_fan_auto_channel_##offset (struct device *dev, struct device_attribute *attr,		\
3038d5d45fbSJean Delvare 	const char *buf, size_t count)						\
3048d5d45fbSJean Delvare {										\
3058d5d45fbSJean Delvare 	return set_fan_auto_channel(dev, buf, count, offset - 1);		\
3068d5d45fbSJean Delvare }										\
3078d5d45fbSJean Delvare static DEVICE_ATTR(auto_fan##offset##_channel, S_IRUGO | S_IWUSR,		\
3088d5d45fbSJean Delvare 		   show_fan_auto_channel_##offset,				\
3098d5d45fbSJean Delvare 		   set_fan_auto_channel_##offset)
3108d5d45fbSJean Delvare 
3118d5d45fbSJean Delvare fan_auto_channel_offset(1);
3128d5d45fbSJean Delvare fan_auto_channel_offset(2);
3138d5d45fbSJean Delvare 
3148d5d45fbSJean Delvare /* Auto Temps */
3158d5d45fbSJean Delvare static ssize_t show_auto_temp_off(struct device *dev, char *buf, int nr)
3168d5d45fbSJean Delvare {
3178d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
3188d5d45fbSJean Delvare 	return sprintf(buf, "%d\n",
3198d5d45fbSJean Delvare 		       AUTO_TEMP_OFF_FROM_REG(data->auto_temp[nr]));
3208d5d45fbSJean Delvare }
3218d5d45fbSJean Delvare static ssize_t show_auto_temp_min(struct device *dev, char *buf, int nr)
3228d5d45fbSJean Delvare {
3238d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
3248d5d45fbSJean Delvare 	return sprintf(buf, "%d\n",
3258d5d45fbSJean Delvare 		       AUTO_TEMP_MIN_FROM_REG(data->auto_temp[nr]));
3268d5d45fbSJean Delvare }
3278d5d45fbSJean Delvare static ssize_t
3288d5d45fbSJean Delvare set_auto_temp_min(struct device *dev, const char *buf, size_t count, int nr)
3298d5d45fbSJean Delvare {
3308d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
3318d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
3328d5d45fbSJean Delvare 	int val = simple_strtol(buf, NULL, 10);
3338d5d45fbSJean Delvare 
3349a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
3358d5d45fbSJean Delvare 	data->auto_temp[nr] = AUTO_TEMP_MIN_TO_REG(val, data->auto_temp[nr]);
3368d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr),
3378d5d45fbSJean Delvare 			    data->auto_temp[nr]);
3389a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
3398d5d45fbSJean Delvare 	return count;
3408d5d45fbSJean Delvare }
3418d5d45fbSJean Delvare static ssize_t show_auto_temp_max(struct device *dev, char *buf, int nr)
3428d5d45fbSJean Delvare {
3438d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
3448d5d45fbSJean Delvare 	return sprintf(buf, "%d\n",
3458d5d45fbSJean Delvare 		       AUTO_TEMP_MAX_FROM_REG(data->auto_temp[nr]));
3468d5d45fbSJean Delvare }
3478d5d45fbSJean Delvare static ssize_t
3488d5d45fbSJean Delvare set_auto_temp_max(struct device *dev, const char *buf, size_t count, int nr)
3498d5d45fbSJean Delvare {
3508d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
3518d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
3528d5d45fbSJean Delvare 	int val = simple_strtol(buf, NULL, 10);
3538d5d45fbSJean Delvare 
3549a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
3558d5d45fbSJean Delvare 	data->temp_max[nr] = AUTO_TEMP_MAX_TO_REG(val, data->auto_temp[nr], data->pwm[nr]);
3568d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr),
3578d5d45fbSJean Delvare 			    data->temp_max[nr]);
3589a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
3598d5d45fbSJean Delvare 	return count;
3608d5d45fbSJean Delvare }
3618d5d45fbSJean Delvare 
3628d5d45fbSJean Delvare #define auto_temp_reg(offset)							\
3638d5d45fbSJean Delvare static ssize_t show_auto_temp_##offset##_off (struct device *dev, struct device_attribute *attr, char *buf)	\
3648d5d45fbSJean Delvare {										\
3658d5d45fbSJean Delvare 	return show_auto_temp_off(dev, buf, offset - 1);			\
3668d5d45fbSJean Delvare }										\
3678d5d45fbSJean Delvare static ssize_t show_auto_temp_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf)	\
3688d5d45fbSJean Delvare {										\
3698d5d45fbSJean Delvare 	return show_auto_temp_min(dev, buf, offset - 1);			\
3708d5d45fbSJean Delvare }										\
3718d5d45fbSJean Delvare static ssize_t show_auto_temp_##offset##_max (struct device *dev, struct device_attribute *attr, char *buf)	\
3728d5d45fbSJean Delvare {										\
3738d5d45fbSJean Delvare 	return show_auto_temp_max(dev, buf, offset - 1);			\
3748d5d45fbSJean Delvare }										\
3758d5d45fbSJean Delvare static ssize_t set_auto_temp_##offset##_min (struct device *dev, struct device_attribute *attr,		\
3768d5d45fbSJean Delvare 					     const char *buf, size_t count)	\
3778d5d45fbSJean Delvare {										\
3788d5d45fbSJean Delvare 	return set_auto_temp_min(dev, buf, count, offset - 1);		\
3798d5d45fbSJean Delvare }										\
3808d5d45fbSJean Delvare static ssize_t set_auto_temp_##offset##_max (struct device *dev, struct device_attribute *attr,		\
3818d5d45fbSJean Delvare 					     const char *buf, size_t count)	\
3828d5d45fbSJean Delvare {										\
3838d5d45fbSJean Delvare 	return set_auto_temp_max(dev, buf, count, offset - 1);		\
3848d5d45fbSJean Delvare }										\
3858d5d45fbSJean Delvare static DEVICE_ATTR(auto_temp##offset##_off, S_IRUGO,				\
3868d5d45fbSJean Delvare 		   show_auto_temp_##offset##_off, NULL);			\
3878d5d45fbSJean Delvare static DEVICE_ATTR(auto_temp##offset##_min, S_IRUGO | S_IWUSR,			\
3888d5d45fbSJean Delvare 		   show_auto_temp_##offset##_min, set_auto_temp_##offset##_min);\
3898d5d45fbSJean Delvare static DEVICE_ATTR(auto_temp##offset##_max, S_IRUGO | S_IWUSR,			\
3908d5d45fbSJean Delvare 		   show_auto_temp_##offset##_max, set_auto_temp_##offset##_max)
3918d5d45fbSJean Delvare 
3928d5d45fbSJean Delvare auto_temp_reg(1);
3938d5d45fbSJean Delvare auto_temp_reg(2);
3948d5d45fbSJean Delvare auto_temp_reg(3);
3958d5d45fbSJean Delvare 
3968d5d45fbSJean Delvare /* pwm */
3978d5d45fbSJean Delvare static ssize_t show_pwm(struct device *dev, char *buf, int nr)
3988d5d45fbSJean Delvare {
3998d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
4008d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm[nr]));
4018d5d45fbSJean Delvare }
4028d5d45fbSJean Delvare static ssize_t
4038d5d45fbSJean Delvare set_pwm(struct device *dev, const char *buf, size_t count, int nr)
4048d5d45fbSJean Delvare {
4058d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
4068d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
4078d5d45fbSJean Delvare 	int val = simple_strtol(buf, NULL, 10);
4088d5d45fbSJean Delvare 	int reg;
4098d5d45fbSJean Delvare 
4109a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
4118d5d45fbSJean Delvare 	if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) &&
4128d5d45fbSJean Delvare 	    (((val>>4) & 0xf) != 5)) {
4138d5d45fbSJean Delvare 		/* In automatic mode, the only PWM accepted is 33% */
4149a61bf63SIngo Molnar 		mutex_unlock(&data->update_lock);
4158d5d45fbSJean Delvare 		return -EINVAL;
4168d5d45fbSJean Delvare 	}
4178d5d45fbSJean Delvare 	data->pwm[nr] = PWM_TO_REG(val);
4188d5d45fbSJean Delvare 	reg = adm1031_read_value(client, ADM1031_REG_PWM);
4198d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_PWM,
4208d5d45fbSJean Delvare 			    nr ? ((data->pwm[nr] << 4) & 0xf0) | (reg & 0xf)
4218d5d45fbSJean Delvare 			    : (data->pwm[nr] & 0xf) | (reg & 0xf0));
4229a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
4238d5d45fbSJean Delvare 	return count;
4248d5d45fbSJean Delvare }
4258d5d45fbSJean Delvare 
4268d5d45fbSJean Delvare #define pwm_reg(offset)							\
4278d5d45fbSJean Delvare static ssize_t show_pwm_##offset (struct device *dev, struct device_attribute *attr, char *buf)	\
4288d5d45fbSJean Delvare {									\
4298d5d45fbSJean Delvare 	return show_pwm(dev, buf, offset - 1);			\
4308d5d45fbSJean Delvare }									\
4318d5d45fbSJean Delvare static ssize_t set_pwm_##offset (struct device *dev, struct device_attribute *attr,			\
4328d5d45fbSJean Delvare 				 const char *buf, size_t count)		\
4338d5d45fbSJean Delvare {									\
4348d5d45fbSJean Delvare 	return set_pwm(dev, buf, count, offset - 1);		\
4358d5d45fbSJean Delvare }									\
4368d5d45fbSJean Delvare static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR,			\
4378d5d45fbSJean Delvare 		   show_pwm_##offset, set_pwm_##offset)
4388d5d45fbSJean Delvare 
4398d5d45fbSJean Delvare pwm_reg(1);
4408d5d45fbSJean Delvare pwm_reg(2);
4418d5d45fbSJean Delvare 
4428d5d45fbSJean Delvare /* Fans */
4438d5d45fbSJean Delvare 
4448d5d45fbSJean Delvare /*
4458d5d45fbSJean Delvare  * That function checks the cases where the fan reading is not
4468d5d45fbSJean Delvare  * relevant.  It is used to provide 0 as fan reading when the fan is
4478d5d45fbSJean Delvare  * not supposed to run
4488d5d45fbSJean Delvare  */
4498d5d45fbSJean Delvare static int trust_fan_readings(struct adm1031_data *data, int chan)
4508d5d45fbSJean Delvare {
4518d5d45fbSJean Delvare 	int res = 0;
4528d5d45fbSJean Delvare 
4538d5d45fbSJean Delvare 	if (data->conf1 & ADM1031_CONF1_AUTO_MODE) {
4548d5d45fbSJean Delvare 		switch (data->conf1 & 0x60) {
4558d5d45fbSJean Delvare 		case 0x00:	/* remote temp1 controls fan1 remote temp2 controls fan2 */
4568d5d45fbSJean Delvare 			res = data->temp[chan+1] >=
4578d5d45fbSJean Delvare 			      AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[chan+1]);
4588d5d45fbSJean Delvare 			break;
4598d5d45fbSJean Delvare 		case 0x20:	/* remote temp1 controls both fans */
4608d5d45fbSJean Delvare 			res =
4618d5d45fbSJean Delvare 			    data->temp[1] >=
4628d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[1]);
4638d5d45fbSJean Delvare 			break;
4648d5d45fbSJean Delvare 		case 0x40:	/* remote temp2 controls both fans */
4658d5d45fbSJean Delvare 			res =
4668d5d45fbSJean Delvare 			    data->temp[2] >=
4678d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[2]);
4688d5d45fbSJean Delvare 			break;
4698d5d45fbSJean Delvare 		case 0x60:	/* max controls both fans */
4708d5d45fbSJean Delvare 			res =
4718d5d45fbSJean Delvare 			    data->temp[0] >=
4728d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[0])
4738d5d45fbSJean Delvare 			    || data->temp[1] >=
4748d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[1])
4758d5d45fbSJean Delvare 			    || (data->chip_type == adm1031
4768d5d45fbSJean Delvare 				&& data->temp[2] >=
4778d5d45fbSJean Delvare 				AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[2]));
4788d5d45fbSJean Delvare 			break;
4798d5d45fbSJean Delvare 		}
4808d5d45fbSJean Delvare 	} else {
4818d5d45fbSJean Delvare 		res = data->pwm[chan] > 0;
4828d5d45fbSJean Delvare 	}
4838d5d45fbSJean Delvare 	return res;
4848d5d45fbSJean Delvare }
4858d5d45fbSJean Delvare 
4868d5d45fbSJean Delvare 
4878d5d45fbSJean Delvare static ssize_t show_fan(struct device *dev, char *buf, int nr)
4888d5d45fbSJean Delvare {
4898d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
4908d5d45fbSJean Delvare 	int value;
4918d5d45fbSJean Delvare 
4928d5d45fbSJean Delvare 	value = trust_fan_readings(data, nr) ? FAN_FROM_REG(data->fan[nr],
4938d5d45fbSJean Delvare 				 FAN_DIV_FROM_REG(data->fan_div[nr])) : 0;
4948d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", value);
4958d5d45fbSJean Delvare }
4968d5d45fbSJean Delvare 
4978d5d45fbSJean Delvare static ssize_t show_fan_div(struct device *dev, char *buf, int nr)
4988d5d45fbSJean Delvare {
4998d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
5008d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", FAN_DIV_FROM_REG(data->fan_div[nr]));
5018d5d45fbSJean Delvare }
5028d5d45fbSJean Delvare static ssize_t show_fan_min(struct device *dev, char *buf, int nr)
5038d5d45fbSJean Delvare {
5048d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
5058d5d45fbSJean Delvare 	return sprintf(buf, "%d\n",
5068d5d45fbSJean Delvare 		       FAN_FROM_REG(data->fan_min[nr],
5078d5d45fbSJean Delvare 				    FAN_DIV_FROM_REG(data->fan_div[nr])));
5088d5d45fbSJean Delvare }
5098d5d45fbSJean Delvare static ssize_t
5108d5d45fbSJean Delvare set_fan_min(struct device *dev, const char *buf, size_t count, int nr)
5118d5d45fbSJean Delvare {
5128d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
5138d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
5148d5d45fbSJean Delvare 	int val = simple_strtol(buf, NULL, 10);
5158d5d45fbSJean Delvare 
5169a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
5178d5d45fbSJean Delvare 	if (val) {
5188d5d45fbSJean Delvare 		data->fan_min[nr] =
5198d5d45fbSJean Delvare 			FAN_TO_REG(val, FAN_DIV_FROM_REG(data->fan_div[nr]));
5208d5d45fbSJean Delvare 	} else {
5218d5d45fbSJean Delvare 		data->fan_min[nr] = 0xff;
5228d5d45fbSJean Delvare 	}
5238d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), data->fan_min[nr]);
5249a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
5258d5d45fbSJean Delvare 	return count;
5268d5d45fbSJean Delvare }
5278d5d45fbSJean Delvare static ssize_t
5288d5d45fbSJean Delvare set_fan_div(struct device *dev, const char *buf, size_t count, int nr)
5298d5d45fbSJean Delvare {
5308d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
5318d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
5328d5d45fbSJean Delvare 	int val = simple_strtol(buf, NULL, 10);
5338d5d45fbSJean Delvare 	u8 tmp;
5348d5d45fbSJean Delvare 	int old_div;
5358d5d45fbSJean Delvare 	int new_min;
5368d5d45fbSJean Delvare 
5378d5d45fbSJean Delvare 	tmp = val == 8 ? 0xc0 :
5388d5d45fbSJean Delvare 	      val == 4 ? 0x80 :
5398d5d45fbSJean Delvare 	      val == 2 ? 0x40 :
5408d5d45fbSJean Delvare 	      val == 1 ? 0x00 :
5418d5d45fbSJean Delvare 	      0xff;
5428d5d45fbSJean Delvare 	if (tmp == 0xff)
5438d5d45fbSJean Delvare 		return -EINVAL;
5448d5d45fbSJean Delvare 
5459a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
54638a1f0e9SJean Delvare 	/* Get fresh readings */
54738a1f0e9SJean Delvare 	data->fan_div[nr] = adm1031_read_value(client,
54838a1f0e9SJean Delvare 					       ADM1031_REG_FAN_DIV(nr));
54938a1f0e9SJean Delvare 	data->fan_min[nr] = adm1031_read_value(client,
55038a1f0e9SJean Delvare 					       ADM1031_REG_FAN_MIN(nr));
55138a1f0e9SJean Delvare 
55238a1f0e9SJean Delvare 	/* Write the new clock divider and fan min */
5538d5d45fbSJean Delvare 	old_div = FAN_DIV_FROM_REG(data->fan_div[nr]);
554*6d6006b8SJean Delvare 	data->fan_div[nr] = tmp | (0x3f & data->fan_div[nr]);
555*6d6006b8SJean Delvare 	new_min = data->fan_min[nr] * old_div / val;
5568d5d45fbSJean Delvare 	data->fan_min[nr] = new_min > 0xff ? 0xff : new_min;
5578d5d45fbSJean Delvare 
5588d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_FAN_DIV(nr),
5598d5d45fbSJean Delvare 			    data->fan_div[nr]);
5608d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr),
5618d5d45fbSJean Delvare 			    data->fan_min[nr]);
56238a1f0e9SJean Delvare 
56338a1f0e9SJean Delvare 	/* Invalidate the cache: fan speed is no longer valid */
56438a1f0e9SJean Delvare 	data->valid = 0;
5659a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
5668d5d45fbSJean Delvare 	return count;
5678d5d45fbSJean Delvare }
5688d5d45fbSJean Delvare 
5698d5d45fbSJean Delvare #define fan_offset(offset)						\
5708d5d45fbSJean Delvare static ssize_t show_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf)	\
5718d5d45fbSJean Delvare {									\
5728d5d45fbSJean Delvare 	return show_fan(dev, buf, offset - 1);			\
5738d5d45fbSJean Delvare }									\
5748d5d45fbSJean Delvare static ssize_t show_fan_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf)	\
5758d5d45fbSJean Delvare {									\
5768d5d45fbSJean Delvare 	return show_fan_min(dev, buf, offset - 1);			\
5778d5d45fbSJean Delvare }									\
5788d5d45fbSJean Delvare static ssize_t show_fan_##offset##_div (struct device *dev, struct device_attribute *attr, char *buf)	\
5798d5d45fbSJean Delvare {									\
5808d5d45fbSJean Delvare 	return show_fan_div(dev, buf, offset - 1);			\
5818d5d45fbSJean Delvare }									\
5828d5d45fbSJean Delvare static ssize_t set_fan_##offset##_min (struct device *dev, struct device_attribute *attr,		\
5838d5d45fbSJean Delvare 	const char *buf, size_t count)					\
5848d5d45fbSJean Delvare {									\
5858d5d45fbSJean Delvare 	return set_fan_min(dev, buf, count, offset - 1);		\
5868d5d45fbSJean Delvare }									\
5878d5d45fbSJean Delvare static ssize_t set_fan_##offset##_div (struct device *dev, struct device_attribute *attr,		\
5888d5d45fbSJean Delvare 	const char *buf, size_t count)					\
5898d5d45fbSJean Delvare {									\
5908d5d45fbSJean Delvare 	return set_fan_div(dev, buf, count, offset - 1);		\
5918d5d45fbSJean Delvare }									\
5928d5d45fbSJean Delvare static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset,	\
5938d5d45fbSJean Delvare 		   NULL);						\
5948d5d45fbSJean Delvare static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,		\
5958d5d45fbSJean Delvare 		   show_fan_##offset##_min, set_fan_##offset##_min);	\
5968d5d45fbSJean Delvare static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR,		\
5978d5d45fbSJean Delvare 		   show_fan_##offset##_div, set_fan_##offset##_div);	\
5988d5d45fbSJean Delvare static DEVICE_ATTR(auto_fan##offset##_min_pwm, S_IRUGO | S_IWUSR,	\
5998d5d45fbSJean Delvare 		   show_pwm_##offset, set_pwm_##offset)
6008d5d45fbSJean Delvare 
6018d5d45fbSJean Delvare fan_offset(1);
6028d5d45fbSJean Delvare fan_offset(2);
6038d5d45fbSJean Delvare 
6048d5d45fbSJean Delvare 
6058d5d45fbSJean Delvare /* Temps */
6068d5d45fbSJean Delvare static ssize_t show_temp(struct device *dev, char *buf, int nr)
6078d5d45fbSJean Delvare {
6088d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
6098d5d45fbSJean Delvare 	int ext;
6108d5d45fbSJean Delvare 	ext = nr == 0 ?
6118d5d45fbSJean Delvare 	    ((data->ext_temp[nr] >> 6) & 0x3) * 2 :
6128d5d45fbSJean Delvare 	    (((data->ext_temp[nr] >> ((nr - 1) * 3)) & 7));
6138d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG_EXT(data->temp[nr], ext));
6148d5d45fbSJean Delvare }
6158d5d45fbSJean Delvare static ssize_t show_temp_min(struct device *dev, char *buf, int nr)
6168d5d45fbSJean Delvare {
6178d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
6188d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr]));
6198d5d45fbSJean Delvare }
6208d5d45fbSJean Delvare static ssize_t show_temp_max(struct device *dev, char *buf, int nr)
6218d5d45fbSJean Delvare {
6228d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
6238d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr]));
6248d5d45fbSJean Delvare }
6258d5d45fbSJean Delvare static ssize_t show_temp_crit(struct device *dev, char *buf, int nr)
6268d5d45fbSJean Delvare {
6278d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
6288d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[nr]));
6298d5d45fbSJean Delvare }
6308d5d45fbSJean Delvare static ssize_t
6318d5d45fbSJean Delvare set_temp_min(struct device *dev, const char *buf, size_t count, int nr)
6328d5d45fbSJean Delvare {
6338d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
6348d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
6358d5d45fbSJean Delvare 	int val;
6368d5d45fbSJean Delvare 
6378d5d45fbSJean Delvare 	val = simple_strtol(buf, NULL, 10);
6388d5d45fbSJean Delvare 	val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875);
6399a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
6408d5d45fbSJean Delvare 	data->temp_min[nr] = TEMP_TO_REG(val);
6418d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_TEMP_MIN(nr),
6428d5d45fbSJean Delvare 			    data->temp_min[nr]);
6439a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
6448d5d45fbSJean Delvare 	return count;
6458d5d45fbSJean Delvare }
6468d5d45fbSJean Delvare static ssize_t
6478d5d45fbSJean Delvare set_temp_max(struct device *dev, const char *buf, size_t count, int nr)
6488d5d45fbSJean Delvare {
6498d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
6508d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
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_max[nr] = TEMP_TO_REG(val);
6578d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_TEMP_MAX(nr),
6588d5d45fbSJean Delvare 			    data->temp_max[nr]);
6599a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
6608d5d45fbSJean Delvare 	return count;
6618d5d45fbSJean Delvare }
6628d5d45fbSJean Delvare static ssize_t
6638d5d45fbSJean Delvare set_temp_crit(struct device *dev, const char *buf, size_t count, int nr)
6648d5d45fbSJean Delvare {
6658d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
6668d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
6678d5d45fbSJean Delvare 	int val;
6688d5d45fbSJean Delvare 
6698d5d45fbSJean Delvare 	val = simple_strtol(buf, NULL, 10);
6708d5d45fbSJean Delvare 	val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875);
6719a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
6728d5d45fbSJean Delvare 	data->temp_crit[nr] = TEMP_TO_REG(val);
6738d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_TEMP_CRIT(nr),
6748d5d45fbSJean Delvare 			    data->temp_crit[nr]);
6759a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
6768d5d45fbSJean Delvare 	return count;
6778d5d45fbSJean Delvare }
6788d5d45fbSJean Delvare 
6798d5d45fbSJean Delvare #define temp_reg(offset)							\
6808d5d45fbSJean Delvare static ssize_t show_temp_##offset (struct device *dev, struct device_attribute *attr, char *buf)		\
6818d5d45fbSJean Delvare {										\
6828d5d45fbSJean Delvare 	return show_temp(dev, buf, offset - 1);				\
6838d5d45fbSJean Delvare }										\
6848d5d45fbSJean Delvare static ssize_t show_temp_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf)		\
6858d5d45fbSJean Delvare {										\
6868d5d45fbSJean Delvare 	return show_temp_min(dev, buf, offset - 1);				\
6878d5d45fbSJean Delvare }										\
6888d5d45fbSJean Delvare static ssize_t show_temp_##offset##_max (struct device *dev, struct device_attribute *attr, char *buf)		\
6898d5d45fbSJean Delvare {										\
6908d5d45fbSJean Delvare 	return show_temp_max(dev, buf, offset - 1);				\
6918d5d45fbSJean Delvare }										\
6928d5d45fbSJean Delvare static ssize_t show_temp_##offset##_crit (struct device *dev, struct device_attribute *attr, char *buf)	\
6938d5d45fbSJean Delvare {										\
6948d5d45fbSJean Delvare 	return show_temp_crit(dev, buf, offset - 1);			\
6958d5d45fbSJean Delvare }										\
6968d5d45fbSJean Delvare static ssize_t set_temp_##offset##_min (struct device *dev, struct device_attribute *attr,			\
6978d5d45fbSJean Delvare 					const char *buf, size_t count)		\
6988d5d45fbSJean Delvare {										\
6998d5d45fbSJean Delvare 	return set_temp_min(dev, buf, count, offset - 1);			\
7008d5d45fbSJean Delvare }										\
7018d5d45fbSJean Delvare static ssize_t set_temp_##offset##_max (struct device *dev, struct device_attribute *attr,			\
7028d5d45fbSJean Delvare 					const char *buf, size_t count)		\
7038d5d45fbSJean Delvare {										\
7048d5d45fbSJean Delvare 	return set_temp_max(dev, buf, count, offset - 1);			\
7058d5d45fbSJean Delvare }										\
7068d5d45fbSJean Delvare static ssize_t set_temp_##offset##_crit (struct device *dev, struct device_attribute *attr,			\
7078d5d45fbSJean Delvare 					 const char *buf, size_t count)		\
7088d5d45fbSJean Delvare {										\
7098d5d45fbSJean Delvare 	return set_temp_crit(dev, buf, count, offset - 1);			\
7108d5d45fbSJean Delvare }										\
7118d5d45fbSJean Delvare static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset,		\
7128d5d45fbSJean Delvare 		   NULL);							\
7138d5d45fbSJean Delvare static DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR,			\
7148d5d45fbSJean Delvare 		   show_temp_##offset##_min, set_temp_##offset##_min);		\
7158d5d45fbSJean Delvare static DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR,			\
7168d5d45fbSJean Delvare 		   show_temp_##offset##_max, set_temp_##offset##_max);		\
7178d5d45fbSJean Delvare static DEVICE_ATTR(temp##offset##_crit, S_IRUGO | S_IWUSR,			\
7188d5d45fbSJean Delvare 		   show_temp_##offset##_crit, set_temp_##offset##_crit)
7198d5d45fbSJean Delvare 
7208d5d45fbSJean Delvare temp_reg(1);
7218d5d45fbSJean Delvare temp_reg(2);
7228d5d45fbSJean Delvare temp_reg(3);
7238d5d45fbSJean Delvare 
7248d5d45fbSJean Delvare /* Alarms */
7258d5d45fbSJean Delvare static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
7268d5d45fbSJean Delvare {
7278d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
7288d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", data->alarm);
7298d5d45fbSJean Delvare }
7308d5d45fbSJean Delvare 
7318d5d45fbSJean Delvare static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
7328d5d45fbSJean Delvare 
7338d5d45fbSJean Delvare 
7348d5d45fbSJean Delvare static int adm1031_attach_adapter(struct i2c_adapter *adapter)
7358d5d45fbSJean Delvare {
7368d5d45fbSJean Delvare 	if (!(adapter->class & I2C_CLASS_HWMON))
7378d5d45fbSJean Delvare 		return 0;
7382ed2dc3cSJean Delvare 	return i2c_probe(adapter, &addr_data, adm1031_detect);
7398d5d45fbSJean Delvare }
7408d5d45fbSJean Delvare 
741681c6f7aSMark M. Hoffman static struct attribute *adm1031_attributes[] = {
742681c6f7aSMark M. Hoffman 	&dev_attr_fan1_input.attr,
743681c6f7aSMark M. Hoffman 	&dev_attr_fan1_div.attr,
744681c6f7aSMark M. Hoffman 	&dev_attr_fan1_min.attr,
745681c6f7aSMark M. Hoffman 	&dev_attr_pwm1.attr,
746681c6f7aSMark M. Hoffman 	&dev_attr_auto_fan1_channel.attr,
747681c6f7aSMark M. Hoffman 	&dev_attr_temp1_input.attr,
748681c6f7aSMark M. Hoffman 	&dev_attr_temp1_min.attr,
749681c6f7aSMark M. Hoffman 	&dev_attr_temp1_max.attr,
750681c6f7aSMark M. Hoffman 	&dev_attr_temp1_crit.attr,
751681c6f7aSMark M. Hoffman 	&dev_attr_temp2_input.attr,
752681c6f7aSMark M. Hoffman 	&dev_attr_temp2_min.attr,
753681c6f7aSMark M. Hoffman 	&dev_attr_temp2_max.attr,
754681c6f7aSMark M. Hoffman 	&dev_attr_temp2_crit.attr,
755681c6f7aSMark M. Hoffman 
756681c6f7aSMark M. Hoffman 	&dev_attr_auto_temp1_off.attr,
757681c6f7aSMark M. Hoffman 	&dev_attr_auto_temp1_min.attr,
758681c6f7aSMark M. Hoffman 	&dev_attr_auto_temp1_max.attr,
759681c6f7aSMark M. Hoffman 
760681c6f7aSMark M. Hoffman 	&dev_attr_auto_temp2_off.attr,
761681c6f7aSMark M. Hoffman 	&dev_attr_auto_temp2_min.attr,
762681c6f7aSMark M. Hoffman 	&dev_attr_auto_temp2_max.attr,
763681c6f7aSMark M. Hoffman 
764681c6f7aSMark M. Hoffman 	&dev_attr_auto_fan1_min_pwm.attr,
765681c6f7aSMark M. Hoffman 
766681c6f7aSMark M. Hoffman 	&dev_attr_alarms.attr,
767681c6f7aSMark M. Hoffman 
768681c6f7aSMark M. Hoffman 	NULL
769681c6f7aSMark M. Hoffman };
770681c6f7aSMark M. Hoffman 
771681c6f7aSMark M. Hoffman static const struct attribute_group adm1031_group = {
772681c6f7aSMark M. Hoffman 	.attrs = adm1031_attributes,
773681c6f7aSMark M. Hoffman };
774681c6f7aSMark M. Hoffman 
775681c6f7aSMark M. Hoffman static struct attribute *adm1031_attributes_opt[] = {
776681c6f7aSMark M. Hoffman 	&dev_attr_fan2_input.attr,
777681c6f7aSMark M. Hoffman 	&dev_attr_fan2_div.attr,
778681c6f7aSMark M. Hoffman 	&dev_attr_fan2_min.attr,
779681c6f7aSMark M. Hoffman 	&dev_attr_pwm2.attr,
780681c6f7aSMark M. Hoffman 	&dev_attr_auto_fan2_channel.attr,
781681c6f7aSMark M. Hoffman 	&dev_attr_temp3_input.attr,
782681c6f7aSMark M. Hoffman 	&dev_attr_temp3_min.attr,
783681c6f7aSMark M. Hoffman 	&dev_attr_temp3_max.attr,
784681c6f7aSMark M. Hoffman 	&dev_attr_temp3_crit.attr,
785681c6f7aSMark M. Hoffman 	&dev_attr_auto_temp3_off.attr,
786681c6f7aSMark M. Hoffman 	&dev_attr_auto_temp3_min.attr,
787681c6f7aSMark M. Hoffman 	&dev_attr_auto_temp3_max.attr,
788681c6f7aSMark M. Hoffman 	&dev_attr_auto_fan2_min_pwm.attr,
789681c6f7aSMark M. Hoffman 	NULL
790681c6f7aSMark M. Hoffman };
791681c6f7aSMark M. Hoffman 
792681c6f7aSMark M. Hoffman static const struct attribute_group adm1031_group_opt = {
793681c6f7aSMark M. Hoffman 	.attrs = adm1031_attributes_opt,
794681c6f7aSMark M. Hoffman };
795681c6f7aSMark M. Hoffman 
7962ed2dc3cSJean Delvare /* This function is called by i2c_probe */
7978d5d45fbSJean Delvare static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind)
7988d5d45fbSJean Delvare {
799*6d6006b8SJean Delvare 	struct i2c_client *client;
8008d5d45fbSJean Delvare 	struct adm1031_data *data;
8018d5d45fbSJean Delvare 	int err = 0;
8028d5d45fbSJean Delvare 	const char *name = "";
8038d5d45fbSJean Delvare 
8048d5d45fbSJean Delvare 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
8058d5d45fbSJean Delvare 		goto exit;
8068d5d45fbSJean Delvare 
807ba9c2e8dSDeepak Saxena 	if (!(data = kzalloc(sizeof(struct adm1031_data), GFP_KERNEL))) {
8088d5d45fbSJean Delvare 		err = -ENOMEM;
8098d5d45fbSJean Delvare 		goto exit;
8108d5d45fbSJean Delvare 	}
8118d5d45fbSJean Delvare 
812*6d6006b8SJean Delvare 	client = &data->client;
813*6d6006b8SJean Delvare 	i2c_set_clientdata(client, data);
814*6d6006b8SJean Delvare 	client->addr = address;
815*6d6006b8SJean Delvare 	client->adapter = adapter;
816*6d6006b8SJean Delvare 	client->driver = &adm1031_driver;
8178d5d45fbSJean Delvare 
8188d5d45fbSJean Delvare 	if (kind < 0) {
8198d5d45fbSJean Delvare 		int id, co;
820*6d6006b8SJean Delvare 		id = i2c_smbus_read_byte_data(client, 0x3d);
821*6d6006b8SJean Delvare 		co = i2c_smbus_read_byte_data(client, 0x3e);
8228d5d45fbSJean Delvare 
8238d5d45fbSJean Delvare 		if (!((id == 0x31 || id == 0x30) && co == 0x41))
8248d5d45fbSJean Delvare 			goto exit_free;
8258d5d45fbSJean Delvare 		kind = (id == 0x30) ? adm1030 : adm1031;
8268d5d45fbSJean Delvare 	}
8278d5d45fbSJean Delvare 
8288d5d45fbSJean Delvare 	if (kind <= 0)
8298d5d45fbSJean Delvare 		kind = adm1031;
8308d5d45fbSJean Delvare 
8318d5d45fbSJean Delvare 	/* Given the detected chip type, set the chip name and the
8328d5d45fbSJean Delvare 	 * auto fan control helper table. */
8338d5d45fbSJean Delvare 	if (kind == adm1030) {
8348d5d45fbSJean Delvare 		name = "adm1030";
8358d5d45fbSJean Delvare 		data->chan_select_table = &auto_channel_select_table_adm1030;
8368d5d45fbSJean Delvare 	} else if (kind == adm1031) {
8378d5d45fbSJean Delvare 		name = "adm1031";
8388d5d45fbSJean Delvare 		data->chan_select_table = &auto_channel_select_table_adm1031;
8398d5d45fbSJean Delvare 	}
8408d5d45fbSJean Delvare 	data->chip_type = kind;
8418d5d45fbSJean Delvare 
842*6d6006b8SJean Delvare 	strlcpy(client->name, name, I2C_NAME_SIZE);
8439a61bf63SIngo Molnar 	mutex_init(&data->update_lock);
8448d5d45fbSJean Delvare 
8458d5d45fbSJean Delvare 	/* Tell the I2C layer a new client has arrived */
846*6d6006b8SJean Delvare 	if ((err = i2c_attach_client(client)))
8478d5d45fbSJean Delvare 		goto exit_free;
8488d5d45fbSJean Delvare 
8498d5d45fbSJean Delvare 	/* Initialize the ADM1031 chip */
850*6d6006b8SJean Delvare 	adm1031_init_client(client);
8518d5d45fbSJean Delvare 
8528d5d45fbSJean Delvare 	/* Register sysfs hooks */
853*6d6006b8SJean Delvare 	if ((err = sysfs_create_group(&client->dev.kobj, &adm1031_group)))
854681c6f7aSMark M. Hoffman 		goto exit_detach;
855681c6f7aSMark M. Hoffman 
856681c6f7aSMark M. Hoffman 	if (kind == adm1031) {
857*6d6006b8SJean Delvare 		if ((err = sysfs_create_group(&client->dev.kobj,
858681c6f7aSMark M. Hoffman 						&adm1031_group_opt)))
859681c6f7aSMark M. Hoffman 			goto exit_remove;
860681c6f7aSMark M. Hoffman 	}
861681c6f7aSMark M. Hoffman 
862*6d6006b8SJean Delvare 	data->hwmon_dev = hwmon_device_register(&client->dev);
8631beeffe4STony Jones 	if (IS_ERR(data->hwmon_dev)) {
8641beeffe4STony Jones 		err = PTR_ERR(data->hwmon_dev);
865681c6f7aSMark M. Hoffman 		goto exit_remove;
8668d5d45fbSJean Delvare 	}
8678d5d45fbSJean Delvare 
8688d5d45fbSJean Delvare 	return 0;
8698d5d45fbSJean Delvare 
870681c6f7aSMark M. Hoffman exit_remove:
871*6d6006b8SJean Delvare 	sysfs_remove_group(&client->dev.kobj, &adm1031_group);
872*6d6006b8SJean Delvare 	sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt);
873943b0830SMark M. Hoffman exit_detach:
874*6d6006b8SJean Delvare 	i2c_detach_client(client);
8758d5d45fbSJean Delvare exit_free:
8761f57ff89SAlexey Dobriyan 	kfree(data);
8778d5d45fbSJean Delvare exit:
8788d5d45fbSJean Delvare 	return err;
8798d5d45fbSJean Delvare }
8808d5d45fbSJean Delvare 
8818d5d45fbSJean Delvare static int adm1031_detach_client(struct i2c_client *client)
8828d5d45fbSJean Delvare {
883943b0830SMark M. Hoffman 	struct adm1031_data *data = i2c_get_clientdata(client);
8848d5d45fbSJean Delvare 	int ret;
885943b0830SMark M. Hoffman 
8861beeffe4STony Jones 	hwmon_device_unregister(data->hwmon_dev);
887681c6f7aSMark M. Hoffman 	sysfs_remove_group(&client->dev.kobj, &adm1031_group);
888681c6f7aSMark M. Hoffman 	sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt);
8898d5d45fbSJean Delvare 	if ((ret = i2c_detach_client(client)) != 0) {
8908d5d45fbSJean Delvare 		return ret;
8918d5d45fbSJean Delvare 	}
892943b0830SMark M. Hoffman 	kfree(data);
8938d5d45fbSJean Delvare 	return 0;
8948d5d45fbSJean Delvare }
8958d5d45fbSJean Delvare 
8968d5d45fbSJean Delvare static void adm1031_init_client(struct i2c_client *client)
8978d5d45fbSJean Delvare {
8988d5d45fbSJean Delvare 	unsigned int read_val;
8998d5d45fbSJean Delvare 	unsigned int mask;
9008d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
9018d5d45fbSJean Delvare 
9028d5d45fbSJean Delvare 	mask = (ADM1031_CONF2_PWM1_ENABLE | ADM1031_CONF2_TACH1_ENABLE);
9038d5d45fbSJean Delvare 	if (data->chip_type == adm1031) {
9048d5d45fbSJean Delvare 		mask |= (ADM1031_CONF2_PWM2_ENABLE |
9058d5d45fbSJean Delvare 			ADM1031_CONF2_TACH2_ENABLE);
9068d5d45fbSJean Delvare 	}
9078d5d45fbSJean Delvare 	/* Initialize the ADM1031 chip (enables fan speed reading ) */
9088d5d45fbSJean Delvare 	read_val = adm1031_read_value(client, ADM1031_REG_CONF2);
9098d5d45fbSJean Delvare 	if ((read_val | mask) != read_val) {
9108d5d45fbSJean Delvare 	    adm1031_write_value(client, ADM1031_REG_CONF2, read_val | mask);
9118d5d45fbSJean Delvare 	}
9128d5d45fbSJean Delvare 
9138d5d45fbSJean Delvare 	read_val = adm1031_read_value(client, ADM1031_REG_CONF1);
9148d5d45fbSJean Delvare 	if ((read_val | ADM1031_CONF1_MONITOR_ENABLE) != read_val) {
9158d5d45fbSJean Delvare 	    adm1031_write_value(client, ADM1031_REG_CONF1, read_val |
9168d5d45fbSJean Delvare 				ADM1031_CONF1_MONITOR_ENABLE);
9178d5d45fbSJean Delvare 	}
9188d5d45fbSJean Delvare 
9198d5d45fbSJean Delvare }
9208d5d45fbSJean Delvare 
9218d5d45fbSJean Delvare static struct adm1031_data *adm1031_update_device(struct device *dev)
9228d5d45fbSJean Delvare {
9238d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
9248d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
9258d5d45fbSJean Delvare 	int chan;
9268d5d45fbSJean Delvare 
9279a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
9288d5d45fbSJean Delvare 
9298d5d45fbSJean Delvare 	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
9308d5d45fbSJean Delvare 	    || !data->valid) {
9318d5d45fbSJean Delvare 
9328d5d45fbSJean Delvare 		dev_dbg(&client->dev, "Starting adm1031 update\n");
9338d5d45fbSJean Delvare 		for (chan = 0;
9348d5d45fbSJean Delvare 		     chan < ((data->chip_type == adm1031) ? 3 : 2); chan++) {
9358d5d45fbSJean Delvare 			u8 oldh, newh;
9368d5d45fbSJean Delvare 
9378d5d45fbSJean Delvare 			oldh =
9388d5d45fbSJean Delvare 			    adm1031_read_value(client, ADM1031_REG_TEMP(chan));
9398d5d45fbSJean Delvare 			data->ext_temp[chan] =
9408d5d45fbSJean Delvare 			    adm1031_read_value(client, ADM1031_REG_EXT_TEMP);
9418d5d45fbSJean Delvare 			newh =
9428d5d45fbSJean Delvare 			    adm1031_read_value(client, ADM1031_REG_TEMP(chan));
9438d5d45fbSJean Delvare 			if (newh != oldh) {
9448d5d45fbSJean Delvare 				data->ext_temp[chan] =
9458d5d45fbSJean Delvare 				    adm1031_read_value(client,
9468d5d45fbSJean Delvare 						       ADM1031_REG_EXT_TEMP);
9478d5d45fbSJean Delvare #ifdef DEBUG
9488d5d45fbSJean Delvare 				oldh =
9498d5d45fbSJean Delvare 				    adm1031_read_value(client,
9508d5d45fbSJean Delvare 						       ADM1031_REG_TEMP(chan));
9518d5d45fbSJean Delvare 
9528d5d45fbSJean Delvare 				/* oldh is actually newer */
9538d5d45fbSJean Delvare 				if (newh != oldh)
9548d5d45fbSJean Delvare 					dev_warn(&client->dev,
9558d5d45fbSJean Delvare 						 "Remote temperature may be "
9568d5d45fbSJean Delvare 						 "wrong.\n");
9578d5d45fbSJean Delvare #endif
9588d5d45fbSJean Delvare 			}
9598d5d45fbSJean Delvare 			data->temp[chan] = newh;
9608d5d45fbSJean Delvare 
9618d5d45fbSJean Delvare 			data->temp_min[chan] =
9628d5d45fbSJean Delvare 			    adm1031_read_value(client,
9638d5d45fbSJean Delvare 					       ADM1031_REG_TEMP_MIN(chan));
9648d5d45fbSJean Delvare 			data->temp_max[chan] =
9658d5d45fbSJean Delvare 			    adm1031_read_value(client,
9668d5d45fbSJean Delvare 					       ADM1031_REG_TEMP_MAX(chan));
9678d5d45fbSJean Delvare 			data->temp_crit[chan] =
9688d5d45fbSJean Delvare 			    adm1031_read_value(client,
9698d5d45fbSJean Delvare 					       ADM1031_REG_TEMP_CRIT(chan));
9708d5d45fbSJean Delvare 			data->auto_temp[chan] =
9718d5d45fbSJean Delvare 			    adm1031_read_value(client,
9728d5d45fbSJean Delvare 					       ADM1031_REG_AUTO_TEMP(chan));
9738d5d45fbSJean Delvare 
9748d5d45fbSJean Delvare 		}
9758d5d45fbSJean Delvare 
9768d5d45fbSJean Delvare 		data->conf1 = adm1031_read_value(client, ADM1031_REG_CONF1);
9778d5d45fbSJean Delvare 		data->conf2 = adm1031_read_value(client, ADM1031_REG_CONF2);
9788d5d45fbSJean Delvare 
9798d5d45fbSJean Delvare 		data->alarm = adm1031_read_value(client, ADM1031_REG_STATUS(0))
9808d5d45fbSJean Delvare 			     | (adm1031_read_value(client, ADM1031_REG_STATUS(1))
9818d5d45fbSJean Delvare 				<< 8);
9828d5d45fbSJean Delvare 		if (data->chip_type == adm1030) {
9838d5d45fbSJean Delvare 			data->alarm &= 0xc0ff;
9848d5d45fbSJean Delvare 		}
9858d5d45fbSJean Delvare 
9868d5d45fbSJean Delvare 		for (chan=0; chan<(data->chip_type == adm1030 ? 1 : 2); chan++) {
9878d5d45fbSJean Delvare 			data->fan_div[chan] =
9888d5d45fbSJean Delvare 			    adm1031_read_value(client, ADM1031_REG_FAN_DIV(chan));
9898d5d45fbSJean Delvare 			data->fan_min[chan] =
9908d5d45fbSJean Delvare 			    adm1031_read_value(client, ADM1031_REG_FAN_MIN(chan));
9918d5d45fbSJean Delvare 			data->fan[chan] =
9928d5d45fbSJean Delvare 			    adm1031_read_value(client, ADM1031_REG_FAN_SPEED(chan));
9938d5d45fbSJean Delvare 			data->pwm[chan] =
9948d5d45fbSJean Delvare 			    0xf & (adm1031_read_value(client, ADM1031_REG_PWM) >>
9958d5d45fbSJean Delvare 				   (4*chan));
9968d5d45fbSJean Delvare 		}
9978d5d45fbSJean Delvare 		data->last_updated = jiffies;
9988d5d45fbSJean Delvare 		data->valid = 1;
9998d5d45fbSJean Delvare 	}
10008d5d45fbSJean Delvare 
10019a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
10028d5d45fbSJean Delvare 
10038d5d45fbSJean Delvare 	return data;
10048d5d45fbSJean Delvare }
10058d5d45fbSJean Delvare 
10068d5d45fbSJean Delvare static int __init sensors_adm1031_init(void)
10078d5d45fbSJean Delvare {
10088d5d45fbSJean Delvare 	return i2c_add_driver(&adm1031_driver);
10098d5d45fbSJean Delvare }
10108d5d45fbSJean Delvare 
10118d5d45fbSJean Delvare static void __exit sensors_adm1031_exit(void)
10128d5d45fbSJean Delvare {
10138d5d45fbSJean Delvare 	i2c_del_driver(&adm1031_driver);
10148d5d45fbSJean Delvare }
10158d5d45fbSJean Delvare 
10168d5d45fbSJean Delvare MODULE_AUTHOR("Alexandre d'Alton <alex@alexdalton.org>");
10178d5d45fbSJean Delvare MODULE_DESCRIPTION("ADM1031/ADM1030 driver");
10188d5d45fbSJean Delvare MODULE_LICENSE("GPL");
10198d5d45fbSJean Delvare 
10208d5d45fbSJean Delvare module_init(sensors_adm1031_init);
10218d5d45fbSJean Delvare module_exit(sensors_adm1031_exit);
1022