xref: /linux/drivers/hwmon/adm1031.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
174ba9207SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
28d5d45fbSJean Delvare /*
3fbb6670dSGuenter Roeck  * adm1031.c - Part of lm_sensors, Linux kernel modules for hardware
4fbb6670dSGuenter Roeck  *	       monitoring
5fbb6670dSGuenter Roeck  * Based on lm75.c and lm85.c
6fbb6670dSGuenter Roeck  * Supports adm1030 / adm1031
7fbb6670dSGuenter Roeck  * Copyright (C) 2004 Alexandre d'Alton <alex@alexdalton.org>
87c81c60fSJean Delvare  * Reworked by Jean Delvare <jdelvare@suse.de>
98d5d45fbSJean Delvare  */
108d5d45fbSJean Delvare 
118d5d45fbSJean Delvare #include <linux/module.h>
128d5d45fbSJean Delvare #include <linux/init.h>
138d5d45fbSJean Delvare #include <linux/slab.h>
148d5d45fbSJean Delvare #include <linux/jiffies.h>
158d5d45fbSJean Delvare #include <linux/i2c.h>
16943b0830SMark M. Hoffman #include <linux/hwmon.h>
17c801082dSJean Delvare #include <linux/hwmon-sysfs.h>
18943b0830SMark M. Hoffman #include <linux/err.h>
199a61bf63SIngo Molnar #include <linux/mutex.h>
208d5d45fbSJean Delvare 
218d5d45fbSJean Delvare /* Following macros takes channel parameter starting from 0 to 2 */
228d5d45fbSJean Delvare #define ADM1031_REG_FAN_SPEED(nr)	(0x08 + (nr))
238d5d45fbSJean Delvare #define ADM1031_REG_FAN_DIV(nr)		(0x20 + (nr))
248d5d45fbSJean Delvare #define ADM1031_REG_PWM			(0x22)
258d5d45fbSJean Delvare #define ADM1031_REG_FAN_MIN(nr)		(0x10 + (nr))
2687c33daaSJean Delvare #define ADM1031_REG_FAN_FILTER		(0x23)
278d5d45fbSJean Delvare 
2849dc9efeSIra Snyder #define ADM1031_REG_TEMP_OFFSET(nr)	(0x0d + (nr))
298d5d45fbSJean Delvare #define ADM1031_REG_TEMP_MAX(nr)	(0x14 + 4 * (nr))
308d5d45fbSJean Delvare #define ADM1031_REG_TEMP_MIN(nr)	(0x15 + 4 * (nr))
318d5d45fbSJean Delvare #define ADM1031_REG_TEMP_CRIT(nr)	(0x16 + 4 * (nr))
328d5d45fbSJean Delvare 
336d6006b8SJean Delvare #define ADM1031_REG_TEMP(nr)		(0x0a + (nr))
348d5d45fbSJean Delvare #define ADM1031_REG_AUTO_TEMP(nr)	(0x24 + (nr))
358d5d45fbSJean Delvare 
368d5d45fbSJean Delvare #define ADM1031_REG_STATUS(nr)		(0x2 + (nr))
378d5d45fbSJean Delvare 
386d6006b8SJean Delvare #define ADM1031_REG_CONF1		0x00
396d6006b8SJean Delvare #define ADM1031_REG_CONF2		0x01
406d6006b8SJean Delvare #define ADM1031_REG_EXT_TEMP		0x06
418d5d45fbSJean Delvare 
428d5d45fbSJean Delvare #define ADM1031_CONF1_MONITOR_ENABLE	0x01	/* Monitoring enable */
438d5d45fbSJean Delvare #define ADM1031_CONF1_PWM_INVERT	0x08	/* PWM Invert */
448d5d45fbSJean Delvare #define ADM1031_CONF1_AUTO_MODE		0x80	/* Auto FAN */
458d5d45fbSJean Delvare 
468d5d45fbSJean Delvare #define ADM1031_CONF2_PWM1_ENABLE	0x01
478d5d45fbSJean Delvare #define ADM1031_CONF2_PWM2_ENABLE	0x02
488d5d45fbSJean Delvare #define ADM1031_CONF2_TACH1_ENABLE	0x04
498d5d45fbSJean Delvare #define ADM1031_CONF2_TACH2_ENABLE	0x08
508d5d45fbSJean Delvare #define ADM1031_CONF2_TEMP_ENABLE(chan)	(0x10 << (chan))
518d5d45fbSJean Delvare 
5287c33daaSJean Delvare #define ADM1031_UPDATE_RATE_MASK	0x1c
5387c33daaSJean Delvare #define ADM1031_UPDATE_RATE_SHIFT	2
5487c33daaSJean Delvare 
558d5d45fbSJean Delvare /* Addresses to scan */
5625e9c86dSMark M. Hoffman static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
578d5d45fbSJean Delvare 
58e5e9f44cSJean Delvare enum chips { adm1030, adm1031 };
598d5d45fbSJean Delvare 
608d5d45fbSJean Delvare typedef u8 auto_chan_table_t[8][2];
618d5d45fbSJean Delvare 
628d5d45fbSJean Delvare /* Each client has this additional data */
638d5d45fbSJean Delvare struct adm1031_data {
64b060f3c4SAxel Lin 	struct i2c_client *client;
65b060f3c4SAxel Lin 	const struct attribute_group *groups[3];
669a61bf63SIngo Molnar 	struct mutex update_lock;
678d5d45fbSJean Delvare 	int chip_type;
68952a11caSPaul Fertser 	bool valid;		/* true if following fields are valid */
698d5d45fbSJean Delvare 	unsigned long last_updated;	/* In jiffies */
70a51b9944SGuenter Roeck 	unsigned int update_interval;	/* In milliseconds */
71fbb6670dSGuenter Roeck 	/*
72fbb6670dSGuenter Roeck 	 * The chan_select_table contains the possible configurations for
738d5d45fbSJean Delvare 	 * auto fan control.
748d5d45fbSJean Delvare 	 */
756d6006b8SJean Delvare 	const auto_chan_table_t *chan_select_table;
768d5d45fbSJean Delvare 	u16 alarm;
778d5d45fbSJean Delvare 	u8 conf1;
788d5d45fbSJean Delvare 	u8 conf2;
798d5d45fbSJean Delvare 	u8 fan[2];
808d5d45fbSJean Delvare 	u8 fan_div[2];
818d5d45fbSJean Delvare 	u8 fan_min[2];
828d5d45fbSJean Delvare 	u8 pwm[2];
838d5d45fbSJean Delvare 	u8 old_pwm[2];
848d5d45fbSJean Delvare 	s8 temp[3];
858d5d45fbSJean Delvare 	u8 ext_temp[3];
868d5d45fbSJean Delvare 	u8 auto_temp[3];
878d5d45fbSJean Delvare 	u8 auto_temp_min[3];
888d5d45fbSJean Delvare 	u8 auto_temp_off[3];
898d5d45fbSJean Delvare 	u8 auto_temp_max[3];
9049dc9efeSIra Snyder 	s8 temp_offset[3];
918d5d45fbSJean Delvare 	s8 temp_min[3];
928d5d45fbSJean Delvare 	s8 temp_max[3];
938d5d45fbSJean Delvare 	s8 temp_crit[3];
948d5d45fbSJean Delvare };
958d5d45fbSJean Delvare 
adm1031_read_value(struct i2c_client * client,u8 reg)968d5d45fbSJean Delvare static inline u8 adm1031_read_value(struct i2c_client *client, u8 reg)
978d5d45fbSJean Delvare {
988d5d45fbSJean Delvare 	return i2c_smbus_read_byte_data(client, reg);
998d5d45fbSJean Delvare }
1008d5d45fbSJean Delvare 
1018d5d45fbSJean Delvare static inline int
adm1031_write_value(struct i2c_client * client,u8 reg,unsigned int value)1028d5d45fbSJean Delvare adm1031_write_value(struct i2c_client *client, u8 reg, unsigned int value)
1038d5d45fbSJean Delvare {
1048d5d45fbSJean Delvare 	return i2c_smbus_write_byte_data(client, reg, value);
1058d5d45fbSJean Delvare }
1068d5d45fbSJean Delvare 
adm1031_update_device(struct device * dev)107278ee1c8SAxel Lin static struct adm1031_data *adm1031_update_device(struct device *dev)
108278ee1c8SAxel Lin {
109b060f3c4SAxel Lin 	struct adm1031_data *data = dev_get_drvdata(dev);
110b060f3c4SAxel Lin 	struct i2c_client *client = data->client;
111278ee1c8SAxel Lin 	unsigned long next_update;
112278ee1c8SAxel Lin 	int chan;
113278ee1c8SAxel Lin 
114278ee1c8SAxel Lin 	mutex_lock(&data->update_lock);
115278ee1c8SAxel Lin 
116278ee1c8SAxel Lin 	next_update = data->last_updated
117278ee1c8SAxel Lin 	  + msecs_to_jiffies(data->update_interval);
118278ee1c8SAxel Lin 	if (time_after(jiffies, next_update) || !data->valid) {
119278ee1c8SAxel Lin 
120278ee1c8SAxel Lin 		dev_dbg(&client->dev, "Starting adm1031 update\n");
121278ee1c8SAxel Lin 		for (chan = 0;
122278ee1c8SAxel Lin 		     chan < ((data->chip_type == adm1031) ? 3 : 2); chan++) {
123278ee1c8SAxel Lin 			u8 oldh, newh;
124278ee1c8SAxel Lin 
125278ee1c8SAxel Lin 			oldh =
126278ee1c8SAxel Lin 			    adm1031_read_value(client, ADM1031_REG_TEMP(chan));
127278ee1c8SAxel Lin 			data->ext_temp[chan] =
128278ee1c8SAxel Lin 			    adm1031_read_value(client, ADM1031_REG_EXT_TEMP);
129278ee1c8SAxel Lin 			newh =
130278ee1c8SAxel Lin 			    adm1031_read_value(client, ADM1031_REG_TEMP(chan));
131278ee1c8SAxel Lin 			if (newh != oldh) {
132278ee1c8SAxel Lin 				data->ext_temp[chan] =
133278ee1c8SAxel Lin 				    adm1031_read_value(client,
134278ee1c8SAxel Lin 						       ADM1031_REG_EXT_TEMP);
135278ee1c8SAxel Lin #ifdef DEBUG
136278ee1c8SAxel Lin 				oldh =
137278ee1c8SAxel Lin 				    adm1031_read_value(client,
138278ee1c8SAxel Lin 						       ADM1031_REG_TEMP(chan));
139278ee1c8SAxel Lin 
140278ee1c8SAxel Lin 				/* oldh is actually newer */
141278ee1c8SAxel Lin 				if (newh != oldh)
142278ee1c8SAxel Lin 					dev_warn(&client->dev,
143278ee1c8SAxel Lin 					  "Remote temperature may be wrong.\n");
144278ee1c8SAxel Lin #endif
145278ee1c8SAxel Lin 			}
146278ee1c8SAxel Lin 			data->temp[chan] = newh;
147278ee1c8SAxel Lin 
148278ee1c8SAxel Lin 			data->temp_offset[chan] =
149278ee1c8SAxel Lin 			    adm1031_read_value(client,
150278ee1c8SAxel Lin 					       ADM1031_REG_TEMP_OFFSET(chan));
151278ee1c8SAxel Lin 			data->temp_min[chan] =
152278ee1c8SAxel Lin 			    adm1031_read_value(client,
153278ee1c8SAxel Lin 					       ADM1031_REG_TEMP_MIN(chan));
154278ee1c8SAxel Lin 			data->temp_max[chan] =
155278ee1c8SAxel Lin 			    adm1031_read_value(client,
156278ee1c8SAxel Lin 					       ADM1031_REG_TEMP_MAX(chan));
157278ee1c8SAxel Lin 			data->temp_crit[chan] =
158278ee1c8SAxel Lin 			    adm1031_read_value(client,
159278ee1c8SAxel Lin 					       ADM1031_REG_TEMP_CRIT(chan));
160278ee1c8SAxel Lin 			data->auto_temp[chan] =
161278ee1c8SAxel Lin 			    adm1031_read_value(client,
162278ee1c8SAxel Lin 					       ADM1031_REG_AUTO_TEMP(chan));
163278ee1c8SAxel Lin 
164278ee1c8SAxel Lin 		}
165278ee1c8SAxel Lin 
166278ee1c8SAxel Lin 		data->conf1 = adm1031_read_value(client, ADM1031_REG_CONF1);
167278ee1c8SAxel Lin 		data->conf2 = adm1031_read_value(client, ADM1031_REG_CONF2);
168278ee1c8SAxel Lin 
169278ee1c8SAxel Lin 		data->alarm = adm1031_read_value(client, ADM1031_REG_STATUS(0))
170278ee1c8SAxel Lin 		    | (adm1031_read_value(client, ADM1031_REG_STATUS(1)) << 8);
171278ee1c8SAxel Lin 		if (data->chip_type == adm1030)
172278ee1c8SAxel Lin 			data->alarm &= 0xc0ff;
173278ee1c8SAxel Lin 
174278ee1c8SAxel Lin 		for (chan = 0; chan < (data->chip_type == adm1030 ? 1 : 2);
175278ee1c8SAxel Lin 		     chan++) {
176278ee1c8SAxel Lin 			data->fan_div[chan] =
177278ee1c8SAxel Lin 			    adm1031_read_value(client,
178278ee1c8SAxel Lin 					       ADM1031_REG_FAN_DIV(chan));
179278ee1c8SAxel Lin 			data->fan_min[chan] =
180278ee1c8SAxel Lin 			    adm1031_read_value(client,
181278ee1c8SAxel Lin 					       ADM1031_REG_FAN_MIN(chan));
182278ee1c8SAxel Lin 			data->fan[chan] =
183278ee1c8SAxel Lin 			    adm1031_read_value(client,
184278ee1c8SAxel Lin 					       ADM1031_REG_FAN_SPEED(chan));
185278ee1c8SAxel Lin 			data->pwm[chan] =
186278ee1c8SAxel Lin 			  (adm1031_read_value(client,
187278ee1c8SAxel Lin 					ADM1031_REG_PWM) >> (4 * chan)) & 0x0f;
188278ee1c8SAxel Lin 		}
189278ee1c8SAxel Lin 		data->last_updated = jiffies;
190952a11caSPaul Fertser 		data->valid = true;
191278ee1c8SAxel Lin 	}
192278ee1c8SAxel Lin 
193278ee1c8SAxel Lin 	mutex_unlock(&data->update_lock);
194278ee1c8SAxel Lin 
195278ee1c8SAxel Lin 	return data;
196278ee1c8SAxel Lin }
1978d5d45fbSJean Delvare 
1988d5d45fbSJean Delvare #define TEMP_TO_REG(val)		(((val) < 0 ? ((val - 500) / 1000) : \
1998d5d45fbSJean Delvare 					((val + 500) / 1000)))
2008d5d45fbSJean Delvare 
2018d5d45fbSJean Delvare #define TEMP_FROM_REG(val)		((val) * 1000)
2028d5d45fbSJean Delvare 
2038d5d45fbSJean Delvare #define TEMP_FROM_REG_EXT(val, ext)	(TEMP_FROM_REG(val) + (ext) * 125)
2048d5d45fbSJean Delvare 
20549dc9efeSIra Snyder #define TEMP_OFFSET_TO_REG(val)		(TEMP_TO_REG(val) & 0x8f)
20649dc9efeSIra Snyder #define TEMP_OFFSET_FROM_REG(val)	TEMP_FROM_REG((val) < 0 ? \
20749dc9efeSIra Snyder 						      (val) | 0x70 : (val))
20849dc9efeSIra Snyder 
2091c720093SGuenter Roeck #define FAN_FROM_REG(reg, div)		((reg) ? \
2101c720093SGuenter Roeck 					 (11250 * 60) / ((reg) * (div)) : 0)
2118d5d45fbSJean Delvare 
FAN_TO_REG(int reg,int div)2128d5d45fbSJean Delvare static int FAN_TO_REG(int reg, int div)
2138d5d45fbSJean Delvare {
2148d5d45fbSJean Delvare 	int tmp;
2152a844c14SGuenter Roeck 	tmp = FAN_FROM_REG(clamp_val(reg, 0, 65535), div);
2168d5d45fbSJean Delvare 	return tmp > 255 ? 255 : tmp;
2178d5d45fbSJean Delvare }
2188d5d45fbSJean Delvare 
2198d5d45fbSJean Delvare #define FAN_DIV_FROM_REG(reg)		(1<<(((reg)&0xc0)>>6))
2208d5d45fbSJean Delvare 
2212a844c14SGuenter Roeck #define PWM_TO_REG(val)			(clamp_val((val), 0, 255) >> 4)
2228d5d45fbSJean Delvare #define PWM_FROM_REG(val)		((val) << 4)
2238d5d45fbSJean Delvare 
2248d5d45fbSJean Delvare #define FAN_CHAN_FROM_REG(reg)		(((reg) >> 5) & 7)
2258d5d45fbSJean Delvare #define FAN_CHAN_TO_REG(val, reg)	\
2268d5d45fbSJean Delvare 	(((reg) & 0x1F) | (((val) << 5) & 0xe0))
2278d5d45fbSJean Delvare 
2288d5d45fbSJean Delvare #define AUTO_TEMP_MIN_TO_REG(val, reg)	\
2298d5d45fbSJean Delvare 	((((val) / 500) & 0xf8) | ((reg) & 0x7))
2308d5d45fbSJean Delvare #define AUTO_TEMP_RANGE_FROM_REG(reg)	(5000 * (1 << ((reg) & 0x7)))
2318d5d45fbSJean Delvare #define AUTO_TEMP_MIN_FROM_REG(reg)	(1000 * ((((reg) >> 3) & 0x1f) << 2))
2328d5d45fbSJean Delvare 
2338d5d45fbSJean Delvare #define AUTO_TEMP_MIN_FROM_REG_DEG(reg)	((((reg) >> 3) & 0x1f) << 2)
2348d5d45fbSJean Delvare 
2358d5d45fbSJean Delvare #define AUTO_TEMP_OFF_FROM_REG(reg)		\
2368d5d45fbSJean Delvare 	(AUTO_TEMP_MIN_FROM_REG(reg) - 5000)
2378d5d45fbSJean Delvare 
2388d5d45fbSJean Delvare #define AUTO_TEMP_MAX_FROM_REG(reg)		\
2398d5d45fbSJean Delvare 	(AUTO_TEMP_RANGE_FROM_REG(reg) +	\
2408d5d45fbSJean Delvare 	AUTO_TEMP_MIN_FROM_REG(reg))
2418d5d45fbSJean Delvare 
AUTO_TEMP_MAX_TO_REG(int val,int reg,int pwm)2428d5d45fbSJean Delvare static int AUTO_TEMP_MAX_TO_REG(int val, int reg, int pwm)
2438d5d45fbSJean Delvare {
2448d5d45fbSJean Delvare 	int ret;
245d7555379SColin Ian King 	int range = ((val - AUTO_TEMP_MIN_FROM_REG(reg)) * 10) / (16 - pwm);
2468d5d45fbSJean Delvare 
2478d5d45fbSJean Delvare 	ret = ((reg & 0xf8) |
2488d5d45fbSJean Delvare 	       (range < 10000 ? 0 :
2498d5d45fbSJean Delvare 		range < 20000 ? 1 :
2508d5d45fbSJean Delvare 		range < 40000 ? 2 : range < 80000 ? 3 : 4));
2518d5d45fbSJean Delvare 	return ret;
2528d5d45fbSJean Delvare }
2538d5d45fbSJean Delvare 
2548d5d45fbSJean Delvare /* FAN auto control */
2558d5d45fbSJean Delvare #define GET_FAN_AUTO_BITFIELD(data, idx)	\
2568d5d45fbSJean Delvare 	(*(data)->chan_select_table)[FAN_CHAN_FROM_REG((data)->conf1)][idx % 2]
2578d5d45fbSJean Delvare 
258fbb6670dSGuenter Roeck /*
259fbb6670dSGuenter Roeck  * The tables below contains the possible values for the auto fan
2608d5d45fbSJean Delvare  * control bitfields. the index in the table is the register value.
2618d5d45fbSJean Delvare  * MSb is the auto fan control enable bit, so the four first entries
2628d5d45fbSJean Delvare  * in the table disables auto fan control when both bitfields are zero.
2638d5d45fbSJean Delvare  */
2646d6006b8SJean Delvare static const auto_chan_table_t auto_channel_select_table_adm1031 = {
2658d5d45fbSJean Delvare 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2668d5d45fbSJean Delvare 	{ 2 /* 0b010 */ , 4 /* 0b100 */ },
2678d5d45fbSJean Delvare 	{ 2 /* 0b010 */ , 2 /* 0b010 */ },
2688d5d45fbSJean Delvare 	{ 4 /* 0b100 */ , 4 /* 0b100 */ },
2698d5d45fbSJean Delvare 	{ 7 /* 0b111 */ , 7 /* 0b111 */ },
2708d5d45fbSJean Delvare };
2718d5d45fbSJean Delvare 
2726d6006b8SJean Delvare static const auto_chan_table_t auto_channel_select_table_adm1030 = {
2738d5d45fbSJean Delvare 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2748d5d45fbSJean Delvare 	{ 2 /* 0b10 */		, 0 },
2758d5d45fbSJean Delvare 	{ 0xff /* invalid */	, 0 },
2768d5d45fbSJean Delvare 	{ 0xff /* invalid */	, 0 },
2778d5d45fbSJean Delvare 	{ 3 /* 0b11 */		, 0 },
2788d5d45fbSJean Delvare };
2798d5d45fbSJean Delvare 
280fbb6670dSGuenter Roeck /*
281fbb6670dSGuenter Roeck  * That function checks if a bitfield is valid and returns the other bitfield
2828d5d45fbSJean Delvare  * nearest match if no exact match where found.
2838d5d45fbSJean Delvare  */
2848d5d45fbSJean Delvare static int
get_fan_auto_nearest(struct adm1031_data * data,int chan,u8 val,u8 reg)285ce15a81dSGuenter Roeck get_fan_auto_nearest(struct adm1031_data *data, int chan, u8 val, u8 reg)
2868d5d45fbSJean Delvare {
2878d5d45fbSJean Delvare 	int i;
2888d5d45fbSJean Delvare 	int first_match = -1, exact_match = -1;
2898d5d45fbSJean Delvare 	u8 other_reg_val =
2908d5d45fbSJean Delvare 	    (*data->chan_select_table)[FAN_CHAN_FROM_REG(reg)][chan ? 0 : 1];
2918d5d45fbSJean Delvare 
292ce15a81dSGuenter Roeck 	if (val == 0)
2938d5d45fbSJean Delvare 		return 0;
2948d5d45fbSJean Delvare 
2958d5d45fbSJean Delvare 	for (i = 0; i < 8; i++) {
2968d5d45fbSJean Delvare 		if ((val == (*data->chan_select_table)[i][chan]) &&
2978d5d45fbSJean Delvare 		    ((*data->chan_select_table)[i][chan ? 0 : 1] ==
2988d5d45fbSJean Delvare 		     other_reg_val)) {
2998d5d45fbSJean Delvare 			/* We found an exact match */
3008d5d45fbSJean Delvare 			exact_match = i;
3018d5d45fbSJean Delvare 			break;
3028d5d45fbSJean Delvare 		} else if (val == (*data->chan_select_table)[i][chan] &&
3038d5d45fbSJean Delvare 			   first_match == -1) {
304fbb6670dSGuenter Roeck 			/*
305fbb6670dSGuenter Roeck 			 * Save the first match in case of an exact match has
3066d6006b8SJean Delvare 			 * not been found
3078d5d45fbSJean Delvare 			 */
3088d5d45fbSJean Delvare 			first_match = i;
3098d5d45fbSJean Delvare 		}
3108d5d45fbSJean Delvare 	}
3118d5d45fbSJean Delvare 
3121c720093SGuenter Roeck 	if (exact_match >= 0)
313ce15a81dSGuenter Roeck 		return exact_match;
3141c720093SGuenter Roeck 	else if (first_match >= 0)
315ce15a81dSGuenter Roeck 		return first_match;
3161c720093SGuenter Roeck 
317ce15a81dSGuenter Roeck 	return -EINVAL;
3188d5d45fbSJean Delvare }
3198d5d45fbSJean Delvare 
fan_auto_channel_show(struct device * dev,struct device_attribute * attr,char * buf)3208e757e15SGuenter Roeck static ssize_t fan_auto_channel_show(struct device *dev,
321c801082dSJean Delvare 				     struct device_attribute *attr, char *buf)
3228d5d45fbSJean Delvare {
323c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
3248d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
3258d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", GET_FAN_AUTO_BITFIELD(data, nr));
3268d5d45fbSJean Delvare }
3278d5d45fbSJean Delvare 
3288d5d45fbSJean Delvare static ssize_t
fan_auto_channel_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)3298e757e15SGuenter Roeck fan_auto_channel_store(struct device *dev, struct device_attribute *attr,
330c801082dSJean Delvare 		       const char *buf, size_t count)
3318d5d45fbSJean Delvare {
332b060f3c4SAxel Lin 	struct adm1031_data *data = dev_get_drvdata(dev);
333b060f3c4SAxel Lin 	struct i2c_client *client = data->client;
334c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
3351c720093SGuenter Roeck 	long val;
3368d5d45fbSJean Delvare 	u8 reg;
3378d5d45fbSJean Delvare 	int ret;
3388d5d45fbSJean Delvare 	u8 old_fan_mode;
3398d5d45fbSJean Delvare 
3401c720093SGuenter Roeck 	ret = kstrtol(buf, 10, &val);
3411c720093SGuenter Roeck 	if (ret)
3421c720093SGuenter Roeck 		return ret;
3431c720093SGuenter Roeck 
3448d5d45fbSJean Delvare 	old_fan_mode = data->conf1;
3458d5d45fbSJean Delvare 
3469a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
3478d5d45fbSJean Delvare 
348ce15a81dSGuenter Roeck 	ret = get_fan_auto_nearest(data, nr, val, data->conf1);
349ce15a81dSGuenter Roeck 	if (ret < 0) {
3509a61bf63SIngo Molnar 		mutex_unlock(&data->update_lock);
3518d5d45fbSJean Delvare 		return ret;
3528d5d45fbSJean Delvare 	}
353ce15a81dSGuenter Roeck 	reg = ret;
3546d6006b8SJean Delvare 	data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1);
3556d6006b8SJean Delvare 	if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) ^
3568d5d45fbSJean Delvare 	    (old_fan_mode & ADM1031_CONF1_AUTO_MODE)) {
3578d5d45fbSJean Delvare 		if (data->conf1 & ADM1031_CONF1_AUTO_MODE) {
358fbb6670dSGuenter Roeck 			/*
359fbb6670dSGuenter Roeck 			 * Switch to Auto Fan Mode
3608d5d45fbSJean Delvare 			 * Save PWM registers
361fbb6670dSGuenter Roeck 			 * Set PWM registers to 33% Both
362fbb6670dSGuenter Roeck 			 */
3638d5d45fbSJean Delvare 			data->old_pwm[0] = data->pwm[0];
3648d5d45fbSJean Delvare 			data->old_pwm[1] = data->pwm[1];
3658d5d45fbSJean Delvare 			adm1031_write_value(client, ADM1031_REG_PWM, 0x55);
3668d5d45fbSJean Delvare 		} else {
3678d5d45fbSJean Delvare 			/* Switch to Manual Mode */
3688d5d45fbSJean Delvare 			data->pwm[0] = data->old_pwm[0];
3698d5d45fbSJean Delvare 			data->pwm[1] = data->old_pwm[1];
3708d5d45fbSJean Delvare 			/* Restore PWM registers */
3718d5d45fbSJean Delvare 			adm1031_write_value(client, ADM1031_REG_PWM,
3728d5d45fbSJean Delvare 					    data->pwm[0] | (data->pwm[1] << 4));
3738d5d45fbSJean Delvare 		}
3748d5d45fbSJean Delvare 	}
3758d5d45fbSJean Delvare 	data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1);
3768d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_CONF1, data->conf1);
3779a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
3788d5d45fbSJean Delvare 	return count;
3798d5d45fbSJean Delvare }
3808d5d45fbSJean Delvare 
3818e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(auto_fan1_channel, fan_auto_channel, 0);
3828e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(auto_fan2_channel, fan_auto_channel, 1);
3838d5d45fbSJean Delvare 
3848d5d45fbSJean Delvare /* Auto Temps */
auto_temp_off_show(struct device * dev,struct device_attribute * attr,char * buf)3858e757e15SGuenter Roeck static ssize_t auto_temp_off_show(struct device *dev,
386c801082dSJean Delvare 				  struct device_attribute *attr, char *buf)
3878d5d45fbSJean Delvare {
388c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
3898d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
3908d5d45fbSJean Delvare 	return sprintf(buf, "%d\n",
3918d5d45fbSJean Delvare 		       AUTO_TEMP_OFF_FROM_REG(data->auto_temp[nr]));
3928d5d45fbSJean Delvare }
auto_temp_min_show(struct device * dev,struct device_attribute * attr,char * buf)3938e757e15SGuenter Roeck static ssize_t auto_temp_min_show(struct device *dev,
394c801082dSJean Delvare 				  struct device_attribute *attr, char *buf)
3958d5d45fbSJean Delvare {
396c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
3978d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
3988d5d45fbSJean Delvare 	return sprintf(buf, "%d\n",
3998d5d45fbSJean Delvare 		       AUTO_TEMP_MIN_FROM_REG(data->auto_temp[nr]));
4008d5d45fbSJean Delvare }
4018d5d45fbSJean Delvare static ssize_t
auto_temp_min_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)4028e757e15SGuenter Roeck auto_temp_min_store(struct device *dev, struct device_attribute *attr,
403c801082dSJean Delvare 		    const char *buf, size_t count)
4048d5d45fbSJean Delvare {
405b060f3c4SAxel Lin 	struct adm1031_data *data = dev_get_drvdata(dev);
406b060f3c4SAxel Lin 	struct i2c_client *client = data->client;
407c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4081c720093SGuenter Roeck 	long val;
4091c720093SGuenter Roeck 	int ret;
4101c720093SGuenter Roeck 
4111c720093SGuenter Roeck 	ret = kstrtol(buf, 10, &val);
4121c720093SGuenter Roeck 	if (ret)
4131c720093SGuenter Roeck 		return ret;
4148d5d45fbSJean Delvare 
415145e74a4SGuenter Roeck 	val = clamp_val(val, 0, 127000);
4169a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
4178d5d45fbSJean Delvare 	data->auto_temp[nr] = AUTO_TEMP_MIN_TO_REG(val, data->auto_temp[nr]);
4188d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr),
4198d5d45fbSJean Delvare 			    data->auto_temp[nr]);
4209a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
4218d5d45fbSJean Delvare 	return count;
4228d5d45fbSJean Delvare }
auto_temp_max_show(struct device * dev,struct device_attribute * attr,char * buf)4238e757e15SGuenter Roeck static ssize_t auto_temp_max_show(struct device *dev,
424c801082dSJean Delvare 				  struct device_attribute *attr, char *buf)
4258d5d45fbSJean Delvare {
426c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4278d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
4288d5d45fbSJean Delvare 	return sprintf(buf, "%d\n",
4298d5d45fbSJean Delvare 		       AUTO_TEMP_MAX_FROM_REG(data->auto_temp[nr]));
4308d5d45fbSJean Delvare }
4318d5d45fbSJean Delvare static ssize_t
auto_temp_max_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)4328e757e15SGuenter Roeck auto_temp_max_store(struct device *dev, struct device_attribute *attr,
433c801082dSJean Delvare 		    const char *buf, size_t count)
4348d5d45fbSJean Delvare {
435b060f3c4SAxel Lin 	struct adm1031_data *data = dev_get_drvdata(dev);
436b060f3c4SAxel Lin 	struct i2c_client *client = data->client;
437c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4381c720093SGuenter Roeck 	long val;
4391c720093SGuenter Roeck 	int ret;
4401c720093SGuenter Roeck 
4411c720093SGuenter Roeck 	ret = kstrtol(buf, 10, &val);
4421c720093SGuenter Roeck 	if (ret)
4431c720093SGuenter Roeck 		return ret;
4448d5d45fbSJean Delvare 
445145e74a4SGuenter Roeck 	val = clamp_val(val, 0, 127000);
4469a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
4471c720093SGuenter Roeck 	data->temp_max[nr] = AUTO_TEMP_MAX_TO_REG(val, data->auto_temp[nr],
4481c720093SGuenter Roeck 						  data->pwm[nr]);
4498d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr),
4508d5d45fbSJean Delvare 			    data->temp_max[nr]);
4519a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
4528d5d45fbSJean Delvare 	return count;
4538d5d45fbSJean Delvare }
4548d5d45fbSJean Delvare 
4558e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(auto_temp1_off, auto_temp_off, 0);
4568e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(auto_temp1_min, auto_temp_min, 0);
4578e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(auto_temp1_max, auto_temp_max, 0);
4588e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(auto_temp2_off, auto_temp_off, 1);
4598e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(auto_temp2_min, auto_temp_min, 1);
4608e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(auto_temp2_max, auto_temp_max, 1);
4618e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(auto_temp3_off, auto_temp_off, 2);
4628e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(auto_temp3_min, auto_temp_min, 2);
4638e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(auto_temp3_max, auto_temp_max, 2);
4648d5d45fbSJean Delvare 
4658d5d45fbSJean Delvare /* pwm */
pwm_show(struct device * dev,struct device_attribute * attr,char * buf)4668e757e15SGuenter Roeck static ssize_t pwm_show(struct device *dev, struct device_attribute *attr,
4678e757e15SGuenter Roeck 			char *buf)
4688d5d45fbSJean Delvare {
469c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4708d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
4718d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm[nr]));
4728d5d45fbSJean Delvare }
pwm_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)4738e757e15SGuenter Roeck static ssize_t pwm_store(struct device *dev, struct device_attribute *attr,
474c801082dSJean Delvare 			 const char *buf, size_t count)
4758d5d45fbSJean Delvare {
476b060f3c4SAxel Lin 	struct adm1031_data *data = dev_get_drvdata(dev);
477b060f3c4SAxel Lin 	struct i2c_client *client = data->client;
478c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4791c720093SGuenter Roeck 	long val;
4801c720093SGuenter Roeck 	int ret, reg;
4811c720093SGuenter Roeck 
4821c720093SGuenter Roeck 	ret = kstrtol(buf, 10, &val);
4831c720093SGuenter Roeck 	if (ret)
4841c720093SGuenter Roeck 		return ret;
4858d5d45fbSJean Delvare 
4869a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
4878d5d45fbSJean Delvare 	if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) &&
4888d5d45fbSJean Delvare 	    (((val>>4) & 0xf) != 5)) {
4898d5d45fbSJean Delvare 		/* In automatic mode, the only PWM accepted is 33% */
4909a61bf63SIngo Molnar 		mutex_unlock(&data->update_lock);
4918d5d45fbSJean Delvare 		return -EINVAL;
4928d5d45fbSJean Delvare 	}
4938d5d45fbSJean Delvare 	data->pwm[nr] = PWM_TO_REG(val);
4948d5d45fbSJean Delvare 	reg = adm1031_read_value(client, ADM1031_REG_PWM);
4958d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_PWM,
4968d5d45fbSJean Delvare 			    nr ? ((data->pwm[nr] << 4) & 0xf0) | (reg & 0xf)
4978d5d45fbSJean Delvare 			    : (data->pwm[nr] & 0xf) | (reg & 0xf0));
4989a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
4998d5d45fbSJean Delvare 	return count;
5008d5d45fbSJean Delvare }
5018d5d45fbSJean Delvare 
5028e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(pwm1, pwm, 0);
5038e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(pwm2, pwm, 1);
5048e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(auto_fan1_min_pwm, pwm, 0);
5058e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(auto_fan2_min_pwm, pwm, 1);
5068d5d45fbSJean Delvare 
5078d5d45fbSJean Delvare /* Fans */
5088d5d45fbSJean Delvare 
5098d5d45fbSJean Delvare /*
5108d5d45fbSJean Delvare  * That function checks the cases where the fan reading is not
5118d5d45fbSJean Delvare  * relevant.  It is used to provide 0 as fan reading when the fan is
5128d5d45fbSJean Delvare  * not supposed to run
5138d5d45fbSJean Delvare  */
trust_fan_readings(struct adm1031_data * data,int chan)5148d5d45fbSJean Delvare static int trust_fan_readings(struct adm1031_data *data, int chan)
5158d5d45fbSJean Delvare {
5168d5d45fbSJean Delvare 	int res = 0;
5178d5d45fbSJean Delvare 
5188d5d45fbSJean Delvare 	if (data->conf1 & ADM1031_CONF1_AUTO_MODE) {
5198d5d45fbSJean Delvare 		switch (data->conf1 & 0x60) {
5201c720093SGuenter Roeck 		case 0x00:
5211c720093SGuenter Roeck 			/*
5221c720093SGuenter Roeck 			 * remote temp1 controls fan1,
5231c720093SGuenter Roeck 			 * remote temp2 controls fan2
5241c720093SGuenter Roeck 			 */
5258d5d45fbSJean Delvare 			res = data->temp[chan+1] >=
5268d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[chan+1]);
5278d5d45fbSJean Delvare 			break;
5288d5d45fbSJean Delvare 		case 0x20:	/* remote temp1 controls both fans */
5298d5d45fbSJean Delvare 			res =
5308d5d45fbSJean Delvare 			    data->temp[1] >=
5318d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[1]);
5328d5d45fbSJean Delvare 			break;
5338d5d45fbSJean Delvare 		case 0x40:	/* remote temp2 controls both fans */
5348d5d45fbSJean Delvare 			res =
5358d5d45fbSJean Delvare 			    data->temp[2] >=
5368d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[2]);
5378d5d45fbSJean Delvare 			break;
5388d5d45fbSJean Delvare 		case 0x60:	/* max controls both fans */
5398d5d45fbSJean Delvare 			res =
5408d5d45fbSJean Delvare 			    data->temp[0] >=
5418d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[0])
5428d5d45fbSJean Delvare 			    || data->temp[1] >=
5438d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[1])
5448d5d45fbSJean Delvare 			    || (data->chip_type == adm1031
5458d5d45fbSJean Delvare 				&& data->temp[2] >=
5468d5d45fbSJean Delvare 				AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[2]));
5478d5d45fbSJean Delvare 			break;
5488d5d45fbSJean Delvare 		}
5498d5d45fbSJean Delvare 	} else {
5508d5d45fbSJean Delvare 		res = data->pwm[chan] > 0;
5518d5d45fbSJean Delvare 	}
5528d5d45fbSJean Delvare 	return res;
5538d5d45fbSJean Delvare }
5548d5d45fbSJean Delvare 
fan_show(struct device * dev,struct device_attribute * attr,char * buf)5558e757e15SGuenter Roeck static ssize_t fan_show(struct device *dev, struct device_attribute *attr,
5568e757e15SGuenter Roeck 			char *buf)
5578d5d45fbSJean Delvare {
558c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
5598d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
5608d5d45fbSJean Delvare 	int value;
5618d5d45fbSJean Delvare 
5628d5d45fbSJean Delvare 	value = trust_fan_readings(data, nr) ? FAN_FROM_REG(data->fan[nr],
5638d5d45fbSJean Delvare 				 FAN_DIV_FROM_REG(data->fan_div[nr])) : 0;
5648d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", value);
5658d5d45fbSJean Delvare }
5668d5d45fbSJean Delvare 
fan_div_show(struct device * dev,struct device_attribute * attr,char * buf)5678e757e15SGuenter Roeck static ssize_t fan_div_show(struct device *dev, struct device_attribute *attr,
5688e757e15SGuenter Roeck 			    char *buf)
5698d5d45fbSJean Delvare {
570c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
5718d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
5728d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", FAN_DIV_FROM_REG(data->fan_div[nr]));
5738d5d45fbSJean Delvare }
fan_min_show(struct device * dev,struct device_attribute * attr,char * buf)5748e757e15SGuenter Roeck static ssize_t fan_min_show(struct device *dev, struct device_attribute *attr,
5758e757e15SGuenter Roeck 			    char *buf)
5768d5d45fbSJean Delvare {
577c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
5788d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
5798d5d45fbSJean Delvare 	return sprintf(buf, "%d\n",
5808d5d45fbSJean Delvare 		       FAN_FROM_REG(data->fan_min[nr],
5818d5d45fbSJean Delvare 				    FAN_DIV_FROM_REG(data->fan_div[nr])));
5828d5d45fbSJean Delvare }
fan_min_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)5838e757e15SGuenter Roeck static ssize_t fan_min_store(struct device *dev,
5848e757e15SGuenter Roeck 			     struct device_attribute *attr, const char *buf,
5858e757e15SGuenter Roeck 			     size_t count)
5868d5d45fbSJean Delvare {
587b060f3c4SAxel Lin 	struct adm1031_data *data = dev_get_drvdata(dev);
588b060f3c4SAxel Lin 	struct i2c_client *client = data->client;
589c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
5901c720093SGuenter Roeck 	long val;
5911c720093SGuenter Roeck 	int ret;
5921c720093SGuenter Roeck 
5931c720093SGuenter Roeck 	ret = kstrtol(buf, 10, &val);
5941c720093SGuenter Roeck 	if (ret)
5951c720093SGuenter Roeck 		return ret;
5968d5d45fbSJean Delvare 
5979a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
5988d5d45fbSJean Delvare 	if (val) {
5998d5d45fbSJean Delvare 		data->fan_min[nr] =
6008d5d45fbSJean Delvare 			FAN_TO_REG(val, FAN_DIV_FROM_REG(data->fan_div[nr]));
6018d5d45fbSJean Delvare 	} else {
6028d5d45fbSJean Delvare 		data->fan_min[nr] = 0xff;
6038d5d45fbSJean Delvare 	}
6048d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), data->fan_min[nr]);
6059a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
6068d5d45fbSJean Delvare 	return count;
6078d5d45fbSJean Delvare }
fan_div_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)6088e757e15SGuenter Roeck static ssize_t fan_div_store(struct device *dev,
6098e757e15SGuenter Roeck 			     struct device_attribute *attr, const char *buf,
6108e757e15SGuenter Roeck 			     size_t count)
6118d5d45fbSJean Delvare {
612b060f3c4SAxel Lin 	struct adm1031_data *data = dev_get_drvdata(dev);
613b060f3c4SAxel Lin 	struct i2c_client *client = data->client;
614c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
6151c720093SGuenter Roeck 	long val;
6168d5d45fbSJean Delvare 	u8 tmp;
6178d5d45fbSJean Delvare 	int old_div;
6188d5d45fbSJean Delvare 	int new_min;
6191c720093SGuenter Roeck 	int ret;
6201c720093SGuenter Roeck 
6211c720093SGuenter Roeck 	ret = kstrtol(buf, 10, &val);
6221c720093SGuenter Roeck 	if (ret)
6231c720093SGuenter Roeck 		return ret;
6248d5d45fbSJean Delvare 
6258d5d45fbSJean Delvare 	tmp = val == 8 ? 0xc0 :
6268d5d45fbSJean Delvare 	      val == 4 ? 0x80 :
6278d5d45fbSJean Delvare 	      val == 2 ? 0x40 :
6288d5d45fbSJean Delvare 	      val == 1 ? 0x00 :
6298d5d45fbSJean Delvare 	      0xff;
6308d5d45fbSJean Delvare 	if (tmp == 0xff)
6318d5d45fbSJean Delvare 		return -EINVAL;
6328d5d45fbSJean Delvare 
6339a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
63438a1f0e9SJean Delvare 	/* Get fresh readings */
63538a1f0e9SJean Delvare 	data->fan_div[nr] = adm1031_read_value(client,
63638a1f0e9SJean Delvare 					       ADM1031_REG_FAN_DIV(nr));
63738a1f0e9SJean Delvare 	data->fan_min[nr] = adm1031_read_value(client,
63838a1f0e9SJean Delvare 					       ADM1031_REG_FAN_MIN(nr));
63938a1f0e9SJean Delvare 
64038a1f0e9SJean Delvare 	/* Write the new clock divider and fan min */
6418d5d45fbSJean Delvare 	old_div = FAN_DIV_FROM_REG(data->fan_div[nr]);
6426d6006b8SJean Delvare 	data->fan_div[nr] = tmp | (0x3f & data->fan_div[nr]);
6436d6006b8SJean Delvare 	new_min = data->fan_min[nr] * old_div / val;
6448d5d45fbSJean Delvare 	data->fan_min[nr] = new_min > 0xff ? 0xff : new_min;
6458d5d45fbSJean Delvare 
6468d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_FAN_DIV(nr),
6478d5d45fbSJean Delvare 			    data->fan_div[nr]);
6488d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr),
6498d5d45fbSJean Delvare 			    data->fan_min[nr]);
65038a1f0e9SJean Delvare 
65138a1f0e9SJean Delvare 	/* Invalidate the cache: fan speed is no longer valid */
652952a11caSPaul Fertser 	data->valid = false;
6539a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
6548d5d45fbSJean Delvare 	return count;
6558d5d45fbSJean Delvare }
6568d5d45fbSJean Delvare 
6578e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan1_input, fan, 0);
6588e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(fan1_min, fan_min, 0);
6598e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(fan1_div, fan_div, 0);
6608e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan2_input, fan, 1);
6618e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(fan2_min, fan_min, 1);
6628e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(fan2_div, fan_div, 1);
6638d5d45fbSJean Delvare 
6648d5d45fbSJean Delvare /* Temps */
temp_show(struct device * dev,struct device_attribute * attr,char * buf)6658e757e15SGuenter Roeck static ssize_t temp_show(struct device *dev, struct device_attribute *attr,
6668e757e15SGuenter Roeck 			 char *buf)
6678d5d45fbSJean Delvare {
668c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
6698d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
6708d5d45fbSJean Delvare 	int ext;
6718d5d45fbSJean Delvare 	ext = nr == 0 ?
6728d5d45fbSJean Delvare 	    ((data->ext_temp[nr] >> 6) & 0x3) * 2 :
6738d5d45fbSJean Delvare 	    (((data->ext_temp[nr] >> ((nr - 1) * 3)) & 7));
6748d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG_EXT(data->temp[nr], ext));
6758d5d45fbSJean Delvare }
temp_offset_show(struct device * dev,struct device_attribute * attr,char * buf)6768e757e15SGuenter Roeck static ssize_t temp_offset_show(struct device *dev,
67749dc9efeSIra Snyder 				struct device_attribute *attr, char *buf)
67849dc9efeSIra Snyder {
67949dc9efeSIra Snyder 	int nr = to_sensor_dev_attr(attr)->index;
68049dc9efeSIra Snyder 	struct adm1031_data *data = adm1031_update_device(dev);
68149dc9efeSIra Snyder 	return sprintf(buf, "%d\n",
68249dc9efeSIra Snyder 		       TEMP_OFFSET_FROM_REG(data->temp_offset[nr]));
68349dc9efeSIra Snyder }
temp_min_show(struct device * dev,struct device_attribute * attr,char * buf)6848e757e15SGuenter Roeck static ssize_t temp_min_show(struct device *dev,
685c801082dSJean Delvare 			     struct device_attribute *attr, char *buf)
6868d5d45fbSJean Delvare {
687c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
6888d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
6898d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr]));
6908d5d45fbSJean Delvare }
temp_max_show(struct device * dev,struct device_attribute * attr,char * buf)6918e757e15SGuenter Roeck static ssize_t temp_max_show(struct device *dev,
692c801082dSJean Delvare 			     struct device_attribute *attr, char *buf)
6938d5d45fbSJean Delvare {
694c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
6958d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
6968d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr]));
6978d5d45fbSJean Delvare }
temp_crit_show(struct device * dev,struct device_attribute * attr,char * buf)6988e757e15SGuenter Roeck static ssize_t temp_crit_show(struct device *dev,
699c801082dSJean Delvare 			      struct device_attribute *attr, char *buf)
7008d5d45fbSJean Delvare {
701c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
7028d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
7038d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[nr]));
7048d5d45fbSJean Delvare }
temp_offset_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)7058e757e15SGuenter Roeck static ssize_t temp_offset_store(struct device *dev,
7068e757e15SGuenter Roeck 				 struct device_attribute *attr,
7078e757e15SGuenter Roeck 				 const char *buf, size_t count)
70849dc9efeSIra Snyder {
709b060f3c4SAxel Lin 	struct adm1031_data *data = dev_get_drvdata(dev);
710b060f3c4SAxel Lin 	struct i2c_client *client = data->client;
71149dc9efeSIra Snyder 	int nr = to_sensor_dev_attr(attr)->index;
7121c720093SGuenter Roeck 	long val;
7131c720093SGuenter Roeck 	int ret;
71449dc9efeSIra Snyder 
7151c720093SGuenter Roeck 	ret = kstrtol(buf, 10, &val);
7161c720093SGuenter Roeck 	if (ret)
7171c720093SGuenter Roeck 		return ret;
7181c720093SGuenter Roeck 
7192a844c14SGuenter Roeck 	val = clamp_val(val, -15000, 15000);
72049dc9efeSIra Snyder 	mutex_lock(&data->update_lock);
72149dc9efeSIra Snyder 	data->temp_offset[nr] = TEMP_OFFSET_TO_REG(val);
72249dc9efeSIra Snyder 	adm1031_write_value(client, ADM1031_REG_TEMP_OFFSET(nr),
72349dc9efeSIra Snyder 			    data->temp_offset[nr]);
72449dc9efeSIra Snyder 	mutex_unlock(&data->update_lock);
72549dc9efeSIra Snyder 	return count;
72649dc9efeSIra Snyder }
temp_min_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)7278e757e15SGuenter Roeck static ssize_t temp_min_store(struct device *dev,
7288e757e15SGuenter Roeck 			      struct device_attribute *attr, const char *buf,
7298e757e15SGuenter Roeck 			      size_t count)
7308d5d45fbSJean Delvare {
731b060f3c4SAxel Lin 	struct adm1031_data *data = dev_get_drvdata(dev);
732b060f3c4SAxel Lin 	struct i2c_client *client = data->client;
733c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
7341c720093SGuenter Roeck 	long val;
7351c720093SGuenter Roeck 	int ret;
7368d5d45fbSJean Delvare 
7371c720093SGuenter Roeck 	ret = kstrtol(buf, 10, &val);
7381c720093SGuenter Roeck 	if (ret)
7391c720093SGuenter Roeck 		return ret;
7401c720093SGuenter Roeck 
741145e74a4SGuenter Roeck 	val = clamp_val(val, -55000, 127000);
7429a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
7438d5d45fbSJean Delvare 	data->temp_min[nr] = TEMP_TO_REG(val);
7448d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_TEMP_MIN(nr),
7458d5d45fbSJean Delvare 			    data->temp_min[nr]);
7469a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
7478d5d45fbSJean Delvare 	return count;
7488d5d45fbSJean Delvare }
temp_max_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)7498e757e15SGuenter Roeck static ssize_t temp_max_store(struct device *dev,
7508e757e15SGuenter Roeck 			      struct device_attribute *attr, const char *buf,
7518e757e15SGuenter Roeck 			      size_t count)
7528d5d45fbSJean Delvare {
753b060f3c4SAxel Lin 	struct adm1031_data *data = dev_get_drvdata(dev);
754b060f3c4SAxel Lin 	struct i2c_client *client = data->client;
755c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
7561c720093SGuenter Roeck 	long val;
7571c720093SGuenter Roeck 	int ret;
7588d5d45fbSJean Delvare 
7591c720093SGuenter Roeck 	ret = kstrtol(buf, 10, &val);
7601c720093SGuenter Roeck 	if (ret)
7611c720093SGuenter Roeck 		return ret;
7621c720093SGuenter Roeck 
763145e74a4SGuenter Roeck 	val = clamp_val(val, -55000, 127000);
7649a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
7658d5d45fbSJean Delvare 	data->temp_max[nr] = TEMP_TO_REG(val);
7668d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_TEMP_MAX(nr),
7678d5d45fbSJean Delvare 			    data->temp_max[nr]);
7689a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
7698d5d45fbSJean Delvare 	return count;
7708d5d45fbSJean Delvare }
temp_crit_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)7718e757e15SGuenter Roeck static ssize_t temp_crit_store(struct device *dev,
7728e757e15SGuenter Roeck 			       struct device_attribute *attr, const char *buf,
7738e757e15SGuenter Roeck 			       size_t count)
7748d5d45fbSJean Delvare {
775b060f3c4SAxel Lin 	struct adm1031_data *data = dev_get_drvdata(dev);
776b060f3c4SAxel Lin 	struct i2c_client *client = data->client;
777c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
7781c720093SGuenter Roeck 	long val;
7791c720093SGuenter Roeck 	int ret;
7808d5d45fbSJean Delvare 
7811c720093SGuenter Roeck 	ret = kstrtol(buf, 10, &val);
7821c720093SGuenter Roeck 	if (ret)
7831c720093SGuenter Roeck 		return ret;
7841c720093SGuenter Roeck 
785145e74a4SGuenter Roeck 	val = clamp_val(val, -55000, 127000);
7869a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
7878d5d45fbSJean Delvare 	data->temp_crit[nr] = TEMP_TO_REG(val);
7888d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_TEMP_CRIT(nr),
7898d5d45fbSJean Delvare 			    data->temp_crit[nr]);
7909a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
7918d5d45fbSJean Delvare 	return count;
7928d5d45fbSJean Delvare }
7938d5d45fbSJean Delvare 
7948e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, 0);
7958e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp1_offset, temp_offset, 0);
7968e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp1_min, temp_min, 0);
7978e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp1_max, temp_max, 0);
7988e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp1_crit, temp_crit, 0);
7998e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp2_input, temp, 1);
8008e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp2_offset, temp_offset, 1);
8018e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp2_min, temp_min, 1);
8028e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp2_max, temp_max, 1);
8038e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp2_crit, temp_crit, 1);
8048e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp3_input, temp, 2);
8058e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp3_offset, temp_offset, 2);
8068e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp3_min, temp_min, 2);
8078e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp3_max, temp_max, 2);
8088e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp3_crit, temp_crit, 2);
8098d5d45fbSJean Delvare 
8108d5d45fbSJean Delvare /* Alarms */
alarms_show(struct device * dev,struct device_attribute * attr,char * buf)811bfb6b173SJulia Lawall static ssize_t alarms_show(struct device *dev, struct device_attribute *attr,
8121c720093SGuenter Roeck 			   char *buf)
8138d5d45fbSJean Delvare {
8148d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
8158d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", data->alarm);
8168d5d45fbSJean Delvare }
8178d5d45fbSJean Delvare 
818bfb6b173SJulia Lawall static DEVICE_ATTR_RO(alarms);
8198d5d45fbSJean Delvare 
alarm_show(struct device * dev,struct device_attribute * attr,char * buf)8208e757e15SGuenter Roeck static ssize_t alarm_show(struct device *dev, struct device_attribute *attr,
8218e757e15SGuenter Roeck 			  char *buf)
822050ab878SJean Delvare {
823050ab878SJean Delvare 	int bitnr = to_sensor_dev_attr(attr)->index;
824050ab878SJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
825050ab878SJean Delvare 	return sprintf(buf, "%d\n", (data->alarm >> bitnr) & 1);
826050ab878SJean Delvare }
827050ab878SJean Delvare 
8288e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan1_alarm, alarm, 0);
8298e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan1_fault, alarm, 1);
8308e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp2_max_alarm, alarm, 2);
8318e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp2_min_alarm, alarm, 3);
8328e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp2_crit_alarm, alarm, 4);
8338e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp2_fault, alarm, 5);
8348e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 6);
8358e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp1_min_alarm, alarm, 7);
8368e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan2_alarm, alarm, 8);
8378e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan2_fault, alarm, 9);
8388e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp3_max_alarm, alarm, 10);
8398e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp3_min_alarm, alarm, 11);
8408e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp3_crit_alarm, alarm, 12);
8418e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp3_fault, alarm, 13);
8428e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, alarm, 14);
8438d5d45fbSJean Delvare 
844a51b9944SGuenter Roeck /* Update Interval */
845a51b9944SGuenter Roeck static const unsigned int update_intervals[] = {
84687c33daaSJean Delvare 	16000, 8000, 4000, 2000, 1000, 500, 250, 125,
84787c33daaSJean Delvare };
84887c33daaSJean Delvare 
update_interval_show(struct device * dev,struct device_attribute * attr,char * buf)849bfb6b173SJulia Lawall static ssize_t update_interval_show(struct device *dev,
85087c33daaSJean Delvare 				    struct device_attribute *attr, char *buf)
85187c33daaSJean Delvare {
852b060f3c4SAxel Lin 	struct adm1031_data *data = dev_get_drvdata(dev);
85387c33daaSJean Delvare 
854a51b9944SGuenter Roeck 	return sprintf(buf, "%u\n", data->update_interval);
85587c33daaSJean Delvare }
85687c33daaSJean Delvare 
update_interval_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)857bfb6b173SJulia Lawall static ssize_t update_interval_store(struct device *dev,
85887c33daaSJean Delvare 				     struct device_attribute *attr,
85987c33daaSJean Delvare 				     const char *buf, size_t count)
86087c33daaSJean Delvare {
861b060f3c4SAxel Lin 	struct adm1031_data *data = dev_get_drvdata(dev);
862b060f3c4SAxel Lin 	struct i2c_client *client = data->client;
86387c33daaSJean Delvare 	unsigned long val;
86487c33daaSJean Delvare 	int i, err;
86587c33daaSJean Delvare 	u8 reg;
86687c33daaSJean Delvare 
867179c4fdbSFrans Meulenbroeks 	err = kstrtoul(buf, 10, &val);
86887c33daaSJean Delvare 	if (err)
86987c33daaSJean Delvare 		return err;
87087c33daaSJean Delvare 
871a51b9944SGuenter Roeck 	/*
872a51b9944SGuenter Roeck 	 * Find the nearest update interval from the table.
873a51b9944SGuenter Roeck 	 * Use it to determine the matching update rate.
874a51b9944SGuenter Roeck 	 */
875a51b9944SGuenter Roeck 	for (i = 0; i < ARRAY_SIZE(update_intervals) - 1; i++) {
876a51b9944SGuenter Roeck 		if (val >= update_intervals[i])
87787c33daaSJean Delvare 			break;
87887c33daaSJean Delvare 	}
879a51b9944SGuenter Roeck 	/* if not found, we point to the last entry (lowest update interval) */
88087c33daaSJean Delvare 
88187c33daaSJean Delvare 	/* set the new update rate while preserving other settings */
88287c33daaSJean Delvare 	reg = adm1031_read_value(client, ADM1031_REG_FAN_FILTER);
88387c33daaSJean Delvare 	reg &= ~ADM1031_UPDATE_RATE_MASK;
88487c33daaSJean Delvare 	reg |= i << ADM1031_UPDATE_RATE_SHIFT;
88587c33daaSJean Delvare 	adm1031_write_value(client, ADM1031_REG_FAN_FILTER, reg);
88687c33daaSJean Delvare 
88787c33daaSJean Delvare 	mutex_lock(&data->update_lock);
888a51b9944SGuenter Roeck 	data->update_interval = update_intervals[i];
88987c33daaSJean Delvare 	mutex_unlock(&data->update_lock);
89087c33daaSJean Delvare 
89187c33daaSJean Delvare 	return count;
89287c33daaSJean Delvare }
89387c33daaSJean Delvare 
894bfb6b173SJulia Lawall static DEVICE_ATTR_RW(update_interval);
89587c33daaSJean Delvare 
896681c6f7aSMark M. Hoffman static struct attribute *adm1031_attributes[] = {
897c801082dSJean Delvare 	&sensor_dev_attr_fan1_input.dev_attr.attr,
898c801082dSJean Delvare 	&sensor_dev_attr_fan1_div.dev_attr.attr,
899c801082dSJean Delvare 	&sensor_dev_attr_fan1_min.dev_attr.attr,
900050ab878SJean Delvare 	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
901050ab878SJean Delvare 	&sensor_dev_attr_fan1_fault.dev_attr.attr,
902c801082dSJean Delvare 	&sensor_dev_attr_pwm1.dev_attr.attr,
903c801082dSJean Delvare 	&sensor_dev_attr_auto_fan1_channel.dev_attr.attr,
904c801082dSJean Delvare 	&sensor_dev_attr_temp1_input.dev_attr.attr,
90549dc9efeSIra Snyder 	&sensor_dev_attr_temp1_offset.dev_attr.attr,
906c801082dSJean Delvare 	&sensor_dev_attr_temp1_min.dev_attr.attr,
907050ab878SJean Delvare 	&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
908c801082dSJean Delvare 	&sensor_dev_attr_temp1_max.dev_attr.attr,
909050ab878SJean Delvare 	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
910c801082dSJean Delvare 	&sensor_dev_attr_temp1_crit.dev_attr.attr,
911050ab878SJean Delvare 	&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
912c801082dSJean Delvare 	&sensor_dev_attr_temp2_input.dev_attr.attr,
91349dc9efeSIra Snyder 	&sensor_dev_attr_temp2_offset.dev_attr.attr,
914c801082dSJean Delvare 	&sensor_dev_attr_temp2_min.dev_attr.attr,
915050ab878SJean Delvare 	&sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
916c801082dSJean Delvare 	&sensor_dev_attr_temp2_max.dev_attr.attr,
917050ab878SJean Delvare 	&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
918c801082dSJean Delvare 	&sensor_dev_attr_temp2_crit.dev_attr.attr,
919050ab878SJean Delvare 	&sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
920050ab878SJean Delvare 	&sensor_dev_attr_temp2_fault.dev_attr.attr,
921681c6f7aSMark M. Hoffman 
922c801082dSJean Delvare 	&sensor_dev_attr_auto_temp1_off.dev_attr.attr,
923c801082dSJean Delvare 	&sensor_dev_attr_auto_temp1_min.dev_attr.attr,
924c801082dSJean Delvare 	&sensor_dev_attr_auto_temp1_max.dev_attr.attr,
925681c6f7aSMark M. Hoffman 
926c801082dSJean Delvare 	&sensor_dev_attr_auto_temp2_off.dev_attr.attr,
927c801082dSJean Delvare 	&sensor_dev_attr_auto_temp2_min.dev_attr.attr,
928c801082dSJean Delvare 	&sensor_dev_attr_auto_temp2_max.dev_attr.attr,
929681c6f7aSMark M. Hoffman 
930c801082dSJean Delvare 	&sensor_dev_attr_auto_fan1_min_pwm.dev_attr.attr,
931681c6f7aSMark M. Hoffman 
932a51b9944SGuenter Roeck 	&dev_attr_update_interval.attr,
933681c6f7aSMark M. Hoffman 	&dev_attr_alarms.attr,
934681c6f7aSMark M. Hoffman 
935681c6f7aSMark M. Hoffman 	NULL
936681c6f7aSMark M. Hoffman };
937681c6f7aSMark M. Hoffman 
938681c6f7aSMark M. Hoffman static const struct attribute_group adm1031_group = {
939681c6f7aSMark M. Hoffman 	.attrs = adm1031_attributes,
940681c6f7aSMark M. Hoffman };
941681c6f7aSMark M. Hoffman 
942681c6f7aSMark M. Hoffman static struct attribute *adm1031_attributes_opt[] = {
943c801082dSJean Delvare 	&sensor_dev_attr_fan2_input.dev_attr.attr,
944c801082dSJean Delvare 	&sensor_dev_attr_fan2_div.dev_attr.attr,
945c801082dSJean Delvare 	&sensor_dev_attr_fan2_min.dev_attr.attr,
946050ab878SJean Delvare 	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
947050ab878SJean Delvare 	&sensor_dev_attr_fan2_fault.dev_attr.attr,
948c801082dSJean Delvare 	&sensor_dev_attr_pwm2.dev_attr.attr,
949c801082dSJean Delvare 	&sensor_dev_attr_auto_fan2_channel.dev_attr.attr,
950c801082dSJean Delvare 	&sensor_dev_attr_temp3_input.dev_attr.attr,
95149dc9efeSIra Snyder 	&sensor_dev_attr_temp3_offset.dev_attr.attr,
952c801082dSJean Delvare 	&sensor_dev_attr_temp3_min.dev_attr.attr,
953050ab878SJean Delvare 	&sensor_dev_attr_temp3_min_alarm.dev_attr.attr,
954c801082dSJean Delvare 	&sensor_dev_attr_temp3_max.dev_attr.attr,
955050ab878SJean Delvare 	&sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
956c801082dSJean Delvare 	&sensor_dev_attr_temp3_crit.dev_attr.attr,
957050ab878SJean Delvare 	&sensor_dev_attr_temp3_crit_alarm.dev_attr.attr,
958050ab878SJean Delvare 	&sensor_dev_attr_temp3_fault.dev_attr.attr,
959c801082dSJean Delvare 	&sensor_dev_attr_auto_temp3_off.dev_attr.attr,
960c801082dSJean Delvare 	&sensor_dev_attr_auto_temp3_min.dev_attr.attr,
961c801082dSJean Delvare 	&sensor_dev_attr_auto_temp3_max.dev_attr.attr,
962c801082dSJean Delvare 	&sensor_dev_attr_auto_fan2_min_pwm.dev_attr.attr,
963681c6f7aSMark M. Hoffman 	NULL
964681c6f7aSMark M. Hoffman };
965681c6f7aSMark M. Hoffman 
966681c6f7aSMark M. Hoffman static const struct attribute_group adm1031_group_opt = {
967681c6f7aSMark M. Hoffman 	.attrs = adm1031_attributes_opt,
968681c6f7aSMark M. Hoffman };
969681c6f7aSMark M. Hoffman 
970af200f88SJean Delvare /* Return 0 if detection is successful, -ENODEV otherwise */
adm1031_detect(struct i2c_client * client,struct i2c_board_info * info)971310ec792SJean Delvare static int adm1031_detect(struct i2c_client *client,
972af200f88SJean Delvare 			  struct i2c_board_info *info)
9738d5d45fbSJean Delvare {
974af200f88SJean Delvare 	struct i2c_adapter *adapter = client->adapter;
97552df6440SJean Delvare 	const char *name;
97652df6440SJean Delvare 	int id, co;
9778d5d45fbSJean Delvare 
9788d5d45fbSJean Delvare 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
979af200f88SJean Delvare 		return -ENODEV;
9808d5d45fbSJean Delvare 
9816d6006b8SJean Delvare 	id = i2c_smbus_read_byte_data(client, 0x3d);
9826d6006b8SJean Delvare 	co = i2c_smbus_read_byte_data(client, 0x3e);
9838d5d45fbSJean Delvare 
9848d5d45fbSJean Delvare 	if (!((id == 0x31 || id == 0x30) && co == 0x41))
985af200f88SJean Delvare 		return -ENODEV;
98652df6440SJean Delvare 	name = (id == 0x30) ? "adm1030" : "adm1031";
9878d5d45fbSJean Delvare 
988f2f394dbSWolfram Sang 	strscpy(info->type, name, I2C_NAME_SIZE);
9898d5d45fbSJean Delvare 
990af200f88SJean Delvare 	return 0;
991af200f88SJean Delvare }
992af200f88SJean Delvare 
adm1031_init_client(struct i2c_client * client)993278ee1c8SAxel Lin static void adm1031_init_client(struct i2c_client *client)
994278ee1c8SAxel Lin {
995278ee1c8SAxel Lin 	unsigned int read_val;
996278ee1c8SAxel Lin 	unsigned int mask;
997278ee1c8SAxel Lin 	int i;
998278ee1c8SAxel Lin 	struct adm1031_data *data = i2c_get_clientdata(client);
999278ee1c8SAxel Lin 
1000278ee1c8SAxel Lin 	mask = (ADM1031_CONF2_PWM1_ENABLE | ADM1031_CONF2_TACH1_ENABLE);
1001278ee1c8SAxel Lin 	if (data->chip_type == adm1031) {
1002278ee1c8SAxel Lin 		mask |= (ADM1031_CONF2_PWM2_ENABLE |
1003278ee1c8SAxel Lin 			ADM1031_CONF2_TACH2_ENABLE);
1004278ee1c8SAxel Lin 	}
1005278ee1c8SAxel Lin 	/* Initialize the ADM1031 chip (enables fan speed reading ) */
1006278ee1c8SAxel Lin 	read_val = adm1031_read_value(client, ADM1031_REG_CONF2);
1007278ee1c8SAxel Lin 	if ((read_val | mask) != read_val)
1008278ee1c8SAxel Lin 		adm1031_write_value(client, ADM1031_REG_CONF2, read_val | mask);
1009278ee1c8SAxel Lin 
1010278ee1c8SAxel Lin 	read_val = adm1031_read_value(client, ADM1031_REG_CONF1);
1011278ee1c8SAxel Lin 	if ((read_val | ADM1031_CONF1_MONITOR_ENABLE) != read_val) {
1012278ee1c8SAxel Lin 		adm1031_write_value(client, ADM1031_REG_CONF1,
1013278ee1c8SAxel Lin 				    read_val | ADM1031_CONF1_MONITOR_ENABLE);
1014278ee1c8SAxel Lin 	}
1015278ee1c8SAxel Lin 
1016278ee1c8SAxel Lin 	/* Read the chip's update rate */
1017278ee1c8SAxel Lin 	mask = ADM1031_UPDATE_RATE_MASK;
1018278ee1c8SAxel Lin 	read_val = adm1031_read_value(client, ADM1031_REG_FAN_FILTER);
1019278ee1c8SAxel Lin 	i = (read_val & mask) >> ADM1031_UPDATE_RATE_SHIFT;
1020278ee1c8SAxel Lin 	/* Save it as update interval */
1021278ee1c8SAxel Lin 	data->update_interval = update_intervals[i];
1022278ee1c8SAxel Lin }
1023278ee1c8SAxel Lin 
adm1031_probe(struct i2c_client * client)102467487038SStephen Kitt static int adm1031_probe(struct i2c_client *client)
1025af200f88SJean Delvare {
1026b060f3c4SAxel Lin 	struct device *dev = &client->dev;
1027b060f3c4SAxel Lin 	struct device *hwmon_dev;
1028af200f88SJean Delvare 	struct adm1031_data *data;
1029af200f88SJean Delvare 
1030b060f3c4SAxel Lin 	data = devm_kzalloc(dev, sizeof(struct adm1031_data), GFP_KERNEL);
1031dc2fd663SGuenter Roeck 	if (!data)
1032dc2fd663SGuenter Roeck 		return -ENOMEM;
1033af200f88SJean Delvare 
1034af200f88SJean Delvare 	i2c_set_clientdata(client, data);
1035b060f3c4SAxel Lin 	data->client = client;
1036*0f1874f8SAndrew Davis 	data->chip_type = (uintptr_t)i2c_get_match_data(client);
10379a61bf63SIngo Molnar 	mutex_init(&data->update_lock);
10388d5d45fbSJean Delvare 
1039af200f88SJean Delvare 	if (data->chip_type == adm1030)
1040af200f88SJean Delvare 		data->chan_select_table = &auto_channel_select_table_adm1030;
1041af200f88SJean Delvare 	else
1042af200f88SJean Delvare 		data->chan_select_table = &auto_channel_select_table_adm1031;
10438d5d45fbSJean Delvare 
10448d5d45fbSJean Delvare 	/* Initialize the ADM1031 chip */
10456d6006b8SJean Delvare 	adm1031_init_client(client);
10468d5d45fbSJean Delvare 
1047b060f3c4SAxel Lin 	/* sysfs hooks */
1048b060f3c4SAxel Lin 	data->groups[0] = &adm1031_group;
1049b060f3c4SAxel Lin 	if (data->chip_type == adm1031)
1050b060f3c4SAxel Lin 		data->groups[1] = &adm1031_group_opt;
1051681c6f7aSMark M. Hoffman 
1052b060f3c4SAxel Lin 	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
1053b060f3c4SAxel Lin 							   data, data->groups);
1054b060f3c4SAxel Lin 	return PTR_ERR_OR_ZERO(hwmon_dev);
10558d5d45fbSJean Delvare }
10568d5d45fbSJean Delvare 
1057278ee1c8SAxel Lin static const struct i2c_device_id adm1031_id[] = {
1058278ee1c8SAxel Lin 	{ "adm1030", adm1030 },
1059278ee1c8SAxel Lin 	{ "adm1031", adm1031 },
1060278ee1c8SAxel Lin 	{ }
1061278ee1c8SAxel Lin };
1062278ee1c8SAxel Lin MODULE_DEVICE_TABLE(i2c, adm1031_id);
10638d5d45fbSJean Delvare 
1064278ee1c8SAxel Lin static struct i2c_driver adm1031_driver = {
1065278ee1c8SAxel Lin 	.class		= I2C_CLASS_HWMON,
1066278ee1c8SAxel Lin 	.driver = {
1067278ee1c8SAxel Lin 		.name = "adm1031",
1068278ee1c8SAxel Lin 	},
10691975d167SUwe Kleine-König 	.probe		= adm1031_probe,
1070278ee1c8SAxel Lin 	.id_table	= adm1031_id,
1071278ee1c8SAxel Lin 	.detect		= adm1031_detect,
1072278ee1c8SAxel Lin 	.address_list	= normal_i2c,
1073278ee1c8SAxel Lin };
10748d5d45fbSJean Delvare 
1075f0967eeaSAxel Lin module_i2c_driver(adm1031_driver);
10768d5d45fbSJean Delvare 
10778d5d45fbSJean Delvare MODULE_AUTHOR("Alexandre d'Alton <alex@alexdalton.org>");
10788d5d45fbSJean Delvare MODULE_DESCRIPTION("ADM1031/ADM1030 driver");
10798d5d45fbSJean Delvare MODULE_LICENSE("GPL");
1080