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