xref: /openbmc/linux/drivers/hwmon/adm1031.c (revision c801082d7d41928b2348507ecdc841d5ebad3490)
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>
30*c801082dSJean 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 */
648d5d45fbSJean Delvare static 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 {
738d5d45fbSJean Delvare 	struct i2c_client client;
741beeffe4STony Jones 	struct device *hwmon_dev;
759a61bf63SIngo Molnar 	struct mutex update_lock;
768d5d45fbSJean Delvare 	int chip_type;
778d5d45fbSJean Delvare 	char valid;		/* !=0 if following fields are valid */
788d5d45fbSJean Delvare 	unsigned long last_updated;	/* In jiffies */
798d5d45fbSJean Delvare 	/* The chan_select_table contains the possible configurations for
808d5d45fbSJean Delvare 	 * auto fan control.
818d5d45fbSJean Delvare 	 */
826d6006b8SJean Delvare 	const auto_chan_table_t *chan_select_table;
838d5d45fbSJean Delvare 	u16 alarm;
848d5d45fbSJean Delvare 	u8 conf1;
858d5d45fbSJean Delvare 	u8 conf2;
868d5d45fbSJean Delvare 	u8 fan[2];
878d5d45fbSJean Delvare 	u8 fan_div[2];
888d5d45fbSJean Delvare 	u8 fan_min[2];
898d5d45fbSJean Delvare 	u8 pwm[2];
908d5d45fbSJean Delvare 	u8 old_pwm[2];
918d5d45fbSJean Delvare 	s8 temp[3];
928d5d45fbSJean Delvare 	u8 ext_temp[3];
938d5d45fbSJean Delvare 	u8 auto_temp[3];
948d5d45fbSJean Delvare 	u8 auto_temp_min[3];
958d5d45fbSJean Delvare 	u8 auto_temp_off[3];
968d5d45fbSJean Delvare 	u8 auto_temp_max[3];
978d5d45fbSJean Delvare 	s8 temp_min[3];
988d5d45fbSJean Delvare 	s8 temp_max[3];
998d5d45fbSJean Delvare 	s8 temp_crit[3];
1008d5d45fbSJean Delvare };
1018d5d45fbSJean Delvare 
1028d5d45fbSJean Delvare static int adm1031_attach_adapter(struct i2c_adapter *adapter);
1038d5d45fbSJean Delvare static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind);
1048d5d45fbSJean Delvare static void adm1031_init_client(struct i2c_client *client);
1058d5d45fbSJean Delvare static int adm1031_detach_client(struct i2c_client *client);
1068d5d45fbSJean Delvare static struct adm1031_data *adm1031_update_device(struct device *dev);
1078d5d45fbSJean Delvare 
1088d5d45fbSJean Delvare /* This is the driver that will be inserted */
1098d5d45fbSJean Delvare static struct i2c_driver adm1031_driver = {
110cdaf7934SLaurent Riffard 	.driver = {
1118d5d45fbSJean Delvare 		.name = "adm1031",
112cdaf7934SLaurent Riffard 	},
1138d5d45fbSJean Delvare 	.attach_adapter = adm1031_attach_adapter,
1148d5d45fbSJean Delvare 	.detach_client = adm1031_detach_client,
1158d5d45fbSJean Delvare };
1168d5d45fbSJean Delvare 
1178d5d45fbSJean Delvare static inline u8 adm1031_read_value(struct i2c_client *client, u8 reg)
1188d5d45fbSJean Delvare {
1198d5d45fbSJean Delvare 	return i2c_smbus_read_byte_data(client, reg);
1208d5d45fbSJean Delvare }
1218d5d45fbSJean Delvare 
1228d5d45fbSJean Delvare static inline int
1238d5d45fbSJean Delvare adm1031_write_value(struct i2c_client *client, u8 reg, unsigned int value)
1248d5d45fbSJean Delvare {
1258d5d45fbSJean Delvare 	return i2c_smbus_write_byte_data(client, reg, value);
1268d5d45fbSJean Delvare }
1278d5d45fbSJean Delvare 
1288d5d45fbSJean Delvare 
1298d5d45fbSJean Delvare #define TEMP_TO_REG(val)		(((val) < 0 ? ((val - 500) / 1000) : \
1308d5d45fbSJean Delvare 					((val + 500) / 1000)))
1318d5d45fbSJean Delvare 
1328d5d45fbSJean Delvare #define TEMP_FROM_REG(val)		((val) * 1000)
1338d5d45fbSJean Delvare 
1348d5d45fbSJean Delvare #define TEMP_FROM_REG_EXT(val, ext)	(TEMP_FROM_REG(val) + (ext) * 125)
1358d5d45fbSJean Delvare 
1368d5d45fbSJean Delvare #define FAN_FROM_REG(reg, div)		((reg) ? (11250 * 60) / ((reg) * (div)) : 0)
1378d5d45fbSJean Delvare 
1388d5d45fbSJean Delvare static int FAN_TO_REG(int reg, int div)
1398d5d45fbSJean Delvare {
1408d5d45fbSJean Delvare 	int tmp;
1418d5d45fbSJean Delvare 	tmp = FAN_FROM_REG(SENSORS_LIMIT(reg, 0, 65535), div);
1428d5d45fbSJean Delvare 	return tmp > 255 ? 255 : tmp;
1438d5d45fbSJean Delvare }
1448d5d45fbSJean Delvare 
1458d5d45fbSJean Delvare #define FAN_DIV_FROM_REG(reg)		(1<<(((reg)&0xc0)>>6))
1468d5d45fbSJean Delvare 
1478d5d45fbSJean Delvare #define PWM_TO_REG(val)			(SENSORS_LIMIT((val), 0, 255) >> 4)
1488d5d45fbSJean Delvare #define PWM_FROM_REG(val)		((val) << 4)
1498d5d45fbSJean Delvare 
1508d5d45fbSJean Delvare #define FAN_CHAN_FROM_REG(reg)		(((reg) >> 5) & 7)
1518d5d45fbSJean Delvare #define FAN_CHAN_TO_REG(val, reg)	\
1528d5d45fbSJean Delvare 	(((reg) & 0x1F) | (((val) << 5) & 0xe0))
1538d5d45fbSJean Delvare 
1548d5d45fbSJean Delvare #define AUTO_TEMP_MIN_TO_REG(val, reg)	\
1558d5d45fbSJean Delvare 	((((val)/500) & 0xf8)|((reg) & 0x7))
1568d5d45fbSJean Delvare #define AUTO_TEMP_RANGE_FROM_REG(reg)	(5000 * (1<< ((reg)&0x7)))
1578d5d45fbSJean Delvare #define AUTO_TEMP_MIN_FROM_REG(reg)	(1000 * ((((reg) >> 3) & 0x1f) << 2))
1588d5d45fbSJean Delvare 
1598d5d45fbSJean Delvare #define AUTO_TEMP_MIN_FROM_REG_DEG(reg)	((((reg) >> 3) & 0x1f) << 2)
1608d5d45fbSJean Delvare 
1618d5d45fbSJean Delvare #define AUTO_TEMP_OFF_FROM_REG(reg)		\
1628d5d45fbSJean Delvare 	(AUTO_TEMP_MIN_FROM_REG(reg) - 5000)
1638d5d45fbSJean Delvare 
1648d5d45fbSJean Delvare #define AUTO_TEMP_MAX_FROM_REG(reg)		\
1658d5d45fbSJean Delvare 	(AUTO_TEMP_RANGE_FROM_REG(reg) +	\
1668d5d45fbSJean Delvare 	AUTO_TEMP_MIN_FROM_REG(reg))
1678d5d45fbSJean Delvare 
1688d5d45fbSJean Delvare static int AUTO_TEMP_MAX_TO_REG(int val, int reg, int pwm)
1698d5d45fbSJean Delvare {
1708d5d45fbSJean Delvare 	int ret;
1718d5d45fbSJean Delvare 	int range = val - AUTO_TEMP_MIN_FROM_REG(reg);
1728d5d45fbSJean Delvare 
1738d5d45fbSJean Delvare 	range = ((val - AUTO_TEMP_MIN_FROM_REG(reg))*10)/(16 - pwm);
1748d5d45fbSJean Delvare 	ret = ((reg & 0xf8) |
1758d5d45fbSJean Delvare 	       (range < 10000 ? 0 :
1768d5d45fbSJean Delvare 		range < 20000 ? 1 :
1778d5d45fbSJean Delvare 		range < 40000 ? 2 : range < 80000 ? 3 : 4));
1788d5d45fbSJean Delvare 	return ret;
1798d5d45fbSJean Delvare }
1808d5d45fbSJean Delvare 
1818d5d45fbSJean Delvare /* FAN auto control */
1828d5d45fbSJean Delvare #define GET_FAN_AUTO_BITFIELD(data, idx)	\
1838d5d45fbSJean Delvare 	(*(data)->chan_select_table)[FAN_CHAN_FROM_REG((data)->conf1)][idx%2]
1848d5d45fbSJean Delvare 
1858d5d45fbSJean Delvare /* The tables below contains the possible values for the auto fan
1868d5d45fbSJean Delvare  * control bitfields. the index in the table is the register value.
1878d5d45fbSJean Delvare  * MSb is the auto fan control enable bit, so the four first entries
1888d5d45fbSJean Delvare  * in the table disables auto fan control when both bitfields are zero.
1898d5d45fbSJean Delvare  */
1906d6006b8SJean Delvare static const auto_chan_table_t auto_channel_select_table_adm1031 = {
1918d5d45fbSJean Delvare 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
1928d5d45fbSJean Delvare 	{ 2 /* 0b010 */ , 4 /* 0b100 */ },
1938d5d45fbSJean Delvare 	{ 2 /* 0b010 */ , 2 /* 0b010 */ },
1948d5d45fbSJean Delvare 	{ 4 /* 0b100 */ , 4 /* 0b100 */ },
1958d5d45fbSJean Delvare 	{ 7 /* 0b111 */ , 7 /* 0b111 */ },
1968d5d45fbSJean Delvare };
1978d5d45fbSJean Delvare 
1986d6006b8SJean Delvare static const auto_chan_table_t auto_channel_select_table_adm1030 = {
1998d5d45fbSJean Delvare 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2008d5d45fbSJean Delvare 	{ 2 /* 0b10 */		, 0 },
2018d5d45fbSJean Delvare 	{ 0xff /* invalid */	, 0 },
2028d5d45fbSJean Delvare 	{ 0xff /* invalid */	, 0 },
2038d5d45fbSJean Delvare 	{ 3 /* 0b11 */		, 0 },
2048d5d45fbSJean Delvare };
2058d5d45fbSJean Delvare 
2068d5d45fbSJean Delvare /* That function checks if a bitfield is valid and returns the other bitfield
2078d5d45fbSJean Delvare  * nearest match if no exact match where found.
2088d5d45fbSJean Delvare  */
2098d5d45fbSJean Delvare static int
2108d5d45fbSJean Delvare get_fan_auto_nearest(struct adm1031_data *data,
2118d5d45fbSJean Delvare 		     int chan, u8 val, u8 reg, u8 * new_reg)
2128d5d45fbSJean Delvare {
2138d5d45fbSJean Delvare 	int i;
2148d5d45fbSJean Delvare 	int first_match = -1, exact_match = -1;
2158d5d45fbSJean Delvare 	u8 other_reg_val =
2168d5d45fbSJean Delvare 	    (*data->chan_select_table)[FAN_CHAN_FROM_REG(reg)][chan ? 0 : 1];
2178d5d45fbSJean Delvare 
2188d5d45fbSJean Delvare 	if (val == 0) {
2198d5d45fbSJean Delvare 		*new_reg = 0;
2208d5d45fbSJean Delvare 		return 0;
2218d5d45fbSJean Delvare 	}
2228d5d45fbSJean Delvare 
2238d5d45fbSJean Delvare 	for (i = 0; i < 8; i++) {
2248d5d45fbSJean Delvare 		if ((val == (*data->chan_select_table)[i][chan]) &&
2258d5d45fbSJean Delvare 		    ((*data->chan_select_table)[i][chan ? 0 : 1] ==
2268d5d45fbSJean Delvare 		     other_reg_val)) {
2278d5d45fbSJean Delvare 			/* We found an exact match */
2288d5d45fbSJean Delvare 			exact_match = i;
2298d5d45fbSJean Delvare 			break;
2308d5d45fbSJean Delvare 		} else if (val == (*data->chan_select_table)[i][chan] &&
2318d5d45fbSJean Delvare 			   first_match == -1) {
2326d6006b8SJean Delvare 			/* Save the first match in case of an exact match has
2336d6006b8SJean Delvare 			 * not been found
2348d5d45fbSJean Delvare 			 */
2358d5d45fbSJean Delvare 			first_match = i;
2368d5d45fbSJean Delvare 		}
2378d5d45fbSJean Delvare 	}
2388d5d45fbSJean Delvare 
2398d5d45fbSJean Delvare 	if (exact_match >= 0) {
2408d5d45fbSJean Delvare 		*new_reg = exact_match;
2418d5d45fbSJean Delvare 	} else if (first_match >= 0) {
2428d5d45fbSJean Delvare 		*new_reg = first_match;
2438d5d45fbSJean Delvare 	} else {
2448d5d45fbSJean Delvare 		return -EINVAL;
2458d5d45fbSJean Delvare 	}
2468d5d45fbSJean Delvare 	return 0;
2478d5d45fbSJean Delvare }
2488d5d45fbSJean Delvare 
249*c801082dSJean Delvare static ssize_t show_fan_auto_channel(struct device *dev,
250*c801082dSJean Delvare 				     struct device_attribute *attr, char *buf)
2518d5d45fbSJean Delvare {
252*c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
2538d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
2548d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", GET_FAN_AUTO_BITFIELD(data, nr));
2558d5d45fbSJean Delvare }
2568d5d45fbSJean Delvare 
2578d5d45fbSJean Delvare static ssize_t
258*c801082dSJean Delvare set_fan_auto_channel(struct device *dev, struct device_attribute *attr,
259*c801082dSJean Delvare 		     const char *buf, size_t count)
2608d5d45fbSJean Delvare {
2618d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
2628d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
263*c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
2648d5d45fbSJean Delvare 	int val = simple_strtol(buf, NULL, 10);
2658d5d45fbSJean Delvare 	u8 reg;
2668d5d45fbSJean Delvare 	int ret;
2678d5d45fbSJean Delvare 	u8 old_fan_mode;
2688d5d45fbSJean Delvare 
2698d5d45fbSJean Delvare 	old_fan_mode = data->conf1;
2708d5d45fbSJean Delvare 
2719a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
2728d5d45fbSJean Delvare 
2738d5d45fbSJean Delvare 	if ((ret = get_fan_auto_nearest(data, nr, val, data->conf1, &reg))) {
2749a61bf63SIngo Molnar 		mutex_unlock(&data->update_lock);
2758d5d45fbSJean Delvare 		return ret;
2768d5d45fbSJean Delvare 	}
2776d6006b8SJean Delvare 	data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1);
2786d6006b8SJean Delvare 	if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) ^
2798d5d45fbSJean Delvare 	    (old_fan_mode & ADM1031_CONF1_AUTO_MODE)) {
2808d5d45fbSJean Delvare 		if (data->conf1 & ADM1031_CONF1_AUTO_MODE){
2818d5d45fbSJean Delvare 			/* Switch to Auto Fan Mode
2828d5d45fbSJean Delvare 			 * Save PWM registers
2838d5d45fbSJean Delvare 			 * Set PWM registers to 33% Both */
2848d5d45fbSJean Delvare 			data->old_pwm[0] = data->pwm[0];
2858d5d45fbSJean Delvare 			data->old_pwm[1] = data->pwm[1];
2868d5d45fbSJean Delvare 			adm1031_write_value(client, ADM1031_REG_PWM, 0x55);
2878d5d45fbSJean Delvare 		} else {
2888d5d45fbSJean Delvare 			/* Switch to Manual Mode */
2898d5d45fbSJean Delvare 			data->pwm[0] = data->old_pwm[0];
2908d5d45fbSJean Delvare 			data->pwm[1] = data->old_pwm[1];
2918d5d45fbSJean Delvare 			/* Restore PWM registers */
2928d5d45fbSJean Delvare 			adm1031_write_value(client, ADM1031_REG_PWM,
2938d5d45fbSJean Delvare 					    data->pwm[0] | (data->pwm[1] << 4));
2948d5d45fbSJean Delvare 		}
2958d5d45fbSJean Delvare 	}
2968d5d45fbSJean Delvare 	data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1);
2978d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_CONF1, data->conf1);
2989a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
2998d5d45fbSJean Delvare 	return count;
3008d5d45fbSJean Delvare }
3018d5d45fbSJean Delvare 
302*c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_fan1_channel, S_IRUGO | S_IWUSR,
303*c801082dSJean Delvare 		show_fan_auto_channel, set_fan_auto_channel, 0);
304*c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_fan2_channel, S_IRUGO | S_IWUSR,
305*c801082dSJean Delvare 		show_fan_auto_channel, set_fan_auto_channel, 1);
3068d5d45fbSJean Delvare 
3078d5d45fbSJean Delvare /* Auto Temps */
308*c801082dSJean Delvare static ssize_t show_auto_temp_off(struct device *dev,
309*c801082dSJean Delvare 				  struct device_attribute *attr, char *buf)
3108d5d45fbSJean Delvare {
311*c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
3128d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
3138d5d45fbSJean Delvare 	return sprintf(buf, "%d\n",
3148d5d45fbSJean Delvare 		       AUTO_TEMP_OFF_FROM_REG(data->auto_temp[nr]));
3158d5d45fbSJean Delvare }
316*c801082dSJean Delvare static ssize_t show_auto_temp_min(struct device *dev,
317*c801082dSJean Delvare 				  struct device_attribute *attr, char *buf)
3188d5d45fbSJean Delvare {
319*c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
3208d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
3218d5d45fbSJean Delvare 	return sprintf(buf, "%d\n",
3228d5d45fbSJean Delvare 		       AUTO_TEMP_MIN_FROM_REG(data->auto_temp[nr]));
3238d5d45fbSJean Delvare }
3248d5d45fbSJean Delvare static ssize_t
325*c801082dSJean Delvare set_auto_temp_min(struct device *dev, struct device_attribute *attr,
326*c801082dSJean Delvare 		  const char *buf, size_t count)
3278d5d45fbSJean Delvare {
3288d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
3298d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
330*c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
3318d5d45fbSJean Delvare 	int val = simple_strtol(buf, NULL, 10);
3328d5d45fbSJean Delvare 
3339a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
3348d5d45fbSJean Delvare 	data->auto_temp[nr] = AUTO_TEMP_MIN_TO_REG(val, data->auto_temp[nr]);
3358d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr),
3368d5d45fbSJean Delvare 			    data->auto_temp[nr]);
3379a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
3388d5d45fbSJean Delvare 	return count;
3398d5d45fbSJean Delvare }
340*c801082dSJean Delvare static ssize_t show_auto_temp_max(struct device *dev,
341*c801082dSJean Delvare 				  struct device_attribute *attr, char *buf)
3428d5d45fbSJean Delvare {
343*c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
3448d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
3458d5d45fbSJean Delvare 	return sprintf(buf, "%d\n",
3468d5d45fbSJean Delvare 		       AUTO_TEMP_MAX_FROM_REG(data->auto_temp[nr]));
3478d5d45fbSJean Delvare }
3488d5d45fbSJean Delvare static ssize_t
349*c801082dSJean Delvare set_auto_temp_max(struct device *dev, struct device_attribute *attr,
350*c801082dSJean Delvare 		  const char *buf, size_t count)
3518d5d45fbSJean Delvare {
3528d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
3538d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
354*c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
3558d5d45fbSJean Delvare 	int val = simple_strtol(buf, NULL, 10);
3568d5d45fbSJean Delvare 
3579a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
3588d5d45fbSJean Delvare 	data->temp_max[nr] = AUTO_TEMP_MAX_TO_REG(val, data->auto_temp[nr], data->pwm[nr]);
3598d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr),
3608d5d45fbSJean Delvare 			    data->temp_max[nr]);
3619a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
3628d5d45fbSJean Delvare 	return count;
3638d5d45fbSJean Delvare }
3648d5d45fbSJean Delvare 
3658d5d45fbSJean Delvare #define auto_temp_reg(offset)						\
366*c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_temp##offset##_off, S_IRUGO,		\
367*c801082dSJean Delvare 		show_auto_temp_off, NULL, offset - 1);			\
368*c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_temp##offset##_min, S_IRUGO | S_IWUSR,	\
369*c801082dSJean Delvare 		show_auto_temp_min, set_auto_temp_min, offset - 1);	\
370*c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_temp##offset##_max, S_IRUGO | S_IWUSR,	\
371*c801082dSJean Delvare 		show_auto_temp_max, set_auto_temp_max, offset - 1)
3728d5d45fbSJean Delvare 
3738d5d45fbSJean Delvare auto_temp_reg(1);
3748d5d45fbSJean Delvare auto_temp_reg(2);
3758d5d45fbSJean Delvare auto_temp_reg(3);
3768d5d45fbSJean Delvare 
3778d5d45fbSJean Delvare /* pwm */
378*c801082dSJean Delvare static ssize_t show_pwm(struct device *dev,
379*c801082dSJean Delvare 			struct device_attribute *attr, char *buf)
3808d5d45fbSJean Delvare {
381*c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
3828d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
3838d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm[nr]));
3848d5d45fbSJean Delvare }
385*c801082dSJean Delvare static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
386*c801082dSJean Delvare 		       const char *buf, size_t count)
3878d5d45fbSJean Delvare {
3888d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
3898d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
390*c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
3918d5d45fbSJean Delvare 	int val = simple_strtol(buf, NULL, 10);
3928d5d45fbSJean Delvare 	int reg;
3938d5d45fbSJean Delvare 
3949a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
3958d5d45fbSJean Delvare 	if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) &&
3968d5d45fbSJean Delvare 	    (((val>>4) & 0xf) != 5)) {
3978d5d45fbSJean Delvare 		/* In automatic mode, the only PWM accepted is 33% */
3989a61bf63SIngo Molnar 		mutex_unlock(&data->update_lock);
3998d5d45fbSJean Delvare 		return -EINVAL;
4008d5d45fbSJean Delvare 	}
4018d5d45fbSJean Delvare 	data->pwm[nr] = PWM_TO_REG(val);
4028d5d45fbSJean Delvare 	reg = adm1031_read_value(client, ADM1031_REG_PWM);
4038d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_PWM,
4048d5d45fbSJean Delvare 			    nr ? ((data->pwm[nr] << 4) & 0xf0) | (reg & 0xf)
4058d5d45fbSJean Delvare 			    : (data->pwm[nr] & 0xf) | (reg & 0xf0));
4069a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
4078d5d45fbSJean Delvare 	return count;
4088d5d45fbSJean Delvare }
4098d5d45fbSJean Delvare 
410*c801082dSJean Delvare static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 0);
411*c801082dSJean Delvare static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 1);
412*c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_fan1_min_pwm, S_IRUGO | S_IWUSR,
413*c801082dSJean Delvare 		show_pwm, set_pwm, 0);
414*c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_fan2_min_pwm, S_IRUGO | S_IWUSR,
415*c801082dSJean Delvare 		show_pwm, set_pwm, 1);
4168d5d45fbSJean Delvare 
4178d5d45fbSJean Delvare /* Fans */
4188d5d45fbSJean Delvare 
4198d5d45fbSJean Delvare /*
4208d5d45fbSJean Delvare  * That function checks the cases where the fan reading is not
4218d5d45fbSJean Delvare  * relevant.  It is used to provide 0 as fan reading when the fan is
4228d5d45fbSJean Delvare  * not supposed to run
4238d5d45fbSJean Delvare  */
4248d5d45fbSJean Delvare static int trust_fan_readings(struct adm1031_data *data, int chan)
4258d5d45fbSJean Delvare {
4268d5d45fbSJean Delvare 	int res = 0;
4278d5d45fbSJean Delvare 
4288d5d45fbSJean Delvare 	if (data->conf1 & ADM1031_CONF1_AUTO_MODE) {
4298d5d45fbSJean Delvare 		switch (data->conf1 & 0x60) {
4308d5d45fbSJean Delvare 		case 0x00:	/* remote temp1 controls fan1 remote temp2 controls fan2 */
4318d5d45fbSJean Delvare 			res = data->temp[chan+1] >=
4328d5d45fbSJean Delvare 			      AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[chan+1]);
4338d5d45fbSJean Delvare 			break;
4348d5d45fbSJean Delvare 		case 0x20:	/* remote temp1 controls both fans */
4358d5d45fbSJean Delvare 			res =
4368d5d45fbSJean Delvare 			    data->temp[1] >=
4378d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[1]);
4388d5d45fbSJean Delvare 			break;
4398d5d45fbSJean Delvare 		case 0x40:	/* remote temp2 controls both fans */
4408d5d45fbSJean Delvare 			res =
4418d5d45fbSJean Delvare 			    data->temp[2] >=
4428d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[2]);
4438d5d45fbSJean Delvare 			break;
4448d5d45fbSJean Delvare 		case 0x60:	/* max controls both fans */
4458d5d45fbSJean Delvare 			res =
4468d5d45fbSJean Delvare 			    data->temp[0] >=
4478d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[0])
4488d5d45fbSJean Delvare 			    || data->temp[1] >=
4498d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[1])
4508d5d45fbSJean Delvare 			    || (data->chip_type == adm1031
4518d5d45fbSJean Delvare 				&& data->temp[2] >=
4528d5d45fbSJean Delvare 				AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[2]));
4538d5d45fbSJean Delvare 			break;
4548d5d45fbSJean Delvare 		}
4558d5d45fbSJean Delvare 	} else {
4568d5d45fbSJean Delvare 		res = data->pwm[chan] > 0;
4578d5d45fbSJean Delvare 	}
4588d5d45fbSJean Delvare 	return res;
4598d5d45fbSJean Delvare }
4608d5d45fbSJean Delvare 
4618d5d45fbSJean Delvare 
462*c801082dSJean Delvare static ssize_t show_fan(struct device *dev,
463*c801082dSJean Delvare 			struct device_attribute *attr, char *buf)
4648d5d45fbSJean Delvare {
465*c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4668d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
4678d5d45fbSJean Delvare 	int value;
4688d5d45fbSJean Delvare 
4698d5d45fbSJean Delvare 	value = trust_fan_readings(data, nr) ? FAN_FROM_REG(data->fan[nr],
4708d5d45fbSJean Delvare 				 FAN_DIV_FROM_REG(data->fan_div[nr])) : 0;
4718d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", value);
4728d5d45fbSJean Delvare }
4738d5d45fbSJean Delvare 
474*c801082dSJean Delvare static ssize_t show_fan_div(struct device *dev,
475*c801082dSJean Delvare 			    struct device_attribute *attr, char *buf)
4768d5d45fbSJean Delvare {
477*c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4788d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
4798d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", FAN_DIV_FROM_REG(data->fan_div[nr]));
4808d5d45fbSJean Delvare }
481*c801082dSJean Delvare static ssize_t show_fan_min(struct device *dev,
482*c801082dSJean Delvare 			    struct device_attribute *attr, char *buf)
4838d5d45fbSJean Delvare {
484*c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4858d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
4868d5d45fbSJean Delvare 	return sprintf(buf, "%d\n",
4878d5d45fbSJean Delvare 		       FAN_FROM_REG(data->fan_min[nr],
4888d5d45fbSJean Delvare 				    FAN_DIV_FROM_REG(data->fan_div[nr])));
4898d5d45fbSJean Delvare }
490*c801082dSJean Delvare static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
491*c801082dSJean Delvare 			   const char *buf, size_t count)
4928d5d45fbSJean Delvare {
4938d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
4948d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
495*c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4968d5d45fbSJean Delvare 	int val = simple_strtol(buf, NULL, 10);
4978d5d45fbSJean Delvare 
4989a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
4998d5d45fbSJean Delvare 	if (val) {
5008d5d45fbSJean Delvare 		data->fan_min[nr] =
5018d5d45fbSJean Delvare 			FAN_TO_REG(val, FAN_DIV_FROM_REG(data->fan_div[nr]));
5028d5d45fbSJean Delvare 	} else {
5038d5d45fbSJean Delvare 		data->fan_min[nr] = 0xff;
5048d5d45fbSJean Delvare 	}
5058d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), data->fan_min[nr]);
5069a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
5078d5d45fbSJean Delvare 	return count;
5088d5d45fbSJean Delvare }
509*c801082dSJean Delvare static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
510*c801082dSJean Delvare 			   const char *buf, size_t count)
5118d5d45fbSJean Delvare {
5128d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
5138d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
514*c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
5158d5d45fbSJean Delvare 	int val = simple_strtol(buf, NULL, 10);
5168d5d45fbSJean Delvare 	u8 tmp;
5178d5d45fbSJean Delvare 	int old_div;
5188d5d45fbSJean Delvare 	int new_min;
5198d5d45fbSJean Delvare 
5208d5d45fbSJean Delvare 	tmp = val == 8 ? 0xc0 :
5218d5d45fbSJean Delvare 	      val == 4 ? 0x80 :
5228d5d45fbSJean Delvare 	      val == 2 ? 0x40 :
5238d5d45fbSJean Delvare 	      val == 1 ? 0x00 :
5248d5d45fbSJean Delvare 	      0xff;
5258d5d45fbSJean Delvare 	if (tmp == 0xff)
5268d5d45fbSJean Delvare 		return -EINVAL;
5278d5d45fbSJean Delvare 
5289a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
52938a1f0e9SJean Delvare 	/* Get fresh readings */
53038a1f0e9SJean Delvare 	data->fan_div[nr] = adm1031_read_value(client,
53138a1f0e9SJean Delvare 					       ADM1031_REG_FAN_DIV(nr));
53238a1f0e9SJean Delvare 	data->fan_min[nr] = adm1031_read_value(client,
53338a1f0e9SJean Delvare 					       ADM1031_REG_FAN_MIN(nr));
53438a1f0e9SJean Delvare 
53538a1f0e9SJean Delvare 	/* Write the new clock divider and fan min */
5368d5d45fbSJean Delvare 	old_div = FAN_DIV_FROM_REG(data->fan_div[nr]);
5376d6006b8SJean Delvare 	data->fan_div[nr] = tmp | (0x3f & data->fan_div[nr]);
5386d6006b8SJean Delvare 	new_min = data->fan_min[nr] * old_div / val;
5398d5d45fbSJean Delvare 	data->fan_min[nr] = new_min > 0xff ? 0xff : new_min;
5408d5d45fbSJean Delvare 
5418d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_FAN_DIV(nr),
5428d5d45fbSJean Delvare 			    data->fan_div[nr]);
5438d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr),
5448d5d45fbSJean Delvare 			    data->fan_min[nr]);
54538a1f0e9SJean Delvare 
54638a1f0e9SJean Delvare 	/* Invalidate the cache: fan speed is no longer valid */
54738a1f0e9SJean Delvare 	data->valid = 0;
5489a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
5498d5d45fbSJean Delvare 	return count;
5508d5d45fbSJean Delvare }
5518d5d45fbSJean Delvare 
5528d5d45fbSJean Delvare #define fan_offset(offset)						\
553*c801082dSJean Delvare static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO,			\
554*c801082dSJean Delvare 		show_fan, NULL, offset - 1);				\
555*c801082dSJean Delvare static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,		\
556*c801082dSJean Delvare 		show_fan_min, set_fan_min, offset - 1);			\
557*c801082dSJean Delvare static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR,		\
558*c801082dSJean Delvare 		show_fan_div, set_fan_div, offset - 1)
5598d5d45fbSJean Delvare 
5608d5d45fbSJean Delvare fan_offset(1);
5618d5d45fbSJean Delvare fan_offset(2);
5628d5d45fbSJean Delvare 
5638d5d45fbSJean Delvare 
5648d5d45fbSJean Delvare /* Temps */
565*c801082dSJean Delvare static ssize_t show_temp(struct device *dev,
566*c801082dSJean Delvare 			 struct device_attribute *attr, char *buf)
5678d5d45fbSJean Delvare {
568*c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
5698d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
5708d5d45fbSJean Delvare 	int ext;
5718d5d45fbSJean Delvare 	ext = nr == 0 ?
5728d5d45fbSJean Delvare 	    ((data->ext_temp[nr] >> 6) & 0x3) * 2 :
5738d5d45fbSJean Delvare 	    (((data->ext_temp[nr] >> ((nr - 1) * 3)) & 7));
5748d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG_EXT(data->temp[nr], ext));
5758d5d45fbSJean Delvare }
576*c801082dSJean Delvare static ssize_t show_temp_min(struct device *dev,
577*c801082dSJean Delvare 			     struct device_attribute *attr, char *buf)
5788d5d45fbSJean Delvare {
579*c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
5808d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
5818d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr]));
5828d5d45fbSJean Delvare }
583*c801082dSJean Delvare static ssize_t show_temp_max(struct device *dev,
584*c801082dSJean Delvare 			     struct device_attribute *attr, char *buf)
5858d5d45fbSJean Delvare {
586*c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
5878d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
5888d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr]));
5898d5d45fbSJean Delvare }
590*c801082dSJean Delvare static ssize_t show_temp_crit(struct device *dev,
591*c801082dSJean Delvare 			      struct device_attribute *attr, char *buf)
5928d5d45fbSJean Delvare {
593*c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
5948d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
5958d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[nr]));
5968d5d45fbSJean Delvare }
597*c801082dSJean Delvare static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
598*c801082dSJean Delvare 			    const char *buf, size_t count)
5998d5d45fbSJean Delvare {
6008d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
6018d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
602*c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
6038d5d45fbSJean Delvare 	int val;
6048d5d45fbSJean Delvare 
6058d5d45fbSJean Delvare 	val = simple_strtol(buf, NULL, 10);
6068d5d45fbSJean Delvare 	val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875);
6079a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
6088d5d45fbSJean Delvare 	data->temp_min[nr] = TEMP_TO_REG(val);
6098d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_TEMP_MIN(nr),
6108d5d45fbSJean Delvare 			    data->temp_min[nr]);
6119a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
6128d5d45fbSJean Delvare 	return count;
6138d5d45fbSJean Delvare }
614*c801082dSJean Delvare static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
615*c801082dSJean Delvare 			    const char *buf, size_t count)
6168d5d45fbSJean Delvare {
6178d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
6188d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
619*c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
6208d5d45fbSJean Delvare 	int val;
6218d5d45fbSJean Delvare 
6228d5d45fbSJean Delvare 	val = simple_strtol(buf, NULL, 10);
6238d5d45fbSJean Delvare 	val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875);
6249a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
6258d5d45fbSJean Delvare 	data->temp_max[nr] = TEMP_TO_REG(val);
6268d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_TEMP_MAX(nr),
6278d5d45fbSJean Delvare 			    data->temp_max[nr]);
6289a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
6298d5d45fbSJean Delvare 	return count;
6308d5d45fbSJean Delvare }
631*c801082dSJean Delvare static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr,
632*c801082dSJean Delvare 			     const char *buf, size_t count)
6338d5d45fbSJean Delvare {
6348d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
6358d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
636*c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
6378d5d45fbSJean Delvare 	int val;
6388d5d45fbSJean Delvare 
6398d5d45fbSJean Delvare 	val = simple_strtol(buf, NULL, 10);
6408d5d45fbSJean Delvare 	val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875);
6419a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
6428d5d45fbSJean Delvare 	data->temp_crit[nr] = TEMP_TO_REG(val);
6438d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_TEMP_CRIT(nr),
6448d5d45fbSJean Delvare 			    data->temp_crit[nr]);
6459a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
6468d5d45fbSJean Delvare 	return count;
6478d5d45fbSJean Delvare }
6488d5d45fbSJean Delvare 
6498d5d45fbSJean Delvare #define temp_reg(offset)						\
650*c801082dSJean Delvare static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO,		\
651*c801082dSJean Delvare 		show_temp, NULL, offset - 1);				\
652*c801082dSJean Delvare static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR,	\
653*c801082dSJean Delvare 		show_temp_min, set_temp_min, offset - 1);		\
654*c801082dSJean Delvare static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR,	\
655*c801082dSJean Delvare 		show_temp_max, set_temp_max, offset - 1);		\
656*c801082dSJean Delvare static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IRUGO | S_IWUSR,	\
657*c801082dSJean Delvare 		show_temp_crit, set_temp_crit, offset - 1)
6588d5d45fbSJean Delvare 
6598d5d45fbSJean Delvare temp_reg(1);
6608d5d45fbSJean Delvare temp_reg(2);
6618d5d45fbSJean Delvare temp_reg(3);
6628d5d45fbSJean Delvare 
6638d5d45fbSJean Delvare /* Alarms */
6648d5d45fbSJean Delvare static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
6658d5d45fbSJean Delvare {
6668d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
6678d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", data->alarm);
6688d5d45fbSJean Delvare }
6698d5d45fbSJean Delvare 
6708d5d45fbSJean Delvare static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
6718d5d45fbSJean Delvare 
6728d5d45fbSJean Delvare 
6738d5d45fbSJean Delvare static int adm1031_attach_adapter(struct i2c_adapter *adapter)
6748d5d45fbSJean Delvare {
6758d5d45fbSJean Delvare 	if (!(adapter->class & I2C_CLASS_HWMON))
6768d5d45fbSJean Delvare 		return 0;
6772ed2dc3cSJean Delvare 	return i2c_probe(adapter, &addr_data, adm1031_detect);
6788d5d45fbSJean Delvare }
6798d5d45fbSJean Delvare 
680681c6f7aSMark M. Hoffman static struct attribute *adm1031_attributes[] = {
681*c801082dSJean Delvare 	&sensor_dev_attr_fan1_input.dev_attr.attr,
682*c801082dSJean Delvare 	&sensor_dev_attr_fan1_div.dev_attr.attr,
683*c801082dSJean Delvare 	&sensor_dev_attr_fan1_min.dev_attr.attr,
684*c801082dSJean Delvare 	&sensor_dev_attr_pwm1.dev_attr.attr,
685*c801082dSJean Delvare 	&sensor_dev_attr_auto_fan1_channel.dev_attr.attr,
686*c801082dSJean Delvare 	&sensor_dev_attr_temp1_input.dev_attr.attr,
687*c801082dSJean Delvare 	&sensor_dev_attr_temp1_min.dev_attr.attr,
688*c801082dSJean Delvare 	&sensor_dev_attr_temp1_max.dev_attr.attr,
689*c801082dSJean Delvare 	&sensor_dev_attr_temp1_crit.dev_attr.attr,
690*c801082dSJean Delvare 	&sensor_dev_attr_temp2_input.dev_attr.attr,
691*c801082dSJean Delvare 	&sensor_dev_attr_temp2_min.dev_attr.attr,
692*c801082dSJean Delvare 	&sensor_dev_attr_temp2_max.dev_attr.attr,
693*c801082dSJean Delvare 	&sensor_dev_attr_temp2_crit.dev_attr.attr,
694681c6f7aSMark M. Hoffman 
695*c801082dSJean Delvare 	&sensor_dev_attr_auto_temp1_off.dev_attr.attr,
696*c801082dSJean Delvare 	&sensor_dev_attr_auto_temp1_min.dev_attr.attr,
697*c801082dSJean Delvare 	&sensor_dev_attr_auto_temp1_max.dev_attr.attr,
698681c6f7aSMark M. Hoffman 
699*c801082dSJean Delvare 	&sensor_dev_attr_auto_temp2_off.dev_attr.attr,
700*c801082dSJean Delvare 	&sensor_dev_attr_auto_temp2_min.dev_attr.attr,
701*c801082dSJean Delvare 	&sensor_dev_attr_auto_temp2_max.dev_attr.attr,
702681c6f7aSMark M. Hoffman 
703*c801082dSJean Delvare 	&sensor_dev_attr_auto_fan1_min_pwm.dev_attr.attr,
704681c6f7aSMark M. Hoffman 
705681c6f7aSMark M. Hoffman 	&dev_attr_alarms.attr,
706681c6f7aSMark M. Hoffman 
707681c6f7aSMark M. Hoffman 	NULL
708681c6f7aSMark M. Hoffman };
709681c6f7aSMark M. Hoffman 
710681c6f7aSMark M. Hoffman static const struct attribute_group adm1031_group = {
711681c6f7aSMark M. Hoffman 	.attrs = adm1031_attributes,
712681c6f7aSMark M. Hoffman };
713681c6f7aSMark M. Hoffman 
714681c6f7aSMark M. Hoffman static struct attribute *adm1031_attributes_opt[] = {
715*c801082dSJean Delvare 	&sensor_dev_attr_fan2_input.dev_attr.attr,
716*c801082dSJean Delvare 	&sensor_dev_attr_fan2_div.dev_attr.attr,
717*c801082dSJean Delvare 	&sensor_dev_attr_fan2_min.dev_attr.attr,
718*c801082dSJean Delvare 	&sensor_dev_attr_pwm2.dev_attr.attr,
719*c801082dSJean Delvare 	&sensor_dev_attr_auto_fan2_channel.dev_attr.attr,
720*c801082dSJean Delvare 	&sensor_dev_attr_temp3_input.dev_attr.attr,
721*c801082dSJean Delvare 	&sensor_dev_attr_temp3_min.dev_attr.attr,
722*c801082dSJean Delvare 	&sensor_dev_attr_temp3_max.dev_attr.attr,
723*c801082dSJean Delvare 	&sensor_dev_attr_temp3_crit.dev_attr.attr,
724*c801082dSJean Delvare 	&sensor_dev_attr_auto_temp3_off.dev_attr.attr,
725*c801082dSJean Delvare 	&sensor_dev_attr_auto_temp3_min.dev_attr.attr,
726*c801082dSJean Delvare 	&sensor_dev_attr_auto_temp3_max.dev_attr.attr,
727*c801082dSJean Delvare 	&sensor_dev_attr_auto_fan2_min_pwm.dev_attr.attr,
728681c6f7aSMark M. Hoffman 	NULL
729681c6f7aSMark M. Hoffman };
730681c6f7aSMark M. Hoffman 
731681c6f7aSMark M. Hoffman static const struct attribute_group adm1031_group_opt = {
732681c6f7aSMark M. Hoffman 	.attrs = adm1031_attributes_opt,
733681c6f7aSMark M. Hoffman };
734681c6f7aSMark M. Hoffman 
7352ed2dc3cSJean Delvare /* This function is called by i2c_probe */
7368d5d45fbSJean Delvare static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind)
7378d5d45fbSJean Delvare {
7386d6006b8SJean Delvare 	struct i2c_client *client;
7398d5d45fbSJean Delvare 	struct adm1031_data *data;
7408d5d45fbSJean Delvare 	int err = 0;
7418d5d45fbSJean Delvare 	const char *name = "";
7428d5d45fbSJean Delvare 
7438d5d45fbSJean Delvare 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
7448d5d45fbSJean Delvare 		goto exit;
7458d5d45fbSJean Delvare 
746ba9c2e8dSDeepak Saxena 	if (!(data = kzalloc(sizeof(struct adm1031_data), GFP_KERNEL))) {
7478d5d45fbSJean Delvare 		err = -ENOMEM;
7488d5d45fbSJean Delvare 		goto exit;
7498d5d45fbSJean Delvare 	}
7508d5d45fbSJean Delvare 
7516d6006b8SJean Delvare 	client = &data->client;
7526d6006b8SJean Delvare 	i2c_set_clientdata(client, data);
7536d6006b8SJean Delvare 	client->addr = address;
7546d6006b8SJean Delvare 	client->adapter = adapter;
7556d6006b8SJean Delvare 	client->driver = &adm1031_driver;
7568d5d45fbSJean Delvare 
7578d5d45fbSJean Delvare 	if (kind < 0) {
7588d5d45fbSJean Delvare 		int id, co;
7596d6006b8SJean Delvare 		id = i2c_smbus_read_byte_data(client, 0x3d);
7606d6006b8SJean Delvare 		co = i2c_smbus_read_byte_data(client, 0x3e);
7618d5d45fbSJean Delvare 
7628d5d45fbSJean Delvare 		if (!((id == 0x31 || id == 0x30) && co == 0x41))
7638d5d45fbSJean Delvare 			goto exit_free;
7648d5d45fbSJean Delvare 		kind = (id == 0x30) ? adm1030 : adm1031;
7658d5d45fbSJean Delvare 	}
7668d5d45fbSJean Delvare 
7678d5d45fbSJean Delvare 	if (kind <= 0)
7688d5d45fbSJean Delvare 		kind = adm1031;
7698d5d45fbSJean Delvare 
7708d5d45fbSJean Delvare 	/* Given the detected chip type, set the chip name and the
7718d5d45fbSJean Delvare 	 * auto fan control helper table. */
7728d5d45fbSJean Delvare 	if (kind == adm1030) {
7738d5d45fbSJean Delvare 		name = "adm1030";
7748d5d45fbSJean Delvare 		data->chan_select_table = &auto_channel_select_table_adm1030;
7758d5d45fbSJean Delvare 	} else if (kind == adm1031) {
7768d5d45fbSJean Delvare 		name = "adm1031";
7778d5d45fbSJean Delvare 		data->chan_select_table = &auto_channel_select_table_adm1031;
7788d5d45fbSJean Delvare 	}
7798d5d45fbSJean Delvare 	data->chip_type = kind;
7808d5d45fbSJean Delvare 
7816d6006b8SJean Delvare 	strlcpy(client->name, name, I2C_NAME_SIZE);
7829a61bf63SIngo Molnar 	mutex_init(&data->update_lock);
7838d5d45fbSJean Delvare 
7848d5d45fbSJean Delvare 	/* Tell the I2C layer a new client has arrived */
7856d6006b8SJean Delvare 	if ((err = i2c_attach_client(client)))
7868d5d45fbSJean Delvare 		goto exit_free;
7878d5d45fbSJean Delvare 
7888d5d45fbSJean Delvare 	/* Initialize the ADM1031 chip */
7896d6006b8SJean Delvare 	adm1031_init_client(client);
7908d5d45fbSJean Delvare 
7918d5d45fbSJean Delvare 	/* Register sysfs hooks */
7926d6006b8SJean Delvare 	if ((err = sysfs_create_group(&client->dev.kobj, &adm1031_group)))
793681c6f7aSMark M. Hoffman 		goto exit_detach;
794681c6f7aSMark M. Hoffman 
795681c6f7aSMark M. Hoffman 	if (kind == adm1031) {
7966d6006b8SJean Delvare 		if ((err = sysfs_create_group(&client->dev.kobj,
797681c6f7aSMark M. Hoffman 						&adm1031_group_opt)))
798681c6f7aSMark M. Hoffman 			goto exit_remove;
799681c6f7aSMark M. Hoffman 	}
800681c6f7aSMark M. Hoffman 
8016d6006b8SJean Delvare 	data->hwmon_dev = hwmon_device_register(&client->dev);
8021beeffe4STony Jones 	if (IS_ERR(data->hwmon_dev)) {
8031beeffe4STony Jones 		err = PTR_ERR(data->hwmon_dev);
804681c6f7aSMark M. Hoffman 		goto exit_remove;
8058d5d45fbSJean Delvare 	}
8068d5d45fbSJean Delvare 
8078d5d45fbSJean Delvare 	return 0;
8088d5d45fbSJean Delvare 
809681c6f7aSMark M. Hoffman exit_remove:
8106d6006b8SJean Delvare 	sysfs_remove_group(&client->dev.kobj, &adm1031_group);
8116d6006b8SJean Delvare 	sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt);
812943b0830SMark M. Hoffman exit_detach:
8136d6006b8SJean Delvare 	i2c_detach_client(client);
8148d5d45fbSJean Delvare exit_free:
8151f57ff89SAlexey Dobriyan 	kfree(data);
8168d5d45fbSJean Delvare exit:
8178d5d45fbSJean Delvare 	return err;
8188d5d45fbSJean Delvare }
8198d5d45fbSJean Delvare 
8208d5d45fbSJean Delvare static int adm1031_detach_client(struct i2c_client *client)
8218d5d45fbSJean Delvare {
822943b0830SMark M. Hoffman 	struct adm1031_data *data = i2c_get_clientdata(client);
8238d5d45fbSJean Delvare 	int ret;
824943b0830SMark M. Hoffman 
8251beeffe4STony Jones 	hwmon_device_unregister(data->hwmon_dev);
826681c6f7aSMark M. Hoffman 	sysfs_remove_group(&client->dev.kobj, &adm1031_group);
827681c6f7aSMark M. Hoffman 	sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt);
8288d5d45fbSJean Delvare 	if ((ret = i2c_detach_client(client)) != 0) {
8298d5d45fbSJean Delvare 		return ret;
8308d5d45fbSJean Delvare 	}
831943b0830SMark M. Hoffman 	kfree(data);
8328d5d45fbSJean Delvare 	return 0;
8338d5d45fbSJean Delvare }
8348d5d45fbSJean Delvare 
8358d5d45fbSJean Delvare static void adm1031_init_client(struct i2c_client *client)
8368d5d45fbSJean Delvare {
8378d5d45fbSJean Delvare 	unsigned int read_val;
8388d5d45fbSJean Delvare 	unsigned int mask;
8398d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
8408d5d45fbSJean Delvare 
8418d5d45fbSJean Delvare 	mask = (ADM1031_CONF2_PWM1_ENABLE | ADM1031_CONF2_TACH1_ENABLE);
8428d5d45fbSJean Delvare 	if (data->chip_type == adm1031) {
8438d5d45fbSJean Delvare 		mask |= (ADM1031_CONF2_PWM2_ENABLE |
8448d5d45fbSJean Delvare 			ADM1031_CONF2_TACH2_ENABLE);
8458d5d45fbSJean Delvare 	}
8468d5d45fbSJean Delvare 	/* Initialize the ADM1031 chip (enables fan speed reading ) */
8478d5d45fbSJean Delvare 	read_val = adm1031_read_value(client, ADM1031_REG_CONF2);
8488d5d45fbSJean Delvare 	if ((read_val | mask) != read_val) {
8498d5d45fbSJean Delvare 	    adm1031_write_value(client, ADM1031_REG_CONF2, read_val | mask);
8508d5d45fbSJean Delvare 	}
8518d5d45fbSJean Delvare 
8528d5d45fbSJean Delvare 	read_val = adm1031_read_value(client, ADM1031_REG_CONF1);
8538d5d45fbSJean Delvare 	if ((read_val | ADM1031_CONF1_MONITOR_ENABLE) != read_val) {
8548d5d45fbSJean Delvare 	    adm1031_write_value(client, ADM1031_REG_CONF1, read_val |
8558d5d45fbSJean Delvare 				ADM1031_CONF1_MONITOR_ENABLE);
8568d5d45fbSJean Delvare 	}
8578d5d45fbSJean Delvare 
8588d5d45fbSJean Delvare }
8598d5d45fbSJean Delvare 
8608d5d45fbSJean Delvare static struct adm1031_data *adm1031_update_device(struct device *dev)
8618d5d45fbSJean Delvare {
8628d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
8638d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
8648d5d45fbSJean Delvare 	int chan;
8658d5d45fbSJean Delvare 
8669a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
8678d5d45fbSJean Delvare 
8688d5d45fbSJean Delvare 	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
8698d5d45fbSJean Delvare 	    || !data->valid) {
8708d5d45fbSJean Delvare 
8718d5d45fbSJean Delvare 		dev_dbg(&client->dev, "Starting adm1031 update\n");
8728d5d45fbSJean Delvare 		for (chan = 0;
8738d5d45fbSJean Delvare 		     chan < ((data->chip_type == adm1031) ? 3 : 2); chan++) {
8748d5d45fbSJean Delvare 			u8 oldh, newh;
8758d5d45fbSJean Delvare 
8768d5d45fbSJean Delvare 			oldh =
8778d5d45fbSJean Delvare 			    adm1031_read_value(client, ADM1031_REG_TEMP(chan));
8788d5d45fbSJean Delvare 			data->ext_temp[chan] =
8798d5d45fbSJean Delvare 			    adm1031_read_value(client, ADM1031_REG_EXT_TEMP);
8808d5d45fbSJean Delvare 			newh =
8818d5d45fbSJean Delvare 			    adm1031_read_value(client, ADM1031_REG_TEMP(chan));
8828d5d45fbSJean Delvare 			if (newh != oldh) {
8838d5d45fbSJean Delvare 				data->ext_temp[chan] =
8848d5d45fbSJean Delvare 				    adm1031_read_value(client,
8858d5d45fbSJean Delvare 						       ADM1031_REG_EXT_TEMP);
8868d5d45fbSJean Delvare #ifdef DEBUG
8878d5d45fbSJean Delvare 				oldh =
8888d5d45fbSJean Delvare 				    adm1031_read_value(client,
8898d5d45fbSJean Delvare 						       ADM1031_REG_TEMP(chan));
8908d5d45fbSJean Delvare 
8918d5d45fbSJean Delvare 				/* oldh is actually newer */
8928d5d45fbSJean Delvare 				if (newh != oldh)
8938d5d45fbSJean Delvare 					dev_warn(&client->dev,
8948d5d45fbSJean Delvare 						 "Remote temperature may be "
8958d5d45fbSJean Delvare 						 "wrong.\n");
8968d5d45fbSJean Delvare #endif
8978d5d45fbSJean Delvare 			}
8988d5d45fbSJean Delvare 			data->temp[chan] = newh;
8998d5d45fbSJean Delvare 
9008d5d45fbSJean Delvare 			data->temp_min[chan] =
9018d5d45fbSJean Delvare 			    adm1031_read_value(client,
9028d5d45fbSJean Delvare 					       ADM1031_REG_TEMP_MIN(chan));
9038d5d45fbSJean Delvare 			data->temp_max[chan] =
9048d5d45fbSJean Delvare 			    adm1031_read_value(client,
9058d5d45fbSJean Delvare 					       ADM1031_REG_TEMP_MAX(chan));
9068d5d45fbSJean Delvare 			data->temp_crit[chan] =
9078d5d45fbSJean Delvare 			    adm1031_read_value(client,
9088d5d45fbSJean Delvare 					       ADM1031_REG_TEMP_CRIT(chan));
9098d5d45fbSJean Delvare 			data->auto_temp[chan] =
9108d5d45fbSJean Delvare 			    adm1031_read_value(client,
9118d5d45fbSJean Delvare 					       ADM1031_REG_AUTO_TEMP(chan));
9128d5d45fbSJean Delvare 
9138d5d45fbSJean Delvare 		}
9148d5d45fbSJean Delvare 
9158d5d45fbSJean Delvare 		data->conf1 = adm1031_read_value(client, ADM1031_REG_CONF1);
9168d5d45fbSJean Delvare 		data->conf2 = adm1031_read_value(client, ADM1031_REG_CONF2);
9178d5d45fbSJean Delvare 
9188d5d45fbSJean Delvare 		data->alarm = adm1031_read_value(client, ADM1031_REG_STATUS(0))
9198d5d45fbSJean Delvare 			     | (adm1031_read_value(client, ADM1031_REG_STATUS(1))
9208d5d45fbSJean Delvare 				<< 8);
9218d5d45fbSJean Delvare 		if (data->chip_type == adm1030) {
9228d5d45fbSJean Delvare 			data->alarm &= 0xc0ff;
9238d5d45fbSJean Delvare 		}
9248d5d45fbSJean Delvare 
9258d5d45fbSJean Delvare 		for (chan=0; chan<(data->chip_type == adm1030 ? 1 : 2); chan++) {
9268d5d45fbSJean Delvare 			data->fan_div[chan] =
9278d5d45fbSJean Delvare 			    adm1031_read_value(client, ADM1031_REG_FAN_DIV(chan));
9288d5d45fbSJean Delvare 			data->fan_min[chan] =
9298d5d45fbSJean Delvare 			    adm1031_read_value(client, ADM1031_REG_FAN_MIN(chan));
9308d5d45fbSJean Delvare 			data->fan[chan] =
9318d5d45fbSJean Delvare 			    adm1031_read_value(client, ADM1031_REG_FAN_SPEED(chan));
9328d5d45fbSJean Delvare 			data->pwm[chan] =
9338d5d45fbSJean Delvare 			    0xf & (adm1031_read_value(client, ADM1031_REG_PWM) >>
9348d5d45fbSJean Delvare 				   (4*chan));
9358d5d45fbSJean Delvare 		}
9368d5d45fbSJean Delvare 		data->last_updated = jiffies;
9378d5d45fbSJean Delvare 		data->valid = 1;
9388d5d45fbSJean Delvare 	}
9398d5d45fbSJean Delvare 
9409a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
9418d5d45fbSJean Delvare 
9428d5d45fbSJean Delvare 	return data;
9438d5d45fbSJean Delvare }
9448d5d45fbSJean Delvare 
9458d5d45fbSJean Delvare static int __init sensors_adm1031_init(void)
9468d5d45fbSJean Delvare {
9478d5d45fbSJean Delvare 	return i2c_add_driver(&adm1031_driver);
9488d5d45fbSJean Delvare }
9498d5d45fbSJean Delvare 
9508d5d45fbSJean Delvare static void __exit sensors_adm1031_exit(void)
9518d5d45fbSJean Delvare {
9528d5d45fbSJean Delvare 	i2c_del_driver(&adm1031_driver);
9538d5d45fbSJean Delvare }
9548d5d45fbSJean Delvare 
9558d5d45fbSJean Delvare MODULE_AUTHOR("Alexandre d'Alton <alex@alexdalton.org>");
9568d5d45fbSJean Delvare MODULE_DESCRIPTION("ADM1031/ADM1030 driver");
9578d5d45fbSJean Delvare MODULE_LICENSE("GPL");
9588d5d45fbSJean Delvare 
9598d5d45fbSJean Delvare module_init(sensors_adm1031_init);
9608d5d45fbSJean Delvare module_exit(sensors_adm1031_exit);
961