xref: /openbmc/linux/drivers/hwmon/adm1031.c (revision 8e757e15a509b8623fd02f18c65eedcc1ed9fed3)
18d5d45fbSJean Delvare /*
2fbb6670dSGuenter Roeck  * adm1031.c - Part of lm_sensors, Linux kernel modules for hardware
3fbb6670dSGuenter Roeck  *	       monitoring
4fbb6670dSGuenter Roeck  * Based on lm75.c and lm85.c
5fbb6670dSGuenter Roeck  * Supports adm1030 / adm1031
6fbb6670dSGuenter Roeck  * Copyright (C) 2004 Alexandre d'Alton <alex@alexdalton.org>
77c81c60fSJean Delvare  * Reworked by Jean Delvare <jdelvare@suse.de>
8fbb6670dSGuenter Roeck  *
9fbb6670dSGuenter Roeck  * This program is free software; you can redistribute it and/or modify
10fbb6670dSGuenter Roeck  * it under the terms of the GNU General Public License as published by
11fbb6670dSGuenter Roeck  * the Free Software Foundation; either version 2 of the License, or
12fbb6670dSGuenter Roeck  * (at your option) any later version.
13fbb6670dSGuenter Roeck  *
14fbb6670dSGuenter Roeck  * This program is distributed in the hope that it will be useful,
15fbb6670dSGuenter Roeck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16fbb6670dSGuenter Roeck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17fbb6670dSGuenter Roeck  * GNU General Public License for more details.
18fbb6670dSGuenter Roeck  *
19fbb6670dSGuenter Roeck  * You should have received a copy of the GNU General Public License
20fbb6670dSGuenter Roeck  * along with this program; if not, write to the Free Software
21fbb6670dSGuenter Roeck  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
228d5d45fbSJean Delvare  */
238d5d45fbSJean Delvare 
248d5d45fbSJean Delvare #include <linux/module.h>
258d5d45fbSJean Delvare #include <linux/init.h>
268d5d45fbSJean Delvare #include <linux/slab.h>
278d5d45fbSJean Delvare #include <linux/jiffies.h>
288d5d45fbSJean Delvare #include <linux/i2c.h>
29943b0830SMark M. Hoffman #include <linux/hwmon.h>
30c801082dSJean Delvare #include <linux/hwmon-sysfs.h>
31943b0830SMark M. Hoffman #include <linux/err.h>
329a61bf63SIngo Molnar #include <linux/mutex.h>
338d5d45fbSJean Delvare 
348d5d45fbSJean Delvare /* Following macros takes channel parameter starting from 0 to 2 */
358d5d45fbSJean Delvare #define ADM1031_REG_FAN_SPEED(nr)	(0x08 + (nr))
368d5d45fbSJean Delvare #define ADM1031_REG_FAN_DIV(nr)		(0x20 + (nr))
378d5d45fbSJean Delvare #define ADM1031_REG_PWM			(0x22)
388d5d45fbSJean Delvare #define ADM1031_REG_FAN_MIN(nr)		(0x10 + (nr))
3987c33daaSJean Delvare #define ADM1031_REG_FAN_FILTER		(0x23)
408d5d45fbSJean Delvare 
4149dc9efeSIra Snyder #define ADM1031_REG_TEMP_OFFSET(nr)	(0x0d + (nr))
428d5d45fbSJean Delvare #define ADM1031_REG_TEMP_MAX(nr)	(0x14 + 4 * (nr))
438d5d45fbSJean Delvare #define ADM1031_REG_TEMP_MIN(nr)	(0x15 + 4 * (nr))
448d5d45fbSJean Delvare #define ADM1031_REG_TEMP_CRIT(nr)	(0x16 + 4 * (nr))
458d5d45fbSJean Delvare 
466d6006b8SJean Delvare #define ADM1031_REG_TEMP(nr)		(0x0a + (nr))
478d5d45fbSJean Delvare #define ADM1031_REG_AUTO_TEMP(nr)	(0x24 + (nr))
488d5d45fbSJean Delvare 
498d5d45fbSJean Delvare #define ADM1031_REG_STATUS(nr)		(0x2 + (nr))
508d5d45fbSJean Delvare 
516d6006b8SJean Delvare #define ADM1031_REG_CONF1		0x00
526d6006b8SJean Delvare #define ADM1031_REG_CONF2		0x01
536d6006b8SJean Delvare #define ADM1031_REG_EXT_TEMP		0x06
548d5d45fbSJean Delvare 
558d5d45fbSJean Delvare #define ADM1031_CONF1_MONITOR_ENABLE	0x01	/* Monitoring enable */
568d5d45fbSJean Delvare #define ADM1031_CONF1_PWM_INVERT	0x08	/* PWM Invert */
578d5d45fbSJean Delvare #define ADM1031_CONF1_AUTO_MODE		0x80	/* Auto FAN */
588d5d45fbSJean Delvare 
598d5d45fbSJean Delvare #define ADM1031_CONF2_PWM1_ENABLE	0x01
608d5d45fbSJean Delvare #define ADM1031_CONF2_PWM2_ENABLE	0x02
618d5d45fbSJean Delvare #define ADM1031_CONF2_TACH1_ENABLE	0x04
628d5d45fbSJean Delvare #define ADM1031_CONF2_TACH2_ENABLE	0x08
638d5d45fbSJean Delvare #define ADM1031_CONF2_TEMP_ENABLE(chan)	(0x10 << (chan))
648d5d45fbSJean Delvare 
6587c33daaSJean Delvare #define ADM1031_UPDATE_RATE_MASK	0x1c
6687c33daaSJean Delvare #define ADM1031_UPDATE_RATE_SHIFT	2
6787c33daaSJean Delvare 
688d5d45fbSJean Delvare /* Addresses to scan */
6925e9c86dSMark M. Hoffman static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
708d5d45fbSJean Delvare 
71e5e9f44cSJean Delvare enum chips { adm1030, adm1031 };
728d5d45fbSJean Delvare 
738d5d45fbSJean Delvare typedef u8 auto_chan_table_t[8][2];
748d5d45fbSJean Delvare 
758d5d45fbSJean Delvare /* Each client has this additional data */
768d5d45fbSJean Delvare struct adm1031_data {
77b060f3c4SAxel Lin 	struct i2c_client *client;
78b060f3c4SAxel Lin 	const struct attribute_group *groups[3];
799a61bf63SIngo Molnar 	struct mutex update_lock;
808d5d45fbSJean Delvare 	int chip_type;
818d5d45fbSJean Delvare 	char valid;		/* !=0 if following fields are valid */
828d5d45fbSJean Delvare 	unsigned long last_updated;	/* In jiffies */
83a51b9944SGuenter Roeck 	unsigned int update_interval;	/* In milliseconds */
84fbb6670dSGuenter Roeck 	/*
85fbb6670dSGuenter Roeck 	 * The chan_select_table contains the possible configurations for
868d5d45fbSJean Delvare 	 * auto fan control.
878d5d45fbSJean Delvare 	 */
886d6006b8SJean Delvare 	const auto_chan_table_t *chan_select_table;
898d5d45fbSJean Delvare 	u16 alarm;
908d5d45fbSJean Delvare 	u8 conf1;
918d5d45fbSJean Delvare 	u8 conf2;
928d5d45fbSJean Delvare 	u8 fan[2];
938d5d45fbSJean Delvare 	u8 fan_div[2];
948d5d45fbSJean Delvare 	u8 fan_min[2];
958d5d45fbSJean Delvare 	u8 pwm[2];
968d5d45fbSJean Delvare 	u8 old_pwm[2];
978d5d45fbSJean Delvare 	s8 temp[3];
988d5d45fbSJean Delvare 	u8 ext_temp[3];
998d5d45fbSJean Delvare 	u8 auto_temp[3];
1008d5d45fbSJean Delvare 	u8 auto_temp_min[3];
1018d5d45fbSJean Delvare 	u8 auto_temp_off[3];
1028d5d45fbSJean Delvare 	u8 auto_temp_max[3];
10349dc9efeSIra Snyder 	s8 temp_offset[3];
1048d5d45fbSJean Delvare 	s8 temp_min[3];
1058d5d45fbSJean Delvare 	s8 temp_max[3];
1068d5d45fbSJean Delvare 	s8 temp_crit[3];
1078d5d45fbSJean Delvare };
1088d5d45fbSJean Delvare 
1098d5d45fbSJean Delvare static inline u8 adm1031_read_value(struct i2c_client *client, u8 reg)
1108d5d45fbSJean Delvare {
1118d5d45fbSJean Delvare 	return i2c_smbus_read_byte_data(client, reg);
1128d5d45fbSJean Delvare }
1138d5d45fbSJean Delvare 
1148d5d45fbSJean Delvare static inline int
1158d5d45fbSJean Delvare adm1031_write_value(struct i2c_client *client, u8 reg, unsigned int value)
1168d5d45fbSJean Delvare {
1178d5d45fbSJean Delvare 	return i2c_smbus_write_byte_data(client, reg, value);
1188d5d45fbSJean Delvare }
1198d5d45fbSJean Delvare 
120278ee1c8SAxel Lin static struct adm1031_data *adm1031_update_device(struct device *dev)
121278ee1c8SAxel Lin {
122b060f3c4SAxel Lin 	struct adm1031_data *data = dev_get_drvdata(dev);
123b060f3c4SAxel Lin 	struct i2c_client *client = data->client;
124278ee1c8SAxel Lin 	unsigned long next_update;
125278ee1c8SAxel Lin 	int chan;
126278ee1c8SAxel Lin 
127278ee1c8SAxel Lin 	mutex_lock(&data->update_lock);
128278ee1c8SAxel Lin 
129278ee1c8SAxel Lin 	next_update = data->last_updated
130278ee1c8SAxel Lin 	  + msecs_to_jiffies(data->update_interval);
131278ee1c8SAxel Lin 	if (time_after(jiffies, next_update) || !data->valid) {
132278ee1c8SAxel Lin 
133278ee1c8SAxel Lin 		dev_dbg(&client->dev, "Starting adm1031 update\n");
134278ee1c8SAxel Lin 		for (chan = 0;
135278ee1c8SAxel Lin 		     chan < ((data->chip_type == adm1031) ? 3 : 2); chan++) {
136278ee1c8SAxel Lin 			u8 oldh, newh;
137278ee1c8SAxel Lin 
138278ee1c8SAxel Lin 			oldh =
139278ee1c8SAxel Lin 			    adm1031_read_value(client, ADM1031_REG_TEMP(chan));
140278ee1c8SAxel Lin 			data->ext_temp[chan] =
141278ee1c8SAxel Lin 			    adm1031_read_value(client, ADM1031_REG_EXT_TEMP);
142278ee1c8SAxel Lin 			newh =
143278ee1c8SAxel Lin 			    adm1031_read_value(client, ADM1031_REG_TEMP(chan));
144278ee1c8SAxel Lin 			if (newh != oldh) {
145278ee1c8SAxel Lin 				data->ext_temp[chan] =
146278ee1c8SAxel Lin 				    adm1031_read_value(client,
147278ee1c8SAxel Lin 						       ADM1031_REG_EXT_TEMP);
148278ee1c8SAxel Lin #ifdef DEBUG
149278ee1c8SAxel Lin 				oldh =
150278ee1c8SAxel Lin 				    adm1031_read_value(client,
151278ee1c8SAxel Lin 						       ADM1031_REG_TEMP(chan));
152278ee1c8SAxel Lin 
153278ee1c8SAxel Lin 				/* oldh is actually newer */
154278ee1c8SAxel Lin 				if (newh != oldh)
155278ee1c8SAxel Lin 					dev_warn(&client->dev,
156278ee1c8SAxel Lin 					  "Remote temperature may be wrong.\n");
157278ee1c8SAxel Lin #endif
158278ee1c8SAxel Lin 			}
159278ee1c8SAxel Lin 			data->temp[chan] = newh;
160278ee1c8SAxel Lin 
161278ee1c8SAxel Lin 			data->temp_offset[chan] =
162278ee1c8SAxel Lin 			    adm1031_read_value(client,
163278ee1c8SAxel Lin 					       ADM1031_REG_TEMP_OFFSET(chan));
164278ee1c8SAxel Lin 			data->temp_min[chan] =
165278ee1c8SAxel Lin 			    adm1031_read_value(client,
166278ee1c8SAxel Lin 					       ADM1031_REG_TEMP_MIN(chan));
167278ee1c8SAxel Lin 			data->temp_max[chan] =
168278ee1c8SAxel Lin 			    adm1031_read_value(client,
169278ee1c8SAxel Lin 					       ADM1031_REG_TEMP_MAX(chan));
170278ee1c8SAxel Lin 			data->temp_crit[chan] =
171278ee1c8SAxel Lin 			    adm1031_read_value(client,
172278ee1c8SAxel Lin 					       ADM1031_REG_TEMP_CRIT(chan));
173278ee1c8SAxel Lin 			data->auto_temp[chan] =
174278ee1c8SAxel Lin 			    adm1031_read_value(client,
175278ee1c8SAxel Lin 					       ADM1031_REG_AUTO_TEMP(chan));
176278ee1c8SAxel Lin 
177278ee1c8SAxel Lin 		}
178278ee1c8SAxel Lin 
179278ee1c8SAxel Lin 		data->conf1 = adm1031_read_value(client, ADM1031_REG_CONF1);
180278ee1c8SAxel Lin 		data->conf2 = adm1031_read_value(client, ADM1031_REG_CONF2);
181278ee1c8SAxel Lin 
182278ee1c8SAxel Lin 		data->alarm = adm1031_read_value(client, ADM1031_REG_STATUS(0))
183278ee1c8SAxel Lin 		    | (adm1031_read_value(client, ADM1031_REG_STATUS(1)) << 8);
184278ee1c8SAxel Lin 		if (data->chip_type == adm1030)
185278ee1c8SAxel Lin 			data->alarm &= 0xc0ff;
186278ee1c8SAxel Lin 
187278ee1c8SAxel Lin 		for (chan = 0; chan < (data->chip_type == adm1030 ? 1 : 2);
188278ee1c8SAxel Lin 		     chan++) {
189278ee1c8SAxel Lin 			data->fan_div[chan] =
190278ee1c8SAxel Lin 			    adm1031_read_value(client,
191278ee1c8SAxel Lin 					       ADM1031_REG_FAN_DIV(chan));
192278ee1c8SAxel Lin 			data->fan_min[chan] =
193278ee1c8SAxel Lin 			    adm1031_read_value(client,
194278ee1c8SAxel Lin 					       ADM1031_REG_FAN_MIN(chan));
195278ee1c8SAxel Lin 			data->fan[chan] =
196278ee1c8SAxel Lin 			    adm1031_read_value(client,
197278ee1c8SAxel Lin 					       ADM1031_REG_FAN_SPEED(chan));
198278ee1c8SAxel Lin 			data->pwm[chan] =
199278ee1c8SAxel Lin 			  (adm1031_read_value(client,
200278ee1c8SAxel Lin 					ADM1031_REG_PWM) >> (4 * chan)) & 0x0f;
201278ee1c8SAxel Lin 		}
202278ee1c8SAxel Lin 		data->last_updated = jiffies;
203278ee1c8SAxel Lin 		data->valid = 1;
204278ee1c8SAxel Lin 	}
205278ee1c8SAxel Lin 
206278ee1c8SAxel Lin 	mutex_unlock(&data->update_lock);
207278ee1c8SAxel Lin 
208278ee1c8SAxel Lin 	return data;
209278ee1c8SAxel Lin }
2108d5d45fbSJean Delvare 
2118d5d45fbSJean Delvare #define TEMP_TO_REG(val)		(((val) < 0 ? ((val - 500) / 1000) : \
2128d5d45fbSJean Delvare 					((val + 500) / 1000)))
2138d5d45fbSJean Delvare 
2148d5d45fbSJean Delvare #define TEMP_FROM_REG(val)		((val) * 1000)
2158d5d45fbSJean Delvare 
2168d5d45fbSJean Delvare #define TEMP_FROM_REG_EXT(val, ext)	(TEMP_FROM_REG(val) + (ext) * 125)
2178d5d45fbSJean Delvare 
21849dc9efeSIra Snyder #define TEMP_OFFSET_TO_REG(val)		(TEMP_TO_REG(val) & 0x8f)
21949dc9efeSIra Snyder #define TEMP_OFFSET_FROM_REG(val)	TEMP_FROM_REG((val) < 0 ? \
22049dc9efeSIra Snyder 						      (val) | 0x70 : (val))
22149dc9efeSIra Snyder 
2221c720093SGuenter Roeck #define FAN_FROM_REG(reg, div)		((reg) ? \
2231c720093SGuenter Roeck 					 (11250 * 60) / ((reg) * (div)) : 0)
2248d5d45fbSJean Delvare 
2258d5d45fbSJean Delvare static int FAN_TO_REG(int reg, int div)
2268d5d45fbSJean Delvare {
2278d5d45fbSJean Delvare 	int tmp;
2282a844c14SGuenter Roeck 	tmp = FAN_FROM_REG(clamp_val(reg, 0, 65535), div);
2298d5d45fbSJean Delvare 	return tmp > 255 ? 255 : tmp;
2308d5d45fbSJean Delvare }
2318d5d45fbSJean Delvare 
2328d5d45fbSJean Delvare #define FAN_DIV_FROM_REG(reg)		(1<<(((reg)&0xc0)>>6))
2338d5d45fbSJean Delvare 
2342a844c14SGuenter Roeck #define PWM_TO_REG(val)			(clamp_val((val), 0, 255) >> 4)
2358d5d45fbSJean Delvare #define PWM_FROM_REG(val)		((val) << 4)
2368d5d45fbSJean Delvare 
2378d5d45fbSJean Delvare #define FAN_CHAN_FROM_REG(reg)		(((reg) >> 5) & 7)
2388d5d45fbSJean Delvare #define FAN_CHAN_TO_REG(val, reg)	\
2398d5d45fbSJean Delvare 	(((reg) & 0x1F) | (((val) << 5) & 0xe0))
2408d5d45fbSJean Delvare 
2418d5d45fbSJean Delvare #define AUTO_TEMP_MIN_TO_REG(val, reg)	\
2428d5d45fbSJean Delvare 	((((val) / 500) & 0xf8) | ((reg) & 0x7))
2438d5d45fbSJean Delvare #define AUTO_TEMP_RANGE_FROM_REG(reg)	(5000 * (1 << ((reg) & 0x7)))
2448d5d45fbSJean Delvare #define AUTO_TEMP_MIN_FROM_REG(reg)	(1000 * ((((reg) >> 3) & 0x1f) << 2))
2458d5d45fbSJean Delvare 
2468d5d45fbSJean Delvare #define AUTO_TEMP_MIN_FROM_REG_DEG(reg)	((((reg) >> 3) & 0x1f) << 2)
2478d5d45fbSJean Delvare 
2488d5d45fbSJean Delvare #define AUTO_TEMP_OFF_FROM_REG(reg)		\
2498d5d45fbSJean Delvare 	(AUTO_TEMP_MIN_FROM_REG(reg) - 5000)
2508d5d45fbSJean Delvare 
2518d5d45fbSJean Delvare #define AUTO_TEMP_MAX_FROM_REG(reg)		\
2528d5d45fbSJean Delvare 	(AUTO_TEMP_RANGE_FROM_REG(reg) +	\
2538d5d45fbSJean Delvare 	AUTO_TEMP_MIN_FROM_REG(reg))
2548d5d45fbSJean Delvare 
2558d5d45fbSJean Delvare static int AUTO_TEMP_MAX_TO_REG(int val, int reg, int pwm)
2568d5d45fbSJean Delvare {
2578d5d45fbSJean Delvare 	int ret;
2588d5d45fbSJean Delvare 	int range = val - AUTO_TEMP_MIN_FROM_REG(reg);
2598d5d45fbSJean Delvare 
2608d5d45fbSJean Delvare 	range = ((val - AUTO_TEMP_MIN_FROM_REG(reg))*10)/(16 - pwm);
2618d5d45fbSJean Delvare 	ret = ((reg & 0xf8) |
2628d5d45fbSJean Delvare 	       (range < 10000 ? 0 :
2638d5d45fbSJean Delvare 		range < 20000 ? 1 :
2648d5d45fbSJean Delvare 		range < 40000 ? 2 : range < 80000 ? 3 : 4));
2658d5d45fbSJean Delvare 	return ret;
2668d5d45fbSJean Delvare }
2678d5d45fbSJean Delvare 
2688d5d45fbSJean Delvare /* FAN auto control */
2698d5d45fbSJean Delvare #define GET_FAN_AUTO_BITFIELD(data, idx)	\
2708d5d45fbSJean Delvare 	(*(data)->chan_select_table)[FAN_CHAN_FROM_REG((data)->conf1)][idx % 2]
2718d5d45fbSJean Delvare 
272fbb6670dSGuenter Roeck /*
273fbb6670dSGuenter Roeck  * The tables below contains the possible values for the auto fan
2748d5d45fbSJean Delvare  * control bitfields. the index in the table is the register value.
2758d5d45fbSJean Delvare  * MSb is the auto fan control enable bit, so the four first entries
2768d5d45fbSJean Delvare  * in the table disables auto fan control when both bitfields are zero.
2778d5d45fbSJean Delvare  */
2786d6006b8SJean Delvare static const auto_chan_table_t auto_channel_select_table_adm1031 = {
2798d5d45fbSJean Delvare 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2808d5d45fbSJean Delvare 	{ 2 /* 0b010 */ , 4 /* 0b100 */ },
2818d5d45fbSJean Delvare 	{ 2 /* 0b010 */ , 2 /* 0b010 */ },
2828d5d45fbSJean Delvare 	{ 4 /* 0b100 */ , 4 /* 0b100 */ },
2838d5d45fbSJean Delvare 	{ 7 /* 0b111 */ , 7 /* 0b111 */ },
2848d5d45fbSJean Delvare };
2858d5d45fbSJean Delvare 
2866d6006b8SJean Delvare static const auto_chan_table_t auto_channel_select_table_adm1030 = {
2878d5d45fbSJean Delvare 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2888d5d45fbSJean Delvare 	{ 2 /* 0b10 */		, 0 },
2898d5d45fbSJean Delvare 	{ 0xff /* invalid */	, 0 },
2908d5d45fbSJean Delvare 	{ 0xff /* invalid */	, 0 },
2918d5d45fbSJean Delvare 	{ 3 /* 0b11 */		, 0 },
2928d5d45fbSJean Delvare };
2938d5d45fbSJean Delvare 
294fbb6670dSGuenter Roeck /*
295fbb6670dSGuenter Roeck  * That function checks if a bitfield is valid and returns the other bitfield
2968d5d45fbSJean Delvare  * nearest match if no exact match where found.
2978d5d45fbSJean Delvare  */
2988d5d45fbSJean Delvare static int
299ce15a81dSGuenter Roeck get_fan_auto_nearest(struct adm1031_data *data, int chan, u8 val, u8 reg)
3008d5d45fbSJean Delvare {
3018d5d45fbSJean Delvare 	int i;
3028d5d45fbSJean Delvare 	int first_match = -1, exact_match = -1;
3038d5d45fbSJean Delvare 	u8 other_reg_val =
3048d5d45fbSJean Delvare 	    (*data->chan_select_table)[FAN_CHAN_FROM_REG(reg)][chan ? 0 : 1];
3058d5d45fbSJean Delvare 
306ce15a81dSGuenter Roeck 	if (val == 0)
3078d5d45fbSJean Delvare 		return 0;
3088d5d45fbSJean Delvare 
3098d5d45fbSJean Delvare 	for (i = 0; i < 8; i++) {
3108d5d45fbSJean Delvare 		if ((val == (*data->chan_select_table)[i][chan]) &&
3118d5d45fbSJean Delvare 		    ((*data->chan_select_table)[i][chan ? 0 : 1] ==
3128d5d45fbSJean Delvare 		     other_reg_val)) {
3138d5d45fbSJean Delvare 			/* We found an exact match */
3148d5d45fbSJean Delvare 			exact_match = i;
3158d5d45fbSJean Delvare 			break;
3168d5d45fbSJean Delvare 		} else if (val == (*data->chan_select_table)[i][chan] &&
3178d5d45fbSJean Delvare 			   first_match == -1) {
318fbb6670dSGuenter Roeck 			/*
319fbb6670dSGuenter Roeck 			 * Save the first match in case of an exact match has
3206d6006b8SJean Delvare 			 * not been found
3218d5d45fbSJean Delvare 			 */
3228d5d45fbSJean Delvare 			first_match = i;
3238d5d45fbSJean Delvare 		}
3248d5d45fbSJean Delvare 	}
3258d5d45fbSJean Delvare 
3261c720093SGuenter Roeck 	if (exact_match >= 0)
327ce15a81dSGuenter Roeck 		return exact_match;
3281c720093SGuenter Roeck 	else if (first_match >= 0)
329ce15a81dSGuenter Roeck 		return first_match;
3301c720093SGuenter Roeck 
331ce15a81dSGuenter Roeck 	return -EINVAL;
3328d5d45fbSJean Delvare }
3338d5d45fbSJean Delvare 
334*8e757e15SGuenter Roeck static ssize_t fan_auto_channel_show(struct device *dev,
335c801082dSJean Delvare 				     struct device_attribute *attr, char *buf)
3368d5d45fbSJean Delvare {
337c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
3388d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
3398d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", GET_FAN_AUTO_BITFIELD(data, nr));
3408d5d45fbSJean Delvare }
3418d5d45fbSJean Delvare 
3428d5d45fbSJean Delvare static ssize_t
343*8e757e15SGuenter Roeck fan_auto_channel_store(struct device *dev, struct device_attribute *attr,
344c801082dSJean Delvare 		       const char *buf, size_t count)
3458d5d45fbSJean Delvare {
346b060f3c4SAxel Lin 	struct adm1031_data *data = dev_get_drvdata(dev);
347b060f3c4SAxel Lin 	struct i2c_client *client = data->client;
348c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
3491c720093SGuenter Roeck 	long val;
3508d5d45fbSJean Delvare 	u8 reg;
3518d5d45fbSJean Delvare 	int ret;
3528d5d45fbSJean Delvare 	u8 old_fan_mode;
3538d5d45fbSJean Delvare 
3541c720093SGuenter Roeck 	ret = kstrtol(buf, 10, &val);
3551c720093SGuenter Roeck 	if (ret)
3561c720093SGuenter Roeck 		return ret;
3571c720093SGuenter Roeck 
3588d5d45fbSJean Delvare 	old_fan_mode = data->conf1;
3598d5d45fbSJean Delvare 
3609a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
3618d5d45fbSJean Delvare 
362ce15a81dSGuenter Roeck 	ret = get_fan_auto_nearest(data, nr, val, data->conf1);
363ce15a81dSGuenter Roeck 	if (ret < 0) {
3649a61bf63SIngo Molnar 		mutex_unlock(&data->update_lock);
3658d5d45fbSJean Delvare 		return ret;
3668d5d45fbSJean Delvare 	}
367ce15a81dSGuenter Roeck 	reg = ret;
3686d6006b8SJean Delvare 	data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1);
3696d6006b8SJean Delvare 	if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) ^
3708d5d45fbSJean Delvare 	    (old_fan_mode & ADM1031_CONF1_AUTO_MODE)) {
3718d5d45fbSJean Delvare 		if (data->conf1 & ADM1031_CONF1_AUTO_MODE) {
372fbb6670dSGuenter Roeck 			/*
373fbb6670dSGuenter Roeck 			 * Switch to Auto Fan Mode
3748d5d45fbSJean Delvare 			 * Save PWM registers
375fbb6670dSGuenter Roeck 			 * Set PWM registers to 33% Both
376fbb6670dSGuenter Roeck 			 */
3778d5d45fbSJean Delvare 			data->old_pwm[0] = data->pwm[0];
3788d5d45fbSJean Delvare 			data->old_pwm[1] = data->pwm[1];
3798d5d45fbSJean Delvare 			adm1031_write_value(client, ADM1031_REG_PWM, 0x55);
3808d5d45fbSJean Delvare 		} else {
3818d5d45fbSJean Delvare 			/* Switch to Manual Mode */
3828d5d45fbSJean Delvare 			data->pwm[0] = data->old_pwm[0];
3838d5d45fbSJean Delvare 			data->pwm[1] = data->old_pwm[1];
3848d5d45fbSJean Delvare 			/* Restore PWM registers */
3858d5d45fbSJean Delvare 			adm1031_write_value(client, ADM1031_REG_PWM,
3868d5d45fbSJean Delvare 					    data->pwm[0] | (data->pwm[1] << 4));
3878d5d45fbSJean Delvare 		}
3888d5d45fbSJean Delvare 	}
3898d5d45fbSJean Delvare 	data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1);
3908d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_CONF1, data->conf1);
3919a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
3928d5d45fbSJean Delvare 	return count;
3938d5d45fbSJean Delvare }
3948d5d45fbSJean Delvare 
395*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(auto_fan1_channel, fan_auto_channel, 0);
396*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(auto_fan2_channel, fan_auto_channel, 1);
3978d5d45fbSJean Delvare 
3988d5d45fbSJean Delvare /* Auto Temps */
399*8e757e15SGuenter Roeck static ssize_t auto_temp_off_show(struct device *dev,
400c801082dSJean Delvare 				  struct device_attribute *attr, char *buf)
4018d5d45fbSJean Delvare {
402c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4038d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
4048d5d45fbSJean Delvare 	return sprintf(buf, "%d\n",
4058d5d45fbSJean Delvare 		       AUTO_TEMP_OFF_FROM_REG(data->auto_temp[nr]));
4068d5d45fbSJean Delvare }
407*8e757e15SGuenter Roeck static ssize_t auto_temp_min_show(struct device *dev,
408c801082dSJean Delvare 				  struct device_attribute *attr, char *buf)
4098d5d45fbSJean Delvare {
410c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4118d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
4128d5d45fbSJean Delvare 	return sprintf(buf, "%d\n",
4138d5d45fbSJean Delvare 		       AUTO_TEMP_MIN_FROM_REG(data->auto_temp[nr]));
4148d5d45fbSJean Delvare }
4158d5d45fbSJean Delvare static ssize_t
416*8e757e15SGuenter Roeck auto_temp_min_store(struct device *dev, struct device_attribute *attr,
417c801082dSJean Delvare 		    const char *buf, size_t count)
4188d5d45fbSJean Delvare {
419b060f3c4SAxel Lin 	struct adm1031_data *data = dev_get_drvdata(dev);
420b060f3c4SAxel Lin 	struct i2c_client *client = data->client;
421c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4221c720093SGuenter Roeck 	long val;
4231c720093SGuenter Roeck 	int ret;
4241c720093SGuenter Roeck 
4251c720093SGuenter Roeck 	ret = kstrtol(buf, 10, &val);
4261c720093SGuenter Roeck 	if (ret)
4271c720093SGuenter Roeck 		return ret;
4288d5d45fbSJean Delvare 
429145e74a4SGuenter Roeck 	val = clamp_val(val, 0, 127000);
4309a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
4318d5d45fbSJean Delvare 	data->auto_temp[nr] = AUTO_TEMP_MIN_TO_REG(val, data->auto_temp[nr]);
4328d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr),
4338d5d45fbSJean Delvare 			    data->auto_temp[nr]);
4349a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
4358d5d45fbSJean Delvare 	return count;
4368d5d45fbSJean Delvare }
437*8e757e15SGuenter Roeck static ssize_t auto_temp_max_show(struct device *dev,
438c801082dSJean Delvare 				  struct device_attribute *attr, char *buf)
4398d5d45fbSJean Delvare {
440c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4418d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
4428d5d45fbSJean Delvare 	return sprintf(buf, "%d\n",
4438d5d45fbSJean Delvare 		       AUTO_TEMP_MAX_FROM_REG(data->auto_temp[nr]));
4448d5d45fbSJean Delvare }
4458d5d45fbSJean Delvare static ssize_t
446*8e757e15SGuenter Roeck auto_temp_max_store(struct device *dev, struct device_attribute *attr,
447c801082dSJean Delvare 		    const char *buf, size_t count)
4488d5d45fbSJean Delvare {
449b060f3c4SAxel Lin 	struct adm1031_data *data = dev_get_drvdata(dev);
450b060f3c4SAxel Lin 	struct i2c_client *client = data->client;
451c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4521c720093SGuenter Roeck 	long val;
4531c720093SGuenter Roeck 	int ret;
4541c720093SGuenter Roeck 
4551c720093SGuenter Roeck 	ret = kstrtol(buf, 10, &val);
4561c720093SGuenter Roeck 	if (ret)
4571c720093SGuenter Roeck 		return ret;
4588d5d45fbSJean Delvare 
459145e74a4SGuenter Roeck 	val = clamp_val(val, 0, 127000);
4609a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
4611c720093SGuenter Roeck 	data->temp_max[nr] = AUTO_TEMP_MAX_TO_REG(val, data->auto_temp[nr],
4621c720093SGuenter Roeck 						  data->pwm[nr]);
4638d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr),
4648d5d45fbSJean Delvare 			    data->temp_max[nr]);
4659a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
4668d5d45fbSJean Delvare 	return count;
4678d5d45fbSJean Delvare }
4688d5d45fbSJean Delvare 
469*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(auto_temp1_off, auto_temp_off, 0);
470*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(auto_temp1_min, auto_temp_min, 0);
471*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(auto_temp1_max, auto_temp_max, 0);
472*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(auto_temp2_off, auto_temp_off, 1);
473*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(auto_temp2_min, auto_temp_min, 1);
474*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(auto_temp2_max, auto_temp_max, 1);
475*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(auto_temp3_off, auto_temp_off, 2);
476*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(auto_temp3_min, auto_temp_min, 2);
477*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(auto_temp3_max, auto_temp_max, 2);
4788d5d45fbSJean Delvare 
4798d5d45fbSJean Delvare /* pwm */
480*8e757e15SGuenter Roeck static ssize_t pwm_show(struct device *dev, struct device_attribute *attr,
481*8e757e15SGuenter Roeck 			char *buf)
4828d5d45fbSJean Delvare {
483c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4848d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
4858d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm[nr]));
4868d5d45fbSJean Delvare }
487*8e757e15SGuenter Roeck static ssize_t pwm_store(struct device *dev, struct device_attribute *attr,
488c801082dSJean Delvare 			 const char *buf, size_t count)
4898d5d45fbSJean Delvare {
490b060f3c4SAxel Lin 	struct adm1031_data *data = dev_get_drvdata(dev);
491b060f3c4SAxel Lin 	struct i2c_client *client = data->client;
492c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4931c720093SGuenter Roeck 	long val;
4941c720093SGuenter Roeck 	int ret, reg;
4951c720093SGuenter Roeck 
4961c720093SGuenter Roeck 	ret = kstrtol(buf, 10, &val);
4971c720093SGuenter Roeck 	if (ret)
4981c720093SGuenter Roeck 		return ret;
4998d5d45fbSJean Delvare 
5009a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
5018d5d45fbSJean Delvare 	if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) &&
5028d5d45fbSJean Delvare 	    (((val>>4) & 0xf) != 5)) {
5038d5d45fbSJean Delvare 		/* In automatic mode, the only PWM accepted is 33% */
5049a61bf63SIngo Molnar 		mutex_unlock(&data->update_lock);
5058d5d45fbSJean Delvare 		return -EINVAL;
5068d5d45fbSJean Delvare 	}
5078d5d45fbSJean Delvare 	data->pwm[nr] = PWM_TO_REG(val);
5088d5d45fbSJean Delvare 	reg = adm1031_read_value(client, ADM1031_REG_PWM);
5098d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_PWM,
5108d5d45fbSJean Delvare 			    nr ? ((data->pwm[nr] << 4) & 0xf0) | (reg & 0xf)
5118d5d45fbSJean Delvare 			    : (data->pwm[nr] & 0xf) | (reg & 0xf0));
5129a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
5138d5d45fbSJean Delvare 	return count;
5148d5d45fbSJean Delvare }
5158d5d45fbSJean Delvare 
516*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(pwm1, pwm, 0);
517*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(pwm2, pwm, 1);
518*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(auto_fan1_min_pwm, pwm, 0);
519*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(auto_fan2_min_pwm, pwm, 1);
5208d5d45fbSJean Delvare 
5218d5d45fbSJean Delvare /* Fans */
5228d5d45fbSJean Delvare 
5238d5d45fbSJean Delvare /*
5248d5d45fbSJean Delvare  * That function checks the cases where the fan reading is not
5258d5d45fbSJean Delvare  * relevant.  It is used to provide 0 as fan reading when the fan is
5268d5d45fbSJean Delvare  * not supposed to run
5278d5d45fbSJean Delvare  */
5288d5d45fbSJean Delvare static int trust_fan_readings(struct adm1031_data *data, int chan)
5298d5d45fbSJean Delvare {
5308d5d45fbSJean Delvare 	int res = 0;
5318d5d45fbSJean Delvare 
5328d5d45fbSJean Delvare 	if (data->conf1 & ADM1031_CONF1_AUTO_MODE) {
5338d5d45fbSJean Delvare 		switch (data->conf1 & 0x60) {
5341c720093SGuenter Roeck 		case 0x00:
5351c720093SGuenter Roeck 			/*
5361c720093SGuenter Roeck 			 * remote temp1 controls fan1,
5371c720093SGuenter Roeck 			 * remote temp2 controls fan2
5381c720093SGuenter Roeck 			 */
5398d5d45fbSJean Delvare 			res = data->temp[chan+1] >=
5408d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[chan+1]);
5418d5d45fbSJean Delvare 			break;
5428d5d45fbSJean Delvare 		case 0x20:	/* remote temp1 controls both fans */
5438d5d45fbSJean Delvare 			res =
5448d5d45fbSJean Delvare 			    data->temp[1] >=
5458d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[1]);
5468d5d45fbSJean Delvare 			break;
5478d5d45fbSJean Delvare 		case 0x40:	/* remote temp2 controls both fans */
5488d5d45fbSJean Delvare 			res =
5498d5d45fbSJean Delvare 			    data->temp[2] >=
5508d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[2]);
5518d5d45fbSJean Delvare 			break;
5528d5d45fbSJean Delvare 		case 0x60:	/* max controls both fans */
5538d5d45fbSJean Delvare 			res =
5548d5d45fbSJean Delvare 			    data->temp[0] >=
5558d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[0])
5568d5d45fbSJean Delvare 			    || data->temp[1] >=
5578d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[1])
5588d5d45fbSJean Delvare 			    || (data->chip_type == adm1031
5598d5d45fbSJean Delvare 				&& data->temp[2] >=
5608d5d45fbSJean Delvare 				AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[2]));
5618d5d45fbSJean Delvare 			break;
5628d5d45fbSJean Delvare 		}
5638d5d45fbSJean Delvare 	} else {
5648d5d45fbSJean Delvare 		res = data->pwm[chan] > 0;
5658d5d45fbSJean Delvare 	}
5668d5d45fbSJean Delvare 	return res;
5678d5d45fbSJean Delvare }
5688d5d45fbSJean Delvare 
569*8e757e15SGuenter Roeck static ssize_t fan_show(struct device *dev, struct device_attribute *attr,
570*8e757e15SGuenter Roeck 			char *buf)
5718d5d45fbSJean Delvare {
572c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
5738d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
5748d5d45fbSJean Delvare 	int value;
5758d5d45fbSJean Delvare 
5768d5d45fbSJean Delvare 	value = trust_fan_readings(data, nr) ? FAN_FROM_REG(data->fan[nr],
5778d5d45fbSJean Delvare 				 FAN_DIV_FROM_REG(data->fan_div[nr])) : 0;
5788d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", value);
5798d5d45fbSJean Delvare }
5808d5d45fbSJean Delvare 
581*8e757e15SGuenter Roeck static ssize_t fan_div_show(struct device *dev, struct device_attribute *attr,
582*8e757e15SGuenter Roeck 			    char *buf)
5838d5d45fbSJean Delvare {
584c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
5858d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
5868d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", FAN_DIV_FROM_REG(data->fan_div[nr]));
5878d5d45fbSJean Delvare }
588*8e757e15SGuenter Roeck static ssize_t fan_min_show(struct device *dev, struct device_attribute *attr,
589*8e757e15SGuenter Roeck 			    char *buf)
5908d5d45fbSJean Delvare {
591c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
5928d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
5938d5d45fbSJean Delvare 	return sprintf(buf, "%d\n",
5948d5d45fbSJean Delvare 		       FAN_FROM_REG(data->fan_min[nr],
5958d5d45fbSJean Delvare 				    FAN_DIV_FROM_REG(data->fan_div[nr])));
5968d5d45fbSJean Delvare }
597*8e757e15SGuenter Roeck static ssize_t fan_min_store(struct device *dev,
598*8e757e15SGuenter Roeck 			     struct device_attribute *attr, const char *buf,
599*8e757e15SGuenter Roeck 			     size_t count)
6008d5d45fbSJean Delvare {
601b060f3c4SAxel Lin 	struct adm1031_data *data = dev_get_drvdata(dev);
602b060f3c4SAxel Lin 	struct i2c_client *client = data->client;
603c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
6041c720093SGuenter Roeck 	long val;
6051c720093SGuenter Roeck 	int ret;
6061c720093SGuenter Roeck 
6071c720093SGuenter Roeck 	ret = kstrtol(buf, 10, &val);
6081c720093SGuenter Roeck 	if (ret)
6091c720093SGuenter Roeck 		return ret;
6108d5d45fbSJean Delvare 
6119a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
6128d5d45fbSJean Delvare 	if (val) {
6138d5d45fbSJean Delvare 		data->fan_min[nr] =
6148d5d45fbSJean Delvare 			FAN_TO_REG(val, FAN_DIV_FROM_REG(data->fan_div[nr]));
6158d5d45fbSJean Delvare 	} else {
6168d5d45fbSJean Delvare 		data->fan_min[nr] = 0xff;
6178d5d45fbSJean Delvare 	}
6188d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), data->fan_min[nr]);
6199a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
6208d5d45fbSJean Delvare 	return count;
6218d5d45fbSJean Delvare }
622*8e757e15SGuenter Roeck static ssize_t fan_div_store(struct device *dev,
623*8e757e15SGuenter Roeck 			     struct device_attribute *attr, const char *buf,
624*8e757e15SGuenter Roeck 			     size_t count)
6258d5d45fbSJean Delvare {
626b060f3c4SAxel Lin 	struct adm1031_data *data = dev_get_drvdata(dev);
627b060f3c4SAxel Lin 	struct i2c_client *client = data->client;
628c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
6291c720093SGuenter Roeck 	long val;
6308d5d45fbSJean Delvare 	u8 tmp;
6318d5d45fbSJean Delvare 	int old_div;
6328d5d45fbSJean Delvare 	int new_min;
6331c720093SGuenter Roeck 	int ret;
6341c720093SGuenter Roeck 
6351c720093SGuenter Roeck 	ret = kstrtol(buf, 10, &val);
6361c720093SGuenter Roeck 	if (ret)
6371c720093SGuenter Roeck 		return ret;
6388d5d45fbSJean Delvare 
6398d5d45fbSJean Delvare 	tmp = val == 8 ? 0xc0 :
6408d5d45fbSJean Delvare 	      val == 4 ? 0x80 :
6418d5d45fbSJean Delvare 	      val == 2 ? 0x40 :
6428d5d45fbSJean Delvare 	      val == 1 ? 0x00 :
6438d5d45fbSJean Delvare 	      0xff;
6448d5d45fbSJean Delvare 	if (tmp == 0xff)
6458d5d45fbSJean Delvare 		return -EINVAL;
6468d5d45fbSJean Delvare 
6479a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
64838a1f0e9SJean Delvare 	/* Get fresh readings */
64938a1f0e9SJean Delvare 	data->fan_div[nr] = adm1031_read_value(client,
65038a1f0e9SJean Delvare 					       ADM1031_REG_FAN_DIV(nr));
65138a1f0e9SJean Delvare 	data->fan_min[nr] = adm1031_read_value(client,
65238a1f0e9SJean Delvare 					       ADM1031_REG_FAN_MIN(nr));
65338a1f0e9SJean Delvare 
65438a1f0e9SJean Delvare 	/* Write the new clock divider and fan min */
6558d5d45fbSJean Delvare 	old_div = FAN_DIV_FROM_REG(data->fan_div[nr]);
6566d6006b8SJean Delvare 	data->fan_div[nr] = tmp | (0x3f & data->fan_div[nr]);
6576d6006b8SJean Delvare 	new_min = data->fan_min[nr] * old_div / val;
6588d5d45fbSJean Delvare 	data->fan_min[nr] = new_min > 0xff ? 0xff : new_min;
6598d5d45fbSJean Delvare 
6608d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_FAN_DIV(nr),
6618d5d45fbSJean Delvare 			    data->fan_div[nr]);
6628d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr),
6638d5d45fbSJean Delvare 			    data->fan_min[nr]);
66438a1f0e9SJean Delvare 
66538a1f0e9SJean Delvare 	/* Invalidate the cache: fan speed is no longer valid */
66638a1f0e9SJean Delvare 	data->valid = 0;
6679a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
6688d5d45fbSJean Delvare 	return count;
6698d5d45fbSJean Delvare }
6708d5d45fbSJean Delvare 
671*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan1_input, fan, 0);
672*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(fan1_min, fan_min, 0);
673*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(fan1_div, fan_div, 0);
674*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan2_input, fan, 1);
675*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(fan2_min, fan_min, 1);
676*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(fan2_div, fan_div, 1);
6778d5d45fbSJean Delvare 
6788d5d45fbSJean Delvare /* Temps */
679*8e757e15SGuenter Roeck static ssize_t temp_show(struct device *dev, struct device_attribute *attr,
680*8e757e15SGuenter Roeck 			 char *buf)
6818d5d45fbSJean Delvare {
682c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
6838d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
6848d5d45fbSJean Delvare 	int ext;
6858d5d45fbSJean Delvare 	ext = nr == 0 ?
6868d5d45fbSJean Delvare 	    ((data->ext_temp[nr] >> 6) & 0x3) * 2 :
6878d5d45fbSJean Delvare 	    (((data->ext_temp[nr] >> ((nr - 1) * 3)) & 7));
6888d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG_EXT(data->temp[nr], ext));
6898d5d45fbSJean Delvare }
690*8e757e15SGuenter Roeck static ssize_t temp_offset_show(struct device *dev,
69149dc9efeSIra Snyder 				struct device_attribute *attr, char *buf)
69249dc9efeSIra Snyder {
69349dc9efeSIra Snyder 	int nr = to_sensor_dev_attr(attr)->index;
69449dc9efeSIra Snyder 	struct adm1031_data *data = adm1031_update_device(dev);
69549dc9efeSIra Snyder 	return sprintf(buf, "%d\n",
69649dc9efeSIra Snyder 		       TEMP_OFFSET_FROM_REG(data->temp_offset[nr]));
69749dc9efeSIra Snyder }
698*8e757e15SGuenter Roeck static ssize_t temp_min_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_min[nr]));
7048d5d45fbSJean Delvare }
705*8e757e15SGuenter Roeck static ssize_t temp_max_show(struct device *dev,
706c801082dSJean Delvare 			     struct device_attribute *attr, char *buf)
7078d5d45fbSJean Delvare {
708c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
7098d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
7108d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr]));
7118d5d45fbSJean Delvare }
712*8e757e15SGuenter Roeck static ssize_t temp_crit_show(struct device *dev,
713c801082dSJean Delvare 			      struct device_attribute *attr, char *buf)
7148d5d45fbSJean Delvare {
715c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
7168d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
7178d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[nr]));
7188d5d45fbSJean Delvare }
719*8e757e15SGuenter Roeck static ssize_t temp_offset_store(struct device *dev,
720*8e757e15SGuenter Roeck 				 struct device_attribute *attr,
721*8e757e15SGuenter Roeck 				 const char *buf, size_t count)
72249dc9efeSIra Snyder {
723b060f3c4SAxel Lin 	struct adm1031_data *data = dev_get_drvdata(dev);
724b060f3c4SAxel Lin 	struct i2c_client *client = data->client;
72549dc9efeSIra Snyder 	int nr = to_sensor_dev_attr(attr)->index;
7261c720093SGuenter Roeck 	long val;
7271c720093SGuenter Roeck 	int ret;
72849dc9efeSIra Snyder 
7291c720093SGuenter Roeck 	ret = kstrtol(buf, 10, &val);
7301c720093SGuenter Roeck 	if (ret)
7311c720093SGuenter Roeck 		return ret;
7321c720093SGuenter Roeck 
7332a844c14SGuenter Roeck 	val = clamp_val(val, -15000, 15000);
73449dc9efeSIra Snyder 	mutex_lock(&data->update_lock);
73549dc9efeSIra Snyder 	data->temp_offset[nr] = TEMP_OFFSET_TO_REG(val);
73649dc9efeSIra Snyder 	adm1031_write_value(client, ADM1031_REG_TEMP_OFFSET(nr),
73749dc9efeSIra Snyder 			    data->temp_offset[nr]);
73849dc9efeSIra Snyder 	mutex_unlock(&data->update_lock);
73949dc9efeSIra Snyder 	return count;
74049dc9efeSIra Snyder }
741*8e757e15SGuenter Roeck static ssize_t temp_min_store(struct device *dev,
742*8e757e15SGuenter Roeck 			      struct device_attribute *attr, const char *buf,
743*8e757e15SGuenter Roeck 			      size_t count)
7448d5d45fbSJean Delvare {
745b060f3c4SAxel Lin 	struct adm1031_data *data = dev_get_drvdata(dev);
746b060f3c4SAxel Lin 	struct i2c_client *client = data->client;
747c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
7481c720093SGuenter Roeck 	long val;
7491c720093SGuenter Roeck 	int ret;
7508d5d45fbSJean Delvare 
7511c720093SGuenter Roeck 	ret = kstrtol(buf, 10, &val);
7521c720093SGuenter Roeck 	if (ret)
7531c720093SGuenter Roeck 		return ret;
7541c720093SGuenter Roeck 
755145e74a4SGuenter Roeck 	val = clamp_val(val, -55000, 127000);
7569a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
7578d5d45fbSJean Delvare 	data->temp_min[nr] = TEMP_TO_REG(val);
7588d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_TEMP_MIN(nr),
7598d5d45fbSJean Delvare 			    data->temp_min[nr]);
7609a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
7618d5d45fbSJean Delvare 	return count;
7628d5d45fbSJean Delvare }
763*8e757e15SGuenter Roeck static ssize_t temp_max_store(struct device *dev,
764*8e757e15SGuenter Roeck 			      struct device_attribute *attr, const char *buf,
765*8e757e15SGuenter Roeck 			      size_t count)
7668d5d45fbSJean Delvare {
767b060f3c4SAxel Lin 	struct adm1031_data *data = dev_get_drvdata(dev);
768b060f3c4SAxel Lin 	struct i2c_client *client = data->client;
769c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
7701c720093SGuenter Roeck 	long val;
7711c720093SGuenter Roeck 	int ret;
7728d5d45fbSJean Delvare 
7731c720093SGuenter Roeck 	ret = kstrtol(buf, 10, &val);
7741c720093SGuenter Roeck 	if (ret)
7751c720093SGuenter Roeck 		return ret;
7761c720093SGuenter Roeck 
777145e74a4SGuenter Roeck 	val = clamp_val(val, -55000, 127000);
7789a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
7798d5d45fbSJean Delvare 	data->temp_max[nr] = TEMP_TO_REG(val);
7808d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_TEMP_MAX(nr),
7818d5d45fbSJean Delvare 			    data->temp_max[nr]);
7829a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
7838d5d45fbSJean Delvare 	return count;
7848d5d45fbSJean Delvare }
785*8e757e15SGuenter Roeck static ssize_t temp_crit_store(struct device *dev,
786*8e757e15SGuenter Roeck 			       struct device_attribute *attr, const char *buf,
787*8e757e15SGuenter Roeck 			       size_t count)
7888d5d45fbSJean Delvare {
789b060f3c4SAxel Lin 	struct adm1031_data *data = dev_get_drvdata(dev);
790b060f3c4SAxel Lin 	struct i2c_client *client = data->client;
791c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
7921c720093SGuenter Roeck 	long val;
7931c720093SGuenter Roeck 	int ret;
7948d5d45fbSJean Delvare 
7951c720093SGuenter Roeck 	ret = kstrtol(buf, 10, &val);
7961c720093SGuenter Roeck 	if (ret)
7971c720093SGuenter Roeck 		return ret;
7981c720093SGuenter Roeck 
799145e74a4SGuenter Roeck 	val = clamp_val(val, -55000, 127000);
8009a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
8018d5d45fbSJean Delvare 	data->temp_crit[nr] = TEMP_TO_REG(val);
8028d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_TEMP_CRIT(nr),
8038d5d45fbSJean Delvare 			    data->temp_crit[nr]);
8049a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
8058d5d45fbSJean Delvare 	return count;
8068d5d45fbSJean Delvare }
8078d5d45fbSJean Delvare 
808*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, 0);
809*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp1_offset, temp_offset, 0);
810*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp1_min, temp_min, 0);
811*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp1_max, temp_max, 0);
812*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp1_crit, temp_crit, 0);
813*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp2_input, temp, 1);
814*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp2_offset, temp_offset, 1);
815*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp2_min, temp_min, 1);
816*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp2_max, temp_max, 1);
817*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp2_crit, temp_crit, 1);
818*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp3_input, temp, 2);
819*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp3_offset, temp_offset, 2);
820*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp3_min, temp_min, 2);
821*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp3_max, temp_max, 2);
822*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RW(temp3_crit, temp_crit, 2);
8238d5d45fbSJean Delvare 
8248d5d45fbSJean Delvare /* Alarms */
825bfb6b173SJulia Lawall static ssize_t alarms_show(struct device *dev, struct device_attribute *attr,
8261c720093SGuenter Roeck 			   char *buf)
8278d5d45fbSJean Delvare {
8288d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
8298d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", data->alarm);
8308d5d45fbSJean Delvare }
8318d5d45fbSJean Delvare 
832bfb6b173SJulia Lawall static DEVICE_ATTR_RO(alarms);
8338d5d45fbSJean Delvare 
834*8e757e15SGuenter Roeck static ssize_t alarm_show(struct device *dev, struct device_attribute *attr,
835*8e757e15SGuenter Roeck 			  char *buf)
836050ab878SJean Delvare {
837050ab878SJean Delvare 	int bitnr = to_sensor_dev_attr(attr)->index;
838050ab878SJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
839050ab878SJean Delvare 	return sprintf(buf, "%d\n", (data->alarm >> bitnr) & 1);
840050ab878SJean Delvare }
841050ab878SJean Delvare 
842*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan1_alarm, alarm, 0);
843*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan1_fault, alarm, 1);
844*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp2_max_alarm, alarm, 2);
845*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp2_min_alarm, alarm, 3);
846*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp2_crit_alarm, alarm, 4);
847*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp2_fault, alarm, 5);
848*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp1_max_alarm, alarm, 6);
849*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp1_min_alarm, alarm, 7);
850*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan2_alarm, alarm, 8);
851*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(fan2_fault, alarm, 9);
852*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp3_max_alarm, alarm, 10);
853*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp3_min_alarm, alarm, 11);
854*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp3_crit_alarm, alarm, 12);
855*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp3_fault, alarm, 13);
856*8e757e15SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, alarm, 14);
8578d5d45fbSJean Delvare 
858a51b9944SGuenter Roeck /* Update Interval */
859a51b9944SGuenter Roeck static const unsigned int update_intervals[] = {
86087c33daaSJean Delvare 	16000, 8000, 4000, 2000, 1000, 500, 250, 125,
86187c33daaSJean Delvare };
86287c33daaSJean Delvare 
863bfb6b173SJulia Lawall static ssize_t update_interval_show(struct device *dev,
86487c33daaSJean Delvare 				    struct device_attribute *attr, char *buf)
86587c33daaSJean Delvare {
866b060f3c4SAxel Lin 	struct adm1031_data *data = dev_get_drvdata(dev);
86787c33daaSJean Delvare 
868a51b9944SGuenter Roeck 	return sprintf(buf, "%u\n", data->update_interval);
86987c33daaSJean Delvare }
87087c33daaSJean Delvare 
871bfb6b173SJulia Lawall static ssize_t update_interval_store(struct device *dev,
87287c33daaSJean Delvare 				     struct device_attribute *attr,
87387c33daaSJean Delvare 				     const char *buf, size_t count)
87487c33daaSJean Delvare {
875b060f3c4SAxel Lin 	struct adm1031_data *data = dev_get_drvdata(dev);
876b060f3c4SAxel Lin 	struct i2c_client *client = data->client;
87787c33daaSJean Delvare 	unsigned long val;
87887c33daaSJean Delvare 	int i, err;
87987c33daaSJean Delvare 	u8 reg;
88087c33daaSJean Delvare 
881179c4fdbSFrans Meulenbroeks 	err = kstrtoul(buf, 10, &val);
88287c33daaSJean Delvare 	if (err)
88387c33daaSJean Delvare 		return err;
88487c33daaSJean Delvare 
885a51b9944SGuenter Roeck 	/*
886a51b9944SGuenter Roeck 	 * Find the nearest update interval from the table.
887a51b9944SGuenter Roeck 	 * Use it to determine the matching update rate.
888a51b9944SGuenter Roeck 	 */
889a51b9944SGuenter Roeck 	for (i = 0; i < ARRAY_SIZE(update_intervals) - 1; i++) {
890a51b9944SGuenter Roeck 		if (val >= update_intervals[i])
89187c33daaSJean Delvare 			break;
89287c33daaSJean Delvare 	}
893a51b9944SGuenter Roeck 	/* if not found, we point to the last entry (lowest update interval) */
89487c33daaSJean Delvare 
89587c33daaSJean Delvare 	/* set the new update rate while preserving other settings */
89687c33daaSJean Delvare 	reg = adm1031_read_value(client, ADM1031_REG_FAN_FILTER);
89787c33daaSJean Delvare 	reg &= ~ADM1031_UPDATE_RATE_MASK;
89887c33daaSJean Delvare 	reg |= i << ADM1031_UPDATE_RATE_SHIFT;
89987c33daaSJean Delvare 	adm1031_write_value(client, ADM1031_REG_FAN_FILTER, reg);
90087c33daaSJean Delvare 
90187c33daaSJean Delvare 	mutex_lock(&data->update_lock);
902a51b9944SGuenter Roeck 	data->update_interval = update_intervals[i];
90387c33daaSJean Delvare 	mutex_unlock(&data->update_lock);
90487c33daaSJean Delvare 
90587c33daaSJean Delvare 	return count;
90687c33daaSJean Delvare }
90787c33daaSJean Delvare 
908bfb6b173SJulia Lawall static DEVICE_ATTR_RW(update_interval);
90987c33daaSJean Delvare 
910681c6f7aSMark M. Hoffman static struct attribute *adm1031_attributes[] = {
911c801082dSJean Delvare 	&sensor_dev_attr_fan1_input.dev_attr.attr,
912c801082dSJean Delvare 	&sensor_dev_attr_fan1_div.dev_attr.attr,
913c801082dSJean Delvare 	&sensor_dev_attr_fan1_min.dev_attr.attr,
914050ab878SJean Delvare 	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
915050ab878SJean Delvare 	&sensor_dev_attr_fan1_fault.dev_attr.attr,
916c801082dSJean Delvare 	&sensor_dev_attr_pwm1.dev_attr.attr,
917c801082dSJean Delvare 	&sensor_dev_attr_auto_fan1_channel.dev_attr.attr,
918c801082dSJean Delvare 	&sensor_dev_attr_temp1_input.dev_attr.attr,
91949dc9efeSIra Snyder 	&sensor_dev_attr_temp1_offset.dev_attr.attr,
920c801082dSJean Delvare 	&sensor_dev_attr_temp1_min.dev_attr.attr,
921050ab878SJean Delvare 	&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
922c801082dSJean Delvare 	&sensor_dev_attr_temp1_max.dev_attr.attr,
923050ab878SJean Delvare 	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
924c801082dSJean Delvare 	&sensor_dev_attr_temp1_crit.dev_attr.attr,
925050ab878SJean Delvare 	&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
926c801082dSJean Delvare 	&sensor_dev_attr_temp2_input.dev_attr.attr,
92749dc9efeSIra Snyder 	&sensor_dev_attr_temp2_offset.dev_attr.attr,
928c801082dSJean Delvare 	&sensor_dev_attr_temp2_min.dev_attr.attr,
929050ab878SJean Delvare 	&sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
930c801082dSJean Delvare 	&sensor_dev_attr_temp2_max.dev_attr.attr,
931050ab878SJean Delvare 	&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
932c801082dSJean Delvare 	&sensor_dev_attr_temp2_crit.dev_attr.attr,
933050ab878SJean Delvare 	&sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
934050ab878SJean Delvare 	&sensor_dev_attr_temp2_fault.dev_attr.attr,
935681c6f7aSMark M. Hoffman 
936c801082dSJean Delvare 	&sensor_dev_attr_auto_temp1_off.dev_attr.attr,
937c801082dSJean Delvare 	&sensor_dev_attr_auto_temp1_min.dev_attr.attr,
938c801082dSJean Delvare 	&sensor_dev_attr_auto_temp1_max.dev_attr.attr,
939681c6f7aSMark M. Hoffman 
940c801082dSJean Delvare 	&sensor_dev_attr_auto_temp2_off.dev_attr.attr,
941c801082dSJean Delvare 	&sensor_dev_attr_auto_temp2_min.dev_attr.attr,
942c801082dSJean Delvare 	&sensor_dev_attr_auto_temp2_max.dev_attr.attr,
943681c6f7aSMark M. Hoffman 
944c801082dSJean Delvare 	&sensor_dev_attr_auto_fan1_min_pwm.dev_attr.attr,
945681c6f7aSMark M. Hoffman 
946a51b9944SGuenter Roeck 	&dev_attr_update_interval.attr,
947681c6f7aSMark M. Hoffman 	&dev_attr_alarms.attr,
948681c6f7aSMark M. Hoffman 
949681c6f7aSMark M. Hoffman 	NULL
950681c6f7aSMark M. Hoffman };
951681c6f7aSMark M. Hoffman 
952681c6f7aSMark M. Hoffman static const struct attribute_group adm1031_group = {
953681c6f7aSMark M. Hoffman 	.attrs = adm1031_attributes,
954681c6f7aSMark M. Hoffman };
955681c6f7aSMark M. Hoffman 
956681c6f7aSMark M. Hoffman static struct attribute *adm1031_attributes_opt[] = {
957c801082dSJean Delvare 	&sensor_dev_attr_fan2_input.dev_attr.attr,
958c801082dSJean Delvare 	&sensor_dev_attr_fan2_div.dev_attr.attr,
959c801082dSJean Delvare 	&sensor_dev_attr_fan2_min.dev_attr.attr,
960050ab878SJean Delvare 	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
961050ab878SJean Delvare 	&sensor_dev_attr_fan2_fault.dev_attr.attr,
962c801082dSJean Delvare 	&sensor_dev_attr_pwm2.dev_attr.attr,
963c801082dSJean Delvare 	&sensor_dev_attr_auto_fan2_channel.dev_attr.attr,
964c801082dSJean Delvare 	&sensor_dev_attr_temp3_input.dev_attr.attr,
96549dc9efeSIra Snyder 	&sensor_dev_attr_temp3_offset.dev_attr.attr,
966c801082dSJean Delvare 	&sensor_dev_attr_temp3_min.dev_attr.attr,
967050ab878SJean Delvare 	&sensor_dev_attr_temp3_min_alarm.dev_attr.attr,
968c801082dSJean Delvare 	&sensor_dev_attr_temp3_max.dev_attr.attr,
969050ab878SJean Delvare 	&sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
970c801082dSJean Delvare 	&sensor_dev_attr_temp3_crit.dev_attr.attr,
971050ab878SJean Delvare 	&sensor_dev_attr_temp3_crit_alarm.dev_attr.attr,
972050ab878SJean Delvare 	&sensor_dev_attr_temp3_fault.dev_attr.attr,
973c801082dSJean Delvare 	&sensor_dev_attr_auto_temp3_off.dev_attr.attr,
974c801082dSJean Delvare 	&sensor_dev_attr_auto_temp3_min.dev_attr.attr,
975c801082dSJean Delvare 	&sensor_dev_attr_auto_temp3_max.dev_attr.attr,
976c801082dSJean Delvare 	&sensor_dev_attr_auto_fan2_min_pwm.dev_attr.attr,
977681c6f7aSMark M. Hoffman 	NULL
978681c6f7aSMark M. Hoffman };
979681c6f7aSMark M. Hoffman 
980681c6f7aSMark M. Hoffman static const struct attribute_group adm1031_group_opt = {
981681c6f7aSMark M. Hoffman 	.attrs = adm1031_attributes_opt,
982681c6f7aSMark M. Hoffman };
983681c6f7aSMark M. Hoffman 
984af200f88SJean Delvare /* Return 0 if detection is successful, -ENODEV otherwise */
985310ec792SJean Delvare static int adm1031_detect(struct i2c_client *client,
986af200f88SJean Delvare 			  struct i2c_board_info *info)
9878d5d45fbSJean Delvare {
988af200f88SJean Delvare 	struct i2c_adapter *adapter = client->adapter;
98952df6440SJean Delvare 	const char *name;
99052df6440SJean Delvare 	int id, co;
9918d5d45fbSJean Delvare 
9928d5d45fbSJean Delvare 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
993af200f88SJean Delvare 		return -ENODEV;
9948d5d45fbSJean Delvare 
9956d6006b8SJean Delvare 	id = i2c_smbus_read_byte_data(client, 0x3d);
9966d6006b8SJean Delvare 	co = i2c_smbus_read_byte_data(client, 0x3e);
9978d5d45fbSJean Delvare 
9988d5d45fbSJean Delvare 	if (!((id == 0x31 || id == 0x30) && co == 0x41))
999af200f88SJean Delvare 		return -ENODEV;
100052df6440SJean Delvare 	name = (id == 0x30) ? "adm1030" : "adm1031";
10018d5d45fbSJean Delvare 
1002af200f88SJean Delvare 	strlcpy(info->type, name, I2C_NAME_SIZE);
10038d5d45fbSJean Delvare 
1004af200f88SJean Delvare 	return 0;
1005af200f88SJean Delvare }
1006af200f88SJean Delvare 
1007278ee1c8SAxel Lin static void adm1031_init_client(struct i2c_client *client)
1008278ee1c8SAxel Lin {
1009278ee1c8SAxel Lin 	unsigned int read_val;
1010278ee1c8SAxel Lin 	unsigned int mask;
1011278ee1c8SAxel Lin 	int i;
1012278ee1c8SAxel Lin 	struct adm1031_data *data = i2c_get_clientdata(client);
1013278ee1c8SAxel Lin 
1014278ee1c8SAxel Lin 	mask = (ADM1031_CONF2_PWM1_ENABLE | ADM1031_CONF2_TACH1_ENABLE);
1015278ee1c8SAxel Lin 	if (data->chip_type == adm1031) {
1016278ee1c8SAxel Lin 		mask |= (ADM1031_CONF2_PWM2_ENABLE |
1017278ee1c8SAxel Lin 			ADM1031_CONF2_TACH2_ENABLE);
1018278ee1c8SAxel Lin 	}
1019278ee1c8SAxel Lin 	/* Initialize the ADM1031 chip (enables fan speed reading ) */
1020278ee1c8SAxel Lin 	read_val = adm1031_read_value(client, ADM1031_REG_CONF2);
1021278ee1c8SAxel Lin 	if ((read_val | mask) != read_val)
1022278ee1c8SAxel Lin 		adm1031_write_value(client, ADM1031_REG_CONF2, read_val | mask);
1023278ee1c8SAxel Lin 
1024278ee1c8SAxel Lin 	read_val = adm1031_read_value(client, ADM1031_REG_CONF1);
1025278ee1c8SAxel Lin 	if ((read_val | ADM1031_CONF1_MONITOR_ENABLE) != read_val) {
1026278ee1c8SAxel Lin 		adm1031_write_value(client, ADM1031_REG_CONF1,
1027278ee1c8SAxel Lin 				    read_val | ADM1031_CONF1_MONITOR_ENABLE);
1028278ee1c8SAxel Lin 	}
1029278ee1c8SAxel Lin 
1030278ee1c8SAxel Lin 	/* Read the chip's update rate */
1031278ee1c8SAxel Lin 	mask = ADM1031_UPDATE_RATE_MASK;
1032278ee1c8SAxel Lin 	read_val = adm1031_read_value(client, ADM1031_REG_FAN_FILTER);
1033278ee1c8SAxel Lin 	i = (read_val & mask) >> ADM1031_UPDATE_RATE_SHIFT;
1034278ee1c8SAxel Lin 	/* Save it as update interval */
1035278ee1c8SAxel Lin 	data->update_interval = update_intervals[i];
1036278ee1c8SAxel Lin }
1037278ee1c8SAxel Lin 
1038af200f88SJean Delvare static int adm1031_probe(struct i2c_client *client,
1039af200f88SJean Delvare 			 const struct i2c_device_id *id)
1040af200f88SJean Delvare {
1041b060f3c4SAxel Lin 	struct device *dev = &client->dev;
1042b060f3c4SAxel Lin 	struct device *hwmon_dev;
1043af200f88SJean Delvare 	struct adm1031_data *data;
1044af200f88SJean Delvare 
1045b060f3c4SAxel Lin 	data = devm_kzalloc(dev, sizeof(struct adm1031_data), GFP_KERNEL);
1046dc2fd663SGuenter Roeck 	if (!data)
1047dc2fd663SGuenter Roeck 		return -ENOMEM;
1048af200f88SJean Delvare 
1049af200f88SJean Delvare 	i2c_set_clientdata(client, data);
1050b060f3c4SAxel Lin 	data->client = client;
1051af200f88SJean Delvare 	data->chip_type = id->driver_data;
10529a61bf63SIngo Molnar 	mutex_init(&data->update_lock);
10538d5d45fbSJean Delvare 
1054af200f88SJean Delvare 	if (data->chip_type == adm1030)
1055af200f88SJean Delvare 		data->chan_select_table = &auto_channel_select_table_adm1030;
1056af200f88SJean Delvare 	else
1057af200f88SJean Delvare 		data->chan_select_table = &auto_channel_select_table_adm1031;
10588d5d45fbSJean Delvare 
10598d5d45fbSJean Delvare 	/* Initialize the ADM1031 chip */
10606d6006b8SJean Delvare 	adm1031_init_client(client);
10618d5d45fbSJean Delvare 
1062b060f3c4SAxel Lin 	/* sysfs hooks */
1063b060f3c4SAxel Lin 	data->groups[0] = &adm1031_group;
1064b060f3c4SAxel Lin 	if (data->chip_type == adm1031)
1065b060f3c4SAxel Lin 		data->groups[1] = &adm1031_group_opt;
1066681c6f7aSMark M. Hoffman 
1067b060f3c4SAxel Lin 	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
1068b060f3c4SAxel Lin 							   data, data->groups);
1069b060f3c4SAxel Lin 	return PTR_ERR_OR_ZERO(hwmon_dev);
10708d5d45fbSJean Delvare }
10718d5d45fbSJean Delvare 
1072278ee1c8SAxel Lin static const struct i2c_device_id adm1031_id[] = {
1073278ee1c8SAxel Lin 	{ "adm1030", adm1030 },
1074278ee1c8SAxel Lin 	{ "adm1031", adm1031 },
1075278ee1c8SAxel Lin 	{ }
1076278ee1c8SAxel Lin };
1077278ee1c8SAxel Lin MODULE_DEVICE_TABLE(i2c, adm1031_id);
10788d5d45fbSJean Delvare 
1079278ee1c8SAxel Lin static struct i2c_driver adm1031_driver = {
1080278ee1c8SAxel Lin 	.class		= I2C_CLASS_HWMON,
1081278ee1c8SAxel Lin 	.driver = {
1082278ee1c8SAxel Lin 		.name = "adm1031",
1083278ee1c8SAxel Lin 	},
1084278ee1c8SAxel Lin 	.probe		= adm1031_probe,
1085278ee1c8SAxel Lin 	.id_table	= adm1031_id,
1086278ee1c8SAxel Lin 	.detect		= adm1031_detect,
1087278ee1c8SAxel Lin 	.address_list	= normal_i2c,
1088278ee1c8SAxel Lin };
10898d5d45fbSJean Delvare 
1090f0967eeaSAxel Lin module_i2c_driver(adm1031_driver);
10918d5d45fbSJean Delvare 
10928d5d45fbSJean Delvare MODULE_AUTHOR("Alexandre d'Alton <alex@alexdalton.org>");
10938d5d45fbSJean Delvare MODULE_DESCRIPTION("ADM1031/ADM1030 driver");
10948d5d45fbSJean Delvare MODULE_LICENSE("GPL");
1095