xref: /linux/drivers/hwmon/adt7462.c (revision 0880830096ee314c953d4bd5d017e27589f0e830)
1c0b4e3abSDarrick J. Wong /*
2c0b4e3abSDarrick J. Wong  * A hwmon driver for the Analog Devices ADT7462
3c0b4e3abSDarrick J. Wong  * Copyright (C) 2008 IBM
4c0b4e3abSDarrick J. Wong  *
5c0b4e3abSDarrick J. Wong  * Author: Darrick J. Wong <djwong@us.ibm.com>
6c0b4e3abSDarrick J. Wong  *
7c0b4e3abSDarrick J. Wong  * This program is free software; you can redistribute it and/or modify
8c0b4e3abSDarrick J. Wong  * it under the terms of the GNU General Public License as published by
9c0b4e3abSDarrick J. Wong  * the Free Software Foundation; either version 2 of the License, or
10c0b4e3abSDarrick J. Wong  * (at your option) any later version.
11c0b4e3abSDarrick J. Wong  *
12c0b4e3abSDarrick J. Wong  * This program is distributed in the hope that it will be useful,
13c0b4e3abSDarrick J. Wong  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14c0b4e3abSDarrick J. Wong  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15c0b4e3abSDarrick J. Wong  * GNU General Public License for more details.
16c0b4e3abSDarrick J. Wong  *
17c0b4e3abSDarrick J. Wong  * You should have received a copy of the GNU General Public License
18c0b4e3abSDarrick J. Wong  * along with this program; if not, write to the Free Software
19c0b4e3abSDarrick J. Wong  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20c0b4e3abSDarrick J. Wong  */
21c0b4e3abSDarrick J. Wong 
22c0b4e3abSDarrick J. Wong #include <linux/module.h>
23c0b4e3abSDarrick J. Wong #include <linux/jiffies.h>
24c0b4e3abSDarrick J. Wong #include <linux/i2c.h>
25c0b4e3abSDarrick J. Wong #include <linux/hwmon.h>
26c0b4e3abSDarrick J. Wong #include <linux/hwmon-sysfs.h>
27c0b4e3abSDarrick J. Wong #include <linux/err.h>
28c0b4e3abSDarrick J. Wong #include <linux/mutex.h>
29c0b4e3abSDarrick J. Wong #include <linux/delay.h>
30c0b4e3abSDarrick J. Wong #include <linux/log2.h>
315a0e3ad6STejun Heo #include <linux/slab.h>
32c0b4e3abSDarrick J. Wong 
33c0b4e3abSDarrick J. Wong /* Addresses to scan */
34c0b4e3abSDarrick J. Wong static const unsigned short normal_i2c[] = { 0x58, 0x5C, I2C_CLIENT_END };
35c0b4e3abSDarrick J. Wong 
36c0b4e3abSDarrick J. Wong /* ADT7462 registers */
37c0b4e3abSDarrick J. Wong #define ADT7462_REG_DEVICE			0x3D
38c0b4e3abSDarrick J. Wong #define ADT7462_REG_VENDOR			0x3E
39c0b4e3abSDarrick J. Wong #define ADT7462_REG_REVISION			0x3F
40c0b4e3abSDarrick J. Wong 
41c0b4e3abSDarrick J. Wong #define ADT7462_REG_MIN_TEMP_BASE_ADDR		0x44
42c0b4e3abSDarrick J. Wong #define ADT7462_REG_MIN_TEMP_MAX_ADDR		0x47
43c0b4e3abSDarrick J. Wong #define ADT7462_REG_MAX_TEMP_BASE_ADDR		0x48
44c0b4e3abSDarrick J. Wong #define ADT7462_REG_MAX_TEMP_MAX_ADDR		0x4B
45c0b4e3abSDarrick J. Wong #define ADT7462_REG_TEMP_BASE_ADDR		0x88
46c0b4e3abSDarrick J. Wong #define ADT7462_REG_TEMP_MAX_ADDR		0x8F
47c0b4e3abSDarrick J. Wong 
48c0b4e3abSDarrick J. Wong #define ADT7462_REG_FAN_BASE_ADDR		0x98
49c0b4e3abSDarrick J. Wong #define ADT7462_REG_FAN_MAX_ADDR		0x9F
50c0b4e3abSDarrick J. Wong #define ADT7462_REG_FAN2_BASE_ADDR		0xA2
51c0b4e3abSDarrick J. Wong #define ADT7462_REG_FAN2_MAX_ADDR		0xA9
52c0b4e3abSDarrick J. Wong #define ADT7462_REG_FAN_ENABLE			0x07
53c0b4e3abSDarrick J. Wong #define ADT7462_REG_FAN_MIN_BASE_ADDR		0x78
54c0b4e3abSDarrick J. Wong #define ADT7462_REG_FAN_MIN_MAX_ADDR		0x7F
55c0b4e3abSDarrick J. Wong 
56c0b4e3abSDarrick J. Wong #define ADT7462_REG_CFG2			0x02
57c0b4e3abSDarrick J. Wong #define		ADT7462_FSPD_MASK		0x20
58c0b4e3abSDarrick J. Wong 
59c0b4e3abSDarrick J. Wong #define ADT7462_REG_PWM_BASE_ADDR		0xAA
60c0b4e3abSDarrick J. Wong #define ADT7462_REG_PWM_MAX_ADDR		0xAD
61c0b4e3abSDarrick J. Wong #define	ADT7462_REG_PWM_MIN_BASE_ADDR		0x28
62c0b4e3abSDarrick J. Wong #define ADT7462_REG_PWM_MIN_MAX_ADDR		0x2B
63c0b4e3abSDarrick J. Wong #define ADT7462_REG_PWM_MAX			0x2C
64c0b4e3abSDarrick J. Wong #define ADT7462_REG_PWM_TEMP_MIN_BASE_ADDR	0x5C
65c0b4e3abSDarrick J. Wong #define ADT7462_REG_PWM_TEMP_MIN_MAX_ADDR	0x5F
66c0b4e3abSDarrick J. Wong #define ADT7462_REG_PWM_TEMP_RANGE_BASE_ADDR	0x60
67c0b4e3abSDarrick J. Wong #define ADT7462_REG_PWM_TEMP_RANGE_MAX_ADDR	0x63
68c0b4e3abSDarrick J. Wong #define	ADT7462_PWM_HYST_MASK			0x0F
69c0b4e3abSDarrick J. Wong #define	ADT7462_PWM_RANGE_MASK			0xF0
70c0b4e3abSDarrick J. Wong #define		ADT7462_PWM_RANGE_SHIFT		4
71c0b4e3abSDarrick J. Wong #define ADT7462_REG_PWM_CFG_BASE_ADDR		0x21
72c0b4e3abSDarrick J. Wong #define ADT7462_REG_PWM_CFG_MAX_ADDR		0x24
73c0b4e3abSDarrick J. Wong #define		ADT7462_PWM_CHANNEL_MASK	0xE0
74c0b4e3abSDarrick J. Wong #define		ADT7462_PWM_CHANNEL_SHIFT	5
75c0b4e3abSDarrick J. Wong 
76c0b4e3abSDarrick J. Wong #define ADT7462_REG_PIN_CFG_BASE_ADDR		0x10
77c0b4e3abSDarrick J. Wong #define ADT7462_REG_PIN_CFG_MAX_ADDR		0x13
78c0b4e3abSDarrick J. Wong #define		ADT7462_PIN7_INPUT		0x01	/* cfg0 */
79c0b4e3abSDarrick J. Wong #define		ADT7462_DIODE3_INPUT		0x20
80c0b4e3abSDarrick J. Wong #define		ADT7462_DIODE1_INPUT		0x40
81c0b4e3abSDarrick J. Wong #define		ADT7462_VID_INPUT		0x80
82c0b4e3abSDarrick J. Wong #define		ADT7462_PIN22_INPUT		0x04	/* cfg1 */
83c0b4e3abSDarrick J. Wong #define		ADT7462_PIN21_INPUT		0x08
84c0b4e3abSDarrick J. Wong #define		ADT7462_PIN19_INPUT		0x10
85c0b4e3abSDarrick J. Wong #define		ADT7462_PIN15_INPUT		0x20
86c0b4e3abSDarrick J. Wong #define		ADT7462_PIN13_INPUT		0x40
87c0b4e3abSDarrick J. Wong #define		ADT7462_PIN8_INPUT		0x80
88c0b4e3abSDarrick J. Wong #define		ADT7462_PIN23_MASK		0x03
89c0b4e3abSDarrick J. Wong #define		ADT7462_PIN23_SHIFT		0
90c0b4e3abSDarrick J. Wong #define		ADT7462_PIN26_MASK		0x0C	/* cfg2 */
91c0b4e3abSDarrick J. Wong #define		ADT7462_PIN26_SHIFT		2
92c0b4e3abSDarrick J. Wong #define		ADT7462_PIN25_MASK		0x30
93c0b4e3abSDarrick J. Wong #define		ADT7462_PIN25_SHIFT		4
94c0b4e3abSDarrick J. Wong #define		ADT7462_PIN24_MASK		0xC0
95c0b4e3abSDarrick J. Wong #define		ADT7462_PIN24_SHIFT		6
96c0b4e3abSDarrick J. Wong #define		ADT7462_PIN26_VOLT_INPUT	0x08
97c0b4e3abSDarrick J. Wong #define		ADT7462_PIN25_VOLT_INPUT	0x20
98bb595c92SRoger Blofeld #define		ADT7462_PIN28_SHIFT		4	/* cfg3 */
99c0b4e3abSDarrick J. Wong #define		ADT7462_PIN28_VOLT		0x5
100c0b4e3abSDarrick J. Wong 
101c0b4e3abSDarrick J. Wong #define ADT7462_REG_ALARM1			0xB8
102c0b4e3abSDarrick J. Wong #define	ADT7462_LT_ALARM			0x02
103c0b4e3abSDarrick J. Wong #define		ADT7462_R1T_ALARM		0x04
104c0b4e3abSDarrick J. Wong #define		ADT7462_R2T_ALARM		0x08
105c0b4e3abSDarrick J. Wong #define		ADT7462_R3T_ALARM		0x10
106c0b4e3abSDarrick J. Wong #define ADT7462_REG_ALARM2			0xBB
107c0b4e3abSDarrick J. Wong #define		ADT7462_V0_ALARM		0x01
108c0b4e3abSDarrick J. Wong #define		ADT7462_V1_ALARM		0x02
109c0b4e3abSDarrick J. Wong #define		ADT7462_V2_ALARM		0x04
110c0b4e3abSDarrick J. Wong #define		ADT7462_V3_ALARM		0x08
111c0b4e3abSDarrick J. Wong #define		ADT7462_V4_ALARM		0x10
112c0b4e3abSDarrick J. Wong #define		ADT7462_V5_ALARM		0x20
113c0b4e3abSDarrick J. Wong #define		ADT7462_V6_ALARM		0x40
114c0b4e3abSDarrick J. Wong #define		ADT7462_V7_ALARM		0x80
115c0b4e3abSDarrick J. Wong #define ADT7462_REG_ALARM3			0xBC
116c0b4e3abSDarrick J. Wong #define		ADT7462_V8_ALARM		0x08
117c0b4e3abSDarrick J. Wong #define		ADT7462_V9_ALARM		0x10
118c0b4e3abSDarrick J. Wong #define		ADT7462_V10_ALARM		0x20
119c0b4e3abSDarrick J. Wong #define		ADT7462_V11_ALARM		0x40
120c0b4e3abSDarrick J. Wong #define		ADT7462_V12_ALARM		0x80
121c0b4e3abSDarrick J. Wong #define ADT7462_REG_ALARM4			0xBD
122c0b4e3abSDarrick J. Wong #define		ADT7462_F0_ALARM		0x01
123c0b4e3abSDarrick J. Wong #define		ADT7462_F1_ALARM		0x02
124c0b4e3abSDarrick J. Wong #define		ADT7462_F2_ALARM		0x04
125c0b4e3abSDarrick J. Wong #define		ADT7462_F3_ALARM		0x08
126c0b4e3abSDarrick J. Wong #define		ADT7462_F4_ALARM		0x10
127c0b4e3abSDarrick J. Wong #define		ADT7462_F5_ALARM		0x20
128c0b4e3abSDarrick J. Wong #define		ADT7462_F6_ALARM		0x40
129c0b4e3abSDarrick J. Wong #define		ADT7462_F7_ALARM		0x80
130c0b4e3abSDarrick J. Wong #define ADT7462_ALARM1				0x0000
131c0b4e3abSDarrick J. Wong #define ADT7462_ALARM2				0x0100
132c0b4e3abSDarrick J. Wong #define ADT7462_ALARM3				0x0200
133c0b4e3abSDarrick J. Wong #define ADT7462_ALARM4				0x0300
134c0b4e3abSDarrick J. Wong #define ADT7462_ALARM_REG_SHIFT			8
135c0b4e3abSDarrick J. Wong #define ADT7462_ALARM_FLAG_MASK			0x0F
136c0b4e3abSDarrick J. Wong 
137c0b4e3abSDarrick J. Wong #define ADT7462_TEMP_COUNT		4
138724cc331SGuenter Roeck #define ADT7462_TEMP_REG(x)		(ADT7462_REG_TEMP_BASE_ADDR + ((x) * 2))
139c0b4e3abSDarrick J. Wong #define ADT7462_TEMP_MIN_REG(x)		(ADT7462_REG_MIN_TEMP_BASE_ADDR + (x))
140c0b4e3abSDarrick J. Wong #define ADT7462_TEMP_MAX_REG(x)		(ADT7462_REG_MAX_TEMP_BASE_ADDR + (x))
141c0b4e3abSDarrick J. Wong #define TEMP_FRAC_OFFSET		6
142c0b4e3abSDarrick J. Wong 
143c0b4e3abSDarrick J. Wong #define ADT7462_FAN_COUNT		8
144c0b4e3abSDarrick J. Wong #define ADT7462_REG_FAN_MIN(x)		(ADT7462_REG_FAN_MIN_BASE_ADDR + (x))
145c0b4e3abSDarrick J. Wong 
146c0b4e3abSDarrick J. Wong #define ADT7462_PWM_COUNT		4
147c0b4e3abSDarrick J. Wong #define ADT7462_REG_PWM(x)		(ADT7462_REG_PWM_BASE_ADDR + (x))
148c0b4e3abSDarrick J. Wong #define ADT7462_REG_PWM_MIN(x)		(ADT7462_REG_PWM_MIN_BASE_ADDR + (x))
149c0b4e3abSDarrick J. Wong #define ADT7462_REG_PWM_TMIN(x)		\
150c0b4e3abSDarrick J. Wong 	(ADT7462_REG_PWM_TEMP_MIN_BASE_ADDR + (x))
151c0b4e3abSDarrick J. Wong #define ADT7462_REG_PWM_TRANGE(x)	\
152c0b4e3abSDarrick J. Wong 	(ADT7462_REG_PWM_TEMP_RANGE_BASE_ADDR + (x))
153c0b4e3abSDarrick J. Wong 
154c0b4e3abSDarrick J. Wong #define ADT7462_PIN_CFG_REG_COUNT	4
155c0b4e3abSDarrick J. Wong #define ADT7462_REG_PIN_CFG(x)		(ADT7462_REG_PIN_CFG_BASE_ADDR + (x))
156c0b4e3abSDarrick J. Wong #define ADT7462_REG_PWM_CFG(x)		(ADT7462_REG_PWM_CFG_BASE_ADDR + (x))
157c0b4e3abSDarrick J. Wong 
158c0b4e3abSDarrick J. Wong #define ADT7462_ALARM_REG_COUNT		4
159c0b4e3abSDarrick J. Wong 
160c0b4e3abSDarrick J. Wong /*
161c0b4e3abSDarrick J. Wong  * The chip can measure 13 different voltage sources:
162c0b4e3abSDarrick J. Wong  *
163c0b4e3abSDarrick J. Wong  * 1. +12V1 (pin 7)
164c0b4e3abSDarrick J. Wong  * 2. Vccp1/+2.5V/+1.8V/+1.5V (pin 23)
165c0b4e3abSDarrick J. Wong  * 3. +12V3 (pin 22)
166c0b4e3abSDarrick J. Wong  * 4. +5V (pin 21)
167c0b4e3abSDarrick J. Wong  * 5. +1.25V/+0.9V (pin 19)
168c0b4e3abSDarrick J. Wong  * 6. +2.5V/+1.8V (pin 15)
169c0b4e3abSDarrick J. Wong  * 7. +3.3v (pin 13)
170c0b4e3abSDarrick J. Wong  * 8. +12V2 (pin 8)
171c0b4e3abSDarrick J. Wong  * 9. Vbatt/FSB_Vtt (pin 26)
172c0b4e3abSDarrick J. Wong  * A. +3.3V/+1.2V1 (pin 25)
173c0b4e3abSDarrick J. Wong  * B. Vccp2/+2.5V/+1.8V/+1.5V (pin 24)
174c0b4e3abSDarrick J. Wong  * C. +1.5V ICH (only if BOTH pin 28/29 are set to +1.5V)
175c0b4e3abSDarrick J. Wong  * D. +1.5V 3GPIO (only if BOTH pin 28/29 are set to +1.5V)
176c0b4e3abSDarrick J. Wong  *
177c0b4e3abSDarrick J. Wong  * Each of these 13 has a factor to convert raw to voltage.  Even better,
178c0b4e3abSDarrick J. Wong  * the pins can be connected to other sensors (tach/gpio/hot/etc), which
179c0b4e3abSDarrick J. Wong  * makes the bookkeeping tricky.
180c0b4e3abSDarrick J. Wong  *
181c0b4e3abSDarrick J. Wong  * Some, but not all, of these voltages have low/high limits.
182c0b4e3abSDarrick J. Wong  */
18385f8d3e5SRay Copeland #define ADT7462_VOLT_COUNT	13
184c0b4e3abSDarrick J. Wong 
185c0b4e3abSDarrick J. Wong #define ADT7462_VENDOR		0x41
186c0b4e3abSDarrick J. Wong #define ADT7462_DEVICE		0x62
187c0b4e3abSDarrick J. Wong /* datasheet only mentions a revision 4 */
188c0b4e3abSDarrick J. Wong #define ADT7462_REVISION	0x04
189c0b4e3abSDarrick J. Wong 
190c0b4e3abSDarrick J. Wong /* How often do we reread sensors values? (In jiffies) */
191c0b4e3abSDarrick J. Wong #define SENSOR_REFRESH_INTERVAL	(2 * HZ)
192c0b4e3abSDarrick J. Wong 
193c0b4e3abSDarrick J. Wong /* How often do we reread sensor limit values? (In jiffies) */
194c0b4e3abSDarrick J. Wong #define LIMIT_REFRESH_INTERVAL	(60 * HZ)
195c0b4e3abSDarrick J. Wong 
196c0b4e3abSDarrick J. Wong /* datasheet says to divide this number by the fan reading to get fan rpm */
197c0b4e3abSDarrick J. Wong #define FAN_PERIOD_TO_RPM(x)	((90000 * 60) / (x))
198c0b4e3abSDarrick J. Wong #define FAN_RPM_TO_PERIOD	FAN_PERIOD_TO_RPM
199c0b4e3abSDarrick J. Wong #define FAN_PERIOD_INVALID	65535
200c0b4e3abSDarrick J. Wong #define FAN_DATA_VALID(x)	((x) && (x) != FAN_PERIOD_INVALID)
201c0b4e3abSDarrick J. Wong 
202c0b4e3abSDarrick J. Wong #define MASK_AND_SHIFT(value, prefix)	\
203c0b4e3abSDarrick J. Wong 	(((value) & prefix##_MASK) >> prefix##_SHIFT)
204c0b4e3abSDarrick J. Wong 
205c0b4e3abSDarrick J. Wong struct adt7462_data {
206c0b4e3abSDarrick J. Wong 	struct device		*hwmon_dev;
207c0b4e3abSDarrick J. Wong 	struct attribute_group	attrs;
208c0b4e3abSDarrick J. Wong 	struct mutex		lock;
209c0b4e3abSDarrick J. Wong 	char			sensors_valid;
210c0b4e3abSDarrick J. Wong 	char			limits_valid;
211c0b4e3abSDarrick J. Wong 	unsigned long		sensors_last_updated;	/* In jiffies */
212c0b4e3abSDarrick J. Wong 	unsigned long		limits_last_updated;	/* In jiffies */
213c0b4e3abSDarrick J. Wong 
214c0b4e3abSDarrick J. Wong 	u8			temp[ADT7462_TEMP_COUNT];
215c0b4e3abSDarrick J. Wong 				/* bits 6-7 are quarter pieces of temp */
216c0b4e3abSDarrick J. Wong 	u8			temp_frac[ADT7462_TEMP_COUNT];
217c0b4e3abSDarrick J. Wong 	u8			temp_min[ADT7462_TEMP_COUNT];
218c0b4e3abSDarrick J. Wong 	u8			temp_max[ADT7462_TEMP_COUNT];
219c0b4e3abSDarrick J. Wong 	u16			fan[ADT7462_FAN_COUNT];
220c0b4e3abSDarrick J. Wong 	u8			fan_enabled;
221c0b4e3abSDarrick J. Wong 	u8			fan_min[ADT7462_FAN_COUNT];
222c0b4e3abSDarrick J. Wong 	u8			cfg2;
223c0b4e3abSDarrick J. Wong 	u8			pwm[ADT7462_PWM_COUNT];
224c0b4e3abSDarrick J. Wong 	u8			pin_cfg[ADT7462_PIN_CFG_REG_COUNT];
225c0b4e3abSDarrick J. Wong 	u8			voltages[ADT7462_VOLT_COUNT];
226c0b4e3abSDarrick J. Wong 	u8			volt_max[ADT7462_VOLT_COUNT];
227c0b4e3abSDarrick J. Wong 	u8			volt_min[ADT7462_VOLT_COUNT];
228c0b4e3abSDarrick J. Wong 	u8			pwm_min[ADT7462_PWM_COUNT];
229c0b4e3abSDarrick J. Wong 	u8			pwm_tmin[ADT7462_PWM_COUNT];
230c0b4e3abSDarrick J. Wong 	u8			pwm_trange[ADT7462_PWM_COUNT];
231c0b4e3abSDarrick J. Wong 	u8			pwm_max;	/* only one per chip */
232c0b4e3abSDarrick J. Wong 	u8			pwm_cfg[ADT7462_PWM_COUNT];
233c0b4e3abSDarrick J. Wong 	u8			alarms[ADT7462_ALARM_REG_COUNT];
234c0b4e3abSDarrick J. Wong };
235c0b4e3abSDarrick J. Wong 
236c0b4e3abSDarrick J. Wong static int adt7462_probe(struct i2c_client *client,
237c0b4e3abSDarrick J. Wong 			 const struct i2c_device_id *id);
238310ec792SJean Delvare static int adt7462_detect(struct i2c_client *client,
239c0b4e3abSDarrick J. Wong 			  struct i2c_board_info *info);
240c0b4e3abSDarrick J. Wong static int adt7462_remove(struct i2c_client *client);
241c0b4e3abSDarrick J. Wong 
242c0b4e3abSDarrick J. Wong static const struct i2c_device_id adt7462_id[] = {
2431f86df49SJean Delvare 	{ "adt7462", 0 },
244c0b4e3abSDarrick J. Wong 	{ }
245c0b4e3abSDarrick J. Wong };
246c0b4e3abSDarrick J. Wong MODULE_DEVICE_TABLE(i2c, adt7462_id);
247c0b4e3abSDarrick J. Wong 
248c0b4e3abSDarrick J. Wong static struct i2c_driver adt7462_driver = {
249c0b4e3abSDarrick J. Wong 	.class		= I2C_CLASS_HWMON,
250c0b4e3abSDarrick J. Wong 	.driver = {
251c0b4e3abSDarrick J. Wong 		.name	= "adt7462",
252c0b4e3abSDarrick J. Wong 	},
253c0b4e3abSDarrick J. Wong 	.probe		= adt7462_probe,
254c0b4e3abSDarrick J. Wong 	.remove		= adt7462_remove,
255c0b4e3abSDarrick J. Wong 	.id_table	= adt7462_id,
256c0b4e3abSDarrick J. Wong 	.detect		= adt7462_detect,
257c3813d6aSJean Delvare 	.address_list	= normal_i2c,
258c0b4e3abSDarrick J. Wong };
259c0b4e3abSDarrick J. Wong 
260c0b4e3abSDarrick J. Wong /*
261c0b4e3abSDarrick J. Wong  * 16-bit registers on the ADT7462 are low-byte first.  The data sheet says
262c0b4e3abSDarrick J. Wong  * that the low byte must be read before the high byte.
263c0b4e3abSDarrick J. Wong  */
264c0b4e3abSDarrick J. Wong static inline int adt7462_read_word_data(struct i2c_client *client, u8 reg)
265c0b4e3abSDarrick J. Wong {
266c0b4e3abSDarrick J. Wong 	u16 foo;
267c0b4e3abSDarrick J. Wong 	foo = i2c_smbus_read_byte_data(client, reg);
268c0b4e3abSDarrick J. Wong 	foo |= ((u16)i2c_smbus_read_byte_data(client, reg + 1) << 8);
269c0b4e3abSDarrick J. Wong 	return foo;
270c0b4e3abSDarrick J. Wong }
271c0b4e3abSDarrick J. Wong 
272c0b4e3abSDarrick J. Wong /* For some reason these registers are not contiguous. */
273c0b4e3abSDarrick J. Wong static int ADT7462_REG_FAN(int fan)
274c0b4e3abSDarrick J. Wong {
275c0b4e3abSDarrick J. Wong 	if (fan < 4)
276c0b4e3abSDarrick J. Wong 		return ADT7462_REG_FAN_BASE_ADDR + (2 * fan);
277c0b4e3abSDarrick J. Wong 	return ADT7462_REG_FAN2_BASE_ADDR + (2 * (fan - 4));
278c0b4e3abSDarrick J. Wong }
279c0b4e3abSDarrick J. Wong 
280c0b4e3abSDarrick J. Wong /* Voltage registers are scattered everywhere */
281c0b4e3abSDarrick J. Wong static int ADT7462_REG_VOLT_MAX(struct adt7462_data *data, int which)
282c0b4e3abSDarrick J. Wong {
283c0b4e3abSDarrick J. Wong 	switch (which) {
284c0b4e3abSDarrick J. Wong 	case 0:
285c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT))
286c0b4e3abSDarrick J. Wong 			return 0x7C;
287c0b4e3abSDarrick J. Wong 		break;
288c0b4e3abSDarrick J. Wong 	case 1:
289c0b4e3abSDarrick J. Wong 		return 0x69;
290c0b4e3abSDarrick J. Wong 	case 2:
291c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT))
292c0b4e3abSDarrick J. Wong 			return 0x7F;
293c0b4e3abSDarrick J. Wong 		break;
294c0b4e3abSDarrick J. Wong 	case 3:
295c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT))
296c0b4e3abSDarrick J. Wong 			return 0x7E;
297c0b4e3abSDarrick J. Wong 		break;
298c0b4e3abSDarrick J. Wong 	case 4:
299c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT))
300c0b4e3abSDarrick J. Wong 			return 0x4B;
301c0b4e3abSDarrick J. Wong 		break;
302c0b4e3abSDarrick J. Wong 	case 5:
303c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT))
304c0b4e3abSDarrick J. Wong 			return 0x49;
305c0b4e3abSDarrick J. Wong 		break;
306c0b4e3abSDarrick J. Wong 	case 6:
307c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT))
308c0b4e3abSDarrick J. Wong 			return 0x68;
309c0b4e3abSDarrick J. Wong 		break;
310c0b4e3abSDarrick J. Wong 	case 7:
311c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT))
312c0b4e3abSDarrick J. Wong 			return 0x7D;
313c0b4e3abSDarrick J. Wong 		break;
314c0b4e3abSDarrick J. Wong 	case 8:
315c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[2] & ADT7462_PIN26_VOLT_INPUT))
316c0b4e3abSDarrick J. Wong 			return 0x6C;
317c0b4e3abSDarrick J. Wong 		break;
318c0b4e3abSDarrick J. Wong 	case 9:
319c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[2] & ADT7462_PIN25_VOLT_INPUT))
320c0b4e3abSDarrick J. Wong 			return 0x6B;
321c0b4e3abSDarrick J. Wong 		break;
322c0b4e3abSDarrick J. Wong 	case 10:
323c0b4e3abSDarrick J. Wong 		return 0x6A;
324c0b4e3abSDarrick J. Wong 	case 11:
325c0b4e3abSDarrick J. Wong 		if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT ==
326c0b4e3abSDarrick J. Wong 					ADT7462_PIN28_VOLT &&
327c0b4e3abSDarrick J. Wong 		    !(data->pin_cfg[0] & ADT7462_VID_INPUT))
328c0b4e3abSDarrick J. Wong 			return 0x50;
329c0b4e3abSDarrick J. Wong 		break;
330c0b4e3abSDarrick J. Wong 	case 12:
331c0b4e3abSDarrick J. Wong 		if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT ==
332c0b4e3abSDarrick J. Wong 					ADT7462_PIN28_VOLT &&
333c0b4e3abSDarrick J. Wong 		    !(data->pin_cfg[0] & ADT7462_VID_INPUT))
334c0b4e3abSDarrick J. Wong 			return 0x4C;
335c0b4e3abSDarrick J. Wong 		break;
336c0b4e3abSDarrick J. Wong 	}
337c0b4e3abSDarrick J. Wong 	return -ENODEV;
338c0b4e3abSDarrick J. Wong }
339c0b4e3abSDarrick J. Wong 
340c0b4e3abSDarrick J. Wong static int ADT7462_REG_VOLT_MIN(struct adt7462_data *data, int which)
341c0b4e3abSDarrick J. Wong {
342c0b4e3abSDarrick J. Wong 	switch (which) {
343c0b4e3abSDarrick J. Wong 	case 0:
344c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT))
345c0b4e3abSDarrick J. Wong 			return 0x6D;
346c0b4e3abSDarrick J. Wong 		break;
347c0b4e3abSDarrick J. Wong 	case 1:
348c0b4e3abSDarrick J. Wong 		return 0x72;
349c0b4e3abSDarrick J. Wong 	case 2:
350c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT))
351c0b4e3abSDarrick J. Wong 			return 0x6F;
352c0b4e3abSDarrick J. Wong 		break;
353c0b4e3abSDarrick J. Wong 	case 3:
354c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT))
355c0b4e3abSDarrick J. Wong 			return 0x71;
356c0b4e3abSDarrick J. Wong 		break;
357c0b4e3abSDarrick J. Wong 	case 4:
358c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT))
359c0b4e3abSDarrick J. Wong 			return 0x47;
360c0b4e3abSDarrick J. Wong 		break;
361c0b4e3abSDarrick J. Wong 	case 5:
362c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT))
363c0b4e3abSDarrick J. Wong 			return 0x45;
364c0b4e3abSDarrick J. Wong 		break;
365c0b4e3abSDarrick J. Wong 	case 6:
366c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT))
367c0b4e3abSDarrick J. Wong 			return 0x70;
368c0b4e3abSDarrick J. Wong 		break;
369c0b4e3abSDarrick J. Wong 	case 7:
370c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT))
371c0b4e3abSDarrick J. Wong 			return 0x6E;
372c0b4e3abSDarrick J. Wong 		break;
373c0b4e3abSDarrick J. Wong 	case 8:
374c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[2] & ADT7462_PIN26_VOLT_INPUT))
375c0b4e3abSDarrick J. Wong 			return 0x75;
376c0b4e3abSDarrick J. Wong 		break;
377c0b4e3abSDarrick J. Wong 	case 9:
378c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[2] & ADT7462_PIN25_VOLT_INPUT))
379c0b4e3abSDarrick J. Wong 			return 0x74;
380c0b4e3abSDarrick J. Wong 		break;
381c0b4e3abSDarrick J. Wong 	case 10:
382c0b4e3abSDarrick J. Wong 		return 0x73;
383c0b4e3abSDarrick J. Wong 	case 11:
384c0b4e3abSDarrick J. Wong 		if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT ==
385c0b4e3abSDarrick J. Wong 					ADT7462_PIN28_VOLT &&
386c0b4e3abSDarrick J. Wong 		    !(data->pin_cfg[0] & ADT7462_VID_INPUT))
387c0b4e3abSDarrick J. Wong 			return 0x76;
388c0b4e3abSDarrick J. Wong 		break;
389c0b4e3abSDarrick J. Wong 	case 12:
390c0b4e3abSDarrick J. Wong 		if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT ==
391c0b4e3abSDarrick J. Wong 					ADT7462_PIN28_VOLT &&
392c0b4e3abSDarrick J. Wong 		    !(data->pin_cfg[0] & ADT7462_VID_INPUT))
393c0b4e3abSDarrick J. Wong 			return 0x77;
394c0b4e3abSDarrick J. Wong 		break;
395c0b4e3abSDarrick J. Wong 	}
396c0b4e3abSDarrick J. Wong 	return -ENODEV;
397c0b4e3abSDarrick J. Wong }
398c0b4e3abSDarrick J. Wong 
399c0b4e3abSDarrick J. Wong static int ADT7462_REG_VOLT(struct adt7462_data *data, int which)
400c0b4e3abSDarrick J. Wong {
401c0b4e3abSDarrick J. Wong 	switch (which) {
402c0b4e3abSDarrick J. Wong 	case 0:
403c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT))
404c0b4e3abSDarrick J. Wong 			return 0xA3;
405c0b4e3abSDarrick J. Wong 		break;
406c0b4e3abSDarrick J. Wong 	case 1:
407c0b4e3abSDarrick J. Wong 		return 0x90;
408c0b4e3abSDarrick J. Wong 	case 2:
409c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT))
410c0b4e3abSDarrick J. Wong 			return 0xA9;
411c0b4e3abSDarrick J. Wong 		break;
412c0b4e3abSDarrick J. Wong 	case 3:
413c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT))
414c0b4e3abSDarrick J. Wong 			return 0xA7;
415c0b4e3abSDarrick J. Wong 		break;
416c0b4e3abSDarrick J. Wong 	case 4:
417c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT))
418c0b4e3abSDarrick J. Wong 			return 0x8F;
419c0b4e3abSDarrick J. Wong 		break;
420c0b4e3abSDarrick J. Wong 	case 5:
421c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT))
422c0b4e3abSDarrick J. Wong 			return 0x8B;
423c0b4e3abSDarrick J. Wong 		break;
424c0b4e3abSDarrick J. Wong 	case 6:
425c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT))
426c0b4e3abSDarrick J. Wong 			return 0x96;
427c0b4e3abSDarrick J. Wong 		break;
428c0b4e3abSDarrick J. Wong 	case 7:
429c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT))
430c0b4e3abSDarrick J. Wong 			return 0xA5;
431c0b4e3abSDarrick J. Wong 		break;
432c0b4e3abSDarrick J. Wong 	case 8:
433c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[2] & ADT7462_PIN26_VOLT_INPUT))
434c0b4e3abSDarrick J. Wong 			return 0x93;
435c0b4e3abSDarrick J. Wong 		break;
436c0b4e3abSDarrick J. Wong 	case 9:
437c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[2] & ADT7462_PIN25_VOLT_INPUT))
438c0b4e3abSDarrick J. Wong 			return 0x92;
439c0b4e3abSDarrick J. Wong 		break;
440c0b4e3abSDarrick J. Wong 	case 10:
441c0b4e3abSDarrick J. Wong 		return 0x91;
442c0b4e3abSDarrick J. Wong 	case 11:
443c0b4e3abSDarrick J. Wong 		if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT ==
444c0b4e3abSDarrick J. Wong 					ADT7462_PIN28_VOLT &&
445c0b4e3abSDarrick J. Wong 		    !(data->pin_cfg[0] & ADT7462_VID_INPUT))
446c0b4e3abSDarrick J. Wong 			return 0x94;
447c0b4e3abSDarrick J. Wong 		break;
448c0b4e3abSDarrick J. Wong 	case 12:
449c0b4e3abSDarrick J. Wong 		if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT ==
450c0b4e3abSDarrick J. Wong 					ADT7462_PIN28_VOLT &&
451c0b4e3abSDarrick J. Wong 		    !(data->pin_cfg[0] & ADT7462_VID_INPUT))
452c0b4e3abSDarrick J. Wong 			return 0x95;
453c0b4e3abSDarrick J. Wong 		break;
454c0b4e3abSDarrick J. Wong 	}
455c0b4e3abSDarrick J. Wong 	return -ENODEV;
456c0b4e3abSDarrick J. Wong }
457c0b4e3abSDarrick J. Wong 
458c0b4e3abSDarrick J. Wong /* Provide labels for sysfs */
459c0b4e3abSDarrick J. Wong static const char *voltage_label(struct adt7462_data *data, int which)
460c0b4e3abSDarrick J. Wong {
461c0b4e3abSDarrick J. Wong 	switch (which) {
462c0b4e3abSDarrick J. Wong 	case 0:
463c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT))
464c0b4e3abSDarrick J. Wong 			return "+12V1";
465c0b4e3abSDarrick J. Wong 		break;
466c0b4e3abSDarrick J. Wong 	case 1:
467c0b4e3abSDarrick J. Wong 		switch (MASK_AND_SHIFT(data->pin_cfg[1], ADT7462_PIN23)) {
468c0b4e3abSDarrick J. Wong 		case 0:
469c0b4e3abSDarrick J. Wong 			return "Vccp1";
470c0b4e3abSDarrick J. Wong 		case 1:
471c0b4e3abSDarrick J. Wong 			return "+2.5V";
472c0b4e3abSDarrick J. Wong 		case 2:
473c0b4e3abSDarrick J. Wong 			return "+1.8V";
474c0b4e3abSDarrick J. Wong 		case 3:
475c0b4e3abSDarrick J. Wong 			return "+1.5V";
476c0b4e3abSDarrick J. Wong 		}
477c0b4e3abSDarrick J. Wong 	case 2:
478c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT))
479c0b4e3abSDarrick J. Wong 			return "+12V3";
480c0b4e3abSDarrick J. Wong 		break;
481c0b4e3abSDarrick J. Wong 	case 3:
482c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT))
483c0b4e3abSDarrick J. Wong 			return "+5V";
484c0b4e3abSDarrick J. Wong 		break;
485c0b4e3abSDarrick J. Wong 	case 4:
486c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT)) {
487c0b4e3abSDarrick J. Wong 			if (data->pin_cfg[1] & ADT7462_PIN19_INPUT)
488c0b4e3abSDarrick J. Wong 				return "+0.9V";
489c0b4e3abSDarrick J. Wong 			return "+1.25V";
490c0b4e3abSDarrick J. Wong 		}
491c0b4e3abSDarrick J. Wong 		break;
492c0b4e3abSDarrick J. Wong 	case 5:
493c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT)) {
494c0b4e3abSDarrick J. Wong 			if (data->pin_cfg[1] & ADT7462_PIN19_INPUT)
495c0b4e3abSDarrick J. Wong 				return "+1.8V";
496c0b4e3abSDarrick J. Wong 			return "+2.5V";
497c0b4e3abSDarrick J. Wong 		}
498c0b4e3abSDarrick J. Wong 		break;
499c0b4e3abSDarrick J. Wong 	case 6:
500c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT))
501c0b4e3abSDarrick J. Wong 			return "+3.3V";
502c0b4e3abSDarrick J. Wong 		break;
503c0b4e3abSDarrick J. Wong 	case 7:
504c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT))
505c0b4e3abSDarrick J. Wong 			return "+12V2";
506c0b4e3abSDarrick J. Wong 		break;
507c0b4e3abSDarrick J. Wong 	case 8:
508c0b4e3abSDarrick J. Wong 		switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN26)) {
509c0b4e3abSDarrick J. Wong 		case 0:
510c0b4e3abSDarrick J. Wong 			return "Vbatt";
511c0b4e3abSDarrick J. Wong 		case 1:
512c0b4e3abSDarrick J. Wong 			return "FSB_Vtt";
513c0b4e3abSDarrick J. Wong 		}
514c0b4e3abSDarrick J. Wong 		break;
515c0b4e3abSDarrick J. Wong 	case 9:
516c0b4e3abSDarrick J. Wong 		switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN25)) {
517c0b4e3abSDarrick J. Wong 		case 0:
518c0b4e3abSDarrick J. Wong 			return "+3.3V";
519c0b4e3abSDarrick J. Wong 		case 1:
520c0b4e3abSDarrick J. Wong 			return "+1.2V1";
521c0b4e3abSDarrick J. Wong 		}
522c0b4e3abSDarrick J. Wong 		break;
523c0b4e3abSDarrick J. Wong 	case 10:
524c0b4e3abSDarrick J. Wong 		switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN24)) {
525c0b4e3abSDarrick J. Wong 		case 0:
526c0b4e3abSDarrick J. Wong 			return "Vccp2";
527c0b4e3abSDarrick J. Wong 		case 1:
528c0b4e3abSDarrick J. Wong 			return "+2.5V";
529c0b4e3abSDarrick J. Wong 		case 2:
530c0b4e3abSDarrick J. Wong 			return "+1.8V";
531c0b4e3abSDarrick J. Wong 		case 3:
532c0b4e3abSDarrick J. Wong 			return "+1.5";
533c0b4e3abSDarrick J. Wong 		}
534c0b4e3abSDarrick J. Wong 	case 11:
535c0b4e3abSDarrick J. Wong 		if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT ==
536c0b4e3abSDarrick J. Wong 					ADT7462_PIN28_VOLT &&
537c0b4e3abSDarrick J. Wong 		    !(data->pin_cfg[0] & ADT7462_VID_INPUT))
538c0b4e3abSDarrick J. Wong 			return "+1.5V ICH";
539c0b4e3abSDarrick J. Wong 		break;
540c0b4e3abSDarrick J. Wong 	case 12:
541c0b4e3abSDarrick J. Wong 		if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT ==
542c0b4e3abSDarrick J. Wong 					ADT7462_PIN28_VOLT &&
543c0b4e3abSDarrick J. Wong 		    !(data->pin_cfg[0] & ADT7462_VID_INPUT))
544c0b4e3abSDarrick J. Wong 			return "+1.5V 3GPIO";
545c0b4e3abSDarrick J. Wong 		break;
546c0b4e3abSDarrick J. Wong 	}
547c0b4e3abSDarrick J. Wong 	return "N/A";
548c0b4e3abSDarrick J. Wong }
549c0b4e3abSDarrick J. Wong 
550c0b4e3abSDarrick J. Wong /* Multipliers are actually in uV, not mV. */
551c0b4e3abSDarrick J. Wong static int voltage_multiplier(struct adt7462_data *data, int which)
552c0b4e3abSDarrick J. Wong {
553c0b4e3abSDarrick J. Wong 	switch (which) {
554c0b4e3abSDarrick J. Wong 	case 0:
555c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT))
556c0b4e3abSDarrick J. Wong 			return 62500;
557c0b4e3abSDarrick J. Wong 		break;
558c0b4e3abSDarrick J. Wong 	case 1:
559c0b4e3abSDarrick J. Wong 		switch (MASK_AND_SHIFT(data->pin_cfg[1], ADT7462_PIN23)) {
560c0b4e3abSDarrick J. Wong 		case 0:
561c0b4e3abSDarrick J. Wong 			if (data->pin_cfg[0] & ADT7462_VID_INPUT)
562c0b4e3abSDarrick J. Wong 				return 12500;
563c0b4e3abSDarrick J. Wong 			return 6250;
564c0b4e3abSDarrick J. Wong 		case 1:
565c0b4e3abSDarrick J. Wong 			return 13000;
566c0b4e3abSDarrick J. Wong 		case 2:
567c0b4e3abSDarrick J. Wong 			return 9400;
568c0b4e3abSDarrick J. Wong 		case 3:
569c0b4e3abSDarrick J. Wong 			return 7800;
570c0b4e3abSDarrick J. Wong 		}
571c0b4e3abSDarrick J. Wong 	case 2:
572c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT))
573c0b4e3abSDarrick J. Wong 			return 62500;
574c0b4e3abSDarrick J. Wong 		break;
575c0b4e3abSDarrick J. Wong 	case 3:
576c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT))
577c0b4e3abSDarrick J. Wong 			return 26000;
578c0b4e3abSDarrick J. Wong 		break;
579c0b4e3abSDarrick J. Wong 	case 4:
580c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT)) {
581c0b4e3abSDarrick J. Wong 			if (data->pin_cfg[1] & ADT7462_PIN19_INPUT)
582c0b4e3abSDarrick J. Wong 				return 4690;
583c0b4e3abSDarrick J. Wong 			return 6500;
584c0b4e3abSDarrick J. Wong 		}
585c0b4e3abSDarrick J. Wong 		break;
586c0b4e3abSDarrick J. Wong 	case 5:
587c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT)) {
588c0b4e3abSDarrick J. Wong 			if (data->pin_cfg[1] & ADT7462_PIN15_INPUT)
589c0b4e3abSDarrick J. Wong 				return 9400;
590c0b4e3abSDarrick J. Wong 			return 13000;
591c0b4e3abSDarrick J. Wong 		}
592c0b4e3abSDarrick J. Wong 		break;
593c0b4e3abSDarrick J. Wong 	case 6:
594c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT))
595c0b4e3abSDarrick J. Wong 			return 17200;
596c0b4e3abSDarrick J. Wong 		break;
597c0b4e3abSDarrick J. Wong 	case 7:
598c0b4e3abSDarrick J. Wong 		if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT))
599c0b4e3abSDarrick J. Wong 			return 62500;
600c0b4e3abSDarrick J. Wong 		break;
601c0b4e3abSDarrick J. Wong 	case 8:
602c0b4e3abSDarrick J. Wong 		switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN26)) {
603c0b4e3abSDarrick J. Wong 		case 0:
604c0b4e3abSDarrick J. Wong 			return 15600;
605c0b4e3abSDarrick J. Wong 		case 1:
606c0b4e3abSDarrick J. Wong 			return 6250;
607c0b4e3abSDarrick J. Wong 		}
608c0b4e3abSDarrick J. Wong 		break;
609c0b4e3abSDarrick J. Wong 	case 9:
610c0b4e3abSDarrick J. Wong 		switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN25)) {
611c0b4e3abSDarrick J. Wong 		case 0:
612c0b4e3abSDarrick J. Wong 			return 17200;
613c0b4e3abSDarrick J. Wong 		case 1:
614c0b4e3abSDarrick J. Wong 			return 6250;
615c0b4e3abSDarrick J. Wong 		}
616c0b4e3abSDarrick J. Wong 		break;
617c0b4e3abSDarrick J. Wong 	case 10:
618c0b4e3abSDarrick J. Wong 		switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN24)) {
619c0b4e3abSDarrick J. Wong 		case 0:
620c0b4e3abSDarrick J. Wong 			return 6250;
621c0b4e3abSDarrick J. Wong 		case 1:
622c0b4e3abSDarrick J. Wong 			return 13000;
623c0b4e3abSDarrick J. Wong 		case 2:
624c0b4e3abSDarrick J. Wong 			return 9400;
625c0b4e3abSDarrick J. Wong 		case 3:
626c0b4e3abSDarrick J. Wong 			return 7800;
627c0b4e3abSDarrick J. Wong 		}
628c0b4e3abSDarrick J. Wong 	case 11:
629c0b4e3abSDarrick J. Wong 	case 12:
630c0b4e3abSDarrick J. Wong 		if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT ==
631c0b4e3abSDarrick J. Wong 					ADT7462_PIN28_VOLT &&
632c0b4e3abSDarrick J. Wong 		    !(data->pin_cfg[0] & ADT7462_VID_INPUT))
633c0b4e3abSDarrick J. Wong 			return 7800;
634c0b4e3abSDarrick J. Wong 	}
635c0b4e3abSDarrick J. Wong 	return 0;
636c0b4e3abSDarrick J. Wong }
637c0b4e3abSDarrick J. Wong 
638c0b4e3abSDarrick J. Wong static int temp_enabled(struct adt7462_data *data, int which)
639c0b4e3abSDarrick J. Wong {
640c0b4e3abSDarrick J. Wong 	switch (which) {
641c0b4e3abSDarrick J. Wong 	case 0:
642c0b4e3abSDarrick J. Wong 	case 2:
643c0b4e3abSDarrick J. Wong 		return 1;
644c0b4e3abSDarrick J. Wong 	case 1:
645c0b4e3abSDarrick J. Wong 		if (data->pin_cfg[0] & ADT7462_DIODE1_INPUT)
646c0b4e3abSDarrick J. Wong 			return 1;
647c0b4e3abSDarrick J. Wong 		break;
648c0b4e3abSDarrick J. Wong 	case 3:
649c0b4e3abSDarrick J. Wong 		if (data->pin_cfg[0] & ADT7462_DIODE3_INPUT)
650c0b4e3abSDarrick J. Wong 			return 1;
651c0b4e3abSDarrick J. Wong 		break;
652c0b4e3abSDarrick J. Wong 	}
653c0b4e3abSDarrick J. Wong 	return 0;
654c0b4e3abSDarrick J. Wong }
655c0b4e3abSDarrick J. Wong 
656c0b4e3abSDarrick J. Wong static const char *temp_label(struct adt7462_data *data, int which)
657c0b4e3abSDarrick J. Wong {
658c0b4e3abSDarrick J. Wong 	switch (which) {
659c0b4e3abSDarrick J. Wong 	case 0:
660c0b4e3abSDarrick J. Wong 		return "local";
661c0b4e3abSDarrick J. Wong 	case 1:
662c0b4e3abSDarrick J. Wong 		if (data->pin_cfg[0] & ADT7462_DIODE1_INPUT)
663c0b4e3abSDarrick J. Wong 			return "remote1";
664c0b4e3abSDarrick J. Wong 		break;
665c0b4e3abSDarrick J. Wong 	case 2:
666c0b4e3abSDarrick J. Wong 		return "remote2";
667c0b4e3abSDarrick J. Wong 	case 3:
668c0b4e3abSDarrick J. Wong 		if (data->pin_cfg[0] & ADT7462_DIODE3_INPUT)
669c0b4e3abSDarrick J. Wong 			return "remote3";
670c0b4e3abSDarrick J. Wong 		break;
671c0b4e3abSDarrick J. Wong 	}
672c0b4e3abSDarrick J. Wong 	return "N/A";
673c0b4e3abSDarrick J. Wong }
674c0b4e3abSDarrick J. Wong 
675c0b4e3abSDarrick J. Wong /* Map Trange register values to mC */
676c0b4e3abSDarrick J. Wong #define NUM_TRANGE_VALUES	16
677c0b4e3abSDarrick J. Wong static const int trange_values[NUM_TRANGE_VALUES] = {
678c0b4e3abSDarrick J. Wong 	2000,
679c0b4e3abSDarrick J. Wong 	2500,
680c0b4e3abSDarrick J. Wong 	3300,
681c0b4e3abSDarrick J. Wong 	4000,
682c0b4e3abSDarrick J. Wong 	5000,
683c0b4e3abSDarrick J. Wong 	6700,
684c0b4e3abSDarrick J. Wong 	8000,
685c0b4e3abSDarrick J. Wong 	10000,
686c0b4e3abSDarrick J. Wong 	13300,
687c0b4e3abSDarrick J. Wong 	16000,
688c0b4e3abSDarrick J. Wong 	20000,
689c0b4e3abSDarrick J. Wong 	26700,
690c0b4e3abSDarrick J. Wong 	32000,
691c0b4e3abSDarrick J. Wong 	40000,
692c0b4e3abSDarrick J. Wong 	53300,
693c0b4e3abSDarrick J. Wong 	80000
694c0b4e3abSDarrick J. Wong };
695c0b4e3abSDarrick J. Wong 
696c0b4e3abSDarrick J. Wong static int find_trange_value(int trange)
697c0b4e3abSDarrick J. Wong {
698c0b4e3abSDarrick J. Wong 	int i;
699c0b4e3abSDarrick J. Wong 
700c0b4e3abSDarrick J. Wong 	for (i = 0; i < NUM_TRANGE_VALUES; i++)
701c0b4e3abSDarrick J. Wong 		if (trange_values[i] == trange)
702c0b4e3abSDarrick J. Wong 			return i;
703c0b4e3abSDarrick J. Wong 
704c0b4e3abSDarrick J. Wong 	return -ENODEV;
705c0b4e3abSDarrick J. Wong }
706c0b4e3abSDarrick J. Wong 
707c0b4e3abSDarrick J. Wong static struct adt7462_data *adt7462_update_device(struct device *dev)
708c0b4e3abSDarrick J. Wong {
709c0b4e3abSDarrick J. Wong 	struct i2c_client *client = to_i2c_client(dev);
710c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = i2c_get_clientdata(client);
711c0b4e3abSDarrick J. Wong 	unsigned long local_jiffies = jiffies;
712c0b4e3abSDarrick J. Wong 	int i;
713c0b4e3abSDarrick J. Wong 
714c0b4e3abSDarrick J. Wong 	mutex_lock(&data->lock);
715c0b4e3abSDarrick J. Wong 	if (time_before(local_jiffies, data->sensors_last_updated +
716c0b4e3abSDarrick J. Wong 		SENSOR_REFRESH_INTERVAL)
717c0b4e3abSDarrick J. Wong 		&& data->sensors_valid)
718c0b4e3abSDarrick J. Wong 		goto no_sensor_update;
719c0b4e3abSDarrick J. Wong 
720c0b4e3abSDarrick J. Wong 	for (i = 0; i < ADT7462_TEMP_COUNT; i++) {
721c0b4e3abSDarrick J. Wong 		/*
722c0b4e3abSDarrick J. Wong 		 * Reading the fractional register locks the integral
723c0b4e3abSDarrick J. Wong 		 * register until both have been read.
724c0b4e3abSDarrick J. Wong 		 */
725c0b4e3abSDarrick J. Wong 		data->temp_frac[i] = i2c_smbus_read_byte_data(client,
726c0b4e3abSDarrick J. Wong 						ADT7462_TEMP_REG(i));
727c0b4e3abSDarrick J. Wong 		data->temp[i] = i2c_smbus_read_byte_data(client,
728c0b4e3abSDarrick J. Wong 						ADT7462_TEMP_REG(i) + 1);
729c0b4e3abSDarrick J. Wong 	}
730c0b4e3abSDarrick J. Wong 
731c0b4e3abSDarrick J. Wong 	for (i = 0; i < ADT7462_FAN_COUNT; i++)
732c0b4e3abSDarrick J. Wong 		data->fan[i] = adt7462_read_word_data(client,
733c0b4e3abSDarrick J. Wong 						ADT7462_REG_FAN(i));
734c0b4e3abSDarrick J. Wong 
735c0b4e3abSDarrick J. Wong 	data->fan_enabled = i2c_smbus_read_byte_data(client,
736c0b4e3abSDarrick J. Wong 					ADT7462_REG_FAN_ENABLE);
737c0b4e3abSDarrick J. Wong 
738c0b4e3abSDarrick J. Wong 	for (i = 0; i < ADT7462_PWM_COUNT; i++)
739c0b4e3abSDarrick J. Wong 		data->pwm[i] = i2c_smbus_read_byte_data(client,
740c0b4e3abSDarrick J. Wong 						ADT7462_REG_PWM(i));
741c0b4e3abSDarrick J. Wong 
742c0b4e3abSDarrick J. Wong 	for (i = 0; i < ADT7462_PIN_CFG_REG_COUNT; i++)
743c0b4e3abSDarrick J. Wong 		data->pin_cfg[i] = i2c_smbus_read_byte_data(client,
744c0b4e3abSDarrick J. Wong 				ADT7462_REG_PIN_CFG(i));
745c0b4e3abSDarrick J. Wong 
746c0b4e3abSDarrick J. Wong 	for (i = 0; i < ADT7462_VOLT_COUNT; i++) {
747c0b4e3abSDarrick J. Wong 		int reg = ADT7462_REG_VOLT(data, i);
748c0b4e3abSDarrick J. Wong 		if (!reg)
749c0b4e3abSDarrick J. Wong 			data->voltages[i] = 0;
750c0b4e3abSDarrick J. Wong 		else
751c0b4e3abSDarrick J. Wong 			data->voltages[i] = i2c_smbus_read_byte_data(client,
752c0b4e3abSDarrick J. Wong 								     reg);
753c0b4e3abSDarrick J. Wong 	}
754c0b4e3abSDarrick J. Wong 
755c0b4e3abSDarrick J. Wong 	data->alarms[0] = i2c_smbus_read_byte_data(client, ADT7462_REG_ALARM1);
756c0b4e3abSDarrick J. Wong 	data->alarms[1] = i2c_smbus_read_byte_data(client, ADT7462_REG_ALARM2);
757c0b4e3abSDarrick J. Wong 	data->alarms[2] = i2c_smbus_read_byte_data(client, ADT7462_REG_ALARM3);
758c0b4e3abSDarrick J. Wong 	data->alarms[3] = i2c_smbus_read_byte_data(client, ADT7462_REG_ALARM4);
759c0b4e3abSDarrick J. Wong 
760c0b4e3abSDarrick J. Wong 	data->sensors_last_updated = local_jiffies;
761c0b4e3abSDarrick J. Wong 	data->sensors_valid = 1;
762c0b4e3abSDarrick J. Wong 
763c0b4e3abSDarrick J. Wong no_sensor_update:
764c0b4e3abSDarrick J. Wong 	if (time_before(local_jiffies, data->limits_last_updated +
765c0b4e3abSDarrick J. Wong 		LIMIT_REFRESH_INTERVAL)
766c0b4e3abSDarrick J. Wong 		&& data->limits_valid)
767c0b4e3abSDarrick J. Wong 		goto out;
768c0b4e3abSDarrick J. Wong 
769c0b4e3abSDarrick J. Wong 	for (i = 0; i < ADT7462_TEMP_COUNT; i++) {
770c0b4e3abSDarrick J. Wong 		data->temp_min[i] = i2c_smbus_read_byte_data(client,
771c0b4e3abSDarrick J. Wong 						ADT7462_TEMP_MIN_REG(i));
772c0b4e3abSDarrick J. Wong 		data->temp_max[i] = i2c_smbus_read_byte_data(client,
773c0b4e3abSDarrick J. Wong 						ADT7462_TEMP_MAX_REG(i));
774c0b4e3abSDarrick J. Wong 	}
775c0b4e3abSDarrick J. Wong 
776c0b4e3abSDarrick J. Wong 	for (i = 0; i < ADT7462_FAN_COUNT; i++)
777c0b4e3abSDarrick J. Wong 		data->fan_min[i] = i2c_smbus_read_byte_data(client,
778c0b4e3abSDarrick J. Wong 						ADT7462_REG_FAN_MIN(i));
779c0b4e3abSDarrick J. Wong 
780c0b4e3abSDarrick J. Wong 	for (i = 0; i < ADT7462_VOLT_COUNT; i++) {
781c0b4e3abSDarrick J. Wong 		int reg = ADT7462_REG_VOLT_MAX(data, i);
782c0b4e3abSDarrick J. Wong 		data->volt_max[i] =
783c0b4e3abSDarrick J. Wong 			(reg ? i2c_smbus_read_byte_data(client, reg) : 0);
784c0b4e3abSDarrick J. Wong 
785c0b4e3abSDarrick J. Wong 		reg = ADT7462_REG_VOLT_MIN(data, i);
786c0b4e3abSDarrick J. Wong 		data->volt_min[i] =
787c0b4e3abSDarrick J. Wong 			(reg ? i2c_smbus_read_byte_data(client, reg) : 0);
788c0b4e3abSDarrick J. Wong 	}
789c0b4e3abSDarrick J. Wong 
790c0b4e3abSDarrick J. Wong 	for (i = 0; i < ADT7462_PWM_COUNT; i++) {
791c0b4e3abSDarrick J. Wong 		data->pwm_min[i] = i2c_smbus_read_byte_data(client,
792c0b4e3abSDarrick J. Wong 						ADT7462_REG_PWM_MIN(i));
793c0b4e3abSDarrick J. Wong 		data->pwm_tmin[i] = i2c_smbus_read_byte_data(client,
794c0b4e3abSDarrick J. Wong 						ADT7462_REG_PWM_TMIN(i));
795c0b4e3abSDarrick J. Wong 		data->pwm_trange[i] = i2c_smbus_read_byte_data(client,
796c0b4e3abSDarrick J. Wong 						ADT7462_REG_PWM_TRANGE(i));
797c0b4e3abSDarrick J. Wong 		data->pwm_cfg[i] = i2c_smbus_read_byte_data(client,
798c0b4e3abSDarrick J. Wong 						ADT7462_REG_PWM_CFG(i));
799c0b4e3abSDarrick J. Wong 	}
800c0b4e3abSDarrick J. Wong 
801c0b4e3abSDarrick J. Wong 	data->pwm_max = i2c_smbus_read_byte_data(client, ADT7462_REG_PWM_MAX);
802c0b4e3abSDarrick J. Wong 
803c0b4e3abSDarrick J. Wong 	data->cfg2 = i2c_smbus_read_byte_data(client, ADT7462_REG_CFG2);
804c0b4e3abSDarrick J. Wong 
805c0b4e3abSDarrick J. Wong 	data->limits_last_updated = local_jiffies;
806c0b4e3abSDarrick J. Wong 	data->limits_valid = 1;
807c0b4e3abSDarrick J. Wong 
808c0b4e3abSDarrick J. Wong out:
809c0b4e3abSDarrick J. Wong 	mutex_unlock(&data->lock);
810c0b4e3abSDarrick J. Wong 	return data;
811c0b4e3abSDarrick J. Wong }
812c0b4e3abSDarrick J. Wong 
813c0b4e3abSDarrick J. Wong static ssize_t show_temp_min(struct device *dev,
814c0b4e3abSDarrick J. Wong 			     struct device_attribute *devattr,
815c0b4e3abSDarrick J. Wong 			     char *buf)
816c0b4e3abSDarrick J. Wong {
817c0b4e3abSDarrick J. Wong 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
818c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = adt7462_update_device(dev);
819c0b4e3abSDarrick J. Wong 
820c0b4e3abSDarrick J. Wong 	if (!temp_enabled(data, attr->index))
821c0b4e3abSDarrick J. Wong 		return sprintf(buf, "0\n");
822c0b4e3abSDarrick J. Wong 
823c0b4e3abSDarrick J. Wong 	return sprintf(buf, "%d\n", 1000 * (data->temp_min[attr->index] - 64));
824c0b4e3abSDarrick J. Wong }
825c0b4e3abSDarrick J. Wong 
826c0b4e3abSDarrick J. Wong static ssize_t set_temp_min(struct device *dev,
827c0b4e3abSDarrick J. Wong 			    struct device_attribute *devattr,
828c0b4e3abSDarrick J. Wong 			    const char *buf,
829c0b4e3abSDarrick J. Wong 			    size_t count)
830c0b4e3abSDarrick J. Wong {
831c0b4e3abSDarrick J. Wong 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
832c0b4e3abSDarrick J. Wong 	struct i2c_client *client = to_i2c_client(dev);
833c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = i2c_get_clientdata(client);
834c0b4e3abSDarrick J. Wong 	long temp;
835c0b4e3abSDarrick J. Wong 
836179c4fdbSFrans Meulenbroeks 	if (kstrtol(buf, 10, &temp) || !temp_enabled(data, attr->index))
837c0b4e3abSDarrick J. Wong 		return -EINVAL;
838c0b4e3abSDarrick J. Wong 
8398f8c1fb0SDarrick J. Wong 	temp = DIV_ROUND_CLOSEST(temp, 1000) + 64;
840c0b4e3abSDarrick J. Wong 	temp = SENSORS_LIMIT(temp, 0, 255);
841c0b4e3abSDarrick J. Wong 
842c0b4e3abSDarrick J. Wong 	mutex_lock(&data->lock);
843c0b4e3abSDarrick J. Wong 	data->temp_min[attr->index] = temp;
844c0b4e3abSDarrick J. Wong 	i2c_smbus_write_byte_data(client, ADT7462_TEMP_MIN_REG(attr->index),
845c0b4e3abSDarrick J. Wong 				  temp);
846c0b4e3abSDarrick J. Wong 	mutex_unlock(&data->lock);
847c0b4e3abSDarrick J. Wong 
848c0b4e3abSDarrick J. Wong 	return count;
849c0b4e3abSDarrick J. Wong }
850c0b4e3abSDarrick J. Wong 
851c0b4e3abSDarrick J. Wong static ssize_t show_temp_max(struct device *dev,
852c0b4e3abSDarrick J. Wong 			     struct device_attribute *devattr,
853c0b4e3abSDarrick J. Wong 			     char *buf)
854c0b4e3abSDarrick J. Wong {
855c0b4e3abSDarrick J. Wong 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
856c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = adt7462_update_device(dev);
857c0b4e3abSDarrick J. Wong 
858c0b4e3abSDarrick J. Wong 	if (!temp_enabled(data, attr->index))
859c0b4e3abSDarrick J. Wong 		return sprintf(buf, "0\n");
860c0b4e3abSDarrick J. Wong 
861c0b4e3abSDarrick J. Wong 	return sprintf(buf, "%d\n", 1000 * (data->temp_max[attr->index] - 64));
862c0b4e3abSDarrick J. Wong }
863c0b4e3abSDarrick J. Wong 
864c0b4e3abSDarrick J. Wong static ssize_t set_temp_max(struct device *dev,
865c0b4e3abSDarrick J. Wong 			    struct device_attribute *devattr,
866c0b4e3abSDarrick J. Wong 			    const char *buf,
867c0b4e3abSDarrick J. Wong 			    size_t count)
868c0b4e3abSDarrick J. Wong {
869c0b4e3abSDarrick J. Wong 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
870c0b4e3abSDarrick J. Wong 	struct i2c_client *client = to_i2c_client(dev);
871c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = i2c_get_clientdata(client);
872c0b4e3abSDarrick J. Wong 	long temp;
873c0b4e3abSDarrick J. Wong 
874179c4fdbSFrans Meulenbroeks 	if (kstrtol(buf, 10, &temp) || !temp_enabled(data, attr->index))
875c0b4e3abSDarrick J. Wong 		return -EINVAL;
876c0b4e3abSDarrick J. Wong 
8778f8c1fb0SDarrick J. Wong 	temp = DIV_ROUND_CLOSEST(temp, 1000) + 64;
878c0b4e3abSDarrick J. Wong 	temp = SENSORS_LIMIT(temp, 0, 255);
879c0b4e3abSDarrick J. Wong 
880c0b4e3abSDarrick J. Wong 	mutex_lock(&data->lock);
881c0b4e3abSDarrick J. Wong 	data->temp_max[attr->index] = temp;
882c0b4e3abSDarrick J. Wong 	i2c_smbus_write_byte_data(client, ADT7462_TEMP_MAX_REG(attr->index),
883c0b4e3abSDarrick J. Wong 				  temp);
884c0b4e3abSDarrick J. Wong 	mutex_unlock(&data->lock);
885c0b4e3abSDarrick J. Wong 
886c0b4e3abSDarrick J. Wong 	return count;
887c0b4e3abSDarrick J. Wong }
888c0b4e3abSDarrick J. Wong 
889c0b4e3abSDarrick J. Wong static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
890c0b4e3abSDarrick J. Wong 			 char *buf)
891c0b4e3abSDarrick J. Wong {
892c0b4e3abSDarrick J. Wong 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
893c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = adt7462_update_device(dev);
894c0b4e3abSDarrick J. Wong 	u8 frac = data->temp_frac[attr->index] >> TEMP_FRAC_OFFSET;
895c0b4e3abSDarrick J. Wong 
896c0b4e3abSDarrick J. Wong 	if (!temp_enabled(data, attr->index))
897c0b4e3abSDarrick J. Wong 		return sprintf(buf, "0\n");
898c0b4e3abSDarrick J. Wong 
899c0b4e3abSDarrick J. Wong 	return sprintf(buf, "%d\n", 1000 * (data->temp[attr->index] - 64) +
900c0b4e3abSDarrick J. Wong 				     250 * frac);
901c0b4e3abSDarrick J. Wong }
902c0b4e3abSDarrick J. Wong 
903c0b4e3abSDarrick J. Wong static ssize_t show_temp_label(struct device *dev,
904c0b4e3abSDarrick J. Wong 			       struct device_attribute *devattr,
905c0b4e3abSDarrick J. Wong 			       char *buf)
906c0b4e3abSDarrick J. Wong {
907c0b4e3abSDarrick J. Wong 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
908c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = adt7462_update_device(dev);
909c0b4e3abSDarrick J. Wong 
910c0b4e3abSDarrick J. Wong 	return sprintf(buf, "%s\n", temp_label(data, attr->index));
911c0b4e3abSDarrick J. Wong }
912c0b4e3abSDarrick J. Wong 
913c0b4e3abSDarrick J. Wong static ssize_t show_volt_max(struct device *dev,
914c0b4e3abSDarrick J. Wong 			     struct device_attribute *devattr,
915c0b4e3abSDarrick J. Wong 			     char *buf)
916c0b4e3abSDarrick J. Wong {
917c0b4e3abSDarrick J. Wong 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
918c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = adt7462_update_device(dev);
919c0b4e3abSDarrick J. Wong 	int x = voltage_multiplier(data, attr->index);
920c0b4e3abSDarrick J. Wong 
921c0b4e3abSDarrick J. Wong 	x *= data->volt_max[attr->index];
922c0b4e3abSDarrick J. Wong 	x /= 1000; /* convert from uV to mV */
923c0b4e3abSDarrick J. Wong 
924c0b4e3abSDarrick J. Wong 	return sprintf(buf, "%d\n", x);
925c0b4e3abSDarrick J. Wong }
926c0b4e3abSDarrick J. Wong 
927c0b4e3abSDarrick J. Wong static ssize_t set_volt_max(struct device *dev,
928c0b4e3abSDarrick J. Wong 			    struct device_attribute *devattr,
929c0b4e3abSDarrick J. Wong 			    const char *buf,
930c0b4e3abSDarrick J. Wong 			    size_t count)
931c0b4e3abSDarrick J. Wong {
932c0b4e3abSDarrick J. Wong 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
933c0b4e3abSDarrick J. Wong 	struct i2c_client *client = to_i2c_client(dev);
934c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = i2c_get_clientdata(client);
935c0b4e3abSDarrick J. Wong 	int x = voltage_multiplier(data, attr->index);
936c0b4e3abSDarrick J. Wong 	long temp;
937c0b4e3abSDarrick J. Wong 
938179c4fdbSFrans Meulenbroeks 	if (kstrtol(buf, 10, &temp) || !x)
939c0b4e3abSDarrick J. Wong 		return -EINVAL;
940c0b4e3abSDarrick J. Wong 
941c0b4e3abSDarrick J. Wong 	temp *= 1000; /* convert mV to uV */
9428f8c1fb0SDarrick J. Wong 	temp = DIV_ROUND_CLOSEST(temp, x);
943c0b4e3abSDarrick J. Wong 	temp = SENSORS_LIMIT(temp, 0, 255);
944c0b4e3abSDarrick J. Wong 
945c0b4e3abSDarrick J. Wong 	mutex_lock(&data->lock);
946c0b4e3abSDarrick J. Wong 	data->volt_max[attr->index] = temp;
947c0b4e3abSDarrick J. Wong 	i2c_smbus_write_byte_data(client,
948c0b4e3abSDarrick J. Wong 				  ADT7462_REG_VOLT_MAX(data, attr->index),
949c0b4e3abSDarrick J. Wong 				  temp);
950c0b4e3abSDarrick J. Wong 	mutex_unlock(&data->lock);
951c0b4e3abSDarrick J. Wong 
952c0b4e3abSDarrick J. Wong 	return count;
953c0b4e3abSDarrick J. Wong }
954c0b4e3abSDarrick J. Wong 
955c0b4e3abSDarrick J. Wong static ssize_t show_volt_min(struct device *dev,
956c0b4e3abSDarrick J. Wong 			     struct device_attribute *devattr,
957c0b4e3abSDarrick J. Wong 			     char *buf)
958c0b4e3abSDarrick J. Wong {
959c0b4e3abSDarrick J. Wong 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
960c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = adt7462_update_device(dev);
961c0b4e3abSDarrick J. Wong 	int x = voltage_multiplier(data, attr->index);
962c0b4e3abSDarrick J. Wong 
963c0b4e3abSDarrick J. Wong 	x *= data->volt_min[attr->index];
964c0b4e3abSDarrick J. Wong 	x /= 1000; /* convert from uV to mV */
965c0b4e3abSDarrick J. Wong 
966c0b4e3abSDarrick J. Wong 	return sprintf(buf, "%d\n", x);
967c0b4e3abSDarrick J. Wong }
968c0b4e3abSDarrick J. Wong 
969c0b4e3abSDarrick J. Wong static ssize_t set_volt_min(struct device *dev,
970c0b4e3abSDarrick J. Wong 			    struct device_attribute *devattr,
971c0b4e3abSDarrick J. Wong 			    const char *buf,
972c0b4e3abSDarrick J. Wong 			    size_t count)
973c0b4e3abSDarrick J. Wong {
974c0b4e3abSDarrick J. Wong 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
975c0b4e3abSDarrick J. Wong 	struct i2c_client *client = to_i2c_client(dev);
976c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = i2c_get_clientdata(client);
977c0b4e3abSDarrick J. Wong 	int x = voltage_multiplier(data, attr->index);
978c0b4e3abSDarrick J. Wong 	long temp;
979c0b4e3abSDarrick J. Wong 
980179c4fdbSFrans Meulenbroeks 	if (kstrtol(buf, 10, &temp) || !x)
981c0b4e3abSDarrick J. Wong 		return -EINVAL;
982c0b4e3abSDarrick J. Wong 
983c0b4e3abSDarrick J. Wong 	temp *= 1000; /* convert mV to uV */
9848f8c1fb0SDarrick J. Wong 	temp = DIV_ROUND_CLOSEST(temp, x);
985c0b4e3abSDarrick J. Wong 	temp = SENSORS_LIMIT(temp, 0, 255);
986c0b4e3abSDarrick J. Wong 
987c0b4e3abSDarrick J. Wong 	mutex_lock(&data->lock);
988c0b4e3abSDarrick J. Wong 	data->volt_min[attr->index] = temp;
989c0b4e3abSDarrick J. Wong 	i2c_smbus_write_byte_data(client,
990c0b4e3abSDarrick J. Wong 				  ADT7462_REG_VOLT_MIN(data, attr->index),
991c0b4e3abSDarrick J. Wong 				  temp);
992c0b4e3abSDarrick J. Wong 	mutex_unlock(&data->lock);
993c0b4e3abSDarrick J. Wong 
994c0b4e3abSDarrick J. Wong 	return count;
995c0b4e3abSDarrick J. Wong }
996c0b4e3abSDarrick J. Wong 
997c0b4e3abSDarrick J. Wong static ssize_t show_voltage(struct device *dev,
998c0b4e3abSDarrick J. Wong 			    struct device_attribute *devattr,
999c0b4e3abSDarrick J. Wong 			    char *buf)
1000c0b4e3abSDarrick J. Wong {
1001c0b4e3abSDarrick J. Wong 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
1002c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = adt7462_update_device(dev);
1003c0b4e3abSDarrick J. Wong 	int x = voltage_multiplier(data, attr->index);
1004c0b4e3abSDarrick J. Wong 
1005c0b4e3abSDarrick J. Wong 	x *= data->voltages[attr->index];
1006c0b4e3abSDarrick J. Wong 	x /= 1000; /* convert from uV to mV */
1007c0b4e3abSDarrick J. Wong 
1008c0b4e3abSDarrick J. Wong 	return sprintf(buf, "%d\n", x);
1009c0b4e3abSDarrick J. Wong }
1010c0b4e3abSDarrick J. Wong 
1011c0b4e3abSDarrick J. Wong static ssize_t show_voltage_label(struct device *dev,
1012c0b4e3abSDarrick J. Wong 				  struct device_attribute *devattr,
1013c0b4e3abSDarrick J. Wong 				  char *buf)
1014c0b4e3abSDarrick J. Wong {
1015c0b4e3abSDarrick J. Wong 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
1016c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = adt7462_update_device(dev);
1017c0b4e3abSDarrick J. Wong 
1018c0b4e3abSDarrick J. Wong 	return sprintf(buf, "%s\n", voltage_label(data, attr->index));
1019c0b4e3abSDarrick J. Wong }
1020c0b4e3abSDarrick J. Wong 
1021c0b4e3abSDarrick J. Wong static ssize_t show_alarm(struct device *dev,
1022c0b4e3abSDarrick J. Wong 			  struct device_attribute *devattr,
1023c0b4e3abSDarrick J. Wong 			  char *buf)
1024c0b4e3abSDarrick J. Wong {
1025c0b4e3abSDarrick J. Wong 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
1026c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = adt7462_update_device(dev);
1027c0b4e3abSDarrick J. Wong 	int reg = attr->index >> ADT7462_ALARM_REG_SHIFT;
1028c0b4e3abSDarrick J. Wong 	int mask = attr->index & ADT7462_ALARM_FLAG_MASK;
1029c0b4e3abSDarrick J. Wong 
1030c0b4e3abSDarrick J. Wong 	if (data->alarms[reg] & mask)
1031c0b4e3abSDarrick J. Wong 		return sprintf(buf, "1\n");
1032c0b4e3abSDarrick J. Wong 	else
1033c0b4e3abSDarrick J. Wong 		return sprintf(buf, "0\n");
1034c0b4e3abSDarrick J. Wong }
1035c0b4e3abSDarrick J. Wong 
1036c0b4e3abSDarrick J. Wong static int fan_enabled(struct adt7462_data *data, int fan)
1037c0b4e3abSDarrick J. Wong {
1038c0b4e3abSDarrick J. Wong 	return data->fan_enabled & (1 << fan);
1039c0b4e3abSDarrick J. Wong }
1040c0b4e3abSDarrick J. Wong 
1041c0b4e3abSDarrick J. Wong static ssize_t show_fan_min(struct device *dev,
1042c0b4e3abSDarrick J. Wong 			    struct device_attribute *devattr,
1043c0b4e3abSDarrick J. Wong 			    char *buf)
1044c0b4e3abSDarrick J. Wong {
1045c0b4e3abSDarrick J. Wong 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
1046c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = adt7462_update_device(dev);
1047c0b4e3abSDarrick J. Wong 	u16 temp;
1048c0b4e3abSDarrick J. Wong 
1049c0b4e3abSDarrick J. Wong 	/* Only the MSB of the min fan period is stored... */
1050c0b4e3abSDarrick J. Wong 	temp = data->fan_min[attr->index];
1051c0b4e3abSDarrick J. Wong 	temp <<= 8;
1052c0b4e3abSDarrick J. Wong 
1053c0b4e3abSDarrick J. Wong 	if (!fan_enabled(data, attr->index) ||
1054c0b4e3abSDarrick J. Wong 	    !FAN_DATA_VALID(temp))
1055c0b4e3abSDarrick J. Wong 		return sprintf(buf, "0\n");
1056c0b4e3abSDarrick J. Wong 
1057c0b4e3abSDarrick J. Wong 	return sprintf(buf, "%d\n", FAN_PERIOD_TO_RPM(temp));
1058c0b4e3abSDarrick J. Wong }
1059c0b4e3abSDarrick J. Wong 
1060c0b4e3abSDarrick J. Wong static ssize_t set_fan_min(struct device *dev,
1061c0b4e3abSDarrick J. Wong 			   struct device_attribute *devattr,
1062c0b4e3abSDarrick J. Wong 			   const char *buf, size_t count)
1063c0b4e3abSDarrick J. Wong {
1064c0b4e3abSDarrick J. Wong 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
1065c0b4e3abSDarrick J. Wong 	struct i2c_client *client = to_i2c_client(dev);
1066c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = i2c_get_clientdata(client);
1067c0b4e3abSDarrick J. Wong 	long temp;
1068c0b4e3abSDarrick J. Wong 
1069179c4fdbSFrans Meulenbroeks 	if (kstrtol(buf, 10, &temp) || !temp ||
1070c0b4e3abSDarrick J. Wong 	    !fan_enabled(data, attr->index))
1071c0b4e3abSDarrick J. Wong 		return -EINVAL;
1072c0b4e3abSDarrick J. Wong 
1073c0b4e3abSDarrick J. Wong 	temp = FAN_RPM_TO_PERIOD(temp);
1074c0b4e3abSDarrick J. Wong 	temp >>= 8;
1075c0b4e3abSDarrick J. Wong 	temp = SENSORS_LIMIT(temp, 1, 255);
1076c0b4e3abSDarrick J. Wong 
1077c0b4e3abSDarrick J. Wong 	mutex_lock(&data->lock);
1078c0b4e3abSDarrick J. Wong 	data->fan_min[attr->index] = temp;
1079c0b4e3abSDarrick J. Wong 	i2c_smbus_write_byte_data(client, ADT7462_REG_FAN_MIN(attr->index),
1080c0b4e3abSDarrick J. Wong 				  temp);
1081c0b4e3abSDarrick J. Wong 	mutex_unlock(&data->lock);
1082c0b4e3abSDarrick J. Wong 
1083c0b4e3abSDarrick J. Wong 	return count;
1084c0b4e3abSDarrick J. Wong }
1085c0b4e3abSDarrick J. Wong 
1086c0b4e3abSDarrick J. Wong static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
1087c0b4e3abSDarrick J. Wong 			char *buf)
1088c0b4e3abSDarrick J. Wong {
1089c0b4e3abSDarrick J. Wong 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
1090c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = adt7462_update_device(dev);
1091c0b4e3abSDarrick J. Wong 
1092c0b4e3abSDarrick J. Wong 	if (!fan_enabled(data, attr->index) ||
1093c0b4e3abSDarrick J. Wong 	    !FAN_DATA_VALID(data->fan[attr->index]))
1094c0b4e3abSDarrick J. Wong 		return sprintf(buf, "0\n");
1095c0b4e3abSDarrick J. Wong 
1096c0b4e3abSDarrick J. Wong 	return sprintf(buf, "%d\n",
1097c0b4e3abSDarrick J. Wong 		       FAN_PERIOD_TO_RPM(data->fan[attr->index]));
1098c0b4e3abSDarrick J. Wong }
1099c0b4e3abSDarrick J. Wong 
1100c0b4e3abSDarrick J. Wong static ssize_t show_force_pwm_max(struct device *dev,
1101c0b4e3abSDarrick J. Wong 				  struct device_attribute *devattr,
1102c0b4e3abSDarrick J. Wong 				  char *buf)
1103c0b4e3abSDarrick J. Wong {
1104c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = adt7462_update_device(dev);
1105c0b4e3abSDarrick J. Wong 	return sprintf(buf, "%d\n", (data->cfg2 & ADT7462_FSPD_MASK ? 1 : 0));
1106c0b4e3abSDarrick J. Wong }
1107c0b4e3abSDarrick J. Wong 
1108c0b4e3abSDarrick J. Wong static ssize_t set_force_pwm_max(struct device *dev,
1109c0b4e3abSDarrick J. Wong 				 struct device_attribute *devattr,
1110c0b4e3abSDarrick J. Wong 				 const char *buf,
1111c0b4e3abSDarrick J. Wong 				 size_t count)
1112c0b4e3abSDarrick J. Wong {
1113c0b4e3abSDarrick J. Wong 	struct i2c_client *client = to_i2c_client(dev);
1114c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = i2c_get_clientdata(client);
1115c0b4e3abSDarrick J. Wong 	long temp;
1116c0b4e3abSDarrick J. Wong 	u8 reg;
1117c0b4e3abSDarrick J. Wong 
1118179c4fdbSFrans Meulenbroeks 	if (kstrtol(buf, 10, &temp))
1119c0b4e3abSDarrick J. Wong 		return -EINVAL;
1120c0b4e3abSDarrick J. Wong 
1121c0b4e3abSDarrick J. Wong 	mutex_lock(&data->lock);
1122c0b4e3abSDarrick J. Wong 	reg = i2c_smbus_read_byte_data(client, ADT7462_REG_CFG2);
1123c0b4e3abSDarrick J. Wong 	if (temp)
1124c0b4e3abSDarrick J. Wong 		reg |= ADT7462_FSPD_MASK;
1125c0b4e3abSDarrick J. Wong 	else
1126c0b4e3abSDarrick J. Wong 		reg &= ~ADT7462_FSPD_MASK;
1127c0b4e3abSDarrick J. Wong 	data->cfg2 = reg;
1128c0b4e3abSDarrick J. Wong 	i2c_smbus_write_byte_data(client, ADT7462_REG_CFG2, reg);
1129c0b4e3abSDarrick J. Wong 	mutex_unlock(&data->lock);
1130c0b4e3abSDarrick J. Wong 
1131c0b4e3abSDarrick J. Wong 	return count;
1132c0b4e3abSDarrick J. Wong }
1133c0b4e3abSDarrick J. Wong 
1134c0b4e3abSDarrick J. Wong static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr,
1135c0b4e3abSDarrick J. Wong 			char *buf)
1136c0b4e3abSDarrick J. Wong {
1137c0b4e3abSDarrick J. Wong 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
1138c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = adt7462_update_device(dev);
1139c0b4e3abSDarrick J. Wong 	return sprintf(buf, "%d\n", data->pwm[attr->index]);
1140c0b4e3abSDarrick J. Wong }
1141c0b4e3abSDarrick J. Wong 
1142c0b4e3abSDarrick J. Wong static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr,
1143c0b4e3abSDarrick J. Wong 			const char *buf, size_t count)
1144c0b4e3abSDarrick J. Wong {
1145c0b4e3abSDarrick J. Wong 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
1146c0b4e3abSDarrick J. Wong 	struct i2c_client *client = to_i2c_client(dev);
1147c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = i2c_get_clientdata(client);
1148c0b4e3abSDarrick J. Wong 	long temp;
1149c0b4e3abSDarrick J. Wong 
1150179c4fdbSFrans Meulenbroeks 	if (kstrtol(buf, 10, &temp))
1151c0b4e3abSDarrick J. Wong 		return -EINVAL;
1152c0b4e3abSDarrick J. Wong 
1153c0b4e3abSDarrick J. Wong 	temp = SENSORS_LIMIT(temp, 0, 255);
1154c0b4e3abSDarrick J. Wong 
1155c0b4e3abSDarrick J. Wong 	mutex_lock(&data->lock);
1156c0b4e3abSDarrick J. Wong 	data->pwm[attr->index] = temp;
1157c0b4e3abSDarrick J. Wong 	i2c_smbus_write_byte_data(client, ADT7462_REG_PWM(attr->index), temp);
1158c0b4e3abSDarrick J. Wong 	mutex_unlock(&data->lock);
1159c0b4e3abSDarrick J. Wong 
1160c0b4e3abSDarrick J. Wong 	return count;
1161c0b4e3abSDarrick J. Wong }
1162c0b4e3abSDarrick J. Wong 
1163c0b4e3abSDarrick J. Wong static ssize_t show_pwm_max(struct device *dev,
1164c0b4e3abSDarrick J. Wong 			    struct device_attribute *devattr,
1165c0b4e3abSDarrick J. Wong 			    char *buf)
1166c0b4e3abSDarrick J. Wong {
1167c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = adt7462_update_device(dev);
1168c0b4e3abSDarrick J. Wong 	return sprintf(buf, "%d\n", data->pwm_max);
1169c0b4e3abSDarrick J. Wong }
1170c0b4e3abSDarrick J. Wong 
1171c0b4e3abSDarrick J. Wong static ssize_t set_pwm_max(struct device *dev,
1172c0b4e3abSDarrick J. Wong 			   struct device_attribute *devattr,
1173c0b4e3abSDarrick J. Wong 			   const char *buf,
1174c0b4e3abSDarrick J. Wong 			   size_t count)
1175c0b4e3abSDarrick J. Wong {
1176c0b4e3abSDarrick J. Wong 	struct i2c_client *client = to_i2c_client(dev);
1177c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = i2c_get_clientdata(client);
1178c0b4e3abSDarrick J. Wong 	long temp;
1179c0b4e3abSDarrick J. Wong 
1180179c4fdbSFrans Meulenbroeks 	if (kstrtol(buf, 10, &temp))
1181c0b4e3abSDarrick J. Wong 		return -EINVAL;
1182c0b4e3abSDarrick J. Wong 
1183c0b4e3abSDarrick J. Wong 	temp = SENSORS_LIMIT(temp, 0, 255);
1184c0b4e3abSDarrick J. Wong 
1185c0b4e3abSDarrick J. Wong 	mutex_lock(&data->lock);
1186c0b4e3abSDarrick J. Wong 	data->pwm_max = temp;
1187c0b4e3abSDarrick J. Wong 	i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_MAX, temp);
1188c0b4e3abSDarrick J. Wong 	mutex_unlock(&data->lock);
1189c0b4e3abSDarrick J. Wong 
1190c0b4e3abSDarrick J. Wong 	return count;
1191c0b4e3abSDarrick J. Wong }
1192c0b4e3abSDarrick J. Wong 
1193c0b4e3abSDarrick J. Wong static ssize_t show_pwm_min(struct device *dev,
1194c0b4e3abSDarrick J. Wong 			    struct device_attribute *devattr,
1195c0b4e3abSDarrick J. Wong 			    char *buf)
1196c0b4e3abSDarrick J. Wong {
1197c0b4e3abSDarrick J. Wong 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
1198c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = adt7462_update_device(dev);
1199c0b4e3abSDarrick J. Wong 	return sprintf(buf, "%d\n", data->pwm_min[attr->index]);
1200c0b4e3abSDarrick J. Wong }
1201c0b4e3abSDarrick J. Wong 
1202c0b4e3abSDarrick J. Wong static ssize_t set_pwm_min(struct device *dev,
1203c0b4e3abSDarrick J. Wong 			   struct device_attribute *devattr,
1204c0b4e3abSDarrick J. Wong 			   const char *buf,
1205c0b4e3abSDarrick J. Wong 			   size_t count)
1206c0b4e3abSDarrick J. Wong {
1207c0b4e3abSDarrick J. Wong 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
1208c0b4e3abSDarrick J. Wong 	struct i2c_client *client = to_i2c_client(dev);
1209c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = i2c_get_clientdata(client);
1210c0b4e3abSDarrick J. Wong 	long temp;
1211c0b4e3abSDarrick J. Wong 
1212179c4fdbSFrans Meulenbroeks 	if (kstrtol(buf, 10, &temp))
1213c0b4e3abSDarrick J. Wong 		return -EINVAL;
1214c0b4e3abSDarrick J. Wong 
1215c0b4e3abSDarrick J. Wong 	temp = SENSORS_LIMIT(temp, 0, 255);
1216c0b4e3abSDarrick J. Wong 
1217c0b4e3abSDarrick J. Wong 	mutex_lock(&data->lock);
1218c0b4e3abSDarrick J. Wong 	data->pwm_min[attr->index] = temp;
1219c0b4e3abSDarrick J. Wong 	i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_MIN(attr->index),
1220c0b4e3abSDarrick J. Wong 				  temp);
1221c0b4e3abSDarrick J. Wong 	mutex_unlock(&data->lock);
1222c0b4e3abSDarrick J. Wong 
1223c0b4e3abSDarrick J. Wong 	return count;
1224c0b4e3abSDarrick J. Wong }
1225c0b4e3abSDarrick J. Wong 
1226c0b4e3abSDarrick J. Wong static ssize_t show_pwm_hyst(struct device *dev,
1227c0b4e3abSDarrick J. Wong 			     struct device_attribute *devattr,
1228c0b4e3abSDarrick J. Wong 			     char *buf)
1229c0b4e3abSDarrick J. Wong {
1230c0b4e3abSDarrick J. Wong 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
1231c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = adt7462_update_device(dev);
1232c0b4e3abSDarrick J. Wong 	return sprintf(buf, "%d\n", 1000 *
1233c0b4e3abSDarrick J. Wong 		      (data->pwm_trange[attr->index] & ADT7462_PWM_HYST_MASK));
1234c0b4e3abSDarrick J. Wong }
1235c0b4e3abSDarrick J. Wong 
1236c0b4e3abSDarrick J. Wong static ssize_t set_pwm_hyst(struct device *dev,
1237c0b4e3abSDarrick J. Wong 			    struct device_attribute *devattr,
1238c0b4e3abSDarrick J. Wong 			    const char *buf,
1239c0b4e3abSDarrick J. Wong 			    size_t count)
1240c0b4e3abSDarrick J. Wong {
1241c0b4e3abSDarrick J. Wong 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
1242c0b4e3abSDarrick J. Wong 	struct i2c_client *client = to_i2c_client(dev);
1243c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = i2c_get_clientdata(client);
1244c0b4e3abSDarrick J. Wong 	long temp;
1245c0b4e3abSDarrick J. Wong 
1246179c4fdbSFrans Meulenbroeks 	if (kstrtol(buf, 10, &temp))
1247c0b4e3abSDarrick J. Wong 		return -EINVAL;
1248c0b4e3abSDarrick J. Wong 
12498f8c1fb0SDarrick J. Wong 	temp = DIV_ROUND_CLOSEST(temp, 1000);
1250c0b4e3abSDarrick J. Wong 	temp = SENSORS_LIMIT(temp, 0, 15);
1251c0b4e3abSDarrick J. Wong 
1252c0b4e3abSDarrick J. Wong 	/* package things up */
1253c0b4e3abSDarrick J. Wong 	temp &= ADT7462_PWM_HYST_MASK;
1254c0b4e3abSDarrick J. Wong 	temp |= data->pwm_trange[attr->index] & ADT7462_PWM_RANGE_MASK;
1255c0b4e3abSDarrick J. Wong 
1256c0b4e3abSDarrick J. Wong 	mutex_lock(&data->lock);
1257c0b4e3abSDarrick J. Wong 	data->pwm_trange[attr->index] = temp;
1258c0b4e3abSDarrick J. Wong 	i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_TRANGE(attr->index),
1259c0b4e3abSDarrick J. Wong 				  temp);
1260c0b4e3abSDarrick J. Wong 	mutex_unlock(&data->lock);
1261c0b4e3abSDarrick J. Wong 
1262c0b4e3abSDarrick J. Wong 	return count;
1263c0b4e3abSDarrick J. Wong }
1264c0b4e3abSDarrick J. Wong 
1265c0b4e3abSDarrick J. Wong static ssize_t show_pwm_tmax(struct device *dev,
1266c0b4e3abSDarrick J. Wong 			     struct device_attribute *devattr,
1267c0b4e3abSDarrick J. Wong 			     char *buf)
1268c0b4e3abSDarrick J. Wong {
1269c0b4e3abSDarrick J. Wong 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
1270c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = adt7462_update_device(dev);
1271c0b4e3abSDarrick J. Wong 
1272c0b4e3abSDarrick J. Wong 	/* tmax = tmin + trange */
1273c0b4e3abSDarrick J. Wong 	int trange = trange_values[data->pwm_trange[attr->index] >>
1274c0b4e3abSDarrick J. Wong 				   ADT7462_PWM_RANGE_SHIFT];
1275c0b4e3abSDarrick J. Wong 	int tmin = (data->pwm_tmin[attr->index] - 64) * 1000;
1276c0b4e3abSDarrick J. Wong 
1277c0b4e3abSDarrick J. Wong 	return sprintf(buf, "%d\n", tmin + trange);
1278c0b4e3abSDarrick J. Wong }
1279c0b4e3abSDarrick J. Wong 
1280c0b4e3abSDarrick J. Wong static ssize_t set_pwm_tmax(struct device *dev,
1281c0b4e3abSDarrick J. Wong 			    struct device_attribute *devattr,
1282c0b4e3abSDarrick J. Wong 			    const char *buf,
1283c0b4e3abSDarrick J. Wong 			    size_t count)
1284c0b4e3abSDarrick J. Wong {
1285c0b4e3abSDarrick J. Wong 	int temp;
1286c0b4e3abSDarrick J. Wong 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
1287c0b4e3abSDarrick J. Wong 	struct i2c_client *client = to_i2c_client(dev);
1288c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = i2c_get_clientdata(client);
1289c0b4e3abSDarrick J. Wong 	int tmin, trange_value;
1290c0b4e3abSDarrick J. Wong 	long trange;
1291c0b4e3abSDarrick J. Wong 
1292179c4fdbSFrans Meulenbroeks 	if (kstrtol(buf, 10, &trange))
1293c0b4e3abSDarrick J. Wong 		return -EINVAL;
1294c0b4e3abSDarrick J. Wong 
1295c0b4e3abSDarrick J. Wong 	/* trange = tmax - tmin */
1296c0b4e3abSDarrick J. Wong 	tmin = (data->pwm_tmin[attr->index] - 64) * 1000;
1297c0b4e3abSDarrick J. Wong 	trange_value = find_trange_value(trange - tmin);
1298c0b4e3abSDarrick J. Wong 
1299c0b4e3abSDarrick J. Wong 	if (trange_value < 0)
1300c0b4e3abSDarrick J. Wong 		return -EINVAL;
1301c0b4e3abSDarrick J. Wong 
1302c0b4e3abSDarrick J. Wong 	temp = trange_value << ADT7462_PWM_RANGE_SHIFT;
1303c0b4e3abSDarrick J. Wong 	temp |= data->pwm_trange[attr->index] & ADT7462_PWM_HYST_MASK;
1304c0b4e3abSDarrick J. Wong 
1305c0b4e3abSDarrick J. Wong 	mutex_lock(&data->lock);
1306c0b4e3abSDarrick J. Wong 	data->pwm_trange[attr->index] = temp;
1307c0b4e3abSDarrick J. Wong 	i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_TRANGE(attr->index),
1308c0b4e3abSDarrick J. Wong 				  temp);
1309c0b4e3abSDarrick J. Wong 	mutex_unlock(&data->lock);
1310c0b4e3abSDarrick J. Wong 
1311c0b4e3abSDarrick J. Wong 	return count;
1312c0b4e3abSDarrick J. Wong }
1313c0b4e3abSDarrick J. Wong 
1314c0b4e3abSDarrick J. Wong static ssize_t show_pwm_tmin(struct device *dev,
1315c0b4e3abSDarrick J. Wong 			     struct device_attribute *devattr,
1316c0b4e3abSDarrick J. Wong 			     char *buf)
1317c0b4e3abSDarrick J. Wong {
1318c0b4e3abSDarrick J. Wong 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
1319c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = adt7462_update_device(dev);
1320c0b4e3abSDarrick J. Wong 	return sprintf(buf, "%d\n", 1000 * (data->pwm_tmin[attr->index] - 64));
1321c0b4e3abSDarrick J. Wong }
1322c0b4e3abSDarrick J. Wong 
1323c0b4e3abSDarrick J. Wong static ssize_t set_pwm_tmin(struct device *dev,
1324c0b4e3abSDarrick J. Wong 			    struct device_attribute *devattr,
1325c0b4e3abSDarrick J. Wong 			    const char *buf,
1326c0b4e3abSDarrick J. Wong 			    size_t count)
1327c0b4e3abSDarrick J. Wong {
1328c0b4e3abSDarrick J. Wong 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
1329c0b4e3abSDarrick J. Wong 	struct i2c_client *client = to_i2c_client(dev);
1330c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = i2c_get_clientdata(client);
1331c0b4e3abSDarrick J. Wong 	long temp;
1332c0b4e3abSDarrick J. Wong 
1333179c4fdbSFrans Meulenbroeks 	if (kstrtol(buf, 10, &temp))
1334c0b4e3abSDarrick J. Wong 		return -EINVAL;
1335c0b4e3abSDarrick J. Wong 
13368f8c1fb0SDarrick J. Wong 	temp = DIV_ROUND_CLOSEST(temp, 1000) + 64;
1337c0b4e3abSDarrick J. Wong 	temp = SENSORS_LIMIT(temp, 0, 255);
1338c0b4e3abSDarrick J. Wong 
1339c0b4e3abSDarrick J. Wong 	mutex_lock(&data->lock);
1340c0b4e3abSDarrick J. Wong 	data->pwm_tmin[attr->index] = temp;
1341c0b4e3abSDarrick J. Wong 	i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_TMIN(attr->index),
1342c0b4e3abSDarrick J. Wong 				  temp);
1343c0b4e3abSDarrick J. Wong 	mutex_unlock(&data->lock);
1344c0b4e3abSDarrick J. Wong 
1345c0b4e3abSDarrick J. Wong 	return count;
1346c0b4e3abSDarrick J. Wong }
1347c0b4e3abSDarrick J. Wong 
1348c0b4e3abSDarrick J. Wong static ssize_t show_pwm_auto(struct device *dev,
1349c0b4e3abSDarrick J. Wong 			     struct device_attribute *devattr,
1350c0b4e3abSDarrick J. Wong 			     char *buf)
1351c0b4e3abSDarrick J. Wong {
1352c0b4e3abSDarrick J. Wong 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
1353c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = adt7462_update_device(dev);
1354c0b4e3abSDarrick J. Wong 	int cfg = data->pwm_cfg[attr->index] >> ADT7462_PWM_CHANNEL_SHIFT;
1355c0b4e3abSDarrick J. Wong 
1356c0b4e3abSDarrick J. Wong 	switch (cfg) {
1357c0b4e3abSDarrick J. Wong 	case 4: /* off */
1358c0b4e3abSDarrick J. Wong 		return sprintf(buf, "0\n");
1359c0b4e3abSDarrick J. Wong 	case 7: /* manual */
1360c0b4e3abSDarrick J. Wong 		return sprintf(buf, "1\n");
1361c0b4e3abSDarrick J. Wong 	default: /* automatic */
1362c0b4e3abSDarrick J. Wong 		return sprintf(buf, "2\n");
1363c0b4e3abSDarrick J. Wong 	}
1364c0b4e3abSDarrick J. Wong }
1365c0b4e3abSDarrick J. Wong 
1366c0b4e3abSDarrick J. Wong static void set_pwm_channel(struct i2c_client *client,
1367c0b4e3abSDarrick J. Wong 			    struct adt7462_data *data,
1368c0b4e3abSDarrick J. Wong 			    int which,
1369c0b4e3abSDarrick J. Wong 			    int value)
1370c0b4e3abSDarrick J. Wong {
1371c0b4e3abSDarrick J. Wong 	int temp = data->pwm_cfg[which] & ~ADT7462_PWM_CHANNEL_MASK;
1372c0b4e3abSDarrick J. Wong 	temp |= value << ADT7462_PWM_CHANNEL_SHIFT;
1373c0b4e3abSDarrick J. Wong 
1374c0b4e3abSDarrick J. Wong 	mutex_lock(&data->lock);
1375c0b4e3abSDarrick J. Wong 	data->pwm_cfg[which] = temp;
1376c0b4e3abSDarrick J. Wong 	i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_CFG(which), temp);
1377c0b4e3abSDarrick J. Wong 	mutex_unlock(&data->lock);
1378c0b4e3abSDarrick J. Wong }
1379c0b4e3abSDarrick J. Wong 
1380c0b4e3abSDarrick J. Wong static ssize_t set_pwm_auto(struct device *dev,
1381c0b4e3abSDarrick J. Wong 			    struct device_attribute *devattr,
1382c0b4e3abSDarrick J. Wong 			    const char *buf,
1383c0b4e3abSDarrick J. Wong 			    size_t count)
1384c0b4e3abSDarrick J. Wong {
1385c0b4e3abSDarrick J. Wong 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
1386c0b4e3abSDarrick J. Wong 	struct i2c_client *client = to_i2c_client(dev);
1387c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = i2c_get_clientdata(client);
1388c0b4e3abSDarrick J. Wong 	long temp;
1389c0b4e3abSDarrick J. Wong 
1390179c4fdbSFrans Meulenbroeks 	if (kstrtol(buf, 10, &temp))
1391c0b4e3abSDarrick J. Wong 		return -EINVAL;
1392c0b4e3abSDarrick J. Wong 
1393c0b4e3abSDarrick J. Wong 	switch (temp) {
1394c0b4e3abSDarrick J. Wong 	case 0: /* off */
1395c0b4e3abSDarrick J. Wong 		set_pwm_channel(client, data, attr->index, 4);
1396c0b4e3abSDarrick J. Wong 		return count;
1397c0b4e3abSDarrick J. Wong 	case 1: /* manual */
1398c0b4e3abSDarrick J. Wong 		set_pwm_channel(client, data, attr->index, 7);
1399c0b4e3abSDarrick J. Wong 		return count;
1400c0b4e3abSDarrick J. Wong 	default:
1401c0b4e3abSDarrick J. Wong 		return -EINVAL;
1402c0b4e3abSDarrick J. Wong 	}
1403c0b4e3abSDarrick J. Wong }
1404c0b4e3abSDarrick J. Wong 
1405c0b4e3abSDarrick J. Wong static ssize_t show_pwm_auto_temp(struct device *dev,
1406c0b4e3abSDarrick J. Wong 				  struct device_attribute *devattr,
1407c0b4e3abSDarrick J. Wong 				  char *buf)
1408c0b4e3abSDarrick J. Wong {
1409c0b4e3abSDarrick J. Wong 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
1410c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = adt7462_update_device(dev);
1411c0b4e3abSDarrick J. Wong 	int channel = data->pwm_cfg[attr->index] >> ADT7462_PWM_CHANNEL_SHIFT;
1412c0b4e3abSDarrick J. Wong 
1413c0b4e3abSDarrick J. Wong 	switch (channel) {
1414c0b4e3abSDarrick J. Wong 	case 0: /* temp[1234] only */
1415c0b4e3abSDarrick J. Wong 	case 1:
1416c0b4e3abSDarrick J. Wong 	case 2:
1417c0b4e3abSDarrick J. Wong 	case 3:
1418c0b4e3abSDarrick J. Wong 		return sprintf(buf, "%d\n", (1 << channel));
1419c0b4e3abSDarrick J. Wong 	case 5: /* temp1 & temp4  */
1420c0b4e3abSDarrick J. Wong 		return sprintf(buf, "9\n");
1421c0b4e3abSDarrick J. Wong 	case 6:
1422c0b4e3abSDarrick J. Wong 		return sprintf(buf, "15\n");
1423c0b4e3abSDarrick J. Wong 	default:
1424c0b4e3abSDarrick J. Wong 		return sprintf(buf, "0\n");
1425c0b4e3abSDarrick J. Wong 	}
1426c0b4e3abSDarrick J. Wong }
1427c0b4e3abSDarrick J. Wong 
1428c0b4e3abSDarrick J. Wong static int cvt_auto_temp(int input)
1429c0b4e3abSDarrick J. Wong {
1430c0b4e3abSDarrick J. Wong 	if (input == 0xF)
1431c0b4e3abSDarrick J. Wong 		return 6;
1432c0b4e3abSDarrick J. Wong 	if (input == 0x9)
1433c0b4e3abSDarrick J. Wong 		return 5;
1434c0b4e3abSDarrick J. Wong 	if (input < 1 || !is_power_of_2(input))
1435c0b4e3abSDarrick J. Wong 		return -EINVAL;
1436c0b4e3abSDarrick J. Wong 	return ilog2(input);
1437c0b4e3abSDarrick J. Wong }
1438c0b4e3abSDarrick J. Wong 
1439c0b4e3abSDarrick J. Wong static ssize_t set_pwm_auto_temp(struct device *dev,
1440c0b4e3abSDarrick J. Wong 				 struct device_attribute *devattr,
1441c0b4e3abSDarrick J. Wong 				 const char *buf,
1442c0b4e3abSDarrick J. Wong 				 size_t count)
1443c0b4e3abSDarrick J. Wong {
1444c0b4e3abSDarrick J. Wong 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
1445c0b4e3abSDarrick J. Wong 	struct i2c_client *client = to_i2c_client(dev);
1446c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = i2c_get_clientdata(client);
1447c0b4e3abSDarrick J. Wong 	long temp;
1448c0b4e3abSDarrick J. Wong 
1449179c4fdbSFrans Meulenbroeks 	if (kstrtol(buf, 10, &temp))
1450c0b4e3abSDarrick J. Wong 		return -EINVAL;
1451c0b4e3abSDarrick J. Wong 
1452c0b4e3abSDarrick J. Wong 	temp = cvt_auto_temp(temp);
1453c0b4e3abSDarrick J. Wong 	if (temp < 0)
1454c0b4e3abSDarrick J. Wong 		return temp;
1455c0b4e3abSDarrick J. Wong 
1456c0b4e3abSDarrick J. Wong 	set_pwm_channel(client, data, attr->index, temp);
1457c0b4e3abSDarrick J. Wong 
1458c0b4e3abSDarrick J. Wong 	return count;
1459c0b4e3abSDarrick J. Wong }
1460c0b4e3abSDarrick J. Wong 
1461c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
1462c0b4e3abSDarrick J. Wong 		    set_temp_max, 0);
1463c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_max,
1464c0b4e3abSDarrick J. Wong 		    set_temp_max, 1);
1465c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_temp_max,
1466c0b4e3abSDarrick J. Wong 		    set_temp_max, 2);
1467c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_temp_max,
1468c0b4e3abSDarrick J. Wong 		    set_temp_max, 3);
1469c0b4e3abSDarrick J. Wong 
1470c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp_min,
1471c0b4e3abSDarrick J. Wong 		    set_temp_min, 0);
1472c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp_min,
1473c0b4e3abSDarrick J. Wong 		    set_temp_min, 1);
1474c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_temp_min,
1475c0b4e3abSDarrick J. Wong 		    set_temp_min, 2);
1476c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp4_min, S_IWUSR | S_IRUGO, show_temp_min,
1477c0b4e3abSDarrick J. Wong 		    set_temp_min, 3);
1478c0b4e3abSDarrick J. Wong 
1479c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
1480c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
1481c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
1482c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3);
1483c0b4e3abSDarrick J. Wong 
1484c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_temp_label, NULL, 0);
1485c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, show_temp_label, NULL, 1);
1486c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, show_temp_label, NULL, 2);
1487c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, show_temp_label, NULL, 3);
1488c0b4e3abSDarrick J. Wong 
1489c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL,
1490c0b4e3abSDarrick J. Wong 			  ADT7462_ALARM1 | ADT7462_LT_ALARM);
1491c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL,
1492c0b4e3abSDarrick J. Wong 			  ADT7462_ALARM1 | ADT7462_R1T_ALARM);
1493c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL,
1494c0b4e3abSDarrick J. Wong 			  ADT7462_ALARM1 | ADT7462_R2T_ALARM);
1495c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp4_alarm, S_IRUGO, show_alarm, NULL,
1496c0b4e3abSDarrick J. Wong 			  ADT7462_ALARM1 | ADT7462_R3T_ALARM);
1497c0b4e3abSDarrick J. Wong 
1498c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in1_max, S_IWUSR | S_IRUGO, show_volt_max,
1499c0b4e3abSDarrick J. Wong 		    set_volt_max, 0);
1500c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in2_max, S_IWUSR | S_IRUGO, show_volt_max,
1501c0b4e3abSDarrick J. Wong 		    set_volt_max, 1);
1502c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in3_max, S_IWUSR | S_IRUGO, show_volt_max,
1503c0b4e3abSDarrick J. Wong 		    set_volt_max, 2);
1504c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in4_max, S_IWUSR | S_IRUGO, show_volt_max,
1505c0b4e3abSDarrick J. Wong 		    set_volt_max, 3);
1506c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in5_max, S_IWUSR | S_IRUGO, show_volt_max,
1507c0b4e3abSDarrick J. Wong 		    set_volt_max, 4);
1508c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in6_max, S_IWUSR | S_IRUGO, show_volt_max,
1509c0b4e3abSDarrick J. Wong 		    set_volt_max, 5);
1510c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in7_max, S_IWUSR | S_IRUGO, show_volt_max,
1511c0b4e3abSDarrick J. Wong 		    set_volt_max, 6);
1512c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in8_max, S_IWUSR | S_IRUGO, show_volt_max,
1513c0b4e3abSDarrick J. Wong 		    set_volt_max, 7);
1514c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in9_max, S_IWUSR | S_IRUGO, show_volt_max,
1515c0b4e3abSDarrick J. Wong 		    set_volt_max, 8);
1516c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in10_max, S_IWUSR | S_IRUGO, show_volt_max,
1517c0b4e3abSDarrick J. Wong 		    set_volt_max, 9);
1518c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in11_max, S_IWUSR | S_IRUGO, show_volt_max,
1519c0b4e3abSDarrick J. Wong 		    set_volt_max, 10);
1520c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in12_max, S_IWUSR | S_IRUGO, show_volt_max,
1521c0b4e3abSDarrick J. Wong 		    set_volt_max, 11);
1522c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in13_max, S_IWUSR | S_IRUGO, show_volt_max,
1523c0b4e3abSDarrick J. Wong 		    set_volt_max, 12);
1524c0b4e3abSDarrick J. Wong 
1525c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in1_min, S_IWUSR | S_IRUGO, show_volt_min,
1526c0b4e3abSDarrick J. Wong 		    set_volt_min, 0);
1527c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in2_min, S_IWUSR | S_IRUGO, show_volt_min,
1528c0b4e3abSDarrick J. Wong 		    set_volt_min, 1);
1529c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in3_min, S_IWUSR | S_IRUGO, show_volt_min,
1530c0b4e3abSDarrick J. Wong 		    set_volt_min, 2);
1531c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in4_min, S_IWUSR | S_IRUGO, show_volt_min,
1532c0b4e3abSDarrick J. Wong 		    set_volt_min, 3);
1533c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in5_min, S_IWUSR | S_IRUGO, show_volt_min,
1534c0b4e3abSDarrick J. Wong 		    set_volt_min, 4);
1535c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in6_min, S_IWUSR | S_IRUGO, show_volt_min,
1536c0b4e3abSDarrick J. Wong 		    set_volt_min, 5);
1537c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in7_min, S_IWUSR | S_IRUGO, show_volt_min,
1538c0b4e3abSDarrick J. Wong 		    set_volt_min, 6);
1539c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in8_min, S_IWUSR | S_IRUGO, show_volt_min,
1540c0b4e3abSDarrick J. Wong 		    set_volt_min, 7);
1541c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in9_min, S_IWUSR | S_IRUGO, show_volt_min,
1542c0b4e3abSDarrick J. Wong 		    set_volt_min, 8);
1543c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in10_min, S_IWUSR | S_IRUGO, show_volt_min,
1544c0b4e3abSDarrick J. Wong 		    set_volt_min, 9);
1545c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in11_min, S_IWUSR | S_IRUGO, show_volt_min,
1546c0b4e3abSDarrick J. Wong 		    set_volt_min, 10);
1547c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in12_min, S_IWUSR | S_IRUGO, show_volt_min,
1548c0b4e3abSDarrick J. Wong 		    set_volt_min, 11);
1549c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in13_min, S_IWUSR | S_IRUGO, show_volt_min,
1550c0b4e3abSDarrick J. Wong 		    set_volt_min, 12);
1551c0b4e3abSDarrick J. Wong 
1552c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_voltage, NULL, 0);
1553c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_voltage, NULL, 1);
1554c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_voltage, NULL, 2);
1555c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_voltage, NULL, 3);
1556c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_voltage, NULL, 4);
1557c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_voltage, NULL, 5);
1558c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_voltage, NULL, 6);
1559c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_voltage, NULL, 7);
1560c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, show_voltage, NULL, 8);
1561c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, show_voltage, NULL, 9);
1562c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, show_voltage, NULL, 10);
1563c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, show_voltage, NULL, 11);
1564c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in13_input, S_IRUGO, show_voltage, NULL, 12);
1565c0b4e3abSDarrick J. Wong 
1566c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in1_label, S_IRUGO, show_voltage_label, NULL, 0);
1567c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in2_label, S_IRUGO, show_voltage_label, NULL, 1);
1568c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_voltage_label, NULL, 2);
1569c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in4_label, S_IRUGO, show_voltage_label, NULL, 3);
1570c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in5_label, S_IRUGO, show_voltage_label, NULL, 4);
1571c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in6_label, S_IRUGO, show_voltage_label, NULL, 5);
1572c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_voltage_label, NULL, 6);
1573c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in8_label, S_IRUGO, show_voltage_label, NULL, 7);
1574c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in9_label, S_IRUGO, show_voltage_label, NULL, 8);
1575c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in10_label, S_IRUGO, show_voltage_label, NULL, 9);
1576c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in11_label, S_IRUGO, show_voltage_label, NULL, 10);
1577c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in12_label, S_IRUGO, show_voltage_label, NULL, 11);
1578c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in13_label, S_IRUGO, show_voltage_label, NULL, 12);
1579c0b4e3abSDarrick J. Wong 
1580c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL,
1581c0b4e3abSDarrick J. Wong 			  ADT7462_ALARM2 | ADT7462_V0_ALARM);
1582c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL,
1583c0b4e3abSDarrick J. Wong 			  ADT7462_ALARM2 | ADT7462_V7_ALARM);
1584c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL,
1585c0b4e3abSDarrick J. Wong 			  ADT7462_ALARM2 | ADT7462_V2_ALARM);
1586c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL,
1587c0b4e3abSDarrick J. Wong 			  ADT7462_ALARM2 | ADT7462_V6_ALARM);
1588c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL,
1589c0b4e3abSDarrick J. Wong 			  ADT7462_ALARM2 | ADT7462_V5_ALARM);
1590c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL,
1591c0b4e3abSDarrick J. Wong 			  ADT7462_ALARM2 | ADT7462_V4_ALARM);
1592c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL,
1593c0b4e3abSDarrick J. Wong 			  ADT7462_ALARM2 | ADT7462_V3_ALARM);
1594c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL,
1595c0b4e3abSDarrick J. Wong 			  ADT7462_ALARM2 | ADT7462_V1_ALARM);
1596c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL,
1597c0b4e3abSDarrick J. Wong 			  ADT7462_ALARM3 | ADT7462_V10_ALARM);
1598c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in10_alarm, S_IRUGO, show_alarm, NULL,
1599c0b4e3abSDarrick J. Wong 			  ADT7462_ALARM3 | ADT7462_V9_ALARM);
1600c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in11_alarm, S_IRUGO, show_alarm, NULL,
1601c0b4e3abSDarrick J. Wong 			  ADT7462_ALARM3 | ADT7462_V8_ALARM);
1602c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in12_alarm, S_IRUGO, show_alarm, NULL,
1603c0b4e3abSDarrick J. Wong 			  ADT7462_ALARM3 | ADT7462_V11_ALARM);
1604c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(in13_alarm, S_IRUGO, show_alarm, NULL,
1605c0b4e3abSDarrick J. Wong 			  ADT7462_ALARM3 | ADT7462_V12_ALARM);
1606c0b4e3abSDarrick J. Wong 
1607c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min,
1608c0b4e3abSDarrick J. Wong 		    set_fan_min, 0);
1609c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min,
1610c0b4e3abSDarrick J. Wong 		    set_fan_min, 1);
1611c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min,
1612c0b4e3abSDarrick J. Wong 		    set_fan_min, 2);
1613c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min,
1614c0b4e3abSDarrick J. Wong 		    set_fan_min, 3);
1615c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min,
1616c0b4e3abSDarrick J. Wong 		    set_fan_min, 4);
1617c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan6_min, S_IWUSR | S_IRUGO, show_fan_min,
1618c0b4e3abSDarrick J. Wong 		    set_fan_min, 5);
1619c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan7_min, S_IWUSR | S_IRUGO, show_fan_min,
1620c0b4e3abSDarrick J. Wong 		    set_fan_min, 6);
1621c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan8_min, S_IWUSR | S_IRUGO, show_fan_min,
1622c0b4e3abSDarrick J. Wong 		    set_fan_min, 7);
1623c0b4e3abSDarrick J. Wong 
1624c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
1625c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
1626c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2);
1627c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3);
1628c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4);
1629c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan, NULL, 5);
1630c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan, NULL, 6);
1631c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_fan, NULL, 7);
1632c0b4e3abSDarrick J. Wong 
1633c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL,
1634c0b4e3abSDarrick J. Wong 			  ADT7462_ALARM4 | ADT7462_F0_ALARM);
1635c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL,
1636c0b4e3abSDarrick J. Wong 			  ADT7462_ALARM4 | ADT7462_F1_ALARM);
1637c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL,
1638c0b4e3abSDarrick J. Wong 			  ADT7462_ALARM4 | ADT7462_F2_ALARM);
1639c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL,
1640c0b4e3abSDarrick J. Wong 			  ADT7462_ALARM4 | ADT7462_F3_ALARM);
1641c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL,
1642c0b4e3abSDarrick J. Wong 			  ADT7462_ALARM4 | ADT7462_F4_ALARM);
1643c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_alarm, NULL,
1644c0b4e3abSDarrick J. Wong 			  ADT7462_ALARM4 | ADT7462_F5_ALARM);
1645c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_alarm, NULL,
1646c0b4e3abSDarrick J. Wong 			  ADT7462_ALARM4 | ADT7462_F6_ALARM);
1647c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO, show_alarm, NULL,
1648c0b4e3abSDarrick J. Wong 			  ADT7462_ALARM4 | ADT7462_F7_ALARM);
1649c0b4e3abSDarrick J. Wong 
1650c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(force_pwm_max, S_IWUSR | S_IRUGO,
1651c0b4e3abSDarrick J. Wong 		    show_force_pwm_max, set_force_pwm_max, 0);
1652c0b4e3abSDarrick J. Wong 
1653c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0);
1654c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1);
1655c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2);
1656c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 3);
1657c0b4e3abSDarrick J. Wong 
1658c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IWUSR | S_IRUGO,
1659c0b4e3abSDarrick J. Wong 		    show_pwm_min, set_pwm_min, 0);
1660c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm2_auto_point1_pwm, S_IWUSR | S_IRUGO,
1661c0b4e3abSDarrick J. Wong 		    show_pwm_min, set_pwm_min, 1);
1662c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm3_auto_point1_pwm, S_IWUSR | S_IRUGO,
1663c0b4e3abSDarrick J. Wong 		    show_pwm_min, set_pwm_min, 2);
1664c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm4_auto_point1_pwm, S_IWUSR | S_IRUGO,
1665c0b4e3abSDarrick J. Wong 		    show_pwm_min, set_pwm_min, 3);
1666c0b4e3abSDarrick J. Wong 
1667c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm1_auto_point2_pwm, S_IWUSR | S_IRUGO,
1668c0b4e3abSDarrick J. Wong 		    show_pwm_max, set_pwm_max, 0);
1669c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm2_auto_point2_pwm, S_IWUSR | S_IRUGO,
1670c0b4e3abSDarrick J. Wong 		    show_pwm_max, set_pwm_max, 1);
1671c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm3_auto_point2_pwm, S_IWUSR | S_IRUGO,
1672c0b4e3abSDarrick J. Wong 		    show_pwm_max, set_pwm_max, 2);
1673c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm4_auto_point2_pwm, S_IWUSR | S_IRUGO,
1674c0b4e3abSDarrick J. Wong 		    show_pwm_max, set_pwm_max, 3);
1675c0b4e3abSDarrick J. Wong 
1676c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp1_auto_point1_hyst, S_IWUSR | S_IRUGO,
1677c0b4e3abSDarrick J. Wong 		    show_pwm_hyst, set_pwm_hyst, 0);
1678c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp2_auto_point1_hyst, S_IWUSR | S_IRUGO,
1679c0b4e3abSDarrick J. Wong 		    show_pwm_hyst, set_pwm_hyst, 1);
1680c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp3_auto_point1_hyst, S_IWUSR | S_IRUGO,
1681c0b4e3abSDarrick J. Wong 		    show_pwm_hyst, set_pwm_hyst, 2);
1682c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp4_auto_point1_hyst, S_IWUSR | S_IRUGO,
1683c0b4e3abSDarrick J. Wong 		    show_pwm_hyst, set_pwm_hyst, 3);
1684c0b4e3abSDarrick J. Wong 
1685c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp1_auto_point2_hyst, S_IWUSR | S_IRUGO,
1686c0b4e3abSDarrick J. Wong 		    show_pwm_hyst, set_pwm_hyst, 0);
1687c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp2_auto_point2_hyst, S_IWUSR | S_IRUGO,
1688c0b4e3abSDarrick J. Wong 		    show_pwm_hyst, set_pwm_hyst, 1);
1689c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp3_auto_point2_hyst, S_IWUSR | S_IRUGO,
1690c0b4e3abSDarrick J. Wong 		    show_pwm_hyst, set_pwm_hyst, 2);
1691c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp4_auto_point2_hyst, S_IWUSR | S_IRUGO,
1692c0b4e3abSDarrick J. Wong 		    show_pwm_hyst, set_pwm_hyst, 3);
1693c0b4e3abSDarrick J. Wong 
1694c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp1_auto_point1_temp, S_IWUSR | S_IRUGO,
1695c0b4e3abSDarrick J. Wong 		    show_pwm_tmin, set_pwm_tmin, 0);
1696c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp2_auto_point1_temp, S_IWUSR | S_IRUGO,
1697c0b4e3abSDarrick J. Wong 		    show_pwm_tmin, set_pwm_tmin, 1);
1698c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp3_auto_point1_temp, S_IWUSR | S_IRUGO,
1699c0b4e3abSDarrick J. Wong 		    show_pwm_tmin, set_pwm_tmin, 2);
1700c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp4_auto_point1_temp, S_IWUSR | S_IRUGO,
1701c0b4e3abSDarrick J. Wong 		    show_pwm_tmin, set_pwm_tmin, 3);
1702c0b4e3abSDarrick J. Wong 
1703c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp1_auto_point2_temp, S_IWUSR | S_IRUGO,
1704c0b4e3abSDarrick J. Wong 		    show_pwm_tmax, set_pwm_tmax, 0);
1705c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp2_auto_point2_temp, S_IWUSR | S_IRUGO,
1706c0b4e3abSDarrick J. Wong 		    show_pwm_tmax, set_pwm_tmax, 1);
1707c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp3_auto_point2_temp, S_IWUSR | S_IRUGO,
1708c0b4e3abSDarrick J. Wong 		    show_pwm_tmax, set_pwm_tmax, 2);
1709c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(temp4_auto_point2_temp, S_IWUSR | S_IRUGO,
1710c0b4e3abSDarrick J. Wong 		    show_pwm_tmax, set_pwm_tmax, 3);
1711c0b4e3abSDarrick J. Wong 
1712c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_auto,
1713c0b4e3abSDarrick J. Wong 		    set_pwm_auto, 0);
1714c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_auto,
1715c0b4e3abSDarrick J. Wong 		    set_pwm_auto, 1);
1716c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, show_pwm_auto,
1717c0b4e3abSDarrick J. Wong 		    set_pwm_auto, 2);
1718c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, show_pwm_auto,
1719c0b4e3abSDarrick J. Wong 		    set_pwm_auto, 3);
1720c0b4e3abSDarrick J. Wong 
1721c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm1_auto_channels_temp, S_IWUSR | S_IRUGO,
1722c0b4e3abSDarrick J. Wong 		    show_pwm_auto_temp, set_pwm_auto_temp, 0);
1723c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm2_auto_channels_temp, S_IWUSR | S_IRUGO,
1724c0b4e3abSDarrick J. Wong 		    show_pwm_auto_temp, set_pwm_auto_temp, 1);
1725c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm3_auto_channels_temp, S_IWUSR | S_IRUGO,
1726c0b4e3abSDarrick J. Wong 		    show_pwm_auto_temp, set_pwm_auto_temp, 2);
1727c0b4e3abSDarrick J. Wong static SENSOR_DEVICE_ATTR(pwm4_auto_channels_temp, S_IWUSR | S_IRUGO,
1728c0b4e3abSDarrick J. Wong 		    show_pwm_auto_temp, set_pwm_auto_temp, 3);
1729c0b4e3abSDarrick J. Wong 
1730724cc331SGuenter Roeck static struct attribute *adt7462_attr[] = {
1731c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp1_max.dev_attr.attr,
1732c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp2_max.dev_attr.attr,
1733c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp3_max.dev_attr.attr,
1734c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp4_max.dev_attr.attr,
1735c0b4e3abSDarrick J. Wong 
1736c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp1_min.dev_attr.attr,
1737c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp2_min.dev_attr.attr,
1738c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp3_min.dev_attr.attr,
1739c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp4_min.dev_attr.attr,
1740c0b4e3abSDarrick J. Wong 
1741c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp1_input.dev_attr.attr,
1742c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp2_input.dev_attr.attr,
1743c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp3_input.dev_attr.attr,
1744c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp4_input.dev_attr.attr,
1745c0b4e3abSDarrick J. Wong 
1746c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp1_label.dev_attr.attr,
1747c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp2_label.dev_attr.attr,
1748c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp3_label.dev_attr.attr,
1749c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp4_label.dev_attr.attr,
1750c0b4e3abSDarrick J. Wong 
1751c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp1_alarm.dev_attr.attr,
1752c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp2_alarm.dev_attr.attr,
1753c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp3_alarm.dev_attr.attr,
1754c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp4_alarm.dev_attr.attr,
1755c0b4e3abSDarrick J. Wong 
1756c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in1_max.dev_attr.attr,
1757c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in2_max.dev_attr.attr,
1758c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in3_max.dev_attr.attr,
1759c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in4_max.dev_attr.attr,
1760c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in5_max.dev_attr.attr,
1761c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in6_max.dev_attr.attr,
1762c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in7_max.dev_attr.attr,
1763c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in8_max.dev_attr.attr,
1764c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in9_max.dev_attr.attr,
1765c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in10_max.dev_attr.attr,
1766c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in11_max.dev_attr.attr,
1767c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in12_max.dev_attr.attr,
1768c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in13_max.dev_attr.attr,
1769c0b4e3abSDarrick J. Wong 
1770c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in1_min.dev_attr.attr,
1771c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in2_min.dev_attr.attr,
1772c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in3_min.dev_attr.attr,
1773c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in4_min.dev_attr.attr,
1774c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in5_min.dev_attr.attr,
1775c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in6_min.dev_attr.attr,
1776c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in7_min.dev_attr.attr,
1777c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in8_min.dev_attr.attr,
1778c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in9_min.dev_attr.attr,
1779c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in10_min.dev_attr.attr,
1780c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in11_min.dev_attr.attr,
1781c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in12_min.dev_attr.attr,
1782c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in13_min.dev_attr.attr,
1783c0b4e3abSDarrick J. Wong 
1784c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in1_input.dev_attr.attr,
1785c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in2_input.dev_attr.attr,
1786c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in3_input.dev_attr.attr,
1787c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in4_input.dev_attr.attr,
1788c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in5_input.dev_attr.attr,
1789c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in6_input.dev_attr.attr,
1790c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in7_input.dev_attr.attr,
1791c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in8_input.dev_attr.attr,
1792c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in9_input.dev_attr.attr,
1793c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in10_input.dev_attr.attr,
1794c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in11_input.dev_attr.attr,
1795c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in12_input.dev_attr.attr,
1796c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in13_input.dev_attr.attr,
1797c0b4e3abSDarrick J. Wong 
1798c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in1_label.dev_attr.attr,
1799c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in2_label.dev_attr.attr,
1800c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in3_label.dev_attr.attr,
1801c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in4_label.dev_attr.attr,
1802c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in5_label.dev_attr.attr,
1803c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in6_label.dev_attr.attr,
1804c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in7_label.dev_attr.attr,
1805c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in8_label.dev_attr.attr,
1806c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in9_label.dev_attr.attr,
1807c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in10_label.dev_attr.attr,
1808c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in11_label.dev_attr.attr,
1809c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in12_label.dev_attr.attr,
1810c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in13_label.dev_attr.attr,
1811c0b4e3abSDarrick J. Wong 
1812c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in1_alarm.dev_attr.attr,
1813c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in2_alarm.dev_attr.attr,
1814c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in3_alarm.dev_attr.attr,
1815c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in4_alarm.dev_attr.attr,
1816c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in5_alarm.dev_attr.attr,
1817c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in6_alarm.dev_attr.attr,
1818c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in7_alarm.dev_attr.attr,
1819c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in8_alarm.dev_attr.attr,
1820c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in9_alarm.dev_attr.attr,
1821c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in10_alarm.dev_attr.attr,
1822c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in11_alarm.dev_attr.attr,
1823c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in12_alarm.dev_attr.attr,
1824c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_in13_alarm.dev_attr.attr,
1825c0b4e3abSDarrick J. Wong 
1826c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_fan1_min.dev_attr.attr,
1827c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_fan2_min.dev_attr.attr,
1828c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_fan3_min.dev_attr.attr,
1829c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_fan4_min.dev_attr.attr,
1830c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_fan5_min.dev_attr.attr,
1831c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_fan6_min.dev_attr.attr,
1832c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_fan7_min.dev_attr.attr,
1833c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_fan8_min.dev_attr.attr,
1834c0b4e3abSDarrick J. Wong 
1835c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_fan1_input.dev_attr.attr,
1836c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_fan2_input.dev_attr.attr,
1837c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_fan3_input.dev_attr.attr,
1838c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_fan4_input.dev_attr.attr,
1839c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_fan5_input.dev_attr.attr,
1840c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_fan6_input.dev_attr.attr,
1841c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_fan7_input.dev_attr.attr,
1842c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_fan8_input.dev_attr.attr,
1843c0b4e3abSDarrick J. Wong 
1844c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
1845c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
1846c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_fan3_alarm.dev_attr.attr,
1847c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_fan4_alarm.dev_attr.attr,
1848c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_fan5_alarm.dev_attr.attr,
1849c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_fan6_alarm.dev_attr.attr,
1850c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_fan7_alarm.dev_attr.attr,
1851c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_fan8_alarm.dev_attr.attr,
1852c0b4e3abSDarrick J. Wong 
1853c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_force_pwm_max.dev_attr.attr,
1854c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_pwm1.dev_attr.attr,
1855c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_pwm2.dev_attr.attr,
1856c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_pwm3.dev_attr.attr,
1857c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_pwm4.dev_attr.attr,
1858c0b4e3abSDarrick J. Wong 
1859c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr,
1860c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr,
1861c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr,
1862c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_pwm4_auto_point1_pwm.dev_attr.attr,
1863c0b4e3abSDarrick J. Wong 
1864c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr,
1865c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr,
1866c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr,
1867c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_pwm4_auto_point2_pwm.dev_attr.attr,
1868c0b4e3abSDarrick J. Wong 
1869c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp1_auto_point1_hyst.dev_attr.attr,
1870c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp2_auto_point1_hyst.dev_attr.attr,
1871c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp3_auto_point1_hyst.dev_attr.attr,
1872c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp4_auto_point1_hyst.dev_attr.attr,
1873c0b4e3abSDarrick J. Wong 
1874c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp1_auto_point2_hyst.dev_attr.attr,
1875c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp2_auto_point2_hyst.dev_attr.attr,
1876c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp3_auto_point2_hyst.dev_attr.attr,
1877c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp4_auto_point2_hyst.dev_attr.attr,
1878c0b4e3abSDarrick J. Wong 
1879c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr,
1880c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr,
1881c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp3_auto_point1_temp.dev_attr.attr,
1882c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp4_auto_point1_temp.dev_attr.attr,
1883c0b4e3abSDarrick J. Wong 
1884c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr,
1885c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr,
1886c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp3_auto_point2_temp.dev_attr.attr,
1887c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_temp4_auto_point2_temp.dev_attr.attr,
1888c0b4e3abSDarrick J. Wong 
1889c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_pwm1_enable.dev_attr.attr,
1890c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_pwm2_enable.dev_attr.attr,
1891c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_pwm3_enable.dev_attr.attr,
1892c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_pwm4_enable.dev_attr.attr,
1893c0b4e3abSDarrick J. Wong 
1894c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr,
1895c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr,
1896c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_pwm3_auto_channels_temp.dev_attr.attr,
1897c0b4e3abSDarrick J. Wong 	&sensor_dev_attr_pwm4_auto_channels_temp.dev_attr.attr,
1898c0b4e3abSDarrick J. Wong 	NULL
1899c0b4e3abSDarrick J. Wong };
1900c0b4e3abSDarrick J. Wong 
1901c0b4e3abSDarrick J. Wong /* Return 0 if detection is successful, -ENODEV otherwise */
1902310ec792SJean Delvare static int adt7462_detect(struct i2c_client *client,
1903c0b4e3abSDarrick J. Wong 			  struct i2c_board_info *info)
1904c0b4e3abSDarrick J. Wong {
1905c0b4e3abSDarrick J. Wong 	struct i2c_adapter *adapter = client->adapter;
190652df6440SJean Delvare 	int vendor, device, revision;
1907c0b4e3abSDarrick J. Wong 
1908c0b4e3abSDarrick J. Wong 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
1909c0b4e3abSDarrick J. Wong 		return -ENODEV;
1910c0b4e3abSDarrick J. Wong 
1911c0b4e3abSDarrick J. Wong 	vendor = i2c_smbus_read_byte_data(client, ADT7462_REG_VENDOR);
1912c0b4e3abSDarrick J. Wong 	if (vendor != ADT7462_VENDOR)
1913c0b4e3abSDarrick J. Wong 		return -ENODEV;
1914c0b4e3abSDarrick J. Wong 
1915c0b4e3abSDarrick J. Wong 	device = i2c_smbus_read_byte_data(client, ADT7462_REG_DEVICE);
1916c0b4e3abSDarrick J. Wong 	if (device != ADT7462_DEVICE)
1917c0b4e3abSDarrick J. Wong 		return -ENODEV;
1918c0b4e3abSDarrick J. Wong 
191952df6440SJean Delvare 	revision = i2c_smbus_read_byte_data(client, ADT7462_REG_REVISION);
1920c0b4e3abSDarrick J. Wong 	if (revision != ADT7462_REVISION)
1921c0b4e3abSDarrick J. Wong 		return -ENODEV;
1922c0b4e3abSDarrick J. Wong 
1923c0b4e3abSDarrick J. Wong 	strlcpy(info->type, "adt7462", I2C_NAME_SIZE);
1924c0b4e3abSDarrick J. Wong 
1925c0b4e3abSDarrick J. Wong 	return 0;
1926c0b4e3abSDarrick J. Wong }
1927c0b4e3abSDarrick J. Wong 
1928c0b4e3abSDarrick J. Wong static int adt7462_probe(struct i2c_client *client,
1929c0b4e3abSDarrick J. Wong 			 const struct i2c_device_id *id)
1930c0b4e3abSDarrick J. Wong {
1931c0b4e3abSDarrick J. Wong 	struct adt7462_data *data;
1932c0b4e3abSDarrick J. Wong 	int err;
1933c0b4e3abSDarrick J. Wong 
1934*08808300SGuenter Roeck 	data = devm_kzalloc(&client->dev, sizeof(struct adt7462_data),
1935*08808300SGuenter Roeck 			    GFP_KERNEL);
1936*08808300SGuenter Roeck 	if (!data)
1937*08808300SGuenter Roeck 		return -ENOMEM;
1938c0b4e3abSDarrick J. Wong 
1939c0b4e3abSDarrick J. Wong 	i2c_set_clientdata(client, data);
1940c0b4e3abSDarrick J. Wong 	mutex_init(&data->lock);
1941c0b4e3abSDarrick J. Wong 
1942c0b4e3abSDarrick J. Wong 	dev_info(&client->dev, "%s chip found\n", client->name);
1943c0b4e3abSDarrick J. Wong 
1944c0b4e3abSDarrick J. Wong 	/* Register sysfs hooks */
1945c0b4e3abSDarrick J. Wong 	data->attrs.attrs = adt7462_attr;
1946c0b4e3abSDarrick J. Wong 	err = sysfs_create_group(&client->dev.kobj, &data->attrs);
1947c0b4e3abSDarrick J. Wong 	if (err)
1948*08808300SGuenter Roeck 		return err;
1949c0b4e3abSDarrick J. Wong 
1950c0b4e3abSDarrick J. Wong 	data->hwmon_dev = hwmon_device_register(&client->dev);
1951c0b4e3abSDarrick J. Wong 	if (IS_ERR(data->hwmon_dev)) {
1952c0b4e3abSDarrick J. Wong 		err = PTR_ERR(data->hwmon_dev);
1953c0b4e3abSDarrick J. Wong 		goto exit_remove;
1954c0b4e3abSDarrick J. Wong 	}
1955c0b4e3abSDarrick J. Wong 
1956c0b4e3abSDarrick J. Wong 	return 0;
1957c0b4e3abSDarrick J. Wong 
1958c0b4e3abSDarrick J. Wong exit_remove:
1959c0b4e3abSDarrick J. Wong 	sysfs_remove_group(&client->dev.kobj, &data->attrs);
1960c0b4e3abSDarrick J. Wong 	return err;
1961c0b4e3abSDarrick J. Wong }
1962c0b4e3abSDarrick J. Wong 
1963c0b4e3abSDarrick J. Wong static int adt7462_remove(struct i2c_client *client)
1964c0b4e3abSDarrick J. Wong {
1965c0b4e3abSDarrick J. Wong 	struct adt7462_data *data = i2c_get_clientdata(client);
1966c0b4e3abSDarrick J. Wong 
1967c0b4e3abSDarrick J. Wong 	hwmon_device_unregister(data->hwmon_dev);
1968c0b4e3abSDarrick J. Wong 	sysfs_remove_group(&client->dev.kobj, &data->attrs);
1969c0b4e3abSDarrick J. Wong 	return 0;
1970c0b4e3abSDarrick J. Wong }
1971c0b4e3abSDarrick J. Wong 
1972f0967eeaSAxel Lin module_i2c_driver(adt7462_driver);
1973c0b4e3abSDarrick J. Wong 
1974c0b4e3abSDarrick J. Wong MODULE_AUTHOR("Darrick J. Wong <djwong@us.ibm.com>");
1975c0b4e3abSDarrick J. Wong MODULE_DESCRIPTION("ADT7462 driver");
1976c0b4e3abSDarrick J. Wong MODULE_LICENSE("GPL");
1977