xref: /openbmc/linux/drivers/hwmon/adm1031.c (revision 278ee1c840fcf32f156fd876efcc3780bc580f6c)
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 {
771beeffe4STony Jones 	struct device *hwmon_dev;
789a61bf63SIngo Molnar 	struct mutex update_lock;
798d5d45fbSJean Delvare 	int chip_type;
808d5d45fbSJean Delvare 	char valid;		/* !=0 if following fields are valid */
818d5d45fbSJean Delvare 	unsigned long last_updated;	/* In jiffies */
82a51b9944SGuenter Roeck 	unsigned int update_interval;	/* In milliseconds */
83fbb6670dSGuenter Roeck 	/*
84fbb6670dSGuenter Roeck 	 * The chan_select_table contains the possible configurations for
858d5d45fbSJean Delvare 	 * auto fan control.
868d5d45fbSJean Delvare 	 */
876d6006b8SJean Delvare 	const auto_chan_table_t *chan_select_table;
888d5d45fbSJean Delvare 	u16 alarm;
898d5d45fbSJean Delvare 	u8 conf1;
908d5d45fbSJean Delvare 	u8 conf2;
918d5d45fbSJean Delvare 	u8 fan[2];
928d5d45fbSJean Delvare 	u8 fan_div[2];
938d5d45fbSJean Delvare 	u8 fan_min[2];
948d5d45fbSJean Delvare 	u8 pwm[2];
958d5d45fbSJean Delvare 	u8 old_pwm[2];
968d5d45fbSJean Delvare 	s8 temp[3];
978d5d45fbSJean Delvare 	u8 ext_temp[3];
988d5d45fbSJean Delvare 	u8 auto_temp[3];
998d5d45fbSJean Delvare 	u8 auto_temp_min[3];
1008d5d45fbSJean Delvare 	u8 auto_temp_off[3];
1018d5d45fbSJean Delvare 	u8 auto_temp_max[3];
10249dc9efeSIra Snyder 	s8 temp_offset[3];
1038d5d45fbSJean Delvare 	s8 temp_min[3];
1048d5d45fbSJean Delvare 	s8 temp_max[3];
1058d5d45fbSJean Delvare 	s8 temp_crit[3];
1068d5d45fbSJean Delvare };
1078d5d45fbSJean Delvare 
1088d5d45fbSJean Delvare static inline u8 adm1031_read_value(struct i2c_client *client, u8 reg)
1098d5d45fbSJean Delvare {
1108d5d45fbSJean Delvare 	return i2c_smbus_read_byte_data(client, reg);
1118d5d45fbSJean Delvare }
1128d5d45fbSJean Delvare 
1138d5d45fbSJean Delvare static inline int
1148d5d45fbSJean Delvare adm1031_write_value(struct i2c_client *client, u8 reg, unsigned int value)
1158d5d45fbSJean Delvare {
1168d5d45fbSJean Delvare 	return i2c_smbus_write_byte_data(client, reg, value);
1178d5d45fbSJean Delvare }
1188d5d45fbSJean Delvare 
119*278ee1c8SAxel Lin static struct adm1031_data *adm1031_update_device(struct device *dev)
120*278ee1c8SAxel Lin {
121*278ee1c8SAxel Lin 	struct i2c_client *client = to_i2c_client(dev);
122*278ee1c8SAxel Lin 	struct adm1031_data *data = i2c_get_clientdata(client);
123*278ee1c8SAxel Lin 	unsigned long next_update;
124*278ee1c8SAxel Lin 	int chan;
125*278ee1c8SAxel Lin 
126*278ee1c8SAxel Lin 	mutex_lock(&data->update_lock);
127*278ee1c8SAxel Lin 
128*278ee1c8SAxel Lin 	next_update = data->last_updated
129*278ee1c8SAxel Lin 	  + msecs_to_jiffies(data->update_interval);
130*278ee1c8SAxel Lin 	if (time_after(jiffies, next_update) || !data->valid) {
131*278ee1c8SAxel Lin 
132*278ee1c8SAxel Lin 		dev_dbg(&client->dev, "Starting adm1031 update\n");
133*278ee1c8SAxel Lin 		for (chan = 0;
134*278ee1c8SAxel Lin 		     chan < ((data->chip_type == adm1031) ? 3 : 2); chan++) {
135*278ee1c8SAxel Lin 			u8 oldh, newh;
136*278ee1c8SAxel Lin 
137*278ee1c8SAxel Lin 			oldh =
138*278ee1c8SAxel Lin 			    adm1031_read_value(client, ADM1031_REG_TEMP(chan));
139*278ee1c8SAxel Lin 			data->ext_temp[chan] =
140*278ee1c8SAxel Lin 			    adm1031_read_value(client, ADM1031_REG_EXT_TEMP);
141*278ee1c8SAxel Lin 			newh =
142*278ee1c8SAxel Lin 			    adm1031_read_value(client, ADM1031_REG_TEMP(chan));
143*278ee1c8SAxel Lin 			if (newh != oldh) {
144*278ee1c8SAxel Lin 				data->ext_temp[chan] =
145*278ee1c8SAxel Lin 				    adm1031_read_value(client,
146*278ee1c8SAxel Lin 						       ADM1031_REG_EXT_TEMP);
147*278ee1c8SAxel Lin #ifdef DEBUG
148*278ee1c8SAxel Lin 				oldh =
149*278ee1c8SAxel Lin 				    adm1031_read_value(client,
150*278ee1c8SAxel Lin 						       ADM1031_REG_TEMP(chan));
151*278ee1c8SAxel Lin 
152*278ee1c8SAxel Lin 				/* oldh is actually newer */
153*278ee1c8SAxel Lin 				if (newh != oldh)
154*278ee1c8SAxel Lin 					dev_warn(&client->dev,
155*278ee1c8SAxel Lin 					  "Remote temperature may be wrong.\n");
156*278ee1c8SAxel Lin #endif
157*278ee1c8SAxel Lin 			}
158*278ee1c8SAxel Lin 			data->temp[chan] = newh;
159*278ee1c8SAxel Lin 
160*278ee1c8SAxel Lin 			data->temp_offset[chan] =
161*278ee1c8SAxel Lin 			    adm1031_read_value(client,
162*278ee1c8SAxel Lin 					       ADM1031_REG_TEMP_OFFSET(chan));
163*278ee1c8SAxel Lin 			data->temp_min[chan] =
164*278ee1c8SAxel Lin 			    adm1031_read_value(client,
165*278ee1c8SAxel Lin 					       ADM1031_REG_TEMP_MIN(chan));
166*278ee1c8SAxel Lin 			data->temp_max[chan] =
167*278ee1c8SAxel Lin 			    adm1031_read_value(client,
168*278ee1c8SAxel Lin 					       ADM1031_REG_TEMP_MAX(chan));
169*278ee1c8SAxel Lin 			data->temp_crit[chan] =
170*278ee1c8SAxel Lin 			    adm1031_read_value(client,
171*278ee1c8SAxel Lin 					       ADM1031_REG_TEMP_CRIT(chan));
172*278ee1c8SAxel Lin 			data->auto_temp[chan] =
173*278ee1c8SAxel Lin 			    adm1031_read_value(client,
174*278ee1c8SAxel Lin 					       ADM1031_REG_AUTO_TEMP(chan));
175*278ee1c8SAxel Lin 
176*278ee1c8SAxel Lin 		}
177*278ee1c8SAxel Lin 
178*278ee1c8SAxel Lin 		data->conf1 = adm1031_read_value(client, ADM1031_REG_CONF1);
179*278ee1c8SAxel Lin 		data->conf2 = adm1031_read_value(client, ADM1031_REG_CONF2);
180*278ee1c8SAxel Lin 
181*278ee1c8SAxel Lin 		data->alarm = adm1031_read_value(client, ADM1031_REG_STATUS(0))
182*278ee1c8SAxel Lin 		    | (adm1031_read_value(client, ADM1031_REG_STATUS(1)) << 8);
183*278ee1c8SAxel Lin 		if (data->chip_type == adm1030)
184*278ee1c8SAxel Lin 			data->alarm &= 0xc0ff;
185*278ee1c8SAxel Lin 
186*278ee1c8SAxel Lin 		for (chan = 0; chan < (data->chip_type == adm1030 ? 1 : 2);
187*278ee1c8SAxel Lin 		     chan++) {
188*278ee1c8SAxel Lin 			data->fan_div[chan] =
189*278ee1c8SAxel Lin 			    adm1031_read_value(client,
190*278ee1c8SAxel Lin 					       ADM1031_REG_FAN_DIV(chan));
191*278ee1c8SAxel Lin 			data->fan_min[chan] =
192*278ee1c8SAxel Lin 			    adm1031_read_value(client,
193*278ee1c8SAxel Lin 					       ADM1031_REG_FAN_MIN(chan));
194*278ee1c8SAxel Lin 			data->fan[chan] =
195*278ee1c8SAxel Lin 			    adm1031_read_value(client,
196*278ee1c8SAxel Lin 					       ADM1031_REG_FAN_SPEED(chan));
197*278ee1c8SAxel Lin 			data->pwm[chan] =
198*278ee1c8SAxel Lin 			  (adm1031_read_value(client,
199*278ee1c8SAxel Lin 					ADM1031_REG_PWM) >> (4 * chan)) & 0x0f;
200*278ee1c8SAxel Lin 		}
201*278ee1c8SAxel Lin 		data->last_updated = jiffies;
202*278ee1c8SAxel Lin 		data->valid = 1;
203*278ee1c8SAxel Lin 	}
204*278ee1c8SAxel Lin 
205*278ee1c8SAxel Lin 	mutex_unlock(&data->update_lock);
206*278ee1c8SAxel Lin 
207*278ee1c8SAxel Lin 	return data;
208*278ee1c8SAxel Lin }
2098d5d45fbSJean Delvare 
2108d5d45fbSJean Delvare #define TEMP_TO_REG(val)		(((val) < 0 ? ((val - 500) / 1000) : \
2118d5d45fbSJean Delvare 					((val + 500) / 1000)))
2128d5d45fbSJean Delvare 
2138d5d45fbSJean Delvare #define TEMP_FROM_REG(val)		((val) * 1000)
2148d5d45fbSJean Delvare 
2158d5d45fbSJean Delvare #define TEMP_FROM_REG_EXT(val, ext)	(TEMP_FROM_REG(val) + (ext) * 125)
2168d5d45fbSJean Delvare 
21749dc9efeSIra Snyder #define TEMP_OFFSET_TO_REG(val)		(TEMP_TO_REG(val) & 0x8f)
21849dc9efeSIra Snyder #define TEMP_OFFSET_FROM_REG(val)	TEMP_FROM_REG((val) < 0 ? \
21949dc9efeSIra Snyder 						      (val) | 0x70 : (val))
22049dc9efeSIra Snyder 
2211c720093SGuenter Roeck #define FAN_FROM_REG(reg, div)		((reg) ? \
2221c720093SGuenter Roeck 					 (11250 * 60) / ((reg) * (div)) : 0)
2238d5d45fbSJean Delvare 
2248d5d45fbSJean Delvare static int FAN_TO_REG(int reg, int div)
2258d5d45fbSJean Delvare {
2268d5d45fbSJean Delvare 	int tmp;
2272a844c14SGuenter Roeck 	tmp = FAN_FROM_REG(clamp_val(reg, 0, 65535), div);
2288d5d45fbSJean Delvare 	return tmp > 255 ? 255 : tmp;
2298d5d45fbSJean Delvare }
2308d5d45fbSJean Delvare 
2318d5d45fbSJean Delvare #define FAN_DIV_FROM_REG(reg)		(1<<(((reg)&0xc0)>>6))
2328d5d45fbSJean Delvare 
2332a844c14SGuenter Roeck #define PWM_TO_REG(val)			(clamp_val((val), 0, 255) >> 4)
2348d5d45fbSJean Delvare #define PWM_FROM_REG(val)		((val) << 4)
2358d5d45fbSJean Delvare 
2368d5d45fbSJean Delvare #define FAN_CHAN_FROM_REG(reg)		(((reg) >> 5) & 7)
2378d5d45fbSJean Delvare #define FAN_CHAN_TO_REG(val, reg)	\
2388d5d45fbSJean Delvare 	(((reg) & 0x1F) | (((val) << 5) & 0xe0))
2398d5d45fbSJean Delvare 
2408d5d45fbSJean Delvare #define AUTO_TEMP_MIN_TO_REG(val, reg)	\
2418d5d45fbSJean Delvare 	((((val) / 500) & 0xf8) | ((reg) & 0x7))
2428d5d45fbSJean Delvare #define AUTO_TEMP_RANGE_FROM_REG(reg)	(5000 * (1 << ((reg) & 0x7)))
2438d5d45fbSJean Delvare #define AUTO_TEMP_MIN_FROM_REG(reg)	(1000 * ((((reg) >> 3) & 0x1f) << 2))
2448d5d45fbSJean Delvare 
2458d5d45fbSJean Delvare #define AUTO_TEMP_MIN_FROM_REG_DEG(reg)	((((reg) >> 3) & 0x1f) << 2)
2468d5d45fbSJean Delvare 
2478d5d45fbSJean Delvare #define AUTO_TEMP_OFF_FROM_REG(reg)		\
2488d5d45fbSJean Delvare 	(AUTO_TEMP_MIN_FROM_REG(reg) - 5000)
2498d5d45fbSJean Delvare 
2508d5d45fbSJean Delvare #define AUTO_TEMP_MAX_FROM_REG(reg)		\
2518d5d45fbSJean Delvare 	(AUTO_TEMP_RANGE_FROM_REG(reg) +	\
2528d5d45fbSJean Delvare 	AUTO_TEMP_MIN_FROM_REG(reg))
2538d5d45fbSJean Delvare 
2548d5d45fbSJean Delvare static int AUTO_TEMP_MAX_TO_REG(int val, int reg, int pwm)
2558d5d45fbSJean Delvare {
2568d5d45fbSJean Delvare 	int ret;
2578d5d45fbSJean Delvare 	int range = val - AUTO_TEMP_MIN_FROM_REG(reg);
2588d5d45fbSJean Delvare 
2598d5d45fbSJean Delvare 	range = ((val - AUTO_TEMP_MIN_FROM_REG(reg))*10)/(16 - pwm);
2608d5d45fbSJean Delvare 	ret = ((reg & 0xf8) |
2618d5d45fbSJean Delvare 	       (range < 10000 ? 0 :
2628d5d45fbSJean Delvare 		range < 20000 ? 1 :
2638d5d45fbSJean Delvare 		range < 40000 ? 2 : range < 80000 ? 3 : 4));
2648d5d45fbSJean Delvare 	return ret;
2658d5d45fbSJean Delvare }
2668d5d45fbSJean Delvare 
2678d5d45fbSJean Delvare /* FAN auto control */
2688d5d45fbSJean Delvare #define GET_FAN_AUTO_BITFIELD(data, idx)	\
2698d5d45fbSJean Delvare 	(*(data)->chan_select_table)[FAN_CHAN_FROM_REG((data)->conf1)][idx % 2]
2708d5d45fbSJean Delvare 
271fbb6670dSGuenter Roeck /*
272fbb6670dSGuenter Roeck  * The tables below contains the possible values for the auto fan
2738d5d45fbSJean Delvare  * control bitfields. the index in the table is the register value.
2748d5d45fbSJean Delvare  * MSb is the auto fan control enable bit, so the four first entries
2758d5d45fbSJean Delvare  * in the table disables auto fan control when both bitfields are zero.
2768d5d45fbSJean Delvare  */
2776d6006b8SJean Delvare static const auto_chan_table_t auto_channel_select_table_adm1031 = {
2788d5d45fbSJean Delvare 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2798d5d45fbSJean Delvare 	{ 2 /* 0b010 */ , 4 /* 0b100 */ },
2808d5d45fbSJean Delvare 	{ 2 /* 0b010 */ , 2 /* 0b010 */ },
2818d5d45fbSJean Delvare 	{ 4 /* 0b100 */ , 4 /* 0b100 */ },
2828d5d45fbSJean Delvare 	{ 7 /* 0b111 */ , 7 /* 0b111 */ },
2838d5d45fbSJean Delvare };
2848d5d45fbSJean Delvare 
2856d6006b8SJean Delvare static const auto_chan_table_t auto_channel_select_table_adm1030 = {
2868d5d45fbSJean Delvare 	{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
2878d5d45fbSJean Delvare 	{ 2 /* 0b10 */		, 0 },
2888d5d45fbSJean Delvare 	{ 0xff /* invalid */	, 0 },
2898d5d45fbSJean Delvare 	{ 0xff /* invalid */	, 0 },
2908d5d45fbSJean Delvare 	{ 3 /* 0b11 */		, 0 },
2918d5d45fbSJean Delvare };
2928d5d45fbSJean Delvare 
293fbb6670dSGuenter Roeck /*
294fbb6670dSGuenter Roeck  * That function checks if a bitfield is valid and returns the other bitfield
2958d5d45fbSJean Delvare  * nearest match if no exact match where found.
2968d5d45fbSJean Delvare  */
2978d5d45fbSJean Delvare static int
298ce15a81dSGuenter Roeck get_fan_auto_nearest(struct adm1031_data *data, int chan, u8 val, u8 reg)
2998d5d45fbSJean Delvare {
3008d5d45fbSJean Delvare 	int i;
3018d5d45fbSJean Delvare 	int first_match = -1, exact_match = -1;
3028d5d45fbSJean Delvare 	u8 other_reg_val =
3038d5d45fbSJean Delvare 	    (*data->chan_select_table)[FAN_CHAN_FROM_REG(reg)][chan ? 0 : 1];
3048d5d45fbSJean Delvare 
305ce15a81dSGuenter Roeck 	if (val == 0)
3068d5d45fbSJean Delvare 		return 0;
3078d5d45fbSJean Delvare 
3088d5d45fbSJean Delvare 	for (i = 0; i < 8; i++) {
3098d5d45fbSJean Delvare 		if ((val == (*data->chan_select_table)[i][chan]) &&
3108d5d45fbSJean Delvare 		    ((*data->chan_select_table)[i][chan ? 0 : 1] ==
3118d5d45fbSJean Delvare 		     other_reg_val)) {
3128d5d45fbSJean Delvare 			/* We found an exact match */
3138d5d45fbSJean Delvare 			exact_match = i;
3148d5d45fbSJean Delvare 			break;
3158d5d45fbSJean Delvare 		} else if (val == (*data->chan_select_table)[i][chan] &&
3168d5d45fbSJean Delvare 			   first_match == -1) {
317fbb6670dSGuenter Roeck 			/*
318fbb6670dSGuenter Roeck 			 * Save the first match in case of an exact match has
3196d6006b8SJean Delvare 			 * not been found
3208d5d45fbSJean Delvare 			 */
3218d5d45fbSJean Delvare 			first_match = i;
3228d5d45fbSJean Delvare 		}
3238d5d45fbSJean Delvare 	}
3248d5d45fbSJean Delvare 
3251c720093SGuenter Roeck 	if (exact_match >= 0)
326ce15a81dSGuenter Roeck 		return exact_match;
3271c720093SGuenter Roeck 	else if (first_match >= 0)
328ce15a81dSGuenter Roeck 		return first_match;
3291c720093SGuenter Roeck 
330ce15a81dSGuenter Roeck 	return -EINVAL;
3318d5d45fbSJean Delvare }
3328d5d45fbSJean Delvare 
333c801082dSJean Delvare static ssize_t show_fan_auto_channel(struct device *dev,
334c801082dSJean Delvare 				     struct device_attribute *attr, char *buf)
3358d5d45fbSJean Delvare {
336c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
3378d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
3388d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", GET_FAN_AUTO_BITFIELD(data, nr));
3398d5d45fbSJean Delvare }
3408d5d45fbSJean Delvare 
3418d5d45fbSJean Delvare static ssize_t
342c801082dSJean Delvare set_fan_auto_channel(struct device *dev, struct device_attribute *attr,
343c801082dSJean Delvare 		     const char *buf, size_t count)
3448d5d45fbSJean Delvare {
3458d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
3468d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
347c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
3481c720093SGuenter Roeck 	long val;
3498d5d45fbSJean Delvare 	u8 reg;
3508d5d45fbSJean Delvare 	int ret;
3518d5d45fbSJean Delvare 	u8 old_fan_mode;
3528d5d45fbSJean Delvare 
3531c720093SGuenter Roeck 	ret = kstrtol(buf, 10, &val);
3541c720093SGuenter Roeck 	if (ret)
3551c720093SGuenter Roeck 		return ret;
3561c720093SGuenter Roeck 
3578d5d45fbSJean Delvare 	old_fan_mode = data->conf1;
3588d5d45fbSJean Delvare 
3599a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
3608d5d45fbSJean Delvare 
361ce15a81dSGuenter Roeck 	ret = get_fan_auto_nearest(data, nr, val, data->conf1);
362ce15a81dSGuenter Roeck 	if (ret < 0) {
3639a61bf63SIngo Molnar 		mutex_unlock(&data->update_lock);
3648d5d45fbSJean Delvare 		return ret;
3658d5d45fbSJean Delvare 	}
366ce15a81dSGuenter Roeck 	reg = ret;
3676d6006b8SJean Delvare 	data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1);
3686d6006b8SJean Delvare 	if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) ^
3698d5d45fbSJean Delvare 	    (old_fan_mode & ADM1031_CONF1_AUTO_MODE)) {
3708d5d45fbSJean Delvare 		if (data->conf1 & ADM1031_CONF1_AUTO_MODE) {
371fbb6670dSGuenter Roeck 			/*
372fbb6670dSGuenter Roeck 			 * Switch to Auto Fan Mode
3738d5d45fbSJean Delvare 			 * Save PWM registers
374fbb6670dSGuenter Roeck 			 * Set PWM registers to 33% Both
375fbb6670dSGuenter Roeck 			 */
3768d5d45fbSJean Delvare 			data->old_pwm[0] = data->pwm[0];
3778d5d45fbSJean Delvare 			data->old_pwm[1] = data->pwm[1];
3788d5d45fbSJean Delvare 			adm1031_write_value(client, ADM1031_REG_PWM, 0x55);
3798d5d45fbSJean Delvare 		} else {
3808d5d45fbSJean Delvare 			/* Switch to Manual Mode */
3818d5d45fbSJean Delvare 			data->pwm[0] = data->old_pwm[0];
3828d5d45fbSJean Delvare 			data->pwm[1] = data->old_pwm[1];
3838d5d45fbSJean Delvare 			/* Restore PWM registers */
3848d5d45fbSJean Delvare 			adm1031_write_value(client, ADM1031_REG_PWM,
3858d5d45fbSJean Delvare 					    data->pwm[0] | (data->pwm[1] << 4));
3868d5d45fbSJean Delvare 		}
3878d5d45fbSJean Delvare 	}
3888d5d45fbSJean Delvare 	data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1);
3898d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_CONF1, data->conf1);
3909a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
3918d5d45fbSJean Delvare 	return count;
3928d5d45fbSJean Delvare }
3938d5d45fbSJean Delvare 
394c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_fan1_channel, S_IRUGO | S_IWUSR,
395c801082dSJean Delvare 		show_fan_auto_channel, set_fan_auto_channel, 0);
396c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_fan2_channel, S_IRUGO | S_IWUSR,
397c801082dSJean Delvare 		show_fan_auto_channel, set_fan_auto_channel, 1);
3988d5d45fbSJean Delvare 
3998d5d45fbSJean Delvare /* Auto Temps */
400c801082dSJean Delvare static ssize_t show_auto_temp_off(struct device *dev,
401c801082dSJean Delvare 				  struct device_attribute *attr, char *buf)
4028d5d45fbSJean Delvare {
403c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4048d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
4058d5d45fbSJean Delvare 	return sprintf(buf, "%d\n",
4068d5d45fbSJean Delvare 		       AUTO_TEMP_OFF_FROM_REG(data->auto_temp[nr]));
4078d5d45fbSJean Delvare }
408c801082dSJean Delvare static ssize_t show_auto_temp_min(struct device *dev,
409c801082dSJean Delvare 				  struct device_attribute *attr, char *buf)
4108d5d45fbSJean Delvare {
411c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4128d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
4138d5d45fbSJean Delvare 	return sprintf(buf, "%d\n",
4148d5d45fbSJean Delvare 		       AUTO_TEMP_MIN_FROM_REG(data->auto_temp[nr]));
4158d5d45fbSJean Delvare }
4168d5d45fbSJean Delvare static ssize_t
417c801082dSJean Delvare set_auto_temp_min(struct device *dev, struct device_attribute *attr,
418c801082dSJean Delvare 		  const char *buf, size_t count)
4198d5d45fbSJean Delvare {
4208d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
4218d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
422c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4231c720093SGuenter Roeck 	long val;
4241c720093SGuenter Roeck 	int ret;
4251c720093SGuenter Roeck 
4261c720093SGuenter Roeck 	ret = kstrtol(buf, 10, &val);
4271c720093SGuenter Roeck 	if (ret)
4281c720093SGuenter Roeck 		return ret;
4298d5d45fbSJean Delvare 
430145e74a4SGuenter Roeck 	val = clamp_val(val, 0, 127000);
4319a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
4328d5d45fbSJean Delvare 	data->auto_temp[nr] = AUTO_TEMP_MIN_TO_REG(val, data->auto_temp[nr]);
4338d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr),
4348d5d45fbSJean Delvare 			    data->auto_temp[nr]);
4359a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
4368d5d45fbSJean Delvare 	return count;
4378d5d45fbSJean Delvare }
438c801082dSJean Delvare static ssize_t show_auto_temp_max(struct device *dev,
439c801082dSJean Delvare 				  struct device_attribute *attr, char *buf)
4408d5d45fbSJean Delvare {
441c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4428d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
4438d5d45fbSJean Delvare 	return sprintf(buf, "%d\n",
4448d5d45fbSJean Delvare 		       AUTO_TEMP_MAX_FROM_REG(data->auto_temp[nr]));
4458d5d45fbSJean Delvare }
4468d5d45fbSJean Delvare static ssize_t
447c801082dSJean Delvare set_auto_temp_max(struct device *dev, struct device_attribute *attr,
448c801082dSJean Delvare 		  const char *buf, size_t count)
4498d5d45fbSJean Delvare {
4508d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
4518d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
452c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4531c720093SGuenter Roeck 	long val;
4541c720093SGuenter Roeck 	int ret;
4551c720093SGuenter Roeck 
4561c720093SGuenter Roeck 	ret = kstrtol(buf, 10, &val);
4571c720093SGuenter Roeck 	if (ret)
4581c720093SGuenter Roeck 		return ret;
4598d5d45fbSJean Delvare 
460145e74a4SGuenter Roeck 	val = clamp_val(val, 0, 127000);
4619a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
4621c720093SGuenter Roeck 	data->temp_max[nr] = AUTO_TEMP_MAX_TO_REG(val, data->auto_temp[nr],
4631c720093SGuenter Roeck 						  data->pwm[nr]);
4648d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr),
4658d5d45fbSJean Delvare 			    data->temp_max[nr]);
4669a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
4678d5d45fbSJean Delvare 	return count;
4688d5d45fbSJean Delvare }
4698d5d45fbSJean Delvare 
4708d5d45fbSJean Delvare #define auto_temp_reg(offset)						\
471c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_temp##offset##_off, S_IRUGO,		\
472c801082dSJean Delvare 		show_auto_temp_off, NULL, offset - 1);			\
473c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_temp##offset##_min, S_IRUGO | S_IWUSR,	\
474c801082dSJean Delvare 		show_auto_temp_min, set_auto_temp_min, offset - 1);	\
475c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_temp##offset##_max, S_IRUGO | S_IWUSR,	\
476c801082dSJean Delvare 		show_auto_temp_max, set_auto_temp_max, offset - 1)
4778d5d45fbSJean Delvare 
4788d5d45fbSJean Delvare auto_temp_reg(1);
4798d5d45fbSJean Delvare auto_temp_reg(2);
4808d5d45fbSJean Delvare auto_temp_reg(3);
4818d5d45fbSJean Delvare 
4828d5d45fbSJean Delvare /* pwm */
483c801082dSJean Delvare static ssize_t show_pwm(struct device *dev,
484c801082dSJean Delvare 			struct device_attribute *attr, char *buf)
4858d5d45fbSJean Delvare {
486c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4878d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
4888d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm[nr]));
4898d5d45fbSJean Delvare }
490c801082dSJean Delvare static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
491c801082dSJean Delvare 		       const char *buf, size_t count)
4928d5d45fbSJean Delvare {
4938d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
4948d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
495c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
4961c720093SGuenter Roeck 	long val;
4971c720093SGuenter Roeck 	int ret, reg;
4981c720093SGuenter Roeck 
4991c720093SGuenter Roeck 	ret = kstrtol(buf, 10, &val);
5001c720093SGuenter Roeck 	if (ret)
5011c720093SGuenter Roeck 		return ret;
5028d5d45fbSJean Delvare 
5039a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
5048d5d45fbSJean Delvare 	if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) &&
5058d5d45fbSJean Delvare 	    (((val>>4) & 0xf) != 5)) {
5068d5d45fbSJean Delvare 		/* In automatic mode, the only PWM accepted is 33% */
5079a61bf63SIngo Molnar 		mutex_unlock(&data->update_lock);
5088d5d45fbSJean Delvare 		return -EINVAL;
5098d5d45fbSJean Delvare 	}
5108d5d45fbSJean Delvare 	data->pwm[nr] = PWM_TO_REG(val);
5118d5d45fbSJean Delvare 	reg = adm1031_read_value(client, ADM1031_REG_PWM);
5128d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_PWM,
5138d5d45fbSJean Delvare 			    nr ? ((data->pwm[nr] << 4) & 0xf0) | (reg & 0xf)
5148d5d45fbSJean Delvare 			    : (data->pwm[nr] & 0xf) | (reg & 0xf0));
5159a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
5168d5d45fbSJean Delvare 	return count;
5178d5d45fbSJean Delvare }
5188d5d45fbSJean Delvare 
519c801082dSJean Delvare static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 0);
520c801082dSJean Delvare static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 1);
521c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_fan1_min_pwm, S_IRUGO | S_IWUSR,
522c801082dSJean Delvare 		show_pwm, set_pwm, 0);
523c801082dSJean Delvare static SENSOR_DEVICE_ATTR(auto_fan2_min_pwm, S_IRUGO | S_IWUSR,
524c801082dSJean Delvare 		show_pwm, set_pwm, 1);
5258d5d45fbSJean Delvare 
5268d5d45fbSJean Delvare /* Fans */
5278d5d45fbSJean Delvare 
5288d5d45fbSJean Delvare /*
5298d5d45fbSJean Delvare  * That function checks the cases where the fan reading is not
5308d5d45fbSJean Delvare  * relevant.  It is used to provide 0 as fan reading when the fan is
5318d5d45fbSJean Delvare  * not supposed to run
5328d5d45fbSJean Delvare  */
5338d5d45fbSJean Delvare static int trust_fan_readings(struct adm1031_data *data, int chan)
5348d5d45fbSJean Delvare {
5358d5d45fbSJean Delvare 	int res = 0;
5368d5d45fbSJean Delvare 
5378d5d45fbSJean Delvare 	if (data->conf1 & ADM1031_CONF1_AUTO_MODE) {
5388d5d45fbSJean Delvare 		switch (data->conf1 & 0x60) {
5391c720093SGuenter Roeck 		case 0x00:
5401c720093SGuenter Roeck 			/*
5411c720093SGuenter Roeck 			 * remote temp1 controls fan1,
5421c720093SGuenter Roeck 			 * remote temp2 controls fan2
5431c720093SGuenter Roeck 			 */
5448d5d45fbSJean Delvare 			res = data->temp[chan+1] >=
5458d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[chan+1]);
5468d5d45fbSJean Delvare 			break;
5478d5d45fbSJean Delvare 		case 0x20:	/* remote temp1 controls both fans */
5488d5d45fbSJean Delvare 			res =
5498d5d45fbSJean Delvare 			    data->temp[1] >=
5508d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[1]);
5518d5d45fbSJean Delvare 			break;
5528d5d45fbSJean Delvare 		case 0x40:	/* remote temp2 controls both fans */
5538d5d45fbSJean Delvare 			res =
5548d5d45fbSJean Delvare 			    data->temp[2] >=
5558d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[2]);
5568d5d45fbSJean Delvare 			break;
5578d5d45fbSJean Delvare 		case 0x60:	/* max controls both fans */
5588d5d45fbSJean Delvare 			res =
5598d5d45fbSJean Delvare 			    data->temp[0] >=
5608d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[0])
5618d5d45fbSJean Delvare 			    || data->temp[1] >=
5628d5d45fbSJean Delvare 			    AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[1])
5638d5d45fbSJean Delvare 			    || (data->chip_type == adm1031
5648d5d45fbSJean Delvare 				&& data->temp[2] >=
5658d5d45fbSJean Delvare 				AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[2]));
5668d5d45fbSJean Delvare 			break;
5678d5d45fbSJean Delvare 		}
5688d5d45fbSJean Delvare 	} else {
5698d5d45fbSJean Delvare 		res = data->pwm[chan] > 0;
5708d5d45fbSJean Delvare 	}
5718d5d45fbSJean Delvare 	return res;
5728d5d45fbSJean Delvare }
5738d5d45fbSJean Delvare 
5748d5d45fbSJean Delvare 
575c801082dSJean Delvare static ssize_t show_fan(struct device *dev,
576c801082dSJean Delvare 			struct device_attribute *attr, char *buf)
5778d5d45fbSJean Delvare {
578c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
5798d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
5808d5d45fbSJean Delvare 	int value;
5818d5d45fbSJean Delvare 
5828d5d45fbSJean Delvare 	value = trust_fan_readings(data, nr) ? FAN_FROM_REG(data->fan[nr],
5838d5d45fbSJean Delvare 				 FAN_DIV_FROM_REG(data->fan_div[nr])) : 0;
5848d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", value);
5858d5d45fbSJean Delvare }
5868d5d45fbSJean Delvare 
587c801082dSJean Delvare static ssize_t show_fan_div(struct device *dev,
588c801082dSJean Delvare 			    struct device_attribute *attr, char *buf)
5898d5d45fbSJean Delvare {
590c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
5918d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
5928d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", FAN_DIV_FROM_REG(data->fan_div[nr]));
5938d5d45fbSJean Delvare }
594c801082dSJean Delvare static ssize_t show_fan_min(struct device *dev,
595c801082dSJean Delvare 			    struct device_attribute *attr, char *buf)
5968d5d45fbSJean Delvare {
597c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
5988d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
5998d5d45fbSJean Delvare 	return sprintf(buf, "%d\n",
6008d5d45fbSJean Delvare 		       FAN_FROM_REG(data->fan_min[nr],
6018d5d45fbSJean Delvare 				    FAN_DIV_FROM_REG(data->fan_div[nr])));
6028d5d45fbSJean Delvare }
603c801082dSJean Delvare static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
604c801082dSJean Delvare 			   const char *buf, size_t count)
6058d5d45fbSJean Delvare {
6068d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
6078d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
608c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
6091c720093SGuenter Roeck 	long val;
6101c720093SGuenter Roeck 	int ret;
6111c720093SGuenter Roeck 
6121c720093SGuenter Roeck 	ret = kstrtol(buf, 10, &val);
6131c720093SGuenter Roeck 	if (ret)
6141c720093SGuenter Roeck 		return ret;
6158d5d45fbSJean Delvare 
6169a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
6178d5d45fbSJean Delvare 	if (val) {
6188d5d45fbSJean Delvare 		data->fan_min[nr] =
6198d5d45fbSJean Delvare 			FAN_TO_REG(val, FAN_DIV_FROM_REG(data->fan_div[nr]));
6208d5d45fbSJean Delvare 	} else {
6218d5d45fbSJean Delvare 		data->fan_min[nr] = 0xff;
6228d5d45fbSJean Delvare 	}
6238d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), data->fan_min[nr]);
6249a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
6258d5d45fbSJean Delvare 	return count;
6268d5d45fbSJean Delvare }
627c801082dSJean Delvare static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
628c801082dSJean Delvare 			   const char *buf, size_t count)
6298d5d45fbSJean Delvare {
6308d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
6318d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
632c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
6331c720093SGuenter Roeck 	long val;
6348d5d45fbSJean Delvare 	u8 tmp;
6358d5d45fbSJean Delvare 	int old_div;
6368d5d45fbSJean Delvare 	int new_min;
6371c720093SGuenter Roeck 	int ret;
6381c720093SGuenter Roeck 
6391c720093SGuenter Roeck 	ret = kstrtol(buf, 10, &val);
6401c720093SGuenter Roeck 	if (ret)
6411c720093SGuenter Roeck 		return ret;
6428d5d45fbSJean Delvare 
6438d5d45fbSJean Delvare 	tmp = val == 8 ? 0xc0 :
6448d5d45fbSJean Delvare 	      val == 4 ? 0x80 :
6458d5d45fbSJean Delvare 	      val == 2 ? 0x40 :
6468d5d45fbSJean Delvare 	      val == 1 ? 0x00 :
6478d5d45fbSJean Delvare 	      0xff;
6488d5d45fbSJean Delvare 	if (tmp == 0xff)
6498d5d45fbSJean Delvare 		return -EINVAL;
6508d5d45fbSJean Delvare 
6519a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
65238a1f0e9SJean Delvare 	/* Get fresh readings */
65338a1f0e9SJean Delvare 	data->fan_div[nr] = adm1031_read_value(client,
65438a1f0e9SJean Delvare 					       ADM1031_REG_FAN_DIV(nr));
65538a1f0e9SJean Delvare 	data->fan_min[nr] = adm1031_read_value(client,
65638a1f0e9SJean Delvare 					       ADM1031_REG_FAN_MIN(nr));
65738a1f0e9SJean Delvare 
65838a1f0e9SJean Delvare 	/* Write the new clock divider and fan min */
6598d5d45fbSJean Delvare 	old_div = FAN_DIV_FROM_REG(data->fan_div[nr]);
6606d6006b8SJean Delvare 	data->fan_div[nr] = tmp | (0x3f & data->fan_div[nr]);
6616d6006b8SJean Delvare 	new_min = data->fan_min[nr] * old_div / val;
6628d5d45fbSJean Delvare 	data->fan_min[nr] = new_min > 0xff ? 0xff : new_min;
6638d5d45fbSJean Delvare 
6648d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_FAN_DIV(nr),
6658d5d45fbSJean Delvare 			    data->fan_div[nr]);
6668d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr),
6678d5d45fbSJean Delvare 			    data->fan_min[nr]);
66838a1f0e9SJean Delvare 
66938a1f0e9SJean Delvare 	/* Invalidate the cache: fan speed is no longer valid */
67038a1f0e9SJean Delvare 	data->valid = 0;
6719a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
6728d5d45fbSJean Delvare 	return count;
6738d5d45fbSJean Delvare }
6748d5d45fbSJean Delvare 
6758d5d45fbSJean Delvare #define fan_offset(offset)						\
676c801082dSJean Delvare static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO,			\
677c801082dSJean Delvare 		show_fan, NULL, offset - 1);				\
678c801082dSJean Delvare static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,		\
679c801082dSJean Delvare 		show_fan_min, set_fan_min, offset - 1);			\
680c801082dSJean Delvare static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR,		\
681c801082dSJean Delvare 		show_fan_div, set_fan_div, offset - 1)
6828d5d45fbSJean Delvare 
6838d5d45fbSJean Delvare fan_offset(1);
6848d5d45fbSJean Delvare fan_offset(2);
6858d5d45fbSJean Delvare 
6868d5d45fbSJean Delvare 
6878d5d45fbSJean Delvare /* Temps */
688c801082dSJean Delvare static ssize_t show_temp(struct device *dev,
689c801082dSJean Delvare 			 struct device_attribute *attr, char *buf)
6908d5d45fbSJean Delvare {
691c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
6928d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
6938d5d45fbSJean Delvare 	int ext;
6948d5d45fbSJean Delvare 	ext = nr == 0 ?
6958d5d45fbSJean Delvare 	    ((data->ext_temp[nr] >> 6) & 0x3) * 2 :
6968d5d45fbSJean Delvare 	    (((data->ext_temp[nr] >> ((nr - 1) * 3)) & 7));
6978d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG_EXT(data->temp[nr], ext));
6988d5d45fbSJean Delvare }
69949dc9efeSIra Snyder static ssize_t show_temp_offset(struct device *dev,
70049dc9efeSIra Snyder 				struct device_attribute *attr, char *buf)
70149dc9efeSIra Snyder {
70249dc9efeSIra Snyder 	int nr = to_sensor_dev_attr(attr)->index;
70349dc9efeSIra Snyder 	struct adm1031_data *data = adm1031_update_device(dev);
70449dc9efeSIra Snyder 	return sprintf(buf, "%d\n",
70549dc9efeSIra Snyder 		       TEMP_OFFSET_FROM_REG(data->temp_offset[nr]));
70649dc9efeSIra Snyder }
707c801082dSJean Delvare static ssize_t show_temp_min(struct device *dev,
708c801082dSJean Delvare 			     struct device_attribute *attr, char *buf)
7098d5d45fbSJean Delvare {
710c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
7118d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
7128d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr]));
7138d5d45fbSJean Delvare }
714c801082dSJean Delvare static ssize_t show_temp_max(struct device *dev,
715c801082dSJean Delvare 			     struct device_attribute *attr, char *buf)
7168d5d45fbSJean Delvare {
717c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
7188d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
7198d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr]));
7208d5d45fbSJean Delvare }
721c801082dSJean Delvare static ssize_t show_temp_crit(struct device *dev,
722c801082dSJean Delvare 			      struct device_attribute *attr, char *buf)
7238d5d45fbSJean Delvare {
724c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
7258d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
7268d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[nr]));
7278d5d45fbSJean Delvare }
72849dc9efeSIra Snyder static ssize_t set_temp_offset(struct device *dev,
72949dc9efeSIra Snyder 			       struct device_attribute *attr, const char *buf,
73049dc9efeSIra Snyder 			       size_t count)
73149dc9efeSIra Snyder {
73249dc9efeSIra Snyder 	struct i2c_client *client = to_i2c_client(dev);
73349dc9efeSIra Snyder 	struct adm1031_data *data = i2c_get_clientdata(client);
73449dc9efeSIra Snyder 	int nr = to_sensor_dev_attr(attr)->index;
7351c720093SGuenter Roeck 	long val;
7361c720093SGuenter Roeck 	int ret;
73749dc9efeSIra Snyder 
7381c720093SGuenter Roeck 	ret = kstrtol(buf, 10, &val);
7391c720093SGuenter Roeck 	if (ret)
7401c720093SGuenter Roeck 		return ret;
7411c720093SGuenter Roeck 
7422a844c14SGuenter Roeck 	val = clamp_val(val, -15000, 15000);
74349dc9efeSIra Snyder 	mutex_lock(&data->update_lock);
74449dc9efeSIra Snyder 	data->temp_offset[nr] = TEMP_OFFSET_TO_REG(val);
74549dc9efeSIra Snyder 	adm1031_write_value(client, ADM1031_REG_TEMP_OFFSET(nr),
74649dc9efeSIra Snyder 			    data->temp_offset[nr]);
74749dc9efeSIra Snyder 	mutex_unlock(&data->update_lock);
74849dc9efeSIra Snyder 	return count;
74949dc9efeSIra Snyder }
750c801082dSJean Delvare static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
751c801082dSJean Delvare 			    const char *buf, size_t count)
7528d5d45fbSJean Delvare {
7538d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
7548d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(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_min[nr] = TEMP_TO_REG(val);
7668d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_TEMP_MIN(nr),
7678d5d45fbSJean Delvare 			    data->temp_min[nr]);
7689a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
7698d5d45fbSJean Delvare 	return count;
7708d5d45fbSJean Delvare }
771c801082dSJean Delvare static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
772c801082dSJean Delvare 			    const char *buf, size_t count)
7738d5d45fbSJean Delvare {
7748d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
7758d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
776c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
7771c720093SGuenter Roeck 	long val;
7781c720093SGuenter Roeck 	int ret;
7798d5d45fbSJean Delvare 
7801c720093SGuenter Roeck 	ret = kstrtol(buf, 10, &val);
7811c720093SGuenter Roeck 	if (ret)
7821c720093SGuenter Roeck 		return ret;
7831c720093SGuenter Roeck 
784145e74a4SGuenter Roeck 	val = clamp_val(val, -55000, 127000);
7859a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
7868d5d45fbSJean Delvare 	data->temp_max[nr] = TEMP_TO_REG(val);
7878d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_TEMP_MAX(nr),
7888d5d45fbSJean Delvare 			    data->temp_max[nr]);
7899a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
7908d5d45fbSJean Delvare 	return count;
7918d5d45fbSJean Delvare }
792c801082dSJean Delvare static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr,
793c801082dSJean Delvare 			     const char *buf, size_t count)
7948d5d45fbSJean Delvare {
7958d5d45fbSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
7968d5d45fbSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
797c801082dSJean Delvare 	int nr = to_sensor_dev_attr(attr)->index;
7981c720093SGuenter Roeck 	long val;
7991c720093SGuenter Roeck 	int ret;
8008d5d45fbSJean Delvare 
8011c720093SGuenter Roeck 	ret = kstrtol(buf, 10, &val);
8021c720093SGuenter Roeck 	if (ret)
8031c720093SGuenter Roeck 		return ret;
8041c720093SGuenter Roeck 
805145e74a4SGuenter Roeck 	val = clamp_val(val, -55000, 127000);
8069a61bf63SIngo Molnar 	mutex_lock(&data->update_lock);
8078d5d45fbSJean Delvare 	data->temp_crit[nr] = TEMP_TO_REG(val);
8088d5d45fbSJean Delvare 	adm1031_write_value(client, ADM1031_REG_TEMP_CRIT(nr),
8098d5d45fbSJean Delvare 			    data->temp_crit[nr]);
8109a61bf63SIngo Molnar 	mutex_unlock(&data->update_lock);
8118d5d45fbSJean Delvare 	return count;
8128d5d45fbSJean Delvare }
8138d5d45fbSJean Delvare 
8148d5d45fbSJean Delvare #define temp_reg(offset)						\
815c801082dSJean Delvare static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO,		\
816c801082dSJean Delvare 		show_temp, NULL, offset - 1);				\
81749dc9efeSIra Snyder static SENSOR_DEVICE_ATTR(temp##offset##_offset, S_IRUGO | S_IWUSR,	\
81849dc9efeSIra Snyder 		show_temp_offset, set_temp_offset, offset - 1);		\
819c801082dSJean Delvare static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR,	\
820c801082dSJean Delvare 		show_temp_min, set_temp_min, offset - 1);		\
821c801082dSJean Delvare static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR,	\
822c801082dSJean Delvare 		show_temp_max, set_temp_max, offset - 1);		\
823c801082dSJean Delvare static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IRUGO | S_IWUSR,	\
824c801082dSJean Delvare 		show_temp_crit, set_temp_crit, offset - 1)
8258d5d45fbSJean Delvare 
8268d5d45fbSJean Delvare temp_reg(1);
8278d5d45fbSJean Delvare temp_reg(2);
8288d5d45fbSJean Delvare temp_reg(3);
8298d5d45fbSJean Delvare 
8308d5d45fbSJean Delvare /* Alarms */
8311c720093SGuenter Roeck static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
8321c720093SGuenter Roeck 			   char *buf)
8338d5d45fbSJean Delvare {
8348d5d45fbSJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
8358d5d45fbSJean Delvare 	return sprintf(buf, "%d\n", data->alarm);
8368d5d45fbSJean Delvare }
8378d5d45fbSJean Delvare 
8388d5d45fbSJean Delvare static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
8398d5d45fbSJean Delvare 
840050ab878SJean Delvare static ssize_t show_alarm(struct device *dev,
841050ab878SJean Delvare 			  struct device_attribute *attr, char *buf)
842050ab878SJean Delvare {
843050ab878SJean Delvare 	int bitnr = to_sensor_dev_attr(attr)->index;
844050ab878SJean Delvare 	struct adm1031_data *data = adm1031_update_device(dev);
845050ab878SJean Delvare 	return sprintf(buf, "%d\n", (data->alarm >> bitnr) & 1);
846050ab878SJean Delvare }
847050ab878SJean Delvare 
848050ab878SJean Delvare static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 0);
849050ab878SJean Delvare static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_alarm, NULL, 1);
850050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 2);
851050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 3);
852050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 4);
853050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 5);
854050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6);
855050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 7);
856050ab878SJean Delvare static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 8);
857050ab878SJean Delvare static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_alarm, NULL, 9);
858050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL, 10);
859050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp3_min_alarm, S_IRUGO, show_alarm, NULL, 11);
860050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 12);
861050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 13);
862050ab878SJean Delvare static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 14);
8638d5d45fbSJean Delvare 
864a51b9944SGuenter Roeck /* Update Interval */
865a51b9944SGuenter Roeck static const unsigned int update_intervals[] = {
86687c33daaSJean Delvare 	16000, 8000, 4000, 2000, 1000, 500, 250, 125,
86787c33daaSJean Delvare };
86887c33daaSJean Delvare 
869a51b9944SGuenter Roeck static ssize_t show_update_interval(struct device *dev,
87087c33daaSJean Delvare 				    struct device_attribute *attr, char *buf)
87187c33daaSJean Delvare {
87287c33daaSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
87387c33daaSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
87487c33daaSJean Delvare 
875a51b9944SGuenter Roeck 	return sprintf(buf, "%u\n", data->update_interval);
87687c33daaSJean Delvare }
87787c33daaSJean Delvare 
878a51b9944SGuenter Roeck static ssize_t set_update_interval(struct device *dev,
87987c33daaSJean Delvare 				   struct device_attribute *attr,
88087c33daaSJean Delvare 				   const char *buf, size_t count)
88187c33daaSJean Delvare {
88287c33daaSJean Delvare 	struct i2c_client *client = to_i2c_client(dev);
88387c33daaSJean Delvare 	struct adm1031_data *data = i2c_get_clientdata(client);
88487c33daaSJean Delvare 	unsigned long val;
88587c33daaSJean Delvare 	int i, err;
88687c33daaSJean Delvare 	u8 reg;
88787c33daaSJean Delvare 
888179c4fdbSFrans Meulenbroeks 	err = kstrtoul(buf, 10, &val);
88987c33daaSJean Delvare 	if (err)
89087c33daaSJean Delvare 		return err;
89187c33daaSJean Delvare 
892a51b9944SGuenter Roeck 	/*
893a51b9944SGuenter Roeck 	 * Find the nearest update interval from the table.
894a51b9944SGuenter Roeck 	 * Use it to determine the matching update rate.
895a51b9944SGuenter Roeck 	 */
896a51b9944SGuenter Roeck 	for (i = 0; i < ARRAY_SIZE(update_intervals) - 1; i++) {
897a51b9944SGuenter Roeck 		if (val >= update_intervals[i])
89887c33daaSJean Delvare 			break;
89987c33daaSJean Delvare 	}
900a51b9944SGuenter Roeck 	/* if not found, we point to the last entry (lowest update interval) */
90187c33daaSJean Delvare 
90287c33daaSJean Delvare 	/* set the new update rate while preserving other settings */
90387c33daaSJean Delvare 	reg = adm1031_read_value(client, ADM1031_REG_FAN_FILTER);
90487c33daaSJean Delvare 	reg &= ~ADM1031_UPDATE_RATE_MASK;
90587c33daaSJean Delvare 	reg |= i << ADM1031_UPDATE_RATE_SHIFT;
90687c33daaSJean Delvare 	adm1031_write_value(client, ADM1031_REG_FAN_FILTER, reg);
90787c33daaSJean Delvare 
90887c33daaSJean Delvare 	mutex_lock(&data->update_lock);
909a51b9944SGuenter Roeck 	data->update_interval = update_intervals[i];
91087c33daaSJean Delvare 	mutex_unlock(&data->update_lock);
91187c33daaSJean Delvare 
91287c33daaSJean Delvare 	return count;
91387c33daaSJean Delvare }
91487c33daaSJean Delvare 
915a51b9944SGuenter Roeck static DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR, show_update_interval,
916a51b9944SGuenter Roeck 		   set_update_interval);
91787c33daaSJean Delvare 
918681c6f7aSMark M. Hoffman static struct attribute *adm1031_attributes[] = {
919c801082dSJean Delvare 	&sensor_dev_attr_fan1_input.dev_attr.attr,
920c801082dSJean Delvare 	&sensor_dev_attr_fan1_div.dev_attr.attr,
921c801082dSJean Delvare 	&sensor_dev_attr_fan1_min.dev_attr.attr,
922050ab878SJean Delvare 	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
923050ab878SJean Delvare 	&sensor_dev_attr_fan1_fault.dev_attr.attr,
924c801082dSJean Delvare 	&sensor_dev_attr_pwm1.dev_attr.attr,
925c801082dSJean Delvare 	&sensor_dev_attr_auto_fan1_channel.dev_attr.attr,
926c801082dSJean Delvare 	&sensor_dev_attr_temp1_input.dev_attr.attr,
92749dc9efeSIra Snyder 	&sensor_dev_attr_temp1_offset.dev_attr.attr,
928c801082dSJean Delvare 	&sensor_dev_attr_temp1_min.dev_attr.attr,
929050ab878SJean Delvare 	&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
930c801082dSJean Delvare 	&sensor_dev_attr_temp1_max.dev_attr.attr,
931050ab878SJean Delvare 	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
932c801082dSJean Delvare 	&sensor_dev_attr_temp1_crit.dev_attr.attr,
933050ab878SJean Delvare 	&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
934c801082dSJean Delvare 	&sensor_dev_attr_temp2_input.dev_attr.attr,
93549dc9efeSIra Snyder 	&sensor_dev_attr_temp2_offset.dev_attr.attr,
936c801082dSJean Delvare 	&sensor_dev_attr_temp2_min.dev_attr.attr,
937050ab878SJean Delvare 	&sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
938c801082dSJean Delvare 	&sensor_dev_attr_temp2_max.dev_attr.attr,
939050ab878SJean Delvare 	&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
940c801082dSJean Delvare 	&sensor_dev_attr_temp2_crit.dev_attr.attr,
941050ab878SJean Delvare 	&sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
942050ab878SJean Delvare 	&sensor_dev_attr_temp2_fault.dev_attr.attr,
943681c6f7aSMark M. Hoffman 
944c801082dSJean Delvare 	&sensor_dev_attr_auto_temp1_off.dev_attr.attr,
945c801082dSJean Delvare 	&sensor_dev_attr_auto_temp1_min.dev_attr.attr,
946c801082dSJean Delvare 	&sensor_dev_attr_auto_temp1_max.dev_attr.attr,
947681c6f7aSMark M. Hoffman 
948c801082dSJean Delvare 	&sensor_dev_attr_auto_temp2_off.dev_attr.attr,
949c801082dSJean Delvare 	&sensor_dev_attr_auto_temp2_min.dev_attr.attr,
950c801082dSJean Delvare 	&sensor_dev_attr_auto_temp2_max.dev_attr.attr,
951681c6f7aSMark M. Hoffman 
952c801082dSJean Delvare 	&sensor_dev_attr_auto_fan1_min_pwm.dev_attr.attr,
953681c6f7aSMark M. Hoffman 
954a51b9944SGuenter Roeck 	&dev_attr_update_interval.attr,
955681c6f7aSMark M. Hoffman 	&dev_attr_alarms.attr,
956681c6f7aSMark M. Hoffman 
957681c6f7aSMark M. Hoffman 	NULL
958681c6f7aSMark M. Hoffman };
959681c6f7aSMark M. Hoffman 
960681c6f7aSMark M. Hoffman static const struct attribute_group adm1031_group = {
961681c6f7aSMark M. Hoffman 	.attrs = adm1031_attributes,
962681c6f7aSMark M. Hoffman };
963681c6f7aSMark M. Hoffman 
964681c6f7aSMark M. Hoffman static struct attribute *adm1031_attributes_opt[] = {
965c801082dSJean Delvare 	&sensor_dev_attr_fan2_input.dev_attr.attr,
966c801082dSJean Delvare 	&sensor_dev_attr_fan2_div.dev_attr.attr,
967c801082dSJean Delvare 	&sensor_dev_attr_fan2_min.dev_attr.attr,
968050ab878SJean Delvare 	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
969050ab878SJean Delvare 	&sensor_dev_attr_fan2_fault.dev_attr.attr,
970c801082dSJean Delvare 	&sensor_dev_attr_pwm2.dev_attr.attr,
971c801082dSJean Delvare 	&sensor_dev_attr_auto_fan2_channel.dev_attr.attr,
972c801082dSJean Delvare 	&sensor_dev_attr_temp3_input.dev_attr.attr,
97349dc9efeSIra Snyder 	&sensor_dev_attr_temp3_offset.dev_attr.attr,
974c801082dSJean Delvare 	&sensor_dev_attr_temp3_min.dev_attr.attr,
975050ab878SJean Delvare 	&sensor_dev_attr_temp3_min_alarm.dev_attr.attr,
976c801082dSJean Delvare 	&sensor_dev_attr_temp3_max.dev_attr.attr,
977050ab878SJean Delvare 	&sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
978c801082dSJean Delvare 	&sensor_dev_attr_temp3_crit.dev_attr.attr,
979050ab878SJean Delvare 	&sensor_dev_attr_temp3_crit_alarm.dev_attr.attr,
980050ab878SJean Delvare 	&sensor_dev_attr_temp3_fault.dev_attr.attr,
981c801082dSJean Delvare 	&sensor_dev_attr_auto_temp3_off.dev_attr.attr,
982c801082dSJean Delvare 	&sensor_dev_attr_auto_temp3_min.dev_attr.attr,
983c801082dSJean Delvare 	&sensor_dev_attr_auto_temp3_max.dev_attr.attr,
984c801082dSJean Delvare 	&sensor_dev_attr_auto_fan2_min_pwm.dev_attr.attr,
985681c6f7aSMark M. Hoffman 	NULL
986681c6f7aSMark M. Hoffman };
987681c6f7aSMark M. Hoffman 
988681c6f7aSMark M. Hoffman static const struct attribute_group adm1031_group_opt = {
989681c6f7aSMark M. Hoffman 	.attrs = adm1031_attributes_opt,
990681c6f7aSMark M. Hoffman };
991681c6f7aSMark M. Hoffman 
992af200f88SJean Delvare /* Return 0 if detection is successful, -ENODEV otherwise */
993310ec792SJean Delvare static int adm1031_detect(struct i2c_client *client,
994af200f88SJean Delvare 			  struct i2c_board_info *info)
9958d5d45fbSJean Delvare {
996af200f88SJean Delvare 	struct i2c_adapter *adapter = client->adapter;
99752df6440SJean Delvare 	const char *name;
99852df6440SJean Delvare 	int id, co;
9998d5d45fbSJean Delvare 
10008d5d45fbSJean Delvare 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
1001af200f88SJean Delvare 		return -ENODEV;
10028d5d45fbSJean Delvare 
10036d6006b8SJean Delvare 	id = i2c_smbus_read_byte_data(client, 0x3d);
10046d6006b8SJean Delvare 	co = i2c_smbus_read_byte_data(client, 0x3e);
10058d5d45fbSJean Delvare 
10068d5d45fbSJean Delvare 	if (!((id == 0x31 || id == 0x30) && co == 0x41))
1007af200f88SJean Delvare 		return -ENODEV;
100852df6440SJean Delvare 	name = (id == 0x30) ? "adm1030" : "adm1031";
10098d5d45fbSJean Delvare 
1010af200f88SJean Delvare 	strlcpy(info->type, name, I2C_NAME_SIZE);
10118d5d45fbSJean Delvare 
1012af200f88SJean Delvare 	return 0;
1013af200f88SJean Delvare }
1014af200f88SJean Delvare 
1015*278ee1c8SAxel Lin static void adm1031_init_client(struct i2c_client *client)
1016*278ee1c8SAxel Lin {
1017*278ee1c8SAxel Lin 	unsigned int read_val;
1018*278ee1c8SAxel Lin 	unsigned int mask;
1019*278ee1c8SAxel Lin 	int i;
1020*278ee1c8SAxel Lin 	struct adm1031_data *data = i2c_get_clientdata(client);
1021*278ee1c8SAxel Lin 
1022*278ee1c8SAxel Lin 	mask = (ADM1031_CONF2_PWM1_ENABLE | ADM1031_CONF2_TACH1_ENABLE);
1023*278ee1c8SAxel Lin 	if (data->chip_type == adm1031) {
1024*278ee1c8SAxel Lin 		mask |= (ADM1031_CONF2_PWM2_ENABLE |
1025*278ee1c8SAxel Lin 			ADM1031_CONF2_TACH2_ENABLE);
1026*278ee1c8SAxel Lin 	}
1027*278ee1c8SAxel Lin 	/* Initialize the ADM1031 chip (enables fan speed reading ) */
1028*278ee1c8SAxel Lin 	read_val = adm1031_read_value(client, ADM1031_REG_CONF2);
1029*278ee1c8SAxel Lin 	if ((read_val | mask) != read_val)
1030*278ee1c8SAxel Lin 		adm1031_write_value(client, ADM1031_REG_CONF2, read_val | mask);
1031*278ee1c8SAxel Lin 
1032*278ee1c8SAxel Lin 	read_val = adm1031_read_value(client, ADM1031_REG_CONF1);
1033*278ee1c8SAxel Lin 	if ((read_val | ADM1031_CONF1_MONITOR_ENABLE) != read_val) {
1034*278ee1c8SAxel Lin 		adm1031_write_value(client, ADM1031_REG_CONF1,
1035*278ee1c8SAxel Lin 				    read_val | ADM1031_CONF1_MONITOR_ENABLE);
1036*278ee1c8SAxel Lin 	}
1037*278ee1c8SAxel Lin 
1038*278ee1c8SAxel Lin 	/* Read the chip's update rate */
1039*278ee1c8SAxel Lin 	mask = ADM1031_UPDATE_RATE_MASK;
1040*278ee1c8SAxel Lin 	read_val = adm1031_read_value(client, ADM1031_REG_FAN_FILTER);
1041*278ee1c8SAxel Lin 	i = (read_val & mask) >> ADM1031_UPDATE_RATE_SHIFT;
1042*278ee1c8SAxel Lin 	/* Save it as update interval */
1043*278ee1c8SAxel Lin 	data->update_interval = update_intervals[i];
1044*278ee1c8SAxel Lin }
1045*278ee1c8SAxel Lin 
1046af200f88SJean Delvare static int adm1031_probe(struct i2c_client *client,
1047af200f88SJean Delvare 			 const struct i2c_device_id *id)
1048af200f88SJean Delvare {
1049af200f88SJean Delvare 	struct adm1031_data *data;
1050af200f88SJean Delvare 	int err;
1051af200f88SJean Delvare 
1052dc2fd663SGuenter Roeck 	data = devm_kzalloc(&client->dev, sizeof(struct adm1031_data),
1053dc2fd663SGuenter Roeck 			    GFP_KERNEL);
1054dc2fd663SGuenter Roeck 	if (!data)
1055dc2fd663SGuenter Roeck 		return -ENOMEM;
1056af200f88SJean Delvare 
1057af200f88SJean Delvare 	i2c_set_clientdata(client, data);
1058af200f88SJean Delvare 	data->chip_type = id->driver_data;
10599a61bf63SIngo Molnar 	mutex_init(&data->update_lock);
10608d5d45fbSJean Delvare 
1061af200f88SJean Delvare 	if (data->chip_type == adm1030)
1062af200f88SJean Delvare 		data->chan_select_table = &auto_channel_select_table_adm1030;
1063af200f88SJean Delvare 	else
1064af200f88SJean Delvare 		data->chan_select_table = &auto_channel_select_table_adm1031;
10658d5d45fbSJean Delvare 
10668d5d45fbSJean Delvare 	/* Initialize the ADM1031 chip */
10676d6006b8SJean Delvare 	adm1031_init_client(client);
10688d5d45fbSJean Delvare 
10698d5d45fbSJean Delvare 	/* Register sysfs hooks */
10701c720093SGuenter Roeck 	err = sysfs_create_group(&client->dev.kobj, &adm1031_group);
10711c720093SGuenter Roeck 	if (err)
1072dc2fd663SGuenter Roeck 		return err;
1073681c6f7aSMark M. Hoffman 
1074af200f88SJean Delvare 	if (data->chip_type == adm1031) {
10751c720093SGuenter Roeck 		err = sysfs_create_group(&client->dev.kobj, &adm1031_group_opt);
10761c720093SGuenter Roeck 		if (err)
1077681c6f7aSMark M. Hoffman 			goto exit_remove;
1078681c6f7aSMark M. Hoffman 	}
1079681c6f7aSMark M. Hoffman 
10806d6006b8SJean Delvare 	data->hwmon_dev = hwmon_device_register(&client->dev);
10811beeffe4STony Jones 	if (IS_ERR(data->hwmon_dev)) {
10821beeffe4STony Jones 		err = PTR_ERR(data->hwmon_dev);
1083681c6f7aSMark M. Hoffman 		goto exit_remove;
10848d5d45fbSJean Delvare 	}
10858d5d45fbSJean Delvare 
10868d5d45fbSJean Delvare 	return 0;
10878d5d45fbSJean Delvare 
1088681c6f7aSMark M. Hoffman exit_remove:
10896d6006b8SJean Delvare 	sysfs_remove_group(&client->dev.kobj, &adm1031_group);
10906d6006b8SJean Delvare 	sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt);
10918d5d45fbSJean Delvare 	return err;
10928d5d45fbSJean Delvare }
10938d5d45fbSJean Delvare 
1094af200f88SJean Delvare static int adm1031_remove(struct i2c_client *client)
10958d5d45fbSJean Delvare {
1096943b0830SMark M. Hoffman 	struct adm1031_data *data = i2c_get_clientdata(client);
1097943b0830SMark M. Hoffman 
10981beeffe4STony Jones 	hwmon_device_unregister(data->hwmon_dev);
1099681c6f7aSMark M. Hoffman 	sysfs_remove_group(&client->dev.kobj, &adm1031_group);
1100681c6f7aSMark M. Hoffman 	sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt);
11018d5d45fbSJean Delvare 	return 0;
11028d5d45fbSJean Delvare }
11038d5d45fbSJean Delvare 
1104*278ee1c8SAxel Lin static const struct i2c_device_id adm1031_id[] = {
1105*278ee1c8SAxel Lin 	{ "adm1030", adm1030 },
1106*278ee1c8SAxel Lin 	{ "adm1031", adm1031 },
1107*278ee1c8SAxel Lin 	{ }
1108*278ee1c8SAxel Lin };
1109*278ee1c8SAxel Lin MODULE_DEVICE_TABLE(i2c, adm1031_id);
11108d5d45fbSJean Delvare 
1111*278ee1c8SAxel Lin static struct i2c_driver adm1031_driver = {
1112*278ee1c8SAxel Lin 	.class		= I2C_CLASS_HWMON,
1113*278ee1c8SAxel Lin 	.driver = {
1114*278ee1c8SAxel Lin 		.name = "adm1031",
1115*278ee1c8SAxel Lin 	},
1116*278ee1c8SAxel Lin 	.probe		= adm1031_probe,
1117*278ee1c8SAxel Lin 	.remove		= adm1031_remove,
1118*278ee1c8SAxel Lin 	.id_table	= adm1031_id,
1119*278ee1c8SAxel Lin 	.detect		= adm1031_detect,
1120*278ee1c8SAxel Lin 	.address_list	= normal_i2c,
1121*278ee1c8SAxel Lin };
11228d5d45fbSJean Delvare 
1123f0967eeaSAxel Lin module_i2c_driver(adm1031_driver);
11248d5d45fbSJean Delvare 
11258d5d45fbSJean Delvare MODULE_AUTHOR("Alexandre d'Alton <alex@alexdalton.org>");
11268d5d45fbSJean Delvare MODULE_DESCRIPTION("ADM1031/ADM1030 driver");
11278d5d45fbSJean Delvare MODULE_LICENSE("GPL");
1128