xref: /openbmc/linux/drivers/hwmon/nct6775-core.c (revision c3963bc0a0cf9ecb205a9d4976eb92b6df2fa3fd)
1*c3963bc0SZev Weiss // SPDX-License-Identifier: GPL-2.0-or-later
2*c3963bc0SZev Weiss /*
3*c3963bc0SZev Weiss  * nct6775 - Driver for the hardware monitoring functionality of
4*c3963bc0SZev Weiss  *	       Nuvoton NCT677x Super-I/O chips
5*c3963bc0SZev Weiss  *
6*c3963bc0SZev Weiss  * Copyright (C) 2012  Guenter Roeck <linux@roeck-us.net>
7*c3963bc0SZev Weiss  *
8*c3963bc0SZev Weiss  * Derived from w83627ehf driver
9*c3963bc0SZev Weiss  * Copyright (C) 2005-2012  Jean Delvare <jdelvare@suse.de>
10*c3963bc0SZev Weiss  * Copyright (C) 2006  Yuan Mu (Winbond),
11*c3963bc0SZev Weiss  *		       Rudolf Marek <r.marek@assembler.cz>
12*c3963bc0SZev Weiss  *		       David Hubbard <david.c.hubbard@gmail.com>
13*c3963bc0SZev Weiss  *		       Daniel J Blueman <daniel.blueman@gmail.com>
14*c3963bc0SZev Weiss  * Copyright (C) 2010  Sheng-Yuan Huang (Nuvoton) (PS00)
15*c3963bc0SZev Weiss  *
16*c3963bc0SZev Weiss  * Shamelessly ripped from the w83627hf driver
17*c3963bc0SZev Weiss  * Copyright (C) 2003  Mark Studebaker
18*c3963bc0SZev Weiss  *
19*c3963bc0SZev Weiss  * Supports the following chips:
20*c3963bc0SZev Weiss  *
21*c3963bc0SZev Weiss  * Chip        #vin    #fan    #pwm    #temp  chip IDs       man ID
22*c3963bc0SZev Weiss  * nct6106d     9      3       3       6+3    0xc450 0xc1    0x5ca3
23*c3963bc0SZev Weiss  * nct6116d     9      5       5       3+3    0xd280 0xc1    0x5ca3
24*c3963bc0SZev Weiss  * nct6775f     9      4       3       6+3    0xb470 0xc1    0x5ca3
25*c3963bc0SZev Weiss  * nct6776f     9      5       3       6+3    0xc330 0xc1    0x5ca3
26*c3963bc0SZev Weiss  * nct6779d    15      5       5       2+6    0xc560 0xc1    0x5ca3
27*c3963bc0SZev Weiss  * nct6791d    15      6       6       2+6    0xc800 0xc1    0x5ca3
28*c3963bc0SZev Weiss  * nct6792d    15      6       6       2+6    0xc910 0xc1    0x5ca3
29*c3963bc0SZev Weiss  * nct6793d    15      6       6       2+6    0xd120 0xc1    0x5ca3
30*c3963bc0SZev Weiss  * nct6795d    14      6       6       2+6    0xd350 0xc1    0x5ca3
31*c3963bc0SZev Weiss  * nct6796d    14      7       7       2+6    0xd420 0xc1    0x5ca3
32*c3963bc0SZev Weiss  * nct6797d    14      7       7       2+6    0xd450 0xc1    0x5ca3
33*c3963bc0SZev Weiss  *                                           (0xd451)
34*c3963bc0SZev Weiss  * nct6798d    14      7       7       2+6    0xd428 0xc1    0x5ca3
35*c3963bc0SZev Weiss  *                                           (0xd429)
36*c3963bc0SZev Weiss  *
37*c3963bc0SZev Weiss  * #temp lists the number of monitored temperature sources (first value) plus
38*c3963bc0SZev Weiss  * the number of directly connectable temperature sensors (second value).
39*c3963bc0SZev Weiss  */
40*c3963bc0SZev Weiss 
41*c3963bc0SZev Weiss #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
42*c3963bc0SZev Weiss 
43*c3963bc0SZev Weiss #include <linux/module.h>
44*c3963bc0SZev Weiss #include <linux/init.h>
45*c3963bc0SZev Weiss #include <linux/slab.h>
46*c3963bc0SZev Weiss #include <linux/jiffies.h>
47*c3963bc0SZev Weiss #include <linux/hwmon.h>
48*c3963bc0SZev Weiss #include <linux/hwmon-sysfs.h>
49*c3963bc0SZev Weiss #include <linux/err.h>
50*c3963bc0SZev Weiss #include <linux/mutex.h>
51*c3963bc0SZev Weiss #include <linux/bitops.h>
52*c3963bc0SZev Weiss #include <linux/nospec.h>
53*c3963bc0SZev Weiss #include <linux/regmap.h>
54*c3963bc0SZev Weiss #include "lm75.h"
55*c3963bc0SZev Weiss #include "nct6775.h"
56*c3963bc0SZev Weiss 
57*c3963bc0SZev Weiss #undef DEFAULT_SYMBOL_NAMESPACE
58*c3963bc0SZev Weiss #define DEFAULT_SYMBOL_NAMESPACE HWMON_NCT6775
59*c3963bc0SZev Weiss 
60*c3963bc0SZev Weiss #define USE_ALTERNATE
61*c3963bc0SZev Weiss 
62*c3963bc0SZev Weiss /* used to set data->name = nct6775_device_names[data->sio_kind] */
63*c3963bc0SZev Weiss static const char * const nct6775_device_names[] = {
64*c3963bc0SZev Weiss 	"nct6106",
65*c3963bc0SZev Weiss 	"nct6116",
66*c3963bc0SZev Weiss 	"nct6775",
67*c3963bc0SZev Weiss 	"nct6776",
68*c3963bc0SZev Weiss 	"nct6779",
69*c3963bc0SZev Weiss 	"nct6791",
70*c3963bc0SZev Weiss 	"nct6792",
71*c3963bc0SZev Weiss 	"nct6793",
72*c3963bc0SZev Weiss 	"nct6795",
73*c3963bc0SZev Weiss 	"nct6796",
74*c3963bc0SZev Weiss 	"nct6797",
75*c3963bc0SZev Weiss 	"nct6798",
76*c3963bc0SZev Weiss };
77*c3963bc0SZev Weiss 
78*c3963bc0SZev Weiss /* Common and NCT6775 specific data */
79*c3963bc0SZev Weiss 
80*c3963bc0SZev Weiss /* Voltage min/max registers for nr=7..14 are in bank 5 */
81*c3963bc0SZev Weiss 
82*c3963bc0SZev Weiss static const u16 NCT6775_REG_IN_MAX[] = {
83*c3963bc0SZev Weiss 	0x2b, 0x2d, 0x2f, 0x31, 0x33, 0x35, 0x37, 0x554, 0x556, 0x558, 0x55a,
84*c3963bc0SZev Weiss 	0x55c, 0x55e, 0x560, 0x562 };
85*c3963bc0SZev Weiss static const u16 NCT6775_REG_IN_MIN[] = {
86*c3963bc0SZev Weiss 	0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x555, 0x557, 0x559, 0x55b,
87*c3963bc0SZev Weiss 	0x55d, 0x55f, 0x561, 0x563 };
88*c3963bc0SZev Weiss static const u16 NCT6775_REG_IN[] = {
89*c3963bc0SZev Weiss 	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x550, 0x551, 0x552
90*c3963bc0SZev Weiss };
91*c3963bc0SZev Weiss 
92*c3963bc0SZev Weiss #define NCT6775_REG_VBAT		0x5D
93*c3963bc0SZev Weiss #define NCT6775_REG_DIODE		0x5E
94*c3963bc0SZev Weiss #define NCT6775_DIODE_MASK		0x02
95*c3963bc0SZev Weiss 
96*c3963bc0SZev Weiss static const u16 NCT6775_REG_ALARM[NUM_REG_ALARM] = { 0x459, 0x45A, 0x45B };
97*c3963bc0SZev Weiss 
98*c3963bc0SZev Weiss /* 0..15 voltages, 16..23 fans, 24..29 temperatures, 30..31 intrusion */
99*c3963bc0SZev Weiss 
100*c3963bc0SZev Weiss static const s8 NCT6775_ALARM_BITS[] = {
101*c3963bc0SZev Weiss 	0, 1, 2, 3, 8, 21, 20, 16,	/* in0.. in7 */
102*c3963bc0SZev Weiss 	17, -1, -1, -1, -1, -1, -1,	/* in8..in14 */
103*c3963bc0SZev Weiss 	-1,				/* unused */
104*c3963bc0SZev Weiss 	6, 7, 11, -1, -1,		/* fan1..fan5 */
105*c3963bc0SZev Weiss 	-1, -1, -1,			/* unused */
106*c3963bc0SZev Weiss 	4, 5, 13, -1, -1, -1,		/* temp1..temp6 */
107*c3963bc0SZev Weiss 	12, -1 };			/* intrusion0, intrusion1 */
108*c3963bc0SZev Weiss 
109*c3963bc0SZev Weiss static const u16 NCT6775_REG_BEEP[NUM_REG_BEEP] = { 0x56, 0x57, 0x453, 0x4e };
110*c3963bc0SZev Weiss 
111*c3963bc0SZev Weiss /*
112*c3963bc0SZev Weiss  * 0..14 voltages, 15 global beep enable, 16..23 fans, 24..29 temperatures,
113*c3963bc0SZev Weiss  * 30..31 intrusion
114*c3963bc0SZev Weiss  */
115*c3963bc0SZev Weiss static const s8 NCT6775_BEEP_BITS[] = {
116*c3963bc0SZev Weiss 	0, 1, 2, 3, 8, 9, 10, 16,	/* in0.. in7 */
117*c3963bc0SZev Weiss 	17, -1, -1, -1, -1, -1, -1,	/* in8..in14 */
118*c3963bc0SZev Weiss 	21,				/* global beep enable */
119*c3963bc0SZev Weiss 	6, 7, 11, 28, -1,		/* fan1..fan5 */
120*c3963bc0SZev Weiss 	-1, -1, -1,			/* unused */
121*c3963bc0SZev Weiss 	4, 5, 13, -1, -1, -1,		/* temp1..temp6 */
122*c3963bc0SZev Weiss 	12, -1 };			/* intrusion0, intrusion1 */
123*c3963bc0SZev Weiss 
124*c3963bc0SZev Weiss /* DC or PWM output fan configuration */
125*c3963bc0SZev Weiss static const u8 NCT6775_REG_PWM_MODE[] = { 0x04, 0x04, 0x12 };
126*c3963bc0SZev Weiss static const u8 NCT6775_PWM_MODE_MASK[] = { 0x01, 0x02, 0x01 };
127*c3963bc0SZev Weiss 
128*c3963bc0SZev Weiss /* Advanced Fan control, some values are common for all fans */
129*c3963bc0SZev Weiss 
130*c3963bc0SZev Weiss static const u16 NCT6775_REG_TARGET[] = {
131*c3963bc0SZev Weiss 	0x101, 0x201, 0x301, 0x801, 0x901, 0xa01, 0xb01 };
132*c3963bc0SZev Weiss static const u16 NCT6775_REG_FAN_MODE[] = {
133*c3963bc0SZev Weiss 	0x102, 0x202, 0x302, 0x802, 0x902, 0xa02, 0xb02 };
134*c3963bc0SZev Weiss static const u16 NCT6775_REG_FAN_STEP_DOWN_TIME[] = {
135*c3963bc0SZev Weiss 	0x103, 0x203, 0x303, 0x803, 0x903, 0xa03, 0xb03 };
136*c3963bc0SZev Weiss static const u16 NCT6775_REG_FAN_STEP_UP_TIME[] = {
137*c3963bc0SZev Weiss 	0x104, 0x204, 0x304, 0x804, 0x904, 0xa04, 0xb04 };
138*c3963bc0SZev Weiss static const u16 NCT6775_REG_FAN_STOP_OUTPUT[] = {
139*c3963bc0SZev Weiss 	0x105, 0x205, 0x305, 0x805, 0x905, 0xa05, 0xb05 };
140*c3963bc0SZev Weiss static const u16 NCT6775_REG_FAN_START_OUTPUT[] = {
141*c3963bc0SZev Weiss 	0x106, 0x206, 0x306, 0x806, 0x906, 0xa06, 0xb06 };
142*c3963bc0SZev Weiss static const u16 NCT6775_REG_FAN_MAX_OUTPUT[] = { 0x10a, 0x20a, 0x30a };
143*c3963bc0SZev Weiss static const u16 NCT6775_REG_FAN_STEP_OUTPUT[] = { 0x10b, 0x20b, 0x30b };
144*c3963bc0SZev Weiss 
145*c3963bc0SZev Weiss static const u16 NCT6775_REG_FAN_STOP_TIME[] = {
146*c3963bc0SZev Weiss 	0x107, 0x207, 0x307, 0x807, 0x907, 0xa07, 0xb07 };
147*c3963bc0SZev Weiss static const u16 NCT6775_REG_PWM[] = {
148*c3963bc0SZev Weiss 	0x109, 0x209, 0x309, 0x809, 0x909, 0xa09, 0xb09 };
149*c3963bc0SZev Weiss static const u16 NCT6775_REG_PWM_READ[] = {
150*c3963bc0SZev Weiss 	0x01, 0x03, 0x11, 0x13, 0x15, 0xa09, 0xb09 };
151*c3963bc0SZev Weiss 
152*c3963bc0SZev Weiss static const u16 NCT6775_REG_FAN[] = { 0x630, 0x632, 0x634, 0x636, 0x638 };
153*c3963bc0SZev Weiss static const u16 NCT6775_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d };
154*c3963bc0SZev Weiss static const u16 NCT6775_REG_FAN_PULSES[NUM_FAN] = {
155*c3963bc0SZev Weiss 	0x641, 0x642, 0x643, 0x644 };
156*c3963bc0SZev Weiss static const u16 NCT6775_FAN_PULSE_SHIFT[NUM_FAN] = { };
157*c3963bc0SZev Weiss 
158*c3963bc0SZev Weiss static const u16 NCT6775_REG_TEMP[] = {
159*c3963bc0SZev Weiss 	0x27, 0x150, 0x250, 0x62b, 0x62c, 0x62d };
160*c3963bc0SZev Weiss 
161*c3963bc0SZev Weiss static const u16 NCT6775_REG_TEMP_MON[] = { 0x73, 0x75, 0x77 };
162*c3963bc0SZev Weiss 
163*c3963bc0SZev Weiss static const u16 NCT6775_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
164*c3963bc0SZev Weiss 	0, 0x152, 0x252, 0x628, 0x629, 0x62A };
165*c3963bc0SZev Weiss static const u16 NCT6775_REG_TEMP_HYST[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
166*c3963bc0SZev Weiss 	0x3a, 0x153, 0x253, 0x673, 0x678, 0x67D };
167*c3963bc0SZev Weiss static const u16 NCT6775_REG_TEMP_OVER[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
168*c3963bc0SZev Weiss 	0x39, 0x155, 0x255, 0x672, 0x677, 0x67C };
169*c3963bc0SZev Weiss 
170*c3963bc0SZev Weiss static const u16 NCT6775_REG_TEMP_SOURCE[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
171*c3963bc0SZev Weiss 	0x621, 0x622, 0x623, 0x624, 0x625, 0x626 };
172*c3963bc0SZev Weiss 
173*c3963bc0SZev Weiss static const u16 NCT6775_REG_TEMP_SEL[] = {
174*c3963bc0SZev Weiss 	0x100, 0x200, 0x300, 0x800, 0x900, 0xa00, 0xb00 };
175*c3963bc0SZev Weiss 
176*c3963bc0SZev Weiss static const u16 NCT6775_REG_WEIGHT_TEMP_SEL[] = {
177*c3963bc0SZev Weiss 	0x139, 0x239, 0x339, 0x839, 0x939, 0xa39 };
178*c3963bc0SZev Weiss static const u16 NCT6775_REG_WEIGHT_TEMP_STEP[] = {
179*c3963bc0SZev Weiss 	0x13a, 0x23a, 0x33a, 0x83a, 0x93a, 0xa3a };
180*c3963bc0SZev Weiss static const u16 NCT6775_REG_WEIGHT_TEMP_STEP_TOL[] = {
181*c3963bc0SZev Weiss 	0x13b, 0x23b, 0x33b, 0x83b, 0x93b, 0xa3b };
182*c3963bc0SZev Weiss static const u16 NCT6775_REG_WEIGHT_DUTY_STEP[] = {
183*c3963bc0SZev Weiss 	0x13c, 0x23c, 0x33c, 0x83c, 0x93c, 0xa3c };
184*c3963bc0SZev Weiss static const u16 NCT6775_REG_WEIGHT_TEMP_BASE[] = {
185*c3963bc0SZev Weiss 	0x13d, 0x23d, 0x33d, 0x83d, 0x93d, 0xa3d };
186*c3963bc0SZev Weiss 
187*c3963bc0SZev Weiss static const u16 NCT6775_REG_TEMP_OFFSET[] = { 0x454, 0x455, 0x456 };
188*c3963bc0SZev Weiss 
189*c3963bc0SZev Weiss static const u16 NCT6775_REG_AUTO_TEMP[] = {
190*c3963bc0SZev Weiss 	0x121, 0x221, 0x321, 0x821, 0x921, 0xa21, 0xb21 };
191*c3963bc0SZev Weiss static const u16 NCT6775_REG_AUTO_PWM[] = {
192*c3963bc0SZev Weiss 	0x127, 0x227, 0x327, 0x827, 0x927, 0xa27, 0xb27 };
193*c3963bc0SZev Weiss 
194*c3963bc0SZev Weiss #define NCT6775_AUTO_TEMP(data, nr, p)	((data)->REG_AUTO_TEMP[nr] + (p))
195*c3963bc0SZev Weiss #define NCT6775_AUTO_PWM(data, nr, p)	((data)->REG_AUTO_PWM[nr] + (p))
196*c3963bc0SZev Weiss 
197*c3963bc0SZev Weiss static const u16 NCT6775_REG_CRITICAL_ENAB[] = { 0x134, 0x234, 0x334 };
198*c3963bc0SZev Weiss 
199*c3963bc0SZev Weiss static const u16 NCT6775_REG_CRITICAL_TEMP[] = {
200*c3963bc0SZev Weiss 	0x135, 0x235, 0x335, 0x835, 0x935, 0xa35, 0xb35 };
201*c3963bc0SZev Weiss static const u16 NCT6775_REG_CRITICAL_TEMP_TOLERANCE[] = {
202*c3963bc0SZev Weiss 	0x138, 0x238, 0x338, 0x838, 0x938, 0xa38, 0xb38 };
203*c3963bc0SZev Weiss 
204*c3963bc0SZev Weiss static const char *const nct6775_temp_label[] = {
205*c3963bc0SZev Weiss 	"",
206*c3963bc0SZev Weiss 	"SYSTIN",
207*c3963bc0SZev Weiss 	"CPUTIN",
208*c3963bc0SZev Weiss 	"AUXTIN",
209*c3963bc0SZev Weiss 	"AMD SB-TSI",
210*c3963bc0SZev Weiss 	"PECI Agent 0",
211*c3963bc0SZev Weiss 	"PECI Agent 1",
212*c3963bc0SZev Weiss 	"PECI Agent 2",
213*c3963bc0SZev Weiss 	"PECI Agent 3",
214*c3963bc0SZev Weiss 	"PECI Agent 4",
215*c3963bc0SZev Weiss 	"PECI Agent 5",
216*c3963bc0SZev Weiss 	"PECI Agent 6",
217*c3963bc0SZev Weiss 	"PECI Agent 7",
218*c3963bc0SZev Weiss 	"PCH_CHIP_CPU_MAX_TEMP",
219*c3963bc0SZev Weiss 	"PCH_CHIP_TEMP",
220*c3963bc0SZev Weiss 	"PCH_CPU_TEMP",
221*c3963bc0SZev Weiss 	"PCH_MCH_TEMP",
222*c3963bc0SZev Weiss 	"PCH_DIM0_TEMP",
223*c3963bc0SZev Weiss 	"PCH_DIM1_TEMP",
224*c3963bc0SZev Weiss 	"PCH_DIM2_TEMP",
225*c3963bc0SZev Weiss 	"PCH_DIM3_TEMP"
226*c3963bc0SZev Weiss };
227*c3963bc0SZev Weiss 
228*c3963bc0SZev Weiss #define NCT6775_TEMP_MASK	0x001ffffe
229*c3963bc0SZev Weiss #define NCT6775_VIRT_TEMP_MASK	0x00000000
230*c3963bc0SZev Weiss 
231*c3963bc0SZev Weiss static const u16 NCT6775_REG_TEMP_ALTERNATE[32] = {
232*c3963bc0SZev Weiss 	[13] = 0x661,
233*c3963bc0SZev Weiss 	[14] = 0x662,
234*c3963bc0SZev Weiss 	[15] = 0x664,
235*c3963bc0SZev Weiss };
236*c3963bc0SZev Weiss 
237*c3963bc0SZev Weiss static const u16 NCT6775_REG_TEMP_CRIT[32] = {
238*c3963bc0SZev Weiss 	[4] = 0xa00,
239*c3963bc0SZev Weiss 	[5] = 0xa01,
240*c3963bc0SZev Weiss 	[6] = 0xa02,
241*c3963bc0SZev Weiss 	[7] = 0xa03,
242*c3963bc0SZev Weiss 	[8] = 0xa04,
243*c3963bc0SZev Weiss 	[9] = 0xa05,
244*c3963bc0SZev Weiss 	[10] = 0xa06,
245*c3963bc0SZev Weiss 	[11] = 0xa07
246*c3963bc0SZev Weiss };
247*c3963bc0SZev Weiss 
248*c3963bc0SZev Weiss static const u16 NCT6775_REG_TSI_TEMP[] = { 0x669 };
249*c3963bc0SZev Weiss 
250*c3963bc0SZev Weiss /* NCT6776 specific data */
251*c3963bc0SZev Weiss 
252*c3963bc0SZev Weiss /* STEP_UP_TIME and STEP_DOWN_TIME regs are swapped for all chips but NCT6775 */
253*c3963bc0SZev Weiss #define NCT6776_REG_FAN_STEP_UP_TIME NCT6775_REG_FAN_STEP_DOWN_TIME
254*c3963bc0SZev Weiss #define NCT6776_REG_FAN_STEP_DOWN_TIME NCT6775_REG_FAN_STEP_UP_TIME
255*c3963bc0SZev Weiss 
256*c3963bc0SZev Weiss static const s8 NCT6776_ALARM_BITS[] = {
257*c3963bc0SZev Weiss 	0, 1, 2, 3, 8, 21, 20, 16,	/* in0.. in7 */
258*c3963bc0SZev Weiss 	17, -1, -1, -1, -1, -1, -1,	/* in8..in14 */
259*c3963bc0SZev Weiss 	-1,				/* unused */
260*c3963bc0SZev Weiss 	6, 7, 11, 10, 23,		/* fan1..fan5 */
261*c3963bc0SZev Weiss 	-1, -1, -1,			/* unused */
262*c3963bc0SZev Weiss 	4, 5, 13, -1, -1, -1,		/* temp1..temp6 */
263*c3963bc0SZev Weiss 	12, 9 };			/* intrusion0, intrusion1 */
264*c3963bc0SZev Weiss 
265*c3963bc0SZev Weiss static const u16 NCT6776_REG_BEEP[NUM_REG_BEEP] = { 0xb2, 0xb3, 0xb4, 0xb5 };
266*c3963bc0SZev Weiss 
267*c3963bc0SZev Weiss static const s8 NCT6776_BEEP_BITS[] = {
268*c3963bc0SZev Weiss 	0, 1, 2, 3, 4, 5, 6, 7,		/* in0.. in7 */
269*c3963bc0SZev Weiss 	8, -1, -1, -1, -1, -1, -1,	/* in8..in14 */
270*c3963bc0SZev Weiss 	24,				/* global beep enable */
271*c3963bc0SZev Weiss 	25, 26, 27, 28, 29,		/* fan1..fan5 */
272*c3963bc0SZev Weiss 	-1, -1, -1,			/* unused */
273*c3963bc0SZev Weiss 	16, 17, 18, 19, 20, 21,		/* temp1..temp6 */
274*c3963bc0SZev Weiss 	30, 31 };			/* intrusion0, intrusion1 */
275*c3963bc0SZev Weiss 
276*c3963bc0SZev Weiss static const u16 NCT6776_REG_TOLERANCE_H[] = {
277*c3963bc0SZev Weiss 	0x10c, 0x20c, 0x30c, 0x80c, 0x90c, 0xa0c, 0xb0c };
278*c3963bc0SZev Weiss 
279*c3963bc0SZev Weiss static const u8 NCT6776_REG_PWM_MODE[] = { 0x04, 0, 0, 0, 0, 0 };
280*c3963bc0SZev Weiss static const u8 NCT6776_PWM_MODE_MASK[] = { 0x01, 0, 0, 0, 0, 0 };
281*c3963bc0SZev Weiss 
282*c3963bc0SZev Weiss static const u16 NCT6776_REG_FAN_MIN[] = {
283*c3963bc0SZev Weiss 	0x63a, 0x63c, 0x63e, 0x640, 0x642, 0x64a, 0x64c };
284*c3963bc0SZev Weiss static const u16 NCT6776_REG_FAN_PULSES[NUM_FAN] = {
285*c3963bc0SZev Weiss 	0x644, 0x645, 0x646, 0x647, 0x648, 0x649 };
286*c3963bc0SZev Weiss 
287*c3963bc0SZev Weiss static const u16 NCT6776_REG_WEIGHT_DUTY_BASE[] = {
288*c3963bc0SZev Weiss 	0x13e, 0x23e, 0x33e, 0x83e, 0x93e, 0xa3e };
289*c3963bc0SZev Weiss 
290*c3963bc0SZev Weiss static const u16 NCT6776_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
291*c3963bc0SZev Weiss 	0x18, 0x152, 0x252, 0x628, 0x629, 0x62A };
292*c3963bc0SZev Weiss 
293*c3963bc0SZev Weiss static const char *const nct6776_temp_label[] = {
294*c3963bc0SZev Weiss 	"",
295*c3963bc0SZev Weiss 	"SYSTIN",
296*c3963bc0SZev Weiss 	"CPUTIN",
297*c3963bc0SZev Weiss 	"AUXTIN",
298*c3963bc0SZev Weiss 	"SMBUSMASTER 0",
299*c3963bc0SZev Weiss 	"SMBUSMASTER 1",
300*c3963bc0SZev Weiss 	"SMBUSMASTER 2",
301*c3963bc0SZev Weiss 	"SMBUSMASTER 3",
302*c3963bc0SZev Weiss 	"SMBUSMASTER 4",
303*c3963bc0SZev Weiss 	"SMBUSMASTER 5",
304*c3963bc0SZev Weiss 	"SMBUSMASTER 6",
305*c3963bc0SZev Weiss 	"SMBUSMASTER 7",
306*c3963bc0SZev Weiss 	"PECI Agent 0",
307*c3963bc0SZev Weiss 	"PECI Agent 1",
308*c3963bc0SZev Weiss 	"PCH_CHIP_CPU_MAX_TEMP",
309*c3963bc0SZev Weiss 	"PCH_CHIP_TEMP",
310*c3963bc0SZev Weiss 	"PCH_CPU_TEMP",
311*c3963bc0SZev Weiss 	"PCH_MCH_TEMP",
312*c3963bc0SZev Weiss 	"PCH_DIM0_TEMP",
313*c3963bc0SZev Weiss 	"PCH_DIM1_TEMP",
314*c3963bc0SZev Weiss 	"PCH_DIM2_TEMP",
315*c3963bc0SZev Weiss 	"PCH_DIM3_TEMP",
316*c3963bc0SZev Weiss 	"BYTE_TEMP"
317*c3963bc0SZev Weiss };
318*c3963bc0SZev Weiss 
319*c3963bc0SZev Weiss #define NCT6776_TEMP_MASK	0x007ffffe
320*c3963bc0SZev Weiss #define NCT6776_VIRT_TEMP_MASK	0x00000000
321*c3963bc0SZev Weiss 
322*c3963bc0SZev Weiss static const u16 NCT6776_REG_TEMP_ALTERNATE[32] = {
323*c3963bc0SZev Weiss 	[14] = 0x401,
324*c3963bc0SZev Weiss 	[15] = 0x402,
325*c3963bc0SZev Weiss 	[16] = 0x404,
326*c3963bc0SZev Weiss };
327*c3963bc0SZev Weiss 
328*c3963bc0SZev Weiss static const u16 NCT6776_REG_TEMP_CRIT[32] = {
329*c3963bc0SZev Weiss 	[11] = 0x709,
330*c3963bc0SZev Weiss 	[12] = 0x70a,
331*c3963bc0SZev Weiss };
332*c3963bc0SZev Weiss 
333*c3963bc0SZev Weiss static const u16 NCT6776_REG_TSI_TEMP[] = {
334*c3963bc0SZev Weiss 	0x409, 0x40b, 0x40d, 0x40f, 0x411, 0x413, 0x415, 0x417 };
335*c3963bc0SZev Weiss 
336*c3963bc0SZev Weiss /* NCT6779 specific data */
337*c3963bc0SZev Weiss 
338*c3963bc0SZev Weiss static const u16 NCT6779_REG_IN[] = {
339*c3963bc0SZev Weiss 	0x480, 0x481, 0x482, 0x483, 0x484, 0x485, 0x486, 0x487,
340*c3963bc0SZev Weiss 	0x488, 0x489, 0x48a, 0x48b, 0x48c, 0x48d, 0x48e };
341*c3963bc0SZev Weiss 
342*c3963bc0SZev Weiss static const u16 NCT6779_REG_ALARM[NUM_REG_ALARM] = {
343*c3963bc0SZev Weiss 	0x459, 0x45A, 0x45B, 0x568 };
344*c3963bc0SZev Weiss 
345*c3963bc0SZev Weiss static const s8 NCT6779_ALARM_BITS[] = {
346*c3963bc0SZev Weiss 	0, 1, 2, 3, 8, 21, 20, 16,	/* in0.. in7 */
347*c3963bc0SZev Weiss 	17, 24, 25, 26, 27, 28, 29,	/* in8..in14 */
348*c3963bc0SZev Weiss 	-1,				/* unused */
349*c3963bc0SZev Weiss 	6, 7, 11, 10, 23,		/* fan1..fan5 */
350*c3963bc0SZev Weiss 	-1, -1, -1,			/* unused */
351*c3963bc0SZev Weiss 	4, 5, 13, -1, -1, -1,		/* temp1..temp6 */
352*c3963bc0SZev Weiss 	12, 9 };			/* intrusion0, intrusion1 */
353*c3963bc0SZev Weiss 
354*c3963bc0SZev Weiss static const s8 NCT6779_BEEP_BITS[] = {
355*c3963bc0SZev Weiss 	0, 1, 2, 3, 4, 5, 6, 7,		/* in0.. in7 */
356*c3963bc0SZev Weiss 	8, 9, 10, 11, 12, 13, 14,	/* in8..in14 */
357*c3963bc0SZev Weiss 	24,				/* global beep enable */
358*c3963bc0SZev Weiss 	25, 26, 27, 28, 29,		/* fan1..fan5 */
359*c3963bc0SZev Weiss 	-1, -1, -1,			/* unused */
360*c3963bc0SZev Weiss 	16, 17, -1, -1, -1, -1,		/* temp1..temp6 */
361*c3963bc0SZev Weiss 	30, 31 };			/* intrusion0, intrusion1 */
362*c3963bc0SZev Weiss 
363*c3963bc0SZev Weiss static const u16 NCT6779_REG_FAN[] = {
364*c3963bc0SZev Weiss 	0x4c0, 0x4c2, 0x4c4, 0x4c6, 0x4c8, 0x4ca, 0x4ce };
365*c3963bc0SZev Weiss static const u16 NCT6779_REG_FAN_PULSES[NUM_FAN] = {
366*c3963bc0SZev Weiss 	0x644, 0x645, 0x646, 0x647, 0x648, 0x649, 0x64f };
367*c3963bc0SZev Weiss 
368*c3963bc0SZev Weiss static const u16 NCT6779_REG_CRITICAL_PWM_ENABLE[] = {
369*c3963bc0SZev Weiss 	0x136, 0x236, 0x336, 0x836, 0x936, 0xa36, 0xb36 };
370*c3963bc0SZev Weiss #define NCT6779_CRITICAL_PWM_ENABLE_MASK	0x01
371*c3963bc0SZev Weiss static const u16 NCT6779_REG_CRITICAL_PWM[] = {
372*c3963bc0SZev Weiss 	0x137, 0x237, 0x337, 0x837, 0x937, 0xa37, 0xb37 };
373*c3963bc0SZev Weiss 
374*c3963bc0SZev Weiss static const u16 NCT6779_REG_TEMP[] = { 0x27, 0x150 };
375*c3963bc0SZev Weiss static const u16 NCT6779_REG_TEMP_MON[] = { 0x73, 0x75, 0x77, 0x79, 0x7b };
376*c3963bc0SZev Weiss static const u16 NCT6779_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
377*c3963bc0SZev Weiss 	0x18, 0x152 };
378*c3963bc0SZev Weiss static const u16 NCT6779_REG_TEMP_HYST[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
379*c3963bc0SZev Weiss 	0x3a, 0x153 };
380*c3963bc0SZev Weiss static const u16 NCT6779_REG_TEMP_OVER[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
381*c3963bc0SZev Weiss 	0x39, 0x155 };
382*c3963bc0SZev Weiss 
383*c3963bc0SZev Weiss static const u16 NCT6779_REG_TEMP_OFFSET[] = {
384*c3963bc0SZev Weiss 	0x454, 0x455, 0x456, 0x44a, 0x44b, 0x44c };
385*c3963bc0SZev Weiss 
386*c3963bc0SZev Weiss static const char *const nct6779_temp_label[] = {
387*c3963bc0SZev Weiss 	"",
388*c3963bc0SZev Weiss 	"SYSTIN",
389*c3963bc0SZev Weiss 	"CPUTIN",
390*c3963bc0SZev Weiss 	"AUXTIN0",
391*c3963bc0SZev Weiss 	"AUXTIN1",
392*c3963bc0SZev Weiss 	"AUXTIN2",
393*c3963bc0SZev Weiss 	"AUXTIN3",
394*c3963bc0SZev Weiss 	"",
395*c3963bc0SZev Weiss 	"SMBUSMASTER 0",
396*c3963bc0SZev Weiss 	"SMBUSMASTER 1",
397*c3963bc0SZev Weiss 	"SMBUSMASTER 2",
398*c3963bc0SZev Weiss 	"SMBUSMASTER 3",
399*c3963bc0SZev Weiss 	"SMBUSMASTER 4",
400*c3963bc0SZev Weiss 	"SMBUSMASTER 5",
401*c3963bc0SZev Weiss 	"SMBUSMASTER 6",
402*c3963bc0SZev Weiss 	"SMBUSMASTER 7",
403*c3963bc0SZev Weiss 	"PECI Agent 0",
404*c3963bc0SZev Weiss 	"PECI Agent 1",
405*c3963bc0SZev Weiss 	"PCH_CHIP_CPU_MAX_TEMP",
406*c3963bc0SZev Weiss 	"PCH_CHIP_TEMP",
407*c3963bc0SZev Weiss 	"PCH_CPU_TEMP",
408*c3963bc0SZev Weiss 	"PCH_MCH_TEMP",
409*c3963bc0SZev Weiss 	"PCH_DIM0_TEMP",
410*c3963bc0SZev Weiss 	"PCH_DIM1_TEMP",
411*c3963bc0SZev Weiss 	"PCH_DIM2_TEMP",
412*c3963bc0SZev Weiss 	"PCH_DIM3_TEMP",
413*c3963bc0SZev Weiss 	"BYTE_TEMP",
414*c3963bc0SZev Weiss 	"",
415*c3963bc0SZev Weiss 	"",
416*c3963bc0SZev Weiss 	"",
417*c3963bc0SZev Weiss 	"",
418*c3963bc0SZev Weiss 	"Virtual_TEMP"
419*c3963bc0SZev Weiss };
420*c3963bc0SZev Weiss 
421*c3963bc0SZev Weiss #define NCT6779_TEMP_MASK	0x07ffff7e
422*c3963bc0SZev Weiss #define NCT6779_VIRT_TEMP_MASK	0x00000000
423*c3963bc0SZev Weiss #define NCT6791_TEMP_MASK	0x87ffff7e
424*c3963bc0SZev Weiss #define NCT6791_VIRT_TEMP_MASK	0x80000000
425*c3963bc0SZev Weiss 
426*c3963bc0SZev Weiss static const u16 NCT6779_REG_TEMP_ALTERNATE[32]
427*c3963bc0SZev Weiss 	= { 0x490, 0x491, 0x492, 0x493, 0x494, 0x495, 0, 0,
428*c3963bc0SZev Weiss 	    0, 0, 0, 0, 0, 0, 0, 0,
429*c3963bc0SZev Weiss 	    0, 0x400, 0x401, 0x402, 0x404, 0x405, 0x406, 0x407,
430*c3963bc0SZev Weiss 	    0x408, 0 };
431*c3963bc0SZev Weiss 
432*c3963bc0SZev Weiss static const u16 NCT6779_REG_TEMP_CRIT[32] = {
433*c3963bc0SZev Weiss 	[15] = 0x709,
434*c3963bc0SZev Weiss 	[16] = 0x70a,
435*c3963bc0SZev Weiss };
436*c3963bc0SZev Weiss 
437*c3963bc0SZev Weiss /* NCT6791 specific data */
438*c3963bc0SZev Weiss 
439*c3963bc0SZev Weiss static const u16 NCT6791_REG_WEIGHT_TEMP_SEL[NUM_FAN] = { 0, 0x239 };
440*c3963bc0SZev Weiss static const u16 NCT6791_REG_WEIGHT_TEMP_STEP[NUM_FAN] = { 0, 0x23a };
441*c3963bc0SZev Weiss static const u16 NCT6791_REG_WEIGHT_TEMP_STEP_TOL[NUM_FAN] = { 0, 0x23b };
442*c3963bc0SZev Weiss static const u16 NCT6791_REG_WEIGHT_DUTY_STEP[NUM_FAN] = { 0, 0x23c };
443*c3963bc0SZev Weiss static const u16 NCT6791_REG_WEIGHT_TEMP_BASE[NUM_FAN] = { 0, 0x23d };
444*c3963bc0SZev Weiss static const u16 NCT6791_REG_WEIGHT_DUTY_BASE[NUM_FAN] = { 0, 0x23e };
445*c3963bc0SZev Weiss 
446*c3963bc0SZev Weiss static const u16 NCT6791_REG_ALARM[NUM_REG_ALARM] = {
447*c3963bc0SZev Weiss 	0x459, 0x45A, 0x45B, 0x568, 0x45D };
448*c3963bc0SZev Weiss 
449*c3963bc0SZev Weiss static const s8 NCT6791_ALARM_BITS[] = {
450*c3963bc0SZev Weiss 	0, 1, 2, 3, 8, 21, 20, 16,	/* in0.. in7 */
451*c3963bc0SZev Weiss 	17, 24, 25, 26, 27, 28, 29,	/* in8..in14 */
452*c3963bc0SZev Weiss 	-1,				/* unused */
453*c3963bc0SZev Weiss 	6, 7, 11, 10, 23, 33,		/* fan1..fan6 */
454*c3963bc0SZev Weiss 	-1, -1,				/* unused */
455*c3963bc0SZev Weiss 	4, 5, 13, -1, -1, -1,		/* temp1..temp6 */
456*c3963bc0SZev Weiss 	12, 9 };			/* intrusion0, intrusion1 */
457*c3963bc0SZev Weiss 
458*c3963bc0SZev Weiss /* NCT6792/NCT6793 specific data */
459*c3963bc0SZev Weiss 
460*c3963bc0SZev Weiss static const u16 NCT6792_REG_TEMP_MON[] = {
461*c3963bc0SZev Weiss 	0x73, 0x75, 0x77, 0x79, 0x7b, 0x7d };
462*c3963bc0SZev Weiss static const u16 NCT6792_REG_BEEP[NUM_REG_BEEP] = {
463*c3963bc0SZev Weiss 	0xb2, 0xb3, 0xb4, 0xb5, 0xbf };
464*c3963bc0SZev Weiss 
465*c3963bc0SZev Weiss static const char *const nct6792_temp_label[] = {
466*c3963bc0SZev Weiss 	"",
467*c3963bc0SZev Weiss 	"SYSTIN",
468*c3963bc0SZev Weiss 	"CPUTIN",
469*c3963bc0SZev Weiss 	"AUXTIN0",
470*c3963bc0SZev Weiss 	"AUXTIN1",
471*c3963bc0SZev Weiss 	"AUXTIN2",
472*c3963bc0SZev Weiss 	"AUXTIN3",
473*c3963bc0SZev Weiss 	"",
474*c3963bc0SZev Weiss 	"SMBUSMASTER 0",
475*c3963bc0SZev Weiss 	"SMBUSMASTER 1",
476*c3963bc0SZev Weiss 	"SMBUSMASTER 2",
477*c3963bc0SZev Weiss 	"SMBUSMASTER 3",
478*c3963bc0SZev Weiss 	"SMBUSMASTER 4",
479*c3963bc0SZev Weiss 	"SMBUSMASTER 5",
480*c3963bc0SZev Weiss 	"SMBUSMASTER 6",
481*c3963bc0SZev Weiss 	"SMBUSMASTER 7",
482*c3963bc0SZev Weiss 	"PECI Agent 0",
483*c3963bc0SZev Weiss 	"PECI Agent 1",
484*c3963bc0SZev Weiss 	"PCH_CHIP_CPU_MAX_TEMP",
485*c3963bc0SZev Weiss 	"PCH_CHIP_TEMP",
486*c3963bc0SZev Weiss 	"PCH_CPU_TEMP",
487*c3963bc0SZev Weiss 	"PCH_MCH_TEMP",
488*c3963bc0SZev Weiss 	"PCH_DIM0_TEMP",
489*c3963bc0SZev Weiss 	"PCH_DIM1_TEMP",
490*c3963bc0SZev Weiss 	"PCH_DIM2_TEMP",
491*c3963bc0SZev Weiss 	"PCH_DIM3_TEMP",
492*c3963bc0SZev Weiss 	"BYTE_TEMP",
493*c3963bc0SZev Weiss 	"PECI Agent 0 Calibration",
494*c3963bc0SZev Weiss 	"PECI Agent 1 Calibration",
495*c3963bc0SZev Weiss 	"",
496*c3963bc0SZev Weiss 	"",
497*c3963bc0SZev Weiss 	"Virtual_TEMP"
498*c3963bc0SZev Weiss };
499*c3963bc0SZev Weiss 
500*c3963bc0SZev Weiss #define NCT6792_TEMP_MASK	0x9fffff7e
501*c3963bc0SZev Weiss #define NCT6792_VIRT_TEMP_MASK	0x80000000
502*c3963bc0SZev Weiss 
503*c3963bc0SZev Weiss static const char *const nct6793_temp_label[] = {
504*c3963bc0SZev Weiss 	"",
505*c3963bc0SZev Weiss 	"SYSTIN",
506*c3963bc0SZev Weiss 	"CPUTIN",
507*c3963bc0SZev Weiss 	"AUXTIN0",
508*c3963bc0SZev Weiss 	"AUXTIN1",
509*c3963bc0SZev Weiss 	"AUXTIN2",
510*c3963bc0SZev Weiss 	"AUXTIN3",
511*c3963bc0SZev Weiss 	"",
512*c3963bc0SZev Weiss 	"SMBUSMASTER 0",
513*c3963bc0SZev Weiss 	"SMBUSMASTER 1",
514*c3963bc0SZev Weiss 	"",
515*c3963bc0SZev Weiss 	"",
516*c3963bc0SZev Weiss 	"",
517*c3963bc0SZev Weiss 	"",
518*c3963bc0SZev Weiss 	"",
519*c3963bc0SZev Weiss 	"",
520*c3963bc0SZev Weiss 	"PECI Agent 0",
521*c3963bc0SZev Weiss 	"PECI Agent 1",
522*c3963bc0SZev Weiss 	"PCH_CHIP_CPU_MAX_TEMP",
523*c3963bc0SZev Weiss 	"PCH_CHIP_TEMP",
524*c3963bc0SZev Weiss 	"PCH_CPU_TEMP",
525*c3963bc0SZev Weiss 	"PCH_MCH_TEMP",
526*c3963bc0SZev Weiss 	"Agent0 Dimm0 ",
527*c3963bc0SZev Weiss 	"Agent0 Dimm1",
528*c3963bc0SZev Weiss 	"Agent1 Dimm0",
529*c3963bc0SZev Weiss 	"Agent1 Dimm1",
530*c3963bc0SZev Weiss 	"BYTE_TEMP0",
531*c3963bc0SZev Weiss 	"BYTE_TEMP1",
532*c3963bc0SZev Weiss 	"PECI Agent 0 Calibration",
533*c3963bc0SZev Weiss 	"PECI Agent 1 Calibration",
534*c3963bc0SZev Weiss 	"",
535*c3963bc0SZev Weiss 	"Virtual_TEMP"
536*c3963bc0SZev Weiss };
537*c3963bc0SZev Weiss 
538*c3963bc0SZev Weiss #define NCT6793_TEMP_MASK	0xbfff037e
539*c3963bc0SZev Weiss #define NCT6793_VIRT_TEMP_MASK	0x80000000
540*c3963bc0SZev Weiss 
541*c3963bc0SZev Weiss static const char *const nct6795_temp_label[] = {
542*c3963bc0SZev Weiss 	"",
543*c3963bc0SZev Weiss 	"SYSTIN",
544*c3963bc0SZev Weiss 	"CPUTIN",
545*c3963bc0SZev Weiss 	"AUXTIN0",
546*c3963bc0SZev Weiss 	"AUXTIN1",
547*c3963bc0SZev Weiss 	"AUXTIN2",
548*c3963bc0SZev Weiss 	"AUXTIN3",
549*c3963bc0SZev Weiss 	"",
550*c3963bc0SZev Weiss 	"SMBUSMASTER 0",
551*c3963bc0SZev Weiss 	"SMBUSMASTER 1",
552*c3963bc0SZev Weiss 	"SMBUSMASTER 2",
553*c3963bc0SZev Weiss 	"SMBUSMASTER 3",
554*c3963bc0SZev Weiss 	"SMBUSMASTER 4",
555*c3963bc0SZev Weiss 	"SMBUSMASTER 5",
556*c3963bc0SZev Weiss 	"SMBUSMASTER 6",
557*c3963bc0SZev Weiss 	"SMBUSMASTER 7",
558*c3963bc0SZev Weiss 	"PECI Agent 0",
559*c3963bc0SZev Weiss 	"PECI Agent 1",
560*c3963bc0SZev Weiss 	"PCH_CHIP_CPU_MAX_TEMP",
561*c3963bc0SZev Weiss 	"PCH_CHIP_TEMP",
562*c3963bc0SZev Weiss 	"PCH_CPU_TEMP",
563*c3963bc0SZev Weiss 	"PCH_MCH_TEMP",
564*c3963bc0SZev Weiss 	"Agent0 Dimm0",
565*c3963bc0SZev Weiss 	"Agent0 Dimm1",
566*c3963bc0SZev Weiss 	"Agent1 Dimm0",
567*c3963bc0SZev Weiss 	"Agent1 Dimm1",
568*c3963bc0SZev Weiss 	"BYTE_TEMP0",
569*c3963bc0SZev Weiss 	"BYTE_TEMP1",
570*c3963bc0SZev Weiss 	"PECI Agent 0 Calibration",
571*c3963bc0SZev Weiss 	"PECI Agent 1 Calibration",
572*c3963bc0SZev Weiss 	"",
573*c3963bc0SZev Weiss 	"Virtual_TEMP"
574*c3963bc0SZev Weiss };
575*c3963bc0SZev Weiss 
576*c3963bc0SZev Weiss #define NCT6795_TEMP_MASK	0xbfffff7e
577*c3963bc0SZev Weiss #define NCT6795_VIRT_TEMP_MASK	0x80000000
578*c3963bc0SZev Weiss 
579*c3963bc0SZev Weiss static const char *const nct6796_temp_label[] = {
580*c3963bc0SZev Weiss 	"",
581*c3963bc0SZev Weiss 	"SYSTIN",
582*c3963bc0SZev Weiss 	"CPUTIN",
583*c3963bc0SZev Weiss 	"AUXTIN0",
584*c3963bc0SZev Weiss 	"AUXTIN1",
585*c3963bc0SZev Weiss 	"AUXTIN2",
586*c3963bc0SZev Weiss 	"AUXTIN3",
587*c3963bc0SZev Weiss 	"AUXTIN4",
588*c3963bc0SZev Weiss 	"SMBUSMASTER 0",
589*c3963bc0SZev Weiss 	"SMBUSMASTER 1",
590*c3963bc0SZev Weiss 	"Virtual_TEMP",
591*c3963bc0SZev Weiss 	"Virtual_TEMP",
592*c3963bc0SZev Weiss 	"",
593*c3963bc0SZev Weiss 	"",
594*c3963bc0SZev Weiss 	"",
595*c3963bc0SZev Weiss 	"",
596*c3963bc0SZev Weiss 	"PECI Agent 0",
597*c3963bc0SZev Weiss 	"PECI Agent 1",
598*c3963bc0SZev Weiss 	"PCH_CHIP_CPU_MAX_TEMP",
599*c3963bc0SZev Weiss 	"PCH_CHIP_TEMP",
600*c3963bc0SZev Weiss 	"PCH_CPU_TEMP",
601*c3963bc0SZev Weiss 	"PCH_MCH_TEMP",
602*c3963bc0SZev Weiss 	"Agent0 Dimm0",
603*c3963bc0SZev Weiss 	"Agent0 Dimm1",
604*c3963bc0SZev Weiss 	"Agent1 Dimm0",
605*c3963bc0SZev Weiss 	"Agent1 Dimm1",
606*c3963bc0SZev Weiss 	"BYTE_TEMP0",
607*c3963bc0SZev Weiss 	"BYTE_TEMP1",
608*c3963bc0SZev Weiss 	"PECI Agent 0 Calibration",
609*c3963bc0SZev Weiss 	"PECI Agent 1 Calibration",
610*c3963bc0SZev Weiss 	"",
611*c3963bc0SZev Weiss 	"Virtual_TEMP"
612*c3963bc0SZev Weiss };
613*c3963bc0SZev Weiss 
614*c3963bc0SZev Weiss #define NCT6796_TEMP_MASK	0xbfff0ffe
615*c3963bc0SZev Weiss #define NCT6796_VIRT_TEMP_MASK	0x80000c00
616*c3963bc0SZev Weiss 
617*c3963bc0SZev Weiss static const u16 NCT6796_REG_TSI_TEMP[] = { 0x409, 0x40b };
618*c3963bc0SZev Weiss 
619*c3963bc0SZev Weiss static const char *const nct6798_temp_label[] = {
620*c3963bc0SZev Weiss 	"",
621*c3963bc0SZev Weiss 	"SYSTIN",
622*c3963bc0SZev Weiss 	"CPUTIN",
623*c3963bc0SZev Weiss 	"AUXTIN0",
624*c3963bc0SZev Weiss 	"AUXTIN1",
625*c3963bc0SZev Weiss 	"AUXTIN2",
626*c3963bc0SZev Weiss 	"AUXTIN3",
627*c3963bc0SZev Weiss 	"AUXTIN4",
628*c3963bc0SZev Weiss 	"SMBUSMASTER 0",
629*c3963bc0SZev Weiss 	"SMBUSMASTER 1",
630*c3963bc0SZev Weiss 	"Virtual_TEMP",
631*c3963bc0SZev Weiss 	"Virtual_TEMP",
632*c3963bc0SZev Weiss 	"",
633*c3963bc0SZev Weiss 	"",
634*c3963bc0SZev Weiss 	"",
635*c3963bc0SZev Weiss 	"",
636*c3963bc0SZev Weiss 	"PECI Agent 0",
637*c3963bc0SZev Weiss 	"PECI Agent 1",
638*c3963bc0SZev Weiss 	"PCH_CHIP_CPU_MAX_TEMP",
639*c3963bc0SZev Weiss 	"PCH_CHIP_TEMP",
640*c3963bc0SZev Weiss 	"PCH_CPU_TEMP",
641*c3963bc0SZev Weiss 	"PCH_MCH_TEMP",
642*c3963bc0SZev Weiss 	"Agent0 Dimm0",
643*c3963bc0SZev Weiss 	"Agent0 Dimm1",
644*c3963bc0SZev Weiss 	"Agent1 Dimm0",
645*c3963bc0SZev Weiss 	"Agent1 Dimm1",
646*c3963bc0SZev Weiss 	"BYTE_TEMP0",
647*c3963bc0SZev Weiss 	"BYTE_TEMP1",
648*c3963bc0SZev Weiss 	"PECI Agent 0 Calibration",	/* undocumented */
649*c3963bc0SZev Weiss 	"PECI Agent 1 Calibration",	/* undocumented */
650*c3963bc0SZev Weiss 	"",
651*c3963bc0SZev Weiss 	"Virtual_TEMP"
652*c3963bc0SZev Weiss };
653*c3963bc0SZev Weiss 
654*c3963bc0SZev Weiss #define NCT6798_TEMP_MASK	0xbfff0ffe
655*c3963bc0SZev Weiss #define NCT6798_VIRT_TEMP_MASK	0x80000c00
656*c3963bc0SZev Weiss 
657*c3963bc0SZev Weiss /* NCT6102D/NCT6106D specific data */
658*c3963bc0SZev Weiss 
659*c3963bc0SZev Weiss #define NCT6106_REG_VBAT	0x318
660*c3963bc0SZev Weiss #define NCT6106_REG_DIODE	0x319
661*c3963bc0SZev Weiss #define NCT6106_DIODE_MASK	0x01
662*c3963bc0SZev Weiss 
663*c3963bc0SZev Weiss static const u16 NCT6106_REG_IN_MAX[] = {
664*c3963bc0SZev Weiss 	0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9e, 0xa0, 0xa2 };
665*c3963bc0SZev Weiss static const u16 NCT6106_REG_IN_MIN[] = {
666*c3963bc0SZev Weiss 	0x91, 0x93, 0x95, 0x97, 0x99, 0x9b, 0x9f, 0xa1, 0xa3 };
667*c3963bc0SZev Weiss static const u16 NCT6106_REG_IN[] = {
668*c3963bc0SZev Weiss 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x07, 0x08, 0x09 };
669*c3963bc0SZev Weiss 
670*c3963bc0SZev Weiss static const u16 NCT6106_REG_TEMP[] = { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15 };
671*c3963bc0SZev Weiss static const u16 NCT6106_REG_TEMP_MON[] = { 0x18, 0x19, 0x1a };
672*c3963bc0SZev Weiss static const u16 NCT6106_REG_TEMP_HYST[] = {
673*c3963bc0SZev Weiss 	0xc3, 0xc7, 0xcb, 0xcf, 0xd3, 0xd7 };
674*c3963bc0SZev Weiss static const u16 NCT6106_REG_TEMP_OVER[] = {
675*c3963bc0SZev Weiss 	0xc2, 0xc6, 0xca, 0xce, 0xd2, 0xd6 };
676*c3963bc0SZev Weiss static const u16 NCT6106_REG_TEMP_CRIT_L[] = {
677*c3963bc0SZev Weiss 	0xc0, 0xc4, 0xc8, 0xcc, 0xd0, 0xd4 };
678*c3963bc0SZev Weiss static const u16 NCT6106_REG_TEMP_CRIT_H[] = {
679*c3963bc0SZev Weiss 	0xc1, 0xc5, 0xc9, 0xcf, 0xd1, 0xd5 };
680*c3963bc0SZev Weiss static const u16 NCT6106_REG_TEMP_OFFSET[] = { 0x311, 0x312, 0x313 };
681*c3963bc0SZev Weiss static const u16 NCT6106_REG_TEMP_CONFIG[] = {
682*c3963bc0SZev Weiss 	0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc };
683*c3963bc0SZev Weiss 
684*c3963bc0SZev Weiss static const u16 NCT6106_REG_FAN[] = { 0x20, 0x22, 0x24 };
685*c3963bc0SZev Weiss static const u16 NCT6106_REG_FAN_MIN[] = { 0xe0, 0xe2, 0xe4 };
686*c3963bc0SZev Weiss static const u16 NCT6106_REG_FAN_PULSES[] = { 0xf6, 0xf6, 0xf6 };
687*c3963bc0SZev Weiss static const u16 NCT6106_FAN_PULSE_SHIFT[] = { 0, 2, 4 };
688*c3963bc0SZev Weiss 
689*c3963bc0SZev Weiss static const u8 NCT6106_REG_PWM_MODE[] = { 0xf3, 0xf3, 0xf3 };
690*c3963bc0SZev Weiss static const u8 NCT6106_PWM_MODE_MASK[] = { 0x01, 0x02, 0x04 };
691*c3963bc0SZev Weiss static const u16 NCT6106_REG_PWM_READ[] = { 0x4a, 0x4b, 0x4c };
692*c3963bc0SZev Weiss static const u16 NCT6106_REG_FAN_MODE[] = { 0x113, 0x123, 0x133 };
693*c3963bc0SZev Weiss static const u16 NCT6106_REG_TEMP_SOURCE[] = {
694*c3963bc0SZev Weiss 	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5 };
695*c3963bc0SZev Weiss 
696*c3963bc0SZev Weiss static const u16 NCT6106_REG_CRITICAL_TEMP[] = { 0x11a, 0x12a, 0x13a };
697*c3963bc0SZev Weiss static const u16 NCT6106_REG_CRITICAL_TEMP_TOLERANCE[] = {
698*c3963bc0SZev Weiss 	0x11b, 0x12b, 0x13b };
699*c3963bc0SZev Weiss 
700*c3963bc0SZev Weiss static const u16 NCT6106_REG_CRITICAL_PWM_ENABLE[] = { 0x11c, 0x12c, 0x13c };
701*c3963bc0SZev Weiss #define NCT6106_CRITICAL_PWM_ENABLE_MASK	0x10
702*c3963bc0SZev Weiss static const u16 NCT6106_REG_CRITICAL_PWM[] = { 0x11d, 0x12d, 0x13d };
703*c3963bc0SZev Weiss 
704*c3963bc0SZev Weiss static const u16 NCT6106_REG_FAN_STEP_UP_TIME[] = { 0x114, 0x124, 0x134 };
705*c3963bc0SZev Weiss static const u16 NCT6106_REG_FAN_STEP_DOWN_TIME[] = { 0x115, 0x125, 0x135 };
706*c3963bc0SZev Weiss static const u16 NCT6106_REG_FAN_STOP_OUTPUT[] = { 0x116, 0x126, 0x136 };
707*c3963bc0SZev Weiss static const u16 NCT6106_REG_FAN_START_OUTPUT[] = { 0x117, 0x127, 0x137 };
708*c3963bc0SZev Weiss static const u16 NCT6106_REG_FAN_STOP_TIME[] = { 0x118, 0x128, 0x138 };
709*c3963bc0SZev Weiss static const u16 NCT6106_REG_TOLERANCE_H[] = { 0x112, 0x122, 0x132 };
710*c3963bc0SZev Weiss 
711*c3963bc0SZev Weiss static const u16 NCT6106_REG_TARGET[] = { 0x111, 0x121, 0x131 };
712*c3963bc0SZev Weiss 
713*c3963bc0SZev Weiss static const u16 NCT6106_REG_WEIGHT_TEMP_SEL[] = { 0x168, 0x178, 0x188 };
714*c3963bc0SZev Weiss static const u16 NCT6106_REG_WEIGHT_TEMP_STEP[] = { 0x169, 0x179, 0x189 };
715*c3963bc0SZev Weiss static const u16 NCT6106_REG_WEIGHT_TEMP_STEP_TOL[] = { 0x16a, 0x17a, 0x18a };
716*c3963bc0SZev Weiss static const u16 NCT6106_REG_WEIGHT_DUTY_STEP[] = { 0x16b, 0x17b, 0x18b };
717*c3963bc0SZev Weiss static const u16 NCT6106_REG_WEIGHT_TEMP_BASE[] = { 0x16c, 0x17c, 0x18c };
718*c3963bc0SZev Weiss static const u16 NCT6106_REG_WEIGHT_DUTY_BASE[] = { 0x16d, 0x17d, 0x18d };
719*c3963bc0SZev Weiss 
720*c3963bc0SZev Weiss static const u16 NCT6106_REG_AUTO_TEMP[] = { 0x160, 0x170, 0x180 };
721*c3963bc0SZev Weiss static const u16 NCT6106_REG_AUTO_PWM[] = { 0x164, 0x174, 0x184 };
722*c3963bc0SZev Weiss 
723*c3963bc0SZev Weiss static const u16 NCT6106_REG_ALARM[NUM_REG_ALARM] = {
724*c3963bc0SZev Weiss 	0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d };
725*c3963bc0SZev Weiss 
726*c3963bc0SZev Weiss static const s8 NCT6106_ALARM_BITS[] = {
727*c3963bc0SZev Weiss 	0, 1, 2, 3, 4, 5, 7, 8,		/* in0.. in7 */
728*c3963bc0SZev Weiss 	9, -1, -1, -1, -1, -1, -1,	/* in8..in14 */
729*c3963bc0SZev Weiss 	-1,				/* unused */
730*c3963bc0SZev Weiss 	32, 33, 34, -1, -1,		/* fan1..fan5 */
731*c3963bc0SZev Weiss 	-1, -1, -1,			/* unused */
732*c3963bc0SZev Weiss 	16, 17, 18, 19, 20, 21,		/* temp1..temp6 */
733*c3963bc0SZev Weiss 	48, -1				/* intrusion0, intrusion1 */
734*c3963bc0SZev Weiss };
735*c3963bc0SZev Weiss 
736*c3963bc0SZev Weiss static const u16 NCT6106_REG_BEEP[NUM_REG_BEEP] = {
737*c3963bc0SZev Weiss 	0x3c0, 0x3c1, 0x3c2, 0x3c3, 0x3c4 };
738*c3963bc0SZev Weiss 
739*c3963bc0SZev Weiss static const s8 NCT6106_BEEP_BITS[] = {
740*c3963bc0SZev Weiss 	0, 1, 2, 3, 4, 5, 7, 8,		/* in0.. in7 */
741*c3963bc0SZev Weiss 	9, 10, 11, 12, -1, -1, -1,	/* in8..in14 */
742*c3963bc0SZev Weiss 	32,				/* global beep enable */
743*c3963bc0SZev Weiss 	24, 25, 26, 27, 28,		/* fan1..fan5 */
744*c3963bc0SZev Weiss 	-1, -1, -1,			/* unused */
745*c3963bc0SZev Weiss 	16, 17, 18, 19, 20, 21,		/* temp1..temp6 */
746*c3963bc0SZev Weiss 	34, -1				/* intrusion0, intrusion1 */
747*c3963bc0SZev Weiss };
748*c3963bc0SZev Weiss 
749*c3963bc0SZev Weiss static const u16 NCT6106_REG_TEMP_ALTERNATE[32] = {
750*c3963bc0SZev Weiss 	[14] = 0x51,
751*c3963bc0SZev Weiss 	[15] = 0x52,
752*c3963bc0SZev Weiss 	[16] = 0x54,
753*c3963bc0SZev Weiss };
754*c3963bc0SZev Weiss 
755*c3963bc0SZev Weiss static const u16 NCT6106_REG_TEMP_CRIT[32] = {
756*c3963bc0SZev Weiss 	[11] = 0x204,
757*c3963bc0SZev Weiss 	[12] = 0x205,
758*c3963bc0SZev Weiss };
759*c3963bc0SZev Weiss 
760*c3963bc0SZev Weiss static const u16 NCT6106_REG_TSI_TEMP[] = { 0x59, 0x5b, 0x5d, 0x5f, 0x61, 0x63, 0x65, 0x67 };
761*c3963bc0SZev Weiss 
762*c3963bc0SZev Weiss /* NCT6112D/NCT6114D/NCT6116D specific data */
763*c3963bc0SZev Weiss 
764*c3963bc0SZev Weiss static const u16 NCT6116_REG_FAN[] = { 0x20, 0x22, 0x24, 0x26, 0x28 };
765*c3963bc0SZev Weiss static const u16 NCT6116_REG_FAN_MIN[] = { 0xe0, 0xe2, 0xe4, 0xe6, 0xe8 };
766*c3963bc0SZev Weiss static const u16 NCT6116_REG_FAN_PULSES[] = { 0xf6, 0xf6, 0xf6, 0xf6, 0xf5 };
767*c3963bc0SZev Weiss static const u16 NCT6116_FAN_PULSE_SHIFT[] = { 0, 2, 4, 6, 6 };
768*c3963bc0SZev Weiss 
769*c3963bc0SZev Weiss static const u16 NCT6116_REG_PWM[] = { 0x119, 0x129, 0x139, 0x199, 0x1a9 };
770*c3963bc0SZev Weiss static const u16 NCT6116_REG_FAN_MODE[] = { 0x113, 0x123, 0x133, 0x193, 0x1a3 };
771*c3963bc0SZev Weiss static const u16 NCT6116_REG_TEMP_SEL[] = { 0x110, 0x120, 0x130, 0x190, 0x1a0 };
772*c3963bc0SZev Weiss static const u16 NCT6116_REG_TEMP_SOURCE[] = {
773*c3963bc0SZev Weiss 	0xb0, 0xb1, 0xb2 };
774*c3963bc0SZev Weiss 
775*c3963bc0SZev Weiss static const u16 NCT6116_REG_CRITICAL_TEMP[] = {
776*c3963bc0SZev Weiss 	0x11a, 0x12a, 0x13a, 0x19a, 0x1aa };
777*c3963bc0SZev Weiss static const u16 NCT6116_REG_CRITICAL_TEMP_TOLERANCE[] = {
778*c3963bc0SZev Weiss 	0x11b, 0x12b, 0x13b, 0x19b, 0x1ab };
779*c3963bc0SZev Weiss 
780*c3963bc0SZev Weiss static const u16 NCT6116_REG_CRITICAL_PWM_ENABLE[] = {
781*c3963bc0SZev Weiss 	0x11c, 0x12c, 0x13c, 0x19c, 0x1ac };
782*c3963bc0SZev Weiss static const u16 NCT6116_REG_CRITICAL_PWM[] = {
783*c3963bc0SZev Weiss 	0x11d, 0x12d, 0x13d, 0x19d, 0x1ad };
784*c3963bc0SZev Weiss 
785*c3963bc0SZev Weiss static const u16 NCT6116_REG_FAN_STEP_UP_TIME[] = {
786*c3963bc0SZev Weiss 	0x114, 0x124, 0x134, 0x194, 0x1a4 };
787*c3963bc0SZev Weiss static const u16 NCT6116_REG_FAN_STEP_DOWN_TIME[] = {
788*c3963bc0SZev Weiss 	0x115, 0x125, 0x135, 0x195, 0x1a5 };
789*c3963bc0SZev Weiss static const u16 NCT6116_REG_FAN_STOP_OUTPUT[] = {
790*c3963bc0SZev Weiss 	0x116, 0x126, 0x136, 0x196, 0x1a6 };
791*c3963bc0SZev Weiss static const u16 NCT6116_REG_FAN_START_OUTPUT[] = {
792*c3963bc0SZev Weiss 	0x117, 0x127, 0x137, 0x197, 0x1a7 };
793*c3963bc0SZev Weiss static const u16 NCT6116_REG_FAN_STOP_TIME[] = {
794*c3963bc0SZev Weiss 	0x118, 0x128, 0x138, 0x198, 0x1a8 };
795*c3963bc0SZev Weiss static const u16 NCT6116_REG_TOLERANCE_H[] = {
796*c3963bc0SZev Weiss 	0x112, 0x122, 0x132, 0x192, 0x1a2 };
797*c3963bc0SZev Weiss 
798*c3963bc0SZev Weiss static const u16 NCT6116_REG_TARGET[] = {
799*c3963bc0SZev Weiss 	0x111, 0x121, 0x131, 0x191, 0x1a1 };
800*c3963bc0SZev Weiss 
801*c3963bc0SZev Weiss static const u16 NCT6116_REG_AUTO_TEMP[] = {
802*c3963bc0SZev Weiss 	0x160, 0x170, 0x180, 0x1d0, 0x1e0 };
803*c3963bc0SZev Weiss static const u16 NCT6116_REG_AUTO_PWM[] = {
804*c3963bc0SZev Weiss 	0x164, 0x174, 0x184, 0x1d4, 0x1e4 };
805*c3963bc0SZev Weiss 
806*c3963bc0SZev Weiss static const s8 NCT6116_ALARM_BITS[] = {
807*c3963bc0SZev Weiss 	0, 1, 2, 3, 4, 5, 7, 8,		/* in0.. in7 */
808*c3963bc0SZev Weiss 	9, -1, -1, -1, -1, -1, -1,	/* in8..in9 */
809*c3963bc0SZev Weiss 	-1,				/* unused */
810*c3963bc0SZev Weiss 	32, 33, 34, 35, 36,		/* fan1..fan5 */
811*c3963bc0SZev Weiss 	-1, -1, -1,			/* unused */
812*c3963bc0SZev Weiss 	16, 17, 18, -1, -1, -1,		/* temp1..temp6 */
813*c3963bc0SZev Weiss 	48, -1				/* intrusion0, intrusion1 */
814*c3963bc0SZev Weiss };
815*c3963bc0SZev Weiss 
816*c3963bc0SZev Weiss static const s8 NCT6116_BEEP_BITS[] = {
817*c3963bc0SZev Weiss 	0, 1, 2, 3, 4, 5, 7, 8,		/* in0.. in7 */
818*c3963bc0SZev Weiss 	9, 10, 11, 12, -1, -1, -1,	/* in8..in14 */
819*c3963bc0SZev Weiss 	32,				/* global beep enable */
820*c3963bc0SZev Weiss 	24, 25, 26, 27, 28,		/* fan1..fan5 */
821*c3963bc0SZev Weiss 	-1, -1, -1,			/* unused */
822*c3963bc0SZev Weiss 	16, 17, 18, -1, -1, -1,		/* temp1..temp6 */
823*c3963bc0SZev Weiss 	34, -1				/* intrusion0, intrusion1 */
824*c3963bc0SZev Weiss };
825*c3963bc0SZev Weiss 
826*c3963bc0SZev Weiss static const u16 NCT6116_REG_TSI_TEMP[] = { 0x59, 0x5b };
827*c3963bc0SZev Weiss 
828*c3963bc0SZev Weiss static enum pwm_enable reg_to_pwm_enable(int pwm, int mode)
829*c3963bc0SZev Weiss {
830*c3963bc0SZev Weiss 	if (mode == 0 && pwm == 255)
831*c3963bc0SZev Weiss 		return off;
832*c3963bc0SZev Weiss 	return mode + 1;
833*c3963bc0SZev Weiss }
834*c3963bc0SZev Weiss 
835*c3963bc0SZev Weiss static int pwm_enable_to_reg(enum pwm_enable mode)
836*c3963bc0SZev Weiss {
837*c3963bc0SZev Weiss 	if (mode == off)
838*c3963bc0SZev Weiss 		return 0;
839*c3963bc0SZev Weiss 	return mode - 1;
840*c3963bc0SZev Weiss }
841*c3963bc0SZev Weiss 
842*c3963bc0SZev Weiss /*
843*c3963bc0SZev Weiss  * Conversions
844*c3963bc0SZev Weiss  */
845*c3963bc0SZev Weiss 
846*c3963bc0SZev Weiss /* 1 is DC mode, output in ms */
847*c3963bc0SZev Weiss static unsigned int step_time_from_reg(u8 reg, u8 mode)
848*c3963bc0SZev Weiss {
849*c3963bc0SZev Weiss 	return mode ? 400 * reg : 100 * reg;
850*c3963bc0SZev Weiss }
851*c3963bc0SZev Weiss 
852*c3963bc0SZev Weiss static u8 step_time_to_reg(unsigned int msec, u8 mode)
853*c3963bc0SZev Weiss {
854*c3963bc0SZev Weiss 	return clamp_val((mode ? (msec + 200) / 400 :
855*c3963bc0SZev Weiss 					(msec + 50) / 100), 1, 255);
856*c3963bc0SZev Weiss }
857*c3963bc0SZev Weiss 
858*c3963bc0SZev Weiss static unsigned int fan_from_reg8(u16 reg, unsigned int divreg)
859*c3963bc0SZev Weiss {
860*c3963bc0SZev Weiss 	if (reg == 0 || reg == 255)
861*c3963bc0SZev Weiss 		return 0;
862*c3963bc0SZev Weiss 	return 1350000U / (reg << divreg);
863*c3963bc0SZev Weiss }
864*c3963bc0SZev Weiss 
865*c3963bc0SZev Weiss static unsigned int fan_from_reg13(u16 reg, unsigned int divreg)
866*c3963bc0SZev Weiss {
867*c3963bc0SZev Weiss 	if ((reg & 0xff1f) == 0xff1f)
868*c3963bc0SZev Weiss 		return 0;
869*c3963bc0SZev Weiss 
870*c3963bc0SZev Weiss 	reg = (reg & 0x1f) | ((reg & 0xff00) >> 3);
871*c3963bc0SZev Weiss 
872*c3963bc0SZev Weiss 	if (reg == 0)
873*c3963bc0SZev Weiss 		return 0;
874*c3963bc0SZev Weiss 
875*c3963bc0SZev Weiss 	return 1350000U / reg;
876*c3963bc0SZev Weiss }
877*c3963bc0SZev Weiss 
878*c3963bc0SZev Weiss static unsigned int fan_from_reg16(u16 reg, unsigned int divreg)
879*c3963bc0SZev Weiss {
880*c3963bc0SZev Weiss 	if (reg == 0 || reg == 0xffff)
881*c3963bc0SZev Weiss 		return 0;
882*c3963bc0SZev Weiss 
883*c3963bc0SZev Weiss 	/*
884*c3963bc0SZev Weiss 	 * Even though the registers are 16 bit wide, the fan divisor
885*c3963bc0SZev Weiss 	 * still applies.
886*c3963bc0SZev Weiss 	 */
887*c3963bc0SZev Weiss 	return 1350000U / (reg << divreg);
888*c3963bc0SZev Weiss }
889*c3963bc0SZev Weiss 
890*c3963bc0SZev Weiss static unsigned int fan_from_reg_rpm(u16 reg, unsigned int divreg)
891*c3963bc0SZev Weiss {
892*c3963bc0SZev Weiss 	return reg;
893*c3963bc0SZev Weiss }
894*c3963bc0SZev Weiss 
895*c3963bc0SZev Weiss static u16 fan_to_reg(u32 fan, unsigned int divreg)
896*c3963bc0SZev Weiss {
897*c3963bc0SZev Weiss 	if (!fan)
898*c3963bc0SZev Weiss 		return 0;
899*c3963bc0SZev Weiss 
900*c3963bc0SZev Weiss 	return (1350000U / fan) >> divreg;
901*c3963bc0SZev Weiss }
902*c3963bc0SZev Weiss 
903*c3963bc0SZev Weiss static inline unsigned int
904*c3963bc0SZev Weiss div_from_reg(u8 reg)
905*c3963bc0SZev Weiss {
906*c3963bc0SZev Weiss 	return BIT(reg);
907*c3963bc0SZev Weiss }
908*c3963bc0SZev Weiss 
909*c3963bc0SZev Weiss /*
910*c3963bc0SZev Weiss  * Some of the voltage inputs have internal scaling, the tables below
911*c3963bc0SZev Weiss  * contain 8 (the ADC LSB in mV) * scaling factor * 100
912*c3963bc0SZev Weiss  */
913*c3963bc0SZev Weiss static const u16 scale_in[15] = {
914*c3963bc0SZev Weiss 	800, 800, 1600, 1600, 800, 800, 800, 1600, 1600, 800, 800, 800, 800,
915*c3963bc0SZev Weiss 	800, 800
916*c3963bc0SZev Weiss };
917*c3963bc0SZev Weiss 
918*c3963bc0SZev Weiss static inline long in_from_reg(u8 reg, u8 nr)
919*c3963bc0SZev Weiss {
920*c3963bc0SZev Weiss 	return DIV_ROUND_CLOSEST(reg * scale_in[nr], 100);
921*c3963bc0SZev Weiss }
922*c3963bc0SZev Weiss 
923*c3963bc0SZev Weiss static inline u8 in_to_reg(u32 val, u8 nr)
924*c3963bc0SZev Weiss {
925*c3963bc0SZev Weiss 	return clamp_val(DIV_ROUND_CLOSEST(val * 100, scale_in[nr]), 0, 255);
926*c3963bc0SZev Weiss }
927*c3963bc0SZev Weiss 
928*c3963bc0SZev Weiss /* TSI temperatures are in 8.3 format */
929*c3963bc0SZev Weiss static inline unsigned int tsi_temp_from_reg(unsigned int reg)
930*c3963bc0SZev Weiss {
931*c3963bc0SZev Weiss 	return (reg >> 5) * 125;
932*c3963bc0SZev Weiss }
933*c3963bc0SZev Weiss 
934*c3963bc0SZev Weiss /*
935*c3963bc0SZev Weiss  * Data structures and manipulation thereof
936*c3963bc0SZev Weiss  */
937*c3963bc0SZev Weiss 
938*c3963bc0SZev Weiss struct sensor_device_template {
939*c3963bc0SZev Weiss 	struct device_attribute dev_attr;
940*c3963bc0SZev Weiss 	union {
941*c3963bc0SZev Weiss 		struct {
942*c3963bc0SZev Weiss 			u8 nr;
943*c3963bc0SZev Weiss 			u8 index;
944*c3963bc0SZev Weiss 		} s;
945*c3963bc0SZev Weiss 		int index;
946*c3963bc0SZev Weiss 	} u;
947*c3963bc0SZev Weiss 	bool s2;	/* true if both index and nr are used */
948*c3963bc0SZev Weiss };
949*c3963bc0SZev Weiss 
950*c3963bc0SZev Weiss struct sensor_device_attr_u {
951*c3963bc0SZev Weiss 	union {
952*c3963bc0SZev Weiss 		struct sensor_device_attribute a1;
953*c3963bc0SZev Weiss 		struct sensor_device_attribute_2 a2;
954*c3963bc0SZev Weiss 	} u;
955*c3963bc0SZev Weiss 	char name[32];
956*c3963bc0SZev Weiss };
957*c3963bc0SZev Weiss 
958*c3963bc0SZev Weiss #define __TEMPLATE_ATTR(_template, _mode, _show, _store) {	\
959*c3963bc0SZev Weiss 	.attr = {.name = _template, .mode = _mode },		\
960*c3963bc0SZev Weiss 	.show	= _show,					\
961*c3963bc0SZev Weiss 	.store	= _store,					\
962*c3963bc0SZev Weiss }
963*c3963bc0SZev Weiss 
964*c3963bc0SZev Weiss #define SENSOR_DEVICE_TEMPLATE(_template, _mode, _show, _store, _index)	\
965*c3963bc0SZev Weiss 	{ .dev_attr = __TEMPLATE_ATTR(_template, _mode, _show, _store),	\
966*c3963bc0SZev Weiss 	  .u.index = _index,						\
967*c3963bc0SZev Weiss 	  .s2 = false }
968*c3963bc0SZev Weiss 
969*c3963bc0SZev Weiss #define SENSOR_DEVICE_TEMPLATE_2(_template, _mode, _show, _store,	\
970*c3963bc0SZev Weiss 				 _nr, _index)				\
971*c3963bc0SZev Weiss 	{ .dev_attr = __TEMPLATE_ATTR(_template, _mode, _show, _store),	\
972*c3963bc0SZev Weiss 	  .u.s.index = _index,						\
973*c3963bc0SZev Weiss 	  .u.s.nr = _nr,						\
974*c3963bc0SZev Weiss 	  .s2 = true }
975*c3963bc0SZev Weiss 
976*c3963bc0SZev Weiss #define SENSOR_TEMPLATE(_name, _template, _mode, _show, _store, _index)	\
977*c3963bc0SZev Weiss static struct sensor_device_template sensor_dev_template_##_name	\
978*c3963bc0SZev Weiss 	= SENSOR_DEVICE_TEMPLATE(_template, _mode, _show, _store,	\
979*c3963bc0SZev Weiss 				 _index)
980*c3963bc0SZev Weiss 
981*c3963bc0SZev Weiss #define SENSOR_TEMPLATE_2(_name, _template, _mode, _show, _store,	\
982*c3963bc0SZev Weiss 			  _nr, _index)					\
983*c3963bc0SZev Weiss static struct sensor_device_template sensor_dev_template_##_name	\
984*c3963bc0SZev Weiss 	= SENSOR_DEVICE_TEMPLATE_2(_template, _mode, _show, _store,	\
985*c3963bc0SZev Weiss 				 _nr, _index)
986*c3963bc0SZev Weiss 
987*c3963bc0SZev Weiss struct sensor_template_group {
988*c3963bc0SZev Weiss 	struct sensor_device_template **templates;
989*c3963bc0SZev Weiss 	umode_t (*is_visible)(struct kobject *, struct attribute *, int);
990*c3963bc0SZev Weiss 	int base;
991*c3963bc0SZev Weiss };
992*c3963bc0SZev Weiss 
993*c3963bc0SZev Weiss static int nct6775_add_template_attr_group(struct device *dev, struct nct6775_data *data,
994*c3963bc0SZev Weiss 					   const struct sensor_template_group *tg, int repeat)
995*c3963bc0SZev Weiss {
996*c3963bc0SZev Weiss 	struct attribute_group *group;
997*c3963bc0SZev Weiss 	struct sensor_device_attr_u *su;
998*c3963bc0SZev Weiss 	struct sensor_device_attribute *a;
999*c3963bc0SZev Weiss 	struct sensor_device_attribute_2 *a2;
1000*c3963bc0SZev Weiss 	struct attribute **attrs;
1001*c3963bc0SZev Weiss 	struct sensor_device_template **t;
1002*c3963bc0SZev Weiss 	int i, count;
1003*c3963bc0SZev Weiss 
1004*c3963bc0SZev Weiss 	if (repeat <= 0)
1005*c3963bc0SZev Weiss 		return -EINVAL;
1006*c3963bc0SZev Weiss 
1007*c3963bc0SZev Weiss 	t = tg->templates;
1008*c3963bc0SZev Weiss 	for (count = 0; *t; t++, count++)
1009*c3963bc0SZev Weiss 		;
1010*c3963bc0SZev Weiss 
1011*c3963bc0SZev Weiss 	if (count == 0)
1012*c3963bc0SZev Weiss 		return -EINVAL;
1013*c3963bc0SZev Weiss 
1014*c3963bc0SZev Weiss 	group = devm_kzalloc(dev, sizeof(*group), GFP_KERNEL);
1015*c3963bc0SZev Weiss 	if (group == NULL)
1016*c3963bc0SZev Weiss 		return -ENOMEM;
1017*c3963bc0SZev Weiss 
1018*c3963bc0SZev Weiss 	attrs = devm_kcalloc(dev, repeat * count + 1, sizeof(*attrs),
1019*c3963bc0SZev Weiss 			     GFP_KERNEL);
1020*c3963bc0SZev Weiss 	if (attrs == NULL)
1021*c3963bc0SZev Weiss 		return -ENOMEM;
1022*c3963bc0SZev Weiss 
1023*c3963bc0SZev Weiss 	su = devm_kzalloc(dev, array3_size(repeat, count, sizeof(*su)),
1024*c3963bc0SZev Weiss 			       GFP_KERNEL);
1025*c3963bc0SZev Weiss 	if (su == NULL)
1026*c3963bc0SZev Weiss 		return -ENOMEM;
1027*c3963bc0SZev Weiss 
1028*c3963bc0SZev Weiss 	group->attrs = attrs;
1029*c3963bc0SZev Weiss 	group->is_visible = tg->is_visible;
1030*c3963bc0SZev Weiss 
1031*c3963bc0SZev Weiss 	for (i = 0; i < repeat; i++) {
1032*c3963bc0SZev Weiss 		t = tg->templates;
1033*c3963bc0SZev Weiss 		while (*t != NULL) {
1034*c3963bc0SZev Weiss 			snprintf(su->name, sizeof(su->name),
1035*c3963bc0SZev Weiss 				 (*t)->dev_attr.attr.name, tg->base + i);
1036*c3963bc0SZev Weiss 			if ((*t)->s2) {
1037*c3963bc0SZev Weiss 				a2 = &su->u.a2;
1038*c3963bc0SZev Weiss 				sysfs_attr_init(&a2->dev_attr.attr);
1039*c3963bc0SZev Weiss 				a2->dev_attr.attr.name = su->name;
1040*c3963bc0SZev Weiss 				a2->nr = (*t)->u.s.nr + i;
1041*c3963bc0SZev Weiss 				a2->index = (*t)->u.s.index;
1042*c3963bc0SZev Weiss 				a2->dev_attr.attr.mode =
1043*c3963bc0SZev Weiss 				  (*t)->dev_attr.attr.mode;
1044*c3963bc0SZev Weiss 				a2->dev_attr.show = (*t)->dev_attr.show;
1045*c3963bc0SZev Weiss 				a2->dev_attr.store = (*t)->dev_attr.store;
1046*c3963bc0SZev Weiss 				*attrs = &a2->dev_attr.attr;
1047*c3963bc0SZev Weiss 			} else {
1048*c3963bc0SZev Weiss 				a = &su->u.a1;
1049*c3963bc0SZev Weiss 				sysfs_attr_init(&a->dev_attr.attr);
1050*c3963bc0SZev Weiss 				a->dev_attr.attr.name = su->name;
1051*c3963bc0SZev Weiss 				a->index = (*t)->u.index + i;
1052*c3963bc0SZev Weiss 				a->dev_attr.attr.mode =
1053*c3963bc0SZev Weiss 				  (*t)->dev_attr.attr.mode;
1054*c3963bc0SZev Weiss 				a->dev_attr.show = (*t)->dev_attr.show;
1055*c3963bc0SZev Weiss 				a->dev_attr.store = (*t)->dev_attr.store;
1056*c3963bc0SZev Weiss 				*attrs = &a->dev_attr.attr;
1057*c3963bc0SZev Weiss 			}
1058*c3963bc0SZev Weiss 			attrs++;
1059*c3963bc0SZev Weiss 			su++;
1060*c3963bc0SZev Weiss 			t++;
1061*c3963bc0SZev Weiss 		}
1062*c3963bc0SZev Weiss 	}
1063*c3963bc0SZev Weiss 
1064*c3963bc0SZev Weiss 	return nct6775_add_attr_group(data, group);
1065*c3963bc0SZev Weiss }
1066*c3963bc0SZev Weiss 
1067*c3963bc0SZev Weiss bool nct6775_reg_is_word_sized(struct nct6775_data *data, u16 reg)
1068*c3963bc0SZev Weiss {
1069*c3963bc0SZev Weiss 	switch (data->kind) {
1070*c3963bc0SZev Weiss 	case nct6106:
1071*c3963bc0SZev Weiss 		return reg == 0x20 || reg == 0x22 || reg == 0x24 ||
1072*c3963bc0SZev Weiss 		  (reg >= 0x59 && reg < 0x69 && (reg & 1)) ||
1073*c3963bc0SZev Weiss 		  reg == 0xe0 || reg == 0xe2 || reg == 0xe4 ||
1074*c3963bc0SZev Weiss 		  reg == 0x111 || reg == 0x121 || reg == 0x131;
1075*c3963bc0SZev Weiss 	case nct6116:
1076*c3963bc0SZev Weiss 		return reg == 0x20 || reg == 0x22 || reg == 0x24 ||
1077*c3963bc0SZev Weiss 		  reg == 0x26 || reg == 0x28 || reg == 0x59 || reg == 0x5b ||
1078*c3963bc0SZev Weiss 		  reg == 0xe0 || reg == 0xe2 || reg == 0xe4 || reg == 0xe6 ||
1079*c3963bc0SZev Weiss 		  reg == 0xe8 || reg == 0x111 || reg == 0x121 || reg == 0x131 ||
1080*c3963bc0SZev Weiss 		  reg == 0x191 || reg == 0x1a1;
1081*c3963bc0SZev Weiss 	case nct6775:
1082*c3963bc0SZev Weiss 		return (((reg & 0xff00) == 0x100 ||
1083*c3963bc0SZev Weiss 		    (reg & 0xff00) == 0x200) &&
1084*c3963bc0SZev Weiss 		   ((reg & 0x00ff) == 0x50 ||
1085*c3963bc0SZev Weiss 		    (reg & 0x00ff) == 0x53 ||
1086*c3963bc0SZev Weiss 		    (reg & 0x00ff) == 0x55)) ||
1087*c3963bc0SZev Weiss 		  (reg & 0xfff0) == 0x630 ||
1088*c3963bc0SZev Weiss 		  reg == 0x640 || reg == 0x642 ||
1089*c3963bc0SZev Weiss 		  reg == 0x662 || reg == 0x669 ||
1090*c3963bc0SZev Weiss 		  ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) ||
1091*c3963bc0SZev Weiss 		  reg == 0x73 || reg == 0x75 || reg == 0x77;
1092*c3963bc0SZev Weiss 	case nct6776:
1093*c3963bc0SZev Weiss 		return (((reg & 0xff00) == 0x100 ||
1094*c3963bc0SZev Weiss 		    (reg & 0xff00) == 0x200) &&
1095*c3963bc0SZev Weiss 		   ((reg & 0x00ff) == 0x50 ||
1096*c3963bc0SZev Weiss 		    (reg & 0x00ff) == 0x53 ||
1097*c3963bc0SZev Weiss 		    (reg & 0x00ff) == 0x55)) ||
1098*c3963bc0SZev Weiss 		  (reg & 0xfff0) == 0x630 ||
1099*c3963bc0SZev Weiss 		  reg == 0x402 ||
1100*c3963bc0SZev Weiss 		  (reg >= 0x409 && reg < 0x419 && (reg & 1)) ||
1101*c3963bc0SZev Weiss 		  reg == 0x640 || reg == 0x642 ||
1102*c3963bc0SZev Weiss 		  ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) ||
1103*c3963bc0SZev Weiss 		  reg == 0x73 || reg == 0x75 || reg == 0x77;
1104*c3963bc0SZev Weiss 	case nct6779:
1105*c3963bc0SZev Weiss 	case nct6791:
1106*c3963bc0SZev Weiss 	case nct6792:
1107*c3963bc0SZev Weiss 	case nct6793:
1108*c3963bc0SZev Weiss 	case nct6795:
1109*c3963bc0SZev Weiss 	case nct6796:
1110*c3963bc0SZev Weiss 	case nct6797:
1111*c3963bc0SZev Weiss 	case nct6798:
1112*c3963bc0SZev Weiss 		return reg == 0x150 || reg == 0x153 || reg == 0x155 ||
1113*c3963bc0SZev Weiss 		  (reg & 0xfff0) == 0x4c0 ||
1114*c3963bc0SZev Weiss 		  reg == 0x402 ||
1115*c3963bc0SZev Weiss 		  (reg >= 0x409 && reg < 0x419 && (reg & 1)) ||
1116*c3963bc0SZev Weiss 		  reg == 0x63a || reg == 0x63c || reg == 0x63e ||
1117*c3963bc0SZev Weiss 		  reg == 0x640 || reg == 0x642 || reg == 0x64a ||
1118*c3963bc0SZev Weiss 		  reg == 0x64c ||
1119*c3963bc0SZev Weiss 		  reg == 0x73 || reg == 0x75 || reg == 0x77 || reg == 0x79 ||
1120*c3963bc0SZev Weiss 		  reg == 0x7b || reg == 0x7d;
1121*c3963bc0SZev Weiss 	}
1122*c3963bc0SZev Weiss 	return false;
1123*c3963bc0SZev Weiss }
1124*c3963bc0SZev Weiss EXPORT_SYMBOL_GPL(nct6775_reg_is_word_sized);
1125*c3963bc0SZev Weiss 
1126*c3963bc0SZev Weiss /* We left-align 8-bit temperature values to make the code simpler */
1127*c3963bc0SZev Weiss static int nct6775_read_temp(struct nct6775_data *data, u16 reg, u16 *val)
1128*c3963bc0SZev Weiss {
1129*c3963bc0SZev Weiss 	int err;
1130*c3963bc0SZev Weiss 
1131*c3963bc0SZev Weiss 	err = nct6775_read_value(data, reg, val);
1132*c3963bc0SZev Weiss 	if (err)
1133*c3963bc0SZev Weiss 		return err;
1134*c3963bc0SZev Weiss 
1135*c3963bc0SZev Weiss 	if (!nct6775_reg_is_word_sized(data, reg))
1136*c3963bc0SZev Weiss 		*val <<= 8;
1137*c3963bc0SZev Weiss 
1138*c3963bc0SZev Weiss 	return 0;
1139*c3963bc0SZev Weiss }
1140*c3963bc0SZev Weiss 
1141*c3963bc0SZev Weiss /* This function assumes that the caller holds data->update_lock */
1142*c3963bc0SZev Weiss static int nct6775_write_fan_div(struct nct6775_data *data, int nr)
1143*c3963bc0SZev Weiss {
1144*c3963bc0SZev Weiss 	u16 reg;
1145*c3963bc0SZev Weiss 	int err;
1146*c3963bc0SZev Weiss 	u16 fandiv_reg = nr < 2 ? NCT6775_REG_FANDIV1 : NCT6775_REG_FANDIV2;
1147*c3963bc0SZev Weiss 	unsigned int oddshift = (nr & 1) * 4; /* masks shift by four if nr is odd */
1148*c3963bc0SZev Weiss 
1149*c3963bc0SZev Weiss 	err = nct6775_read_value(data, fandiv_reg, &reg);
1150*c3963bc0SZev Weiss 	if (err)
1151*c3963bc0SZev Weiss 		return err;
1152*c3963bc0SZev Weiss 	reg &= 0x70 >> oddshift;
1153*c3963bc0SZev Weiss 	reg |= data->fan_div[nr] & (0x7 << oddshift);
1154*c3963bc0SZev Weiss 	return nct6775_write_value(data, fandiv_reg, reg);
1155*c3963bc0SZev Weiss }
1156*c3963bc0SZev Weiss 
1157*c3963bc0SZev Weiss static int nct6775_write_fan_div_common(struct nct6775_data *data, int nr)
1158*c3963bc0SZev Weiss {
1159*c3963bc0SZev Weiss 	if (data->kind == nct6775)
1160*c3963bc0SZev Weiss 		return nct6775_write_fan_div(data, nr);
1161*c3963bc0SZev Weiss 	return 0;
1162*c3963bc0SZev Weiss }
1163*c3963bc0SZev Weiss 
1164*c3963bc0SZev Weiss static int nct6775_update_fan_div(struct nct6775_data *data)
1165*c3963bc0SZev Weiss {
1166*c3963bc0SZev Weiss 	int err;
1167*c3963bc0SZev Weiss 	u16 i;
1168*c3963bc0SZev Weiss 
1169*c3963bc0SZev Weiss 	err = nct6775_read_value(data, NCT6775_REG_FANDIV1, &i);
1170*c3963bc0SZev Weiss 	if (err)
1171*c3963bc0SZev Weiss 		return err;
1172*c3963bc0SZev Weiss 	data->fan_div[0] = i & 0x7;
1173*c3963bc0SZev Weiss 	data->fan_div[1] = (i & 0x70) >> 4;
1174*c3963bc0SZev Weiss 	err = nct6775_read_value(data, NCT6775_REG_FANDIV2, &i);
1175*c3963bc0SZev Weiss 	if (err)
1176*c3963bc0SZev Weiss 		return err;
1177*c3963bc0SZev Weiss 	data->fan_div[2] = i & 0x7;
1178*c3963bc0SZev Weiss 	if (data->has_fan & BIT(3))
1179*c3963bc0SZev Weiss 		data->fan_div[3] = (i & 0x70) >> 4;
1180*c3963bc0SZev Weiss 
1181*c3963bc0SZev Weiss 	return 0;
1182*c3963bc0SZev Weiss }
1183*c3963bc0SZev Weiss 
1184*c3963bc0SZev Weiss static int nct6775_update_fan_div_common(struct nct6775_data *data)
1185*c3963bc0SZev Weiss {
1186*c3963bc0SZev Weiss 	if (data->kind == nct6775)
1187*c3963bc0SZev Weiss 		return nct6775_update_fan_div(data);
1188*c3963bc0SZev Weiss 	return 0;
1189*c3963bc0SZev Weiss }
1190*c3963bc0SZev Weiss 
1191*c3963bc0SZev Weiss static int nct6775_init_fan_div(struct nct6775_data *data)
1192*c3963bc0SZev Weiss {
1193*c3963bc0SZev Weiss 	int i, err;
1194*c3963bc0SZev Weiss 
1195*c3963bc0SZev Weiss 	err = nct6775_update_fan_div_common(data);
1196*c3963bc0SZev Weiss 	if (err)
1197*c3963bc0SZev Weiss 		return err;
1198*c3963bc0SZev Weiss 
1199*c3963bc0SZev Weiss 	/*
1200*c3963bc0SZev Weiss 	 * For all fans, start with highest divider value if the divider
1201*c3963bc0SZev Weiss 	 * register is not initialized. This ensures that we get a
1202*c3963bc0SZev Weiss 	 * reading from the fan count register, even if it is not optimal.
1203*c3963bc0SZev Weiss 	 * We'll compute a better divider later on.
1204*c3963bc0SZev Weiss 	 */
1205*c3963bc0SZev Weiss 	for (i = 0; i < ARRAY_SIZE(data->fan_div); i++) {
1206*c3963bc0SZev Weiss 		if (!(data->has_fan & BIT(i)))
1207*c3963bc0SZev Weiss 			continue;
1208*c3963bc0SZev Weiss 		if (data->fan_div[i] == 0) {
1209*c3963bc0SZev Weiss 			data->fan_div[i] = 7;
1210*c3963bc0SZev Weiss 			err = nct6775_write_fan_div_common(data, i);
1211*c3963bc0SZev Weiss 			if (err)
1212*c3963bc0SZev Weiss 				return err;
1213*c3963bc0SZev Weiss 		}
1214*c3963bc0SZev Weiss 	}
1215*c3963bc0SZev Weiss 
1216*c3963bc0SZev Weiss 	return 0;
1217*c3963bc0SZev Weiss }
1218*c3963bc0SZev Weiss 
1219*c3963bc0SZev Weiss static int nct6775_init_fan_common(struct device *dev,
1220*c3963bc0SZev Weiss 				   struct nct6775_data *data)
1221*c3963bc0SZev Weiss {
1222*c3963bc0SZev Weiss 	int i, err;
1223*c3963bc0SZev Weiss 	u16 reg;
1224*c3963bc0SZev Weiss 
1225*c3963bc0SZev Weiss 	if (data->has_fan_div) {
1226*c3963bc0SZev Weiss 		err = nct6775_init_fan_div(data);
1227*c3963bc0SZev Weiss 		if (err)
1228*c3963bc0SZev Weiss 			return err;
1229*c3963bc0SZev Weiss 	}
1230*c3963bc0SZev Weiss 
1231*c3963bc0SZev Weiss 	/*
1232*c3963bc0SZev Weiss 	 * If fan_min is not set (0), set it to 0xff to disable it. This
1233*c3963bc0SZev Weiss 	 * prevents the unnecessary warning when fanX_min is reported as 0.
1234*c3963bc0SZev Weiss 	 */
1235*c3963bc0SZev Weiss 	for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) {
1236*c3963bc0SZev Weiss 		if (data->has_fan_min & BIT(i)) {
1237*c3963bc0SZev Weiss 			err = nct6775_read_value(data, data->REG_FAN_MIN[i], &reg);
1238*c3963bc0SZev Weiss 			if (err)
1239*c3963bc0SZev Weiss 				return err;
1240*c3963bc0SZev Weiss 			if (!reg) {
1241*c3963bc0SZev Weiss 				err = nct6775_write_value(data, data->REG_FAN_MIN[i],
1242*c3963bc0SZev Weiss 							  data->has_fan_div ? 0xff : 0xff1f);
1243*c3963bc0SZev Weiss 				if (err)
1244*c3963bc0SZev Weiss 					return err;
1245*c3963bc0SZev Weiss 			}
1246*c3963bc0SZev Weiss 		}
1247*c3963bc0SZev Weiss 	}
1248*c3963bc0SZev Weiss 
1249*c3963bc0SZev Weiss 	return 0;
1250*c3963bc0SZev Weiss }
1251*c3963bc0SZev Weiss 
1252*c3963bc0SZev Weiss static int nct6775_select_fan_div(struct device *dev,
1253*c3963bc0SZev Weiss 				  struct nct6775_data *data, int nr, u16 reg)
1254*c3963bc0SZev Weiss {
1255*c3963bc0SZev Weiss 	int err;
1256*c3963bc0SZev Weiss 	u8 fan_div = data->fan_div[nr];
1257*c3963bc0SZev Weiss 	u16 fan_min;
1258*c3963bc0SZev Weiss 
1259*c3963bc0SZev Weiss 	if (!data->has_fan_div)
1260*c3963bc0SZev Weiss 		return 0;
1261*c3963bc0SZev Weiss 
1262*c3963bc0SZev Weiss 	/*
1263*c3963bc0SZev Weiss 	 * If we failed to measure the fan speed, or the reported value is not
1264*c3963bc0SZev Weiss 	 * in the optimal range, and the clock divider can be modified,
1265*c3963bc0SZev Weiss 	 * let's try that for next time.
1266*c3963bc0SZev Weiss 	 */
1267*c3963bc0SZev Weiss 	if (reg == 0x00 && fan_div < 0x07)
1268*c3963bc0SZev Weiss 		fan_div++;
1269*c3963bc0SZev Weiss 	else if (reg != 0x00 && reg < 0x30 && fan_div > 0)
1270*c3963bc0SZev Weiss 		fan_div--;
1271*c3963bc0SZev Weiss 
1272*c3963bc0SZev Weiss 	if (fan_div != data->fan_div[nr]) {
1273*c3963bc0SZev Weiss 		dev_dbg(dev, "Modifying fan%d clock divider from %u to %u\n",
1274*c3963bc0SZev Weiss 			nr + 1, div_from_reg(data->fan_div[nr]),
1275*c3963bc0SZev Weiss 			div_from_reg(fan_div));
1276*c3963bc0SZev Weiss 
1277*c3963bc0SZev Weiss 		/* Preserve min limit if possible */
1278*c3963bc0SZev Weiss 		if (data->has_fan_min & BIT(nr)) {
1279*c3963bc0SZev Weiss 			fan_min = data->fan_min[nr];
1280*c3963bc0SZev Weiss 			if (fan_div > data->fan_div[nr]) {
1281*c3963bc0SZev Weiss 				if (fan_min != 255 && fan_min > 1)
1282*c3963bc0SZev Weiss 					fan_min >>= 1;
1283*c3963bc0SZev Weiss 			} else {
1284*c3963bc0SZev Weiss 				if (fan_min != 255) {
1285*c3963bc0SZev Weiss 					fan_min <<= 1;
1286*c3963bc0SZev Weiss 					if (fan_min > 254)
1287*c3963bc0SZev Weiss 						fan_min = 254;
1288*c3963bc0SZev Weiss 				}
1289*c3963bc0SZev Weiss 			}
1290*c3963bc0SZev Weiss 			if (fan_min != data->fan_min[nr]) {
1291*c3963bc0SZev Weiss 				data->fan_min[nr] = fan_min;
1292*c3963bc0SZev Weiss 				err = nct6775_write_value(data, data->REG_FAN_MIN[nr], fan_min);
1293*c3963bc0SZev Weiss 				if (err)
1294*c3963bc0SZev Weiss 					return err;
1295*c3963bc0SZev Weiss 			}
1296*c3963bc0SZev Weiss 		}
1297*c3963bc0SZev Weiss 		data->fan_div[nr] = fan_div;
1298*c3963bc0SZev Weiss 		err = nct6775_write_fan_div_common(data, nr);
1299*c3963bc0SZev Weiss 		if (err)
1300*c3963bc0SZev Weiss 			return err;
1301*c3963bc0SZev Weiss 	}
1302*c3963bc0SZev Weiss 
1303*c3963bc0SZev Weiss 	return 0;
1304*c3963bc0SZev Weiss }
1305*c3963bc0SZev Weiss 
1306*c3963bc0SZev Weiss static int nct6775_update_pwm(struct device *dev)
1307*c3963bc0SZev Weiss {
1308*c3963bc0SZev Weiss 	struct nct6775_data *data = dev_get_drvdata(dev);
1309*c3963bc0SZev Weiss 	int i, j, err;
1310*c3963bc0SZev Weiss 	u16 fanmodecfg, reg;
1311*c3963bc0SZev Weiss 	bool duty_is_dc;
1312*c3963bc0SZev Weiss 
1313*c3963bc0SZev Weiss 	for (i = 0; i < data->pwm_num; i++) {
1314*c3963bc0SZev Weiss 		if (!(data->has_pwm & BIT(i)))
1315*c3963bc0SZev Weiss 			continue;
1316*c3963bc0SZev Weiss 
1317*c3963bc0SZev Weiss 		err = nct6775_read_value(data, data->REG_PWM_MODE[i], &reg);
1318*c3963bc0SZev Weiss 		if (err)
1319*c3963bc0SZev Weiss 			return err;
1320*c3963bc0SZev Weiss 		duty_is_dc = data->REG_PWM_MODE[i] && (reg & data->PWM_MODE_MASK[i]);
1321*c3963bc0SZev Weiss 		data->pwm_mode[i] = !duty_is_dc;
1322*c3963bc0SZev Weiss 
1323*c3963bc0SZev Weiss 		err = nct6775_read_value(data, data->REG_FAN_MODE[i], &fanmodecfg);
1324*c3963bc0SZev Weiss 		if (err)
1325*c3963bc0SZev Weiss 			return err;
1326*c3963bc0SZev Weiss 		for (j = 0; j < ARRAY_SIZE(data->REG_PWM); j++) {
1327*c3963bc0SZev Weiss 			if (data->REG_PWM[j] && data->REG_PWM[j][i]) {
1328*c3963bc0SZev Weiss 				err = nct6775_read_value(data, data->REG_PWM[j][i], &reg);
1329*c3963bc0SZev Weiss 				if (err)
1330*c3963bc0SZev Weiss 					return err;
1331*c3963bc0SZev Weiss 				data->pwm[j][i] = reg;
1332*c3963bc0SZev Weiss 			}
1333*c3963bc0SZev Weiss 		}
1334*c3963bc0SZev Weiss 
1335*c3963bc0SZev Weiss 		data->pwm_enable[i] = reg_to_pwm_enable(data->pwm[0][i],
1336*c3963bc0SZev Weiss 							(fanmodecfg >> 4) & 7);
1337*c3963bc0SZev Weiss 
1338*c3963bc0SZev Weiss 		if (!data->temp_tolerance[0][i] ||
1339*c3963bc0SZev Weiss 		    data->pwm_enable[i] != speed_cruise)
1340*c3963bc0SZev Weiss 			data->temp_tolerance[0][i] = fanmodecfg & 0x0f;
1341*c3963bc0SZev Weiss 		if (!data->target_speed_tolerance[i] ||
1342*c3963bc0SZev Weiss 		    data->pwm_enable[i] == speed_cruise) {
1343*c3963bc0SZev Weiss 			u8 t = fanmodecfg & 0x0f;
1344*c3963bc0SZev Weiss 
1345*c3963bc0SZev Weiss 			if (data->REG_TOLERANCE_H) {
1346*c3963bc0SZev Weiss 				err = nct6775_read_value(data, data->REG_TOLERANCE_H[i], &reg);
1347*c3963bc0SZev Weiss 				if (err)
1348*c3963bc0SZev Weiss 					return err;
1349*c3963bc0SZev Weiss 				t |= (reg & 0x70) >> 1;
1350*c3963bc0SZev Weiss 			}
1351*c3963bc0SZev Weiss 			data->target_speed_tolerance[i] = t;
1352*c3963bc0SZev Weiss 		}
1353*c3963bc0SZev Weiss 
1354*c3963bc0SZev Weiss 		err = nct6775_read_value(data, data->REG_CRITICAL_TEMP_TOLERANCE[i], &reg);
1355*c3963bc0SZev Weiss 		if (err)
1356*c3963bc0SZev Weiss 			return err;
1357*c3963bc0SZev Weiss 		data->temp_tolerance[1][i] = reg;
1358*c3963bc0SZev Weiss 
1359*c3963bc0SZev Weiss 		err = nct6775_read_value(data, data->REG_TEMP_SEL[i], &reg);
1360*c3963bc0SZev Weiss 		if (err)
1361*c3963bc0SZev Weiss 			return err;
1362*c3963bc0SZev Weiss 		data->pwm_temp_sel[i] = reg & 0x1f;
1363*c3963bc0SZev Weiss 		/* If fan can stop, report floor as 0 */
1364*c3963bc0SZev Weiss 		if (reg & 0x80)
1365*c3963bc0SZev Weiss 			data->pwm[2][i] = 0;
1366*c3963bc0SZev Weiss 
1367*c3963bc0SZev Weiss 		if (!data->REG_WEIGHT_TEMP_SEL[i])
1368*c3963bc0SZev Weiss 			continue;
1369*c3963bc0SZev Weiss 
1370*c3963bc0SZev Weiss 		err = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[i], &reg);
1371*c3963bc0SZev Weiss 		if (err)
1372*c3963bc0SZev Weiss 			return err;
1373*c3963bc0SZev Weiss 		data->pwm_weight_temp_sel[i] = reg & 0x1f;
1374*c3963bc0SZev Weiss 		/* If weight is disabled, report weight source as 0 */
1375*c3963bc0SZev Weiss 		if (!(reg & 0x80))
1376*c3963bc0SZev Weiss 			data->pwm_weight_temp_sel[i] = 0;
1377*c3963bc0SZev Weiss 
1378*c3963bc0SZev Weiss 		/* Weight temp data */
1379*c3963bc0SZev Weiss 		for (j = 0; j < ARRAY_SIZE(data->weight_temp); j++) {
1380*c3963bc0SZev Weiss 			err = nct6775_read_value(data, data->REG_WEIGHT_TEMP[j][i], &reg);
1381*c3963bc0SZev Weiss 			if (err)
1382*c3963bc0SZev Weiss 				return err;
1383*c3963bc0SZev Weiss 			data->weight_temp[j][i] = reg;
1384*c3963bc0SZev Weiss 		}
1385*c3963bc0SZev Weiss 	}
1386*c3963bc0SZev Weiss 
1387*c3963bc0SZev Weiss 	return 0;
1388*c3963bc0SZev Weiss }
1389*c3963bc0SZev Weiss 
1390*c3963bc0SZev Weiss static int nct6775_update_pwm_limits(struct device *dev)
1391*c3963bc0SZev Weiss {
1392*c3963bc0SZev Weiss 	struct nct6775_data *data = dev_get_drvdata(dev);
1393*c3963bc0SZev Weiss 	int i, j, err;
1394*c3963bc0SZev Weiss 	u16 reg, reg_t;
1395*c3963bc0SZev Weiss 
1396*c3963bc0SZev Weiss 	for (i = 0; i < data->pwm_num; i++) {
1397*c3963bc0SZev Weiss 		if (!(data->has_pwm & BIT(i)))
1398*c3963bc0SZev Weiss 			continue;
1399*c3963bc0SZev Weiss 
1400*c3963bc0SZev Weiss 		for (j = 0; j < ARRAY_SIZE(data->fan_time); j++) {
1401*c3963bc0SZev Weiss 			err = nct6775_read_value(data, data->REG_FAN_TIME[j][i], &reg);
1402*c3963bc0SZev Weiss 			if (err)
1403*c3963bc0SZev Weiss 				return err;
1404*c3963bc0SZev Weiss 			data->fan_time[j][i] = reg;
1405*c3963bc0SZev Weiss 		}
1406*c3963bc0SZev Weiss 
1407*c3963bc0SZev Weiss 		err = nct6775_read_value(data, data->REG_TARGET[i], &reg_t);
1408*c3963bc0SZev Weiss 		if (err)
1409*c3963bc0SZev Weiss 			return err;
1410*c3963bc0SZev Weiss 
1411*c3963bc0SZev Weiss 		/* Update only in matching mode or if never updated */
1412*c3963bc0SZev Weiss 		if (!data->target_temp[i] ||
1413*c3963bc0SZev Weiss 		    data->pwm_enable[i] == thermal_cruise)
1414*c3963bc0SZev Weiss 			data->target_temp[i] = reg_t & data->target_temp_mask;
1415*c3963bc0SZev Weiss 		if (!data->target_speed[i] ||
1416*c3963bc0SZev Weiss 		    data->pwm_enable[i] == speed_cruise) {
1417*c3963bc0SZev Weiss 			if (data->REG_TOLERANCE_H) {
1418*c3963bc0SZev Weiss 				err = nct6775_read_value(data, data->REG_TOLERANCE_H[i], &reg);
1419*c3963bc0SZev Weiss 				if (err)
1420*c3963bc0SZev Weiss 					return err;
1421*c3963bc0SZev Weiss 				reg_t |= (reg & 0x0f) << 8;
1422*c3963bc0SZev Weiss 			}
1423*c3963bc0SZev Weiss 			data->target_speed[i] = reg_t;
1424*c3963bc0SZev Weiss 		}
1425*c3963bc0SZev Weiss 
1426*c3963bc0SZev Weiss 		for (j = 0; j < data->auto_pwm_num; j++) {
1427*c3963bc0SZev Weiss 			err = nct6775_read_value(data, NCT6775_AUTO_PWM(data, i, j), &reg);
1428*c3963bc0SZev Weiss 			if (err)
1429*c3963bc0SZev Weiss 				return err;
1430*c3963bc0SZev Weiss 			data->auto_pwm[i][j] = reg;
1431*c3963bc0SZev Weiss 
1432*c3963bc0SZev Weiss 			err = nct6775_read_value(data, NCT6775_AUTO_TEMP(data, i, j), &reg);
1433*c3963bc0SZev Weiss 			if (err)
1434*c3963bc0SZev Weiss 				return err;
1435*c3963bc0SZev Weiss 			data->auto_temp[i][j] = reg;
1436*c3963bc0SZev Weiss 		}
1437*c3963bc0SZev Weiss 
1438*c3963bc0SZev Weiss 		/* critical auto_pwm temperature data */
1439*c3963bc0SZev Weiss 		err = nct6775_read_value(data, data->REG_CRITICAL_TEMP[i], &reg);
1440*c3963bc0SZev Weiss 		if (err)
1441*c3963bc0SZev Weiss 			return err;
1442*c3963bc0SZev Weiss 		data->auto_temp[i][data->auto_pwm_num] = reg;
1443*c3963bc0SZev Weiss 
1444*c3963bc0SZev Weiss 		switch (data->kind) {
1445*c3963bc0SZev Weiss 		case nct6775:
1446*c3963bc0SZev Weiss 			err = nct6775_read_value(data, NCT6775_REG_CRITICAL_ENAB[i], &reg);
1447*c3963bc0SZev Weiss 			if (err)
1448*c3963bc0SZev Weiss 				return err;
1449*c3963bc0SZev Weiss 			data->auto_pwm[i][data->auto_pwm_num] =
1450*c3963bc0SZev Weiss 						(reg & 0x02) ? 0xff : 0x00;
1451*c3963bc0SZev Weiss 			break;
1452*c3963bc0SZev Weiss 		case nct6776:
1453*c3963bc0SZev Weiss 			data->auto_pwm[i][data->auto_pwm_num] = 0xff;
1454*c3963bc0SZev Weiss 			break;
1455*c3963bc0SZev Weiss 		case nct6106:
1456*c3963bc0SZev Weiss 		case nct6116:
1457*c3963bc0SZev Weiss 		case nct6779:
1458*c3963bc0SZev Weiss 		case nct6791:
1459*c3963bc0SZev Weiss 		case nct6792:
1460*c3963bc0SZev Weiss 		case nct6793:
1461*c3963bc0SZev Weiss 		case nct6795:
1462*c3963bc0SZev Weiss 		case nct6796:
1463*c3963bc0SZev Weiss 		case nct6797:
1464*c3963bc0SZev Weiss 		case nct6798:
1465*c3963bc0SZev Weiss 			err = nct6775_read_value(data, data->REG_CRITICAL_PWM_ENABLE[i], &reg);
1466*c3963bc0SZev Weiss 			if (err)
1467*c3963bc0SZev Weiss 				return err;
1468*c3963bc0SZev Weiss 			if (reg & data->CRITICAL_PWM_ENABLE_MASK) {
1469*c3963bc0SZev Weiss 				err = nct6775_read_value(data, data->REG_CRITICAL_PWM[i], &reg);
1470*c3963bc0SZev Weiss 				if (err)
1471*c3963bc0SZev Weiss 					return err;
1472*c3963bc0SZev Weiss 			} else {
1473*c3963bc0SZev Weiss 				reg = 0xff;
1474*c3963bc0SZev Weiss 			}
1475*c3963bc0SZev Weiss 			data->auto_pwm[i][data->auto_pwm_num] = reg;
1476*c3963bc0SZev Weiss 			break;
1477*c3963bc0SZev Weiss 		}
1478*c3963bc0SZev Weiss 	}
1479*c3963bc0SZev Weiss 
1480*c3963bc0SZev Weiss 	return 0;
1481*c3963bc0SZev Weiss }
1482*c3963bc0SZev Weiss 
1483*c3963bc0SZev Weiss static struct nct6775_data *nct6775_update_device(struct device *dev)
1484*c3963bc0SZev Weiss {
1485*c3963bc0SZev Weiss 	struct nct6775_data *data = dev_get_drvdata(dev);
1486*c3963bc0SZev Weiss 	int i, j, err = 0;
1487*c3963bc0SZev Weiss 	u16 reg;
1488*c3963bc0SZev Weiss 
1489*c3963bc0SZev Weiss 	mutex_lock(&data->update_lock);
1490*c3963bc0SZev Weiss 
1491*c3963bc0SZev Weiss 	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
1492*c3963bc0SZev Weiss 	    || !data->valid) {
1493*c3963bc0SZev Weiss 		/* Fan clock dividers */
1494*c3963bc0SZev Weiss 		err = nct6775_update_fan_div_common(data);
1495*c3963bc0SZev Weiss 		if (err)
1496*c3963bc0SZev Weiss 			goto out;
1497*c3963bc0SZev Weiss 
1498*c3963bc0SZev Weiss 		/* Measured voltages and limits */
1499*c3963bc0SZev Weiss 		for (i = 0; i < data->in_num; i++) {
1500*c3963bc0SZev Weiss 			if (!(data->have_in & BIT(i)))
1501*c3963bc0SZev Weiss 				continue;
1502*c3963bc0SZev Weiss 
1503*c3963bc0SZev Weiss 			err = nct6775_read_value(data, data->REG_VIN[i], &reg);
1504*c3963bc0SZev Weiss 			if (err)
1505*c3963bc0SZev Weiss 				goto out;
1506*c3963bc0SZev Weiss 			data->in[i][0] = reg;
1507*c3963bc0SZev Weiss 
1508*c3963bc0SZev Weiss 			err = nct6775_read_value(data, data->REG_IN_MINMAX[0][i], &reg);
1509*c3963bc0SZev Weiss 			if (err)
1510*c3963bc0SZev Weiss 				goto out;
1511*c3963bc0SZev Weiss 			data->in[i][1] = reg;
1512*c3963bc0SZev Weiss 
1513*c3963bc0SZev Weiss 			err = nct6775_read_value(data, data->REG_IN_MINMAX[1][i], &reg);
1514*c3963bc0SZev Weiss 			if (err)
1515*c3963bc0SZev Weiss 				goto out;
1516*c3963bc0SZev Weiss 			data->in[i][2] = reg;
1517*c3963bc0SZev Weiss 		}
1518*c3963bc0SZev Weiss 
1519*c3963bc0SZev Weiss 		/* Measured fan speeds and limits */
1520*c3963bc0SZev Weiss 		for (i = 0; i < ARRAY_SIZE(data->rpm); i++) {
1521*c3963bc0SZev Weiss 			if (!(data->has_fan & BIT(i)))
1522*c3963bc0SZev Weiss 				continue;
1523*c3963bc0SZev Weiss 
1524*c3963bc0SZev Weiss 			err = nct6775_read_value(data, data->REG_FAN[i], &reg);
1525*c3963bc0SZev Weiss 			if (err)
1526*c3963bc0SZev Weiss 				goto out;
1527*c3963bc0SZev Weiss 			data->rpm[i] = data->fan_from_reg(reg,
1528*c3963bc0SZev Weiss 							  data->fan_div[i]);
1529*c3963bc0SZev Weiss 
1530*c3963bc0SZev Weiss 			if (data->has_fan_min & BIT(i)) {
1531*c3963bc0SZev Weiss 				err = nct6775_read_value(data, data->REG_FAN_MIN[i], &reg);
1532*c3963bc0SZev Weiss 				if (err)
1533*c3963bc0SZev Weiss 					goto out;
1534*c3963bc0SZev Weiss 				data->fan_min[i] = reg;
1535*c3963bc0SZev Weiss 			}
1536*c3963bc0SZev Weiss 
1537*c3963bc0SZev Weiss 			if (data->REG_FAN_PULSES[i]) {
1538*c3963bc0SZev Weiss 				err = nct6775_read_value(data, data->REG_FAN_PULSES[i], &reg);
1539*c3963bc0SZev Weiss 				if (err)
1540*c3963bc0SZev Weiss 					goto out;
1541*c3963bc0SZev Weiss 				data->fan_pulses[i] = (reg >> data->FAN_PULSE_SHIFT[i]) & 0x03;
1542*c3963bc0SZev Weiss 			}
1543*c3963bc0SZev Weiss 
1544*c3963bc0SZev Weiss 			err = nct6775_select_fan_div(dev, data, i, reg);
1545*c3963bc0SZev Weiss 			if (err)
1546*c3963bc0SZev Weiss 				goto out;
1547*c3963bc0SZev Weiss 		}
1548*c3963bc0SZev Weiss 
1549*c3963bc0SZev Weiss 		err = nct6775_update_pwm(dev);
1550*c3963bc0SZev Weiss 		if (err)
1551*c3963bc0SZev Weiss 			goto out;
1552*c3963bc0SZev Weiss 
1553*c3963bc0SZev Weiss 		err = nct6775_update_pwm_limits(dev);
1554*c3963bc0SZev Weiss 		if (err)
1555*c3963bc0SZev Weiss 			goto out;
1556*c3963bc0SZev Weiss 
1557*c3963bc0SZev Weiss 		/* Measured temperatures and limits */
1558*c3963bc0SZev Weiss 		for (i = 0; i < NUM_TEMP; i++) {
1559*c3963bc0SZev Weiss 			if (!(data->have_temp & BIT(i)))
1560*c3963bc0SZev Weiss 				continue;
1561*c3963bc0SZev Weiss 			for (j = 0; j < ARRAY_SIZE(data->reg_temp); j++) {
1562*c3963bc0SZev Weiss 				if (data->reg_temp[j][i]) {
1563*c3963bc0SZev Weiss 					err = nct6775_read_temp(data, data->reg_temp[j][i], &reg);
1564*c3963bc0SZev Weiss 					if (err)
1565*c3963bc0SZev Weiss 						goto out;
1566*c3963bc0SZev Weiss 					data->temp[j][i] = reg;
1567*c3963bc0SZev Weiss 				}
1568*c3963bc0SZev Weiss 			}
1569*c3963bc0SZev Weiss 			if (i >= NUM_TEMP_FIXED ||
1570*c3963bc0SZev Weiss 			    !(data->have_temp_fixed & BIT(i)))
1571*c3963bc0SZev Weiss 				continue;
1572*c3963bc0SZev Weiss 			err = nct6775_read_value(data, data->REG_TEMP_OFFSET[i], &reg);
1573*c3963bc0SZev Weiss 			if (err)
1574*c3963bc0SZev Weiss 				goto out;
1575*c3963bc0SZev Weiss 			data->temp_offset[i] = reg;
1576*c3963bc0SZev Weiss 		}
1577*c3963bc0SZev Weiss 
1578*c3963bc0SZev Weiss 		for (i = 0; i < NUM_TSI_TEMP; i++) {
1579*c3963bc0SZev Weiss 			if (!(data->have_tsi_temp & BIT(i)))
1580*c3963bc0SZev Weiss 				continue;
1581*c3963bc0SZev Weiss 			err = nct6775_read_value(data, data->REG_TSI_TEMP[i], &reg);
1582*c3963bc0SZev Weiss 			if (err)
1583*c3963bc0SZev Weiss 				goto out;
1584*c3963bc0SZev Weiss 			data->tsi_temp[i] = reg;
1585*c3963bc0SZev Weiss 		}
1586*c3963bc0SZev Weiss 
1587*c3963bc0SZev Weiss 		data->alarms = 0;
1588*c3963bc0SZev Weiss 		for (i = 0; i < NUM_REG_ALARM; i++) {
1589*c3963bc0SZev Weiss 			u16 alarm;
1590*c3963bc0SZev Weiss 
1591*c3963bc0SZev Weiss 			if (!data->REG_ALARM[i])
1592*c3963bc0SZev Weiss 				continue;
1593*c3963bc0SZev Weiss 			err = nct6775_read_value(data, data->REG_ALARM[i], &alarm);
1594*c3963bc0SZev Weiss 			if (err)
1595*c3963bc0SZev Weiss 				goto out;
1596*c3963bc0SZev Weiss 			data->alarms |= ((u64)alarm) << (i << 3);
1597*c3963bc0SZev Weiss 		}
1598*c3963bc0SZev Weiss 
1599*c3963bc0SZev Weiss 		data->beeps = 0;
1600*c3963bc0SZev Weiss 		for (i = 0; i < NUM_REG_BEEP; i++) {
1601*c3963bc0SZev Weiss 			u16 beep;
1602*c3963bc0SZev Weiss 
1603*c3963bc0SZev Weiss 			if (!data->REG_BEEP[i])
1604*c3963bc0SZev Weiss 				continue;
1605*c3963bc0SZev Weiss 			err = nct6775_read_value(data, data->REG_BEEP[i], &beep);
1606*c3963bc0SZev Weiss 			if (err)
1607*c3963bc0SZev Weiss 				goto out;
1608*c3963bc0SZev Weiss 			data->beeps |= ((u64)beep) << (i << 3);
1609*c3963bc0SZev Weiss 		}
1610*c3963bc0SZev Weiss 
1611*c3963bc0SZev Weiss 		data->last_updated = jiffies;
1612*c3963bc0SZev Weiss 		data->valid = true;
1613*c3963bc0SZev Weiss 	}
1614*c3963bc0SZev Weiss out:
1615*c3963bc0SZev Weiss 	mutex_unlock(&data->update_lock);
1616*c3963bc0SZev Weiss 	return err ? ERR_PTR(err) : data;
1617*c3963bc0SZev Weiss }
1618*c3963bc0SZev Weiss 
1619*c3963bc0SZev Weiss /*
1620*c3963bc0SZev Weiss  * Sysfs callback functions
1621*c3963bc0SZev Weiss  */
1622*c3963bc0SZev Weiss static ssize_t
1623*c3963bc0SZev Weiss show_in_reg(struct device *dev, struct device_attribute *attr, char *buf)
1624*c3963bc0SZev Weiss {
1625*c3963bc0SZev Weiss 	struct nct6775_data *data = nct6775_update_device(dev);
1626*c3963bc0SZev Weiss 	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1627*c3963bc0SZev Weiss 	int index = sattr->index;
1628*c3963bc0SZev Weiss 	int nr = sattr->nr;
1629*c3963bc0SZev Weiss 
1630*c3963bc0SZev Weiss 	if (IS_ERR(data))
1631*c3963bc0SZev Weiss 		return PTR_ERR(data);
1632*c3963bc0SZev Weiss 
1633*c3963bc0SZev Weiss 	return sprintf(buf, "%ld\n", in_from_reg(data->in[nr][index], nr));
1634*c3963bc0SZev Weiss }
1635*c3963bc0SZev Weiss 
1636*c3963bc0SZev Weiss static ssize_t
1637*c3963bc0SZev Weiss store_in_reg(struct device *dev, struct device_attribute *attr, const char *buf,
1638*c3963bc0SZev Weiss 	     size_t count)
1639*c3963bc0SZev Weiss {
1640*c3963bc0SZev Weiss 	struct nct6775_data *data = dev_get_drvdata(dev);
1641*c3963bc0SZev Weiss 	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1642*c3963bc0SZev Weiss 	int index = sattr->index;
1643*c3963bc0SZev Weiss 	int nr = sattr->nr;
1644*c3963bc0SZev Weiss 	unsigned long val;
1645*c3963bc0SZev Weiss 	int err;
1646*c3963bc0SZev Weiss 
1647*c3963bc0SZev Weiss 	err = kstrtoul(buf, 10, &val);
1648*c3963bc0SZev Weiss 	if (err < 0)
1649*c3963bc0SZev Weiss 		return err;
1650*c3963bc0SZev Weiss 	mutex_lock(&data->update_lock);
1651*c3963bc0SZev Weiss 	data->in[nr][index] = in_to_reg(val, nr);
1652*c3963bc0SZev Weiss 	err = nct6775_write_value(data, data->REG_IN_MINMAX[index - 1][nr], data->in[nr][index]);
1653*c3963bc0SZev Weiss 	mutex_unlock(&data->update_lock);
1654*c3963bc0SZev Weiss 	return err ? : count;
1655*c3963bc0SZev Weiss }
1656*c3963bc0SZev Weiss 
1657*c3963bc0SZev Weiss ssize_t
1658*c3963bc0SZev Weiss nct6775_show_alarm(struct device *dev, struct device_attribute *attr, char *buf)
1659*c3963bc0SZev Weiss {
1660*c3963bc0SZev Weiss 	struct nct6775_data *data = nct6775_update_device(dev);
1661*c3963bc0SZev Weiss 	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1662*c3963bc0SZev Weiss 	int nr;
1663*c3963bc0SZev Weiss 
1664*c3963bc0SZev Weiss 	if (IS_ERR(data))
1665*c3963bc0SZev Weiss 		return PTR_ERR(data);
1666*c3963bc0SZev Weiss 
1667*c3963bc0SZev Weiss 	nr = data->ALARM_BITS[sattr->index];
1668*c3963bc0SZev Weiss 	return sprintf(buf, "%u\n",
1669*c3963bc0SZev Weiss 		       (unsigned int)((data->alarms >> nr) & 0x01));
1670*c3963bc0SZev Weiss }
1671*c3963bc0SZev Weiss EXPORT_SYMBOL_GPL(nct6775_show_alarm);
1672*c3963bc0SZev Weiss 
1673*c3963bc0SZev Weiss static int find_temp_source(struct nct6775_data *data, int index, int count)
1674*c3963bc0SZev Weiss {
1675*c3963bc0SZev Weiss 	int source = data->temp_src[index];
1676*c3963bc0SZev Weiss 	int nr, err;
1677*c3963bc0SZev Weiss 
1678*c3963bc0SZev Weiss 	for (nr = 0; nr < count; nr++) {
1679*c3963bc0SZev Weiss 		u16 src;
1680*c3963bc0SZev Weiss 
1681*c3963bc0SZev Weiss 		err = nct6775_read_value(data, data->REG_TEMP_SOURCE[nr], &src);
1682*c3963bc0SZev Weiss 		if (err)
1683*c3963bc0SZev Weiss 			return err;
1684*c3963bc0SZev Weiss 		if ((src & 0x1f) == source)
1685*c3963bc0SZev Weiss 			return nr;
1686*c3963bc0SZev Weiss 	}
1687*c3963bc0SZev Weiss 	return -ENODEV;
1688*c3963bc0SZev Weiss }
1689*c3963bc0SZev Weiss 
1690*c3963bc0SZev Weiss static ssize_t
1691*c3963bc0SZev Weiss show_temp_alarm(struct device *dev, struct device_attribute *attr, char *buf)
1692*c3963bc0SZev Weiss {
1693*c3963bc0SZev Weiss 	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1694*c3963bc0SZev Weiss 	struct nct6775_data *data = nct6775_update_device(dev);
1695*c3963bc0SZev Weiss 	unsigned int alarm = 0;
1696*c3963bc0SZev Weiss 	int nr;
1697*c3963bc0SZev Weiss 
1698*c3963bc0SZev Weiss 	if (IS_ERR(data))
1699*c3963bc0SZev Weiss 		return PTR_ERR(data);
1700*c3963bc0SZev Weiss 
1701*c3963bc0SZev Weiss 	/*
1702*c3963bc0SZev Weiss 	 * For temperatures, there is no fixed mapping from registers to alarm
1703*c3963bc0SZev Weiss 	 * bits. Alarm bits are determined by the temperature source mapping.
1704*c3963bc0SZev Weiss 	 */
1705*c3963bc0SZev Weiss 	nr = find_temp_source(data, sattr->index, data->num_temp_alarms);
1706*c3963bc0SZev Weiss 	if (nr >= 0) {
1707*c3963bc0SZev Weiss 		int bit = data->ALARM_BITS[nr + TEMP_ALARM_BASE];
1708*c3963bc0SZev Weiss 
1709*c3963bc0SZev Weiss 		alarm = (data->alarms >> bit) & 0x01;
1710*c3963bc0SZev Weiss 	}
1711*c3963bc0SZev Weiss 	return sprintf(buf, "%u\n", alarm);
1712*c3963bc0SZev Weiss }
1713*c3963bc0SZev Weiss 
1714*c3963bc0SZev Weiss ssize_t
1715*c3963bc0SZev Weiss nct6775_show_beep(struct device *dev, struct device_attribute *attr, char *buf)
1716*c3963bc0SZev Weiss {
1717*c3963bc0SZev Weiss 	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1718*c3963bc0SZev Weiss 	struct nct6775_data *data = nct6775_update_device(dev);
1719*c3963bc0SZev Weiss 	int nr;
1720*c3963bc0SZev Weiss 
1721*c3963bc0SZev Weiss 	if (IS_ERR(data))
1722*c3963bc0SZev Weiss 		return PTR_ERR(data);
1723*c3963bc0SZev Weiss 
1724*c3963bc0SZev Weiss 	nr = data->BEEP_BITS[sattr->index];
1725*c3963bc0SZev Weiss 
1726*c3963bc0SZev Weiss 	return sprintf(buf, "%u\n",
1727*c3963bc0SZev Weiss 		       (unsigned int)((data->beeps >> nr) & 0x01));
1728*c3963bc0SZev Weiss }
1729*c3963bc0SZev Weiss EXPORT_SYMBOL_GPL(nct6775_show_beep);
1730*c3963bc0SZev Weiss 
1731*c3963bc0SZev Weiss ssize_t
1732*c3963bc0SZev Weiss nct6775_store_beep(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
1733*c3963bc0SZev Weiss {
1734*c3963bc0SZev Weiss 	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1735*c3963bc0SZev Weiss 	struct nct6775_data *data = dev_get_drvdata(dev);
1736*c3963bc0SZev Weiss 	int nr = data->BEEP_BITS[sattr->index];
1737*c3963bc0SZev Weiss 	int regindex = nr >> 3;
1738*c3963bc0SZev Weiss 	unsigned long val;
1739*c3963bc0SZev Weiss 	int err;
1740*c3963bc0SZev Weiss 
1741*c3963bc0SZev Weiss 	err = kstrtoul(buf, 10, &val);
1742*c3963bc0SZev Weiss 	if (err < 0)
1743*c3963bc0SZev Weiss 		return err;
1744*c3963bc0SZev Weiss 	if (val > 1)
1745*c3963bc0SZev Weiss 		return -EINVAL;
1746*c3963bc0SZev Weiss 
1747*c3963bc0SZev Weiss 	mutex_lock(&data->update_lock);
1748*c3963bc0SZev Weiss 	if (val)
1749*c3963bc0SZev Weiss 		data->beeps |= (1ULL << nr);
1750*c3963bc0SZev Weiss 	else
1751*c3963bc0SZev Weiss 		data->beeps &= ~(1ULL << nr);
1752*c3963bc0SZev Weiss 	err = nct6775_write_value(data, data->REG_BEEP[regindex],
1753*c3963bc0SZev Weiss 				  (data->beeps >> (regindex << 3)) & 0xff);
1754*c3963bc0SZev Weiss 	mutex_unlock(&data->update_lock);
1755*c3963bc0SZev Weiss 	return err ? : count;
1756*c3963bc0SZev Weiss }
1757*c3963bc0SZev Weiss EXPORT_SYMBOL_GPL(nct6775_store_beep);
1758*c3963bc0SZev Weiss 
1759*c3963bc0SZev Weiss static ssize_t
1760*c3963bc0SZev Weiss show_temp_beep(struct device *dev, struct device_attribute *attr, char *buf)
1761*c3963bc0SZev Weiss {
1762*c3963bc0SZev Weiss 	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1763*c3963bc0SZev Weiss 	struct nct6775_data *data = nct6775_update_device(dev);
1764*c3963bc0SZev Weiss 	unsigned int beep = 0;
1765*c3963bc0SZev Weiss 	int nr;
1766*c3963bc0SZev Weiss 
1767*c3963bc0SZev Weiss 	if (IS_ERR(data))
1768*c3963bc0SZev Weiss 		return PTR_ERR(data);
1769*c3963bc0SZev Weiss 
1770*c3963bc0SZev Weiss 	/*
1771*c3963bc0SZev Weiss 	 * For temperatures, there is no fixed mapping from registers to beep
1772*c3963bc0SZev Weiss 	 * enable bits. Beep enable bits are determined by the temperature
1773*c3963bc0SZev Weiss 	 * source mapping.
1774*c3963bc0SZev Weiss 	 */
1775*c3963bc0SZev Weiss 	nr = find_temp_source(data, sattr->index, data->num_temp_beeps);
1776*c3963bc0SZev Weiss 	if (nr >= 0) {
1777*c3963bc0SZev Weiss 		int bit = data->BEEP_BITS[nr + TEMP_ALARM_BASE];
1778*c3963bc0SZev Weiss 
1779*c3963bc0SZev Weiss 		beep = (data->beeps >> bit) & 0x01;
1780*c3963bc0SZev Weiss 	}
1781*c3963bc0SZev Weiss 	return sprintf(buf, "%u\n", beep);
1782*c3963bc0SZev Weiss }
1783*c3963bc0SZev Weiss 
1784*c3963bc0SZev Weiss static ssize_t
1785*c3963bc0SZev Weiss store_temp_beep(struct device *dev, struct device_attribute *attr,
1786*c3963bc0SZev Weiss 		const char *buf, size_t count)
1787*c3963bc0SZev Weiss {
1788*c3963bc0SZev Weiss 	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1789*c3963bc0SZev Weiss 	struct nct6775_data *data = dev_get_drvdata(dev);
1790*c3963bc0SZev Weiss 	int nr, bit, regindex;
1791*c3963bc0SZev Weiss 	unsigned long val;
1792*c3963bc0SZev Weiss 	int err;
1793*c3963bc0SZev Weiss 
1794*c3963bc0SZev Weiss 	err = kstrtoul(buf, 10, &val);
1795*c3963bc0SZev Weiss 	if (err < 0)
1796*c3963bc0SZev Weiss 		return err;
1797*c3963bc0SZev Weiss 	if (val > 1)
1798*c3963bc0SZev Weiss 		return -EINVAL;
1799*c3963bc0SZev Weiss 
1800*c3963bc0SZev Weiss 	nr = find_temp_source(data, sattr->index, data->num_temp_beeps);
1801*c3963bc0SZev Weiss 	if (nr < 0)
1802*c3963bc0SZev Weiss 		return nr;
1803*c3963bc0SZev Weiss 
1804*c3963bc0SZev Weiss 	bit = data->BEEP_BITS[nr + TEMP_ALARM_BASE];
1805*c3963bc0SZev Weiss 	regindex = bit >> 3;
1806*c3963bc0SZev Weiss 
1807*c3963bc0SZev Weiss 	mutex_lock(&data->update_lock);
1808*c3963bc0SZev Weiss 	if (val)
1809*c3963bc0SZev Weiss 		data->beeps |= (1ULL << bit);
1810*c3963bc0SZev Weiss 	else
1811*c3963bc0SZev Weiss 		data->beeps &= ~(1ULL << bit);
1812*c3963bc0SZev Weiss 	err = nct6775_write_value(data, data->REG_BEEP[regindex],
1813*c3963bc0SZev Weiss 				  (data->beeps >> (regindex << 3)) & 0xff);
1814*c3963bc0SZev Weiss 	mutex_unlock(&data->update_lock);
1815*c3963bc0SZev Weiss 
1816*c3963bc0SZev Weiss 	return err ? : count;
1817*c3963bc0SZev Weiss }
1818*c3963bc0SZev Weiss 
1819*c3963bc0SZev Weiss static umode_t nct6775_in_is_visible(struct kobject *kobj,
1820*c3963bc0SZev Weiss 				     struct attribute *attr, int index)
1821*c3963bc0SZev Weiss {
1822*c3963bc0SZev Weiss 	struct device *dev = kobj_to_dev(kobj);
1823*c3963bc0SZev Weiss 	struct nct6775_data *data = dev_get_drvdata(dev);
1824*c3963bc0SZev Weiss 	int in = index / 5;	/* voltage index */
1825*c3963bc0SZev Weiss 
1826*c3963bc0SZev Weiss 	if (!(data->have_in & BIT(in)))
1827*c3963bc0SZev Weiss 		return 0;
1828*c3963bc0SZev Weiss 
1829*c3963bc0SZev Weiss 	return nct6775_attr_mode(data, attr);
1830*c3963bc0SZev Weiss }
1831*c3963bc0SZev Weiss 
1832*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(in_input, "in%d_input", 0444, show_in_reg, NULL, 0, 0);
1833*c3963bc0SZev Weiss SENSOR_TEMPLATE(in_alarm, "in%d_alarm", 0444, nct6775_show_alarm, NULL, 0);
1834*c3963bc0SZev Weiss SENSOR_TEMPLATE(in_beep, "in%d_beep", 0644, nct6775_show_beep, nct6775_store_beep, 0);
1835*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(in_min, "in%d_min", 0644, show_in_reg, store_in_reg, 0, 1);
1836*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(in_max, "in%d_max", 0644, show_in_reg, store_in_reg, 0, 2);
1837*c3963bc0SZev Weiss 
1838*c3963bc0SZev Weiss /*
1839*c3963bc0SZev Weiss  * nct6775_in_is_visible uses the index into the following array
1840*c3963bc0SZev Weiss  * to determine if attributes should be created or not.
1841*c3963bc0SZev Weiss  * Any change in order or content must be matched.
1842*c3963bc0SZev Weiss  */
1843*c3963bc0SZev Weiss static struct sensor_device_template *nct6775_attributes_in_template[] = {
1844*c3963bc0SZev Weiss 	&sensor_dev_template_in_input,
1845*c3963bc0SZev Weiss 	&sensor_dev_template_in_alarm,
1846*c3963bc0SZev Weiss 	&sensor_dev_template_in_beep,
1847*c3963bc0SZev Weiss 	&sensor_dev_template_in_min,
1848*c3963bc0SZev Weiss 	&sensor_dev_template_in_max,
1849*c3963bc0SZev Weiss 	NULL
1850*c3963bc0SZev Weiss };
1851*c3963bc0SZev Weiss 
1852*c3963bc0SZev Weiss static const struct sensor_template_group nct6775_in_template_group = {
1853*c3963bc0SZev Weiss 	.templates = nct6775_attributes_in_template,
1854*c3963bc0SZev Weiss 	.is_visible = nct6775_in_is_visible,
1855*c3963bc0SZev Weiss };
1856*c3963bc0SZev Weiss 
1857*c3963bc0SZev Weiss static ssize_t
1858*c3963bc0SZev Weiss show_fan(struct device *dev, struct device_attribute *attr, char *buf)
1859*c3963bc0SZev Weiss {
1860*c3963bc0SZev Weiss 	struct nct6775_data *data = nct6775_update_device(dev);
1861*c3963bc0SZev Weiss 	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1862*c3963bc0SZev Weiss 	int nr = sattr->index;
1863*c3963bc0SZev Weiss 
1864*c3963bc0SZev Weiss 	if (IS_ERR(data))
1865*c3963bc0SZev Weiss 		return PTR_ERR(data);
1866*c3963bc0SZev Weiss 
1867*c3963bc0SZev Weiss 	return sprintf(buf, "%d\n", data->rpm[nr]);
1868*c3963bc0SZev Weiss }
1869*c3963bc0SZev Weiss 
1870*c3963bc0SZev Weiss static ssize_t
1871*c3963bc0SZev Weiss show_fan_min(struct device *dev, struct device_attribute *attr, char *buf)
1872*c3963bc0SZev Weiss {
1873*c3963bc0SZev Weiss 	struct nct6775_data *data = nct6775_update_device(dev);
1874*c3963bc0SZev Weiss 	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1875*c3963bc0SZev Weiss 	int nr = sattr->index;
1876*c3963bc0SZev Weiss 
1877*c3963bc0SZev Weiss 	if (IS_ERR(data))
1878*c3963bc0SZev Weiss 		return PTR_ERR(data);
1879*c3963bc0SZev Weiss 
1880*c3963bc0SZev Weiss 	return sprintf(buf, "%d\n",
1881*c3963bc0SZev Weiss 		       data->fan_from_reg_min(data->fan_min[nr],
1882*c3963bc0SZev Weiss 					      data->fan_div[nr]));
1883*c3963bc0SZev Weiss }
1884*c3963bc0SZev Weiss 
1885*c3963bc0SZev Weiss static ssize_t
1886*c3963bc0SZev Weiss show_fan_div(struct device *dev, struct device_attribute *attr, char *buf)
1887*c3963bc0SZev Weiss {
1888*c3963bc0SZev Weiss 	struct nct6775_data *data = nct6775_update_device(dev);
1889*c3963bc0SZev Weiss 	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1890*c3963bc0SZev Weiss 	int nr = sattr->index;
1891*c3963bc0SZev Weiss 
1892*c3963bc0SZev Weiss 	if (IS_ERR(data))
1893*c3963bc0SZev Weiss 		return PTR_ERR(data);
1894*c3963bc0SZev Weiss 
1895*c3963bc0SZev Weiss 	return sprintf(buf, "%u\n", div_from_reg(data->fan_div[nr]));
1896*c3963bc0SZev Weiss }
1897*c3963bc0SZev Weiss 
1898*c3963bc0SZev Weiss static ssize_t
1899*c3963bc0SZev Weiss store_fan_min(struct device *dev, struct device_attribute *attr,
1900*c3963bc0SZev Weiss 	      const char *buf, size_t count)
1901*c3963bc0SZev Weiss {
1902*c3963bc0SZev Weiss 	struct nct6775_data *data = dev_get_drvdata(dev);
1903*c3963bc0SZev Weiss 	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1904*c3963bc0SZev Weiss 	int nr = sattr->index;
1905*c3963bc0SZev Weiss 	unsigned long val;
1906*c3963bc0SZev Weiss 	unsigned int reg;
1907*c3963bc0SZev Weiss 	u8 new_div;
1908*c3963bc0SZev Weiss 	int err;
1909*c3963bc0SZev Weiss 
1910*c3963bc0SZev Weiss 	err = kstrtoul(buf, 10, &val);
1911*c3963bc0SZev Weiss 	if (err < 0)
1912*c3963bc0SZev Weiss 		return err;
1913*c3963bc0SZev Weiss 
1914*c3963bc0SZev Weiss 	mutex_lock(&data->update_lock);
1915*c3963bc0SZev Weiss 	if (!data->has_fan_div) {
1916*c3963bc0SZev Weiss 		/* NCT6776F or NCT6779D; we know this is a 13 bit register */
1917*c3963bc0SZev Weiss 		if (!val) {
1918*c3963bc0SZev Weiss 			val = 0xff1f;
1919*c3963bc0SZev Weiss 		} else {
1920*c3963bc0SZev Weiss 			if (val > 1350000U)
1921*c3963bc0SZev Weiss 				val = 135000U;
1922*c3963bc0SZev Weiss 			val = 1350000U / val;
1923*c3963bc0SZev Weiss 			val = (val & 0x1f) | ((val << 3) & 0xff00);
1924*c3963bc0SZev Weiss 		}
1925*c3963bc0SZev Weiss 		data->fan_min[nr] = val;
1926*c3963bc0SZev Weiss 		goto write_min;	/* Leave fan divider alone */
1927*c3963bc0SZev Weiss 	}
1928*c3963bc0SZev Weiss 	if (!val) {
1929*c3963bc0SZev Weiss 		/* No min limit, alarm disabled */
1930*c3963bc0SZev Weiss 		data->fan_min[nr] = 255;
1931*c3963bc0SZev Weiss 		new_div = data->fan_div[nr]; /* No change */
1932*c3963bc0SZev Weiss 		dev_info(dev, "fan%u low limit and alarm disabled\n", nr + 1);
1933*c3963bc0SZev Weiss 		goto write_div;
1934*c3963bc0SZev Weiss 	}
1935*c3963bc0SZev Weiss 	reg = 1350000U / val;
1936*c3963bc0SZev Weiss 	if (reg >= 128 * 255) {
1937*c3963bc0SZev Weiss 		/*
1938*c3963bc0SZev Weiss 		 * Speed below this value cannot possibly be represented,
1939*c3963bc0SZev Weiss 		 * even with the highest divider (128)
1940*c3963bc0SZev Weiss 		 */
1941*c3963bc0SZev Weiss 		data->fan_min[nr] = 254;
1942*c3963bc0SZev Weiss 		new_div = 7; /* 128 == BIT(7) */
1943*c3963bc0SZev Weiss 		dev_warn(dev,
1944*c3963bc0SZev Weiss 			 "fan%u low limit %lu below minimum %u, set to minimum\n",
1945*c3963bc0SZev Weiss 			 nr + 1, val, data->fan_from_reg_min(254, 7));
1946*c3963bc0SZev Weiss 	} else if (!reg) {
1947*c3963bc0SZev Weiss 		/*
1948*c3963bc0SZev Weiss 		 * Speed above this value cannot possibly be represented,
1949*c3963bc0SZev Weiss 		 * even with the lowest divider (1)
1950*c3963bc0SZev Weiss 		 */
1951*c3963bc0SZev Weiss 		data->fan_min[nr] = 1;
1952*c3963bc0SZev Weiss 		new_div = 0; /* 1 == BIT(0) */
1953*c3963bc0SZev Weiss 		dev_warn(dev,
1954*c3963bc0SZev Weiss 			 "fan%u low limit %lu above maximum %u, set to maximum\n",
1955*c3963bc0SZev Weiss 			 nr + 1, val, data->fan_from_reg_min(1, 0));
1956*c3963bc0SZev Weiss 	} else {
1957*c3963bc0SZev Weiss 		/*
1958*c3963bc0SZev Weiss 		 * Automatically pick the best divider, i.e. the one such
1959*c3963bc0SZev Weiss 		 * that the min limit will correspond to a register value
1960*c3963bc0SZev Weiss 		 * in the 96..192 range
1961*c3963bc0SZev Weiss 		 */
1962*c3963bc0SZev Weiss 		new_div = 0;
1963*c3963bc0SZev Weiss 		while (reg > 192 && new_div < 7) {
1964*c3963bc0SZev Weiss 			reg >>= 1;
1965*c3963bc0SZev Weiss 			new_div++;
1966*c3963bc0SZev Weiss 		}
1967*c3963bc0SZev Weiss 		data->fan_min[nr] = reg;
1968*c3963bc0SZev Weiss 	}
1969*c3963bc0SZev Weiss 
1970*c3963bc0SZev Weiss write_div:
1971*c3963bc0SZev Weiss 	/*
1972*c3963bc0SZev Weiss 	 * Write both the fan clock divider (if it changed) and the new
1973*c3963bc0SZev Weiss 	 * fan min (unconditionally)
1974*c3963bc0SZev Weiss 	 */
1975*c3963bc0SZev Weiss 	if (new_div != data->fan_div[nr]) {
1976*c3963bc0SZev Weiss 		dev_dbg(dev, "fan%u clock divider changed from %u to %u\n",
1977*c3963bc0SZev Weiss 			nr + 1, div_from_reg(data->fan_div[nr]),
1978*c3963bc0SZev Weiss 			div_from_reg(new_div));
1979*c3963bc0SZev Weiss 		data->fan_div[nr] = new_div;
1980*c3963bc0SZev Weiss 		err = nct6775_write_fan_div_common(data, nr);
1981*c3963bc0SZev Weiss 		if (err)
1982*c3963bc0SZev Weiss 			goto write_min;
1983*c3963bc0SZev Weiss 		/* Give the chip time to sample a new speed value */
1984*c3963bc0SZev Weiss 		data->last_updated = jiffies;
1985*c3963bc0SZev Weiss 	}
1986*c3963bc0SZev Weiss 
1987*c3963bc0SZev Weiss write_min:
1988*c3963bc0SZev Weiss 	err = nct6775_write_value(data, data->REG_FAN_MIN[nr], data->fan_min[nr]);
1989*c3963bc0SZev Weiss 	mutex_unlock(&data->update_lock);
1990*c3963bc0SZev Weiss 
1991*c3963bc0SZev Weiss 	return err ? : count;
1992*c3963bc0SZev Weiss }
1993*c3963bc0SZev Weiss 
1994*c3963bc0SZev Weiss static ssize_t
1995*c3963bc0SZev Weiss show_fan_pulses(struct device *dev, struct device_attribute *attr, char *buf)
1996*c3963bc0SZev Weiss {
1997*c3963bc0SZev Weiss 	struct nct6775_data *data = nct6775_update_device(dev);
1998*c3963bc0SZev Weiss 	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1999*c3963bc0SZev Weiss 	int p;
2000*c3963bc0SZev Weiss 
2001*c3963bc0SZev Weiss 	if (IS_ERR(data))
2002*c3963bc0SZev Weiss 		return PTR_ERR(data);
2003*c3963bc0SZev Weiss 
2004*c3963bc0SZev Weiss 	p = data->fan_pulses[sattr->index];
2005*c3963bc0SZev Weiss 	return sprintf(buf, "%d\n", p ? : 4);
2006*c3963bc0SZev Weiss }
2007*c3963bc0SZev Weiss 
2008*c3963bc0SZev Weiss static ssize_t
2009*c3963bc0SZev Weiss store_fan_pulses(struct device *dev, struct device_attribute *attr,
2010*c3963bc0SZev Weiss 		 const char *buf, size_t count)
2011*c3963bc0SZev Weiss {
2012*c3963bc0SZev Weiss 	struct nct6775_data *data = dev_get_drvdata(dev);
2013*c3963bc0SZev Weiss 	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2014*c3963bc0SZev Weiss 	int nr = sattr->index;
2015*c3963bc0SZev Weiss 	unsigned long val;
2016*c3963bc0SZev Weiss 	int err;
2017*c3963bc0SZev Weiss 	u16 reg;
2018*c3963bc0SZev Weiss 
2019*c3963bc0SZev Weiss 	err = kstrtoul(buf, 10, &val);
2020*c3963bc0SZev Weiss 	if (err < 0)
2021*c3963bc0SZev Weiss 		return err;
2022*c3963bc0SZev Weiss 
2023*c3963bc0SZev Weiss 	if (val > 4)
2024*c3963bc0SZev Weiss 		return -EINVAL;
2025*c3963bc0SZev Weiss 
2026*c3963bc0SZev Weiss 	mutex_lock(&data->update_lock);
2027*c3963bc0SZev Weiss 	data->fan_pulses[nr] = val & 3;
2028*c3963bc0SZev Weiss 	err = nct6775_read_value(data, data->REG_FAN_PULSES[nr], &reg);
2029*c3963bc0SZev Weiss 	if (err)
2030*c3963bc0SZev Weiss 		goto out;
2031*c3963bc0SZev Weiss 	reg &= ~(0x03 << data->FAN_PULSE_SHIFT[nr]);
2032*c3963bc0SZev Weiss 	reg |= (val & 3) << data->FAN_PULSE_SHIFT[nr];
2033*c3963bc0SZev Weiss 	err = nct6775_write_value(data, data->REG_FAN_PULSES[nr], reg);
2034*c3963bc0SZev Weiss out:
2035*c3963bc0SZev Weiss 	mutex_unlock(&data->update_lock);
2036*c3963bc0SZev Weiss 
2037*c3963bc0SZev Weiss 	return err ? : count;
2038*c3963bc0SZev Weiss }
2039*c3963bc0SZev Weiss 
2040*c3963bc0SZev Weiss static umode_t nct6775_fan_is_visible(struct kobject *kobj,
2041*c3963bc0SZev Weiss 				      struct attribute *attr, int index)
2042*c3963bc0SZev Weiss {
2043*c3963bc0SZev Weiss 	struct device *dev = kobj_to_dev(kobj);
2044*c3963bc0SZev Weiss 	struct nct6775_data *data = dev_get_drvdata(dev);
2045*c3963bc0SZev Weiss 	int fan = index / 6;	/* fan index */
2046*c3963bc0SZev Weiss 	int nr = index % 6;	/* attribute index */
2047*c3963bc0SZev Weiss 
2048*c3963bc0SZev Weiss 	if (!(data->has_fan & BIT(fan)))
2049*c3963bc0SZev Weiss 		return 0;
2050*c3963bc0SZev Weiss 
2051*c3963bc0SZev Weiss 	if (nr == 1 && data->ALARM_BITS[FAN_ALARM_BASE + fan] == -1)
2052*c3963bc0SZev Weiss 		return 0;
2053*c3963bc0SZev Weiss 	if (nr == 2 && data->BEEP_BITS[FAN_ALARM_BASE + fan] == -1)
2054*c3963bc0SZev Weiss 		return 0;
2055*c3963bc0SZev Weiss 	if (nr == 3 && !data->REG_FAN_PULSES[fan])
2056*c3963bc0SZev Weiss 		return 0;
2057*c3963bc0SZev Weiss 	if (nr == 4 && !(data->has_fan_min & BIT(fan)))
2058*c3963bc0SZev Weiss 		return 0;
2059*c3963bc0SZev Weiss 	if (nr == 5 && data->kind != nct6775)
2060*c3963bc0SZev Weiss 		return 0;
2061*c3963bc0SZev Weiss 
2062*c3963bc0SZev Weiss 	return nct6775_attr_mode(data, attr);
2063*c3963bc0SZev Weiss }
2064*c3963bc0SZev Weiss 
2065*c3963bc0SZev Weiss SENSOR_TEMPLATE(fan_input, "fan%d_input", 0444, show_fan, NULL, 0);
2066*c3963bc0SZev Weiss SENSOR_TEMPLATE(fan_alarm, "fan%d_alarm", 0444, nct6775_show_alarm, NULL, FAN_ALARM_BASE);
2067*c3963bc0SZev Weiss SENSOR_TEMPLATE(fan_beep, "fan%d_beep", 0644, nct6775_show_beep,
2068*c3963bc0SZev Weiss 		nct6775_store_beep, FAN_ALARM_BASE);
2069*c3963bc0SZev Weiss SENSOR_TEMPLATE(fan_pulses, "fan%d_pulses", 0644, show_fan_pulses, store_fan_pulses, 0);
2070*c3963bc0SZev Weiss SENSOR_TEMPLATE(fan_min, "fan%d_min", 0644, show_fan_min, store_fan_min, 0);
2071*c3963bc0SZev Weiss SENSOR_TEMPLATE(fan_div, "fan%d_div", 0444, show_fan_div, NULL, 0);
2072*c3963bc0SZev Weiss 
2073*c3963bc0SZev Weiss /*
2074*c3963bc0SZev Weiss  * nct6775_fan_is_visible uses the index into the following array
2075*c3963bc0SZev Weiss  * to determine if attributes should be created or not.
2076*c3963bc0SZev Weiss  * Any change in order or content must be matched.
2077*c3963bc0SZev Weiss  */
2078*c3963bc0SZev Weiss static struct sensor_device_template *nct6775_attributes_fan_template[] = {
2079*c3963bc0SZev Weiss 	&sensor_dev_template_fan_input,
2080*c3963bc0SZev Weiss 	&sensor_dev_template_fan_alarm,	/* 1 */
2081*c3963bc0SZev Weiss 	&sensor_dev_template_fan_beep,	/* 2 */
2082*c3963bc0SZev Weiss 	&sensor_dev_template_fan_pulses,
2083*c3963bc0SZev Weiss 	&sensor_dev_template_fan_min,	/* 4 */
2084*c3963bc0SZev Weiss 	&sensor_dev_template_fan_div,	/* 5 */
2085*c3963bc0SZev Weiss 	NULL
2086*c3963bc0SZev Weiss };
2087*c3963bc0SZev Weiss 
2088*c3963bc0SZev Weiss static const struct sensor_template_group nct6775_fan_template_group = {
2089*c3963bc0SZev Weiss 	.templates = nct6775_attributes_fan_template,
2090*c3963bc0SZev Weiss 	.is_visible = nct6775_fan_is_visible,
2091*c3963bc0SZev Weiss 	.base = 1,
2092*c3963bc0SZev Weiss };
2093*c3963bc0SZev Weiss 
2094*c3963bc0SZev Weiss static ssize_t
2095*c3963bc0SZev Weiss show_temp_label(struct device *dev, struct device_attribute *attr, char *buf)
2096*c3963bc0SZev Weiss {
2097*c3963bc0SZev Weiss 	struct nct6775_data *data = nct6775_update_device(dev);
2098*c3963bc0SZev Weiss 	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2099*c3963bc0SZev Weiss 	int nr = sattr->index;
2100*c3963bc0SZev Weiss 
2101*c3963bc0SZev Weiss 	if (IS_ERR(data))
2102*c3963bc0SZev Weiss 		return PTR_ERR(data);
2103*c3963bc0SZev Weiss 
2104*c3963bc0SZev Weiss 	return sprintf(buf, "%s\n", data->temp_label[data->temp_src[nr]]);
2105*c3963bc0SZev Weiss }
2106*c3963bc0SZev Weiss 
2107*c3963bc0SZev Weiss static ssize_t
2108*c3963bc0SZev Weiss show_temp(struct device *dev, struct device_attribute *attr, char *buf)
2109*c3963bc0SZev Weiss {
2110*c3963bc0SZev Weiss 	struct nct6775_data *data = nct6775_update_device(dev);
2111*c3963bc0SZev Weiss 	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2112*c3963bc0SZev Weiss 	int nr = sattr->nr;
2113*c3963bc0SZev Weiss 	int index = sattr->index;
2114*c3963bc0SZev Weiss 
2115*c3963bc0SZev Weiss 	if (IS_ERR(data))
2116*c3963bc0SZev Weiss 		return PTR_ERR(data);
2117*c3963bc0SZev Weiss 
2118*c3963bc0SZev Weiss 	return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->temp[index][nr]));
2119*c3963bc0SZev Weiss }
2120*c3963bc0SZev Weiss 
2121*c3963bc0SZev Weiss static ssize_t
2122*c3963bc0SZev Weiss store_temp(struct device *dev, struct device_attribute *attr, const char *buf,
2123*c3963bc0SZev Weiss 	   size_t count)
2124*c3963bc0SZev Weiss {
2125*c3963bc0SZev Weiss 	struct nct6775_data *data = dev_get_drvdata(dev);
2126*c3963bc0SZev Weiss 	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2127*c3963bc0SZev Weiss 	int nr = sattr->nr;
2128*c3963bc0SZev Weiss 	int index = sattr->index;
2129*c3963bc0SZev Weiss 	int err;
2130*c3963bc0SZev Weiss 	long val;
2131*c3963bc0SZev Weiss 
2132*c3963bc0SZev Weiss 	err = kstrtol(buf, 10, &val);
2133*c3963bc0SZev Weiss 	if (err < 0)
2134*c3963bc0SZev Weiss 		return err;
2135*c3963bc0SZev Weiss 
2136*c3963bc0SZev Weiss 	mutex_lock(&data->update_lock);
2137*c3963bc0SZev Weiss 	data->temp[index][nr] = LM75_TEMP_TO_REG(val);
2138*c3963bc0SZev Weiss 	err = nct6775_write_temp(data, data->reg_temp[index][nr], data->temp[index][nr]);
2139*c3963bc0SZev Weiss 	mutex_unlock(&data->update_lock);
2140*c3963bc0SZev Weiss 	return err ? : count;
2141*c3963bc0SZev Weiss }
2142*c3963bc0SZev Weiss 
2143*c3963bc0SZev Weiss static ssize_t
2144*c3963bc0SZev Weiss show_temp_offset(struct device *dev, struct device_attribute *attr, char *buf)
2145*c3963bc0SZev Weiss {
2146*c3963bc0SZev Weiss 	struct nct6775_data *data = nct6775_update_device(dev);
2147*c3963bc0SZev Weiss 	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2148*c3963bc0SZev Weiss 
2149*c3963bc0SZev Weiss 	if (IS_ERR(data))
2150*c3963bc0SZev Weiss 		return PTR_ERR(data);
2151*c3963bc0SZev Weiss 
2152*c3963bc0SZev Weiss 	return sprintf(buf, "%d\n", data->temp_offset[sattr->index] * 1000);
2153*c3963bc0SZev Weiss }
2154*c3963bc0SZev Weiss 
2155*c3963bc0SZev Weiss static ssize_t
2156*c3963bc0SZev Weiss store_temp_offset(struct device *dev, struct device_attribute *attr,
2157*c3963bc0SZev Weiss 		  const char *buf, size_t count)
2158*c3963bc0SZev Weiss {
2159*c3963bc0SZev Weiss 	struct nct6775_data *data = dev_get_drvdata(dev);
2160*c3963bc0SZev Weiss 	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2161*c3963bc0SZev Weiss 	int nr = sattr->index;
2162*c3963bc0SZev Weiss 	long val;
2163*c3963bc0SZev Weiss 	int err;
2164*c3963bc0SZev Weiss 
2165*c3963bc0SZev Weiss 	err = kstrtol(buf, 10, &val);
2166*c3963bc0SZev Weiss 	if (err < 0)
2167*c3963bc0SZev Weiss 		return err;
2168*c3963bc0SZev Weiss 
2169*c3963bc0SZev Weiss 	val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -128, 127);
2170*c3963bc0SZev Weiss 
2171*c3963bc0SZev Weiss 	mutex_lock(&data->update_lock);
2172*c3963bc0SZev Weiss 	data->temp_offset[nr] = val;
2173*c3963bc0SZev Weiss 	err = nct6775_write_value(data, data->REG_TEMP_OFFSET[nr], val);
2174*c3963bc0SZev Weiss 	mutex_unlock(&data->update_lock);
2175*c3963bc0SZev Weiss 
2176*c3963bc0SZev Weiss 	return err ? : count;
2177*c3963bc0SZev Weiss }
2178*c3963bc0SZev Weiss 
2179*c3963bc0SZev Weiss static ssize_t
2180*c3963bc0SZev Weiss show_temp_type(struct device *dev, struct device_attribute *attr, char *buf)
2181*c3963bc0SZev Weiss {
2182*c3963bc0SZev Weiss 	struct nct6775_data *data = nct6775_update_device(dev);
2183*c3963bc0SZev Weiss 	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2184*c3963bc0SZev Weiss 	int nr = sattr->index;
2185*c3963bc0SZev Weiss 
2186*c3963bc0SZev Weiss 	if (IS_ERR(data))
2187*c3963bc0SZev Weiss 		return PTR_ERR(data);
2188*c3963bc0SZev Weiss 
2189*c3963bc0SZev Weiss 	return sprintf(buf, "%d\n", (int)data->temp_type[nr]);
2190*c3963bc0SZev Weiss }
2191*c3963bc0SZev Weiss 
2192*c3963bc0SZev Weiss static ssize_t
2193*c3963bc0SZev Weiss store_temp_type(struct device *dev, struct device_attribute *attr,
2194*c3963bc0SZev Weiss 		const char *buf, size_t count)
2195*c3963bc0SZev Weiss {
2196*c3963bc0SZev Weiss 	struct nct6775_data *data = nct6775_update_device(dev);
2197*c3963bc0SZev Weiss 	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2198*c3963bc0SZev Weiss 	int nr = sattr->index;
2199*c3963bc0SZev Weiss 	unsigned long val;
2200*c3963bc0SZev Weiss 	int err;
2201*c3963bc0SZev Weiss 	u8 vbit, dbit;
2202*c3963bc0SZev Weiss 	u16 vbat, diode;
2203*c3963bc0SZev Weiss 
2204*c3963bc0SZev Weiss 	if (IS_ERR(data))
2205*c3963bc0SZev Weiss 		return PTR_ERR(data);
2206*c3963bc0SZev Weiss 
2207*c3963bc0SZev Weiss 	err = kstrtoul(buf, 10, &val);
2208*c3963bc0SZev Weiss 	if (err < 0)
2209*c3963bc0SZev Weiss 		return err;
2210*c3963bc0SZev Weiss 
2211*c3963bc0SZev Weiss 	if (val != 1 && val != 3 && val != 4)
2212*c3963bc0SZev Weiss 		return -EINVAL;
2213*c3963bc0SZev Weiss 
2214*c3963bc0SZev Weiss 	mutex_lock(&data->update_lock);
2215*c3963bc0SZev Weiss 
2216*c3963bc0SZev Weiss 	data->temp_type[nr] = val;
2217*c3963bc0SZev Weiss 	vbit = 0x02 << nr;
2218*c3963bc0SZev Weiss 	dbit = data->DIODE_MASK << nr;
2219*c3963bc0SZev Weiss 
2220*c3963bc0SZev Weiss 	err = nct6775_read_value(data, data->REG_VBAT, &vbat);
2221*c3963bc0SZev Weiss 	if (err)
2222*c3963bc0SZev Weiss 		goto out;
2223*c3963bc0SZev Weiss 	vbat &= ~vbit;
2224*c3963bc0SZev Weiss 
2225*c3963bc0SZev Weiss 	err = nct6775_read_value(data, data->REG_DIODE, &diode);
2226*c3963bc0SZev Weiss 	if (err)
2227*c3963bc0SZev Weiss 		goto out;
2228*c3963bc0SZev Weiss 	diode &= ~dbit;
2229*c3963bc0SZev Weiss 
2230*c3963bc0SZev Weiss 	switch (val) {
2231*c3963bc0SZev Weiss 	case 1:	/* CPU diode (diode, current mode) */
2232*c3963bc0SZev Weiss 		vbat |= vbit;
2233*c3963bc0SZev Weiss 		diode |= dbit;
2234*c3963bc0SZev Weiss 		break;
2235*c3963bc0SZev Weiss 	case 3: /* diode, voltage mode */
2236*c3963bc0SZev Weiss 		vbat |= dbit;
2237*c3963bc0SZev Weiss 		break;
2238*c3963bc0SZev Weiss 	case 4:	/* thermistor */
2239*c3963bc0SZev Weiss 		break;
2240*c3963bc0SZev Weiss 	}
2241*c3963bc0SZev Weiss 	err = nct6775_write_value(data, data->REG_VBAT, vbat);
2242*c3963bc0SZev Weiss 	if (err)
2243*c3963bc0SZev Weiss 		goto out;
2244*c3963bc0SZev Weiss 	err = nct6775_write_value(data, data->REG_DIODE, diode);
2245*c3963bc0SZev Weiss out:
2246*c3963bc0SZev Weiss 	mutex_unlock(&data->update_lock);
2247*c3963bc0SZev Weiss 	return err ? : count;
2248*c3963bc0SZev Weiss }
2249*c3963bc0SZev Weiss 
2250*c3963bc0SZev Weiss static umode_t nct6775_temp_is_visible(struct kobject *kobj,
2251*c3963bc0SZev Weiss 				       struct attribute *attr, int index)
2252*c3963bc0SZev Weiss {
2253*c3963bc0SZev Weiss 	struct device *dev = kobj_to_dev(kobj);
2254*c3963bc0SZev Weiss 	struct nct6775_data *data = dev_get_drvdata(dev);
2255*c3963bc0SZev Weiss 	int temp = index / 10;	/* temp index */
2256*c3963bc0SZev Weiss 	int nr = index % 10;	/* attribute index */
2257*c3963bc0SZev Weiss 
2258*c3963bc0SZev Weiss 	if (!(data->have_temp & BIT(temp)))
2259*c3963bc0SZev Weiss 		return 0;
2260*c3963bc0SZev Weiss 
2261*c3963bc0SZev Weiss 	if (nr == 1 && !data->temp_label)
2262*c3963bc0SZev Weiss 		return 0;
2263*c3963bc0SZev Weiss 
2264*c3963bc0SZev Weiss 	if (nr == 2 && find_temp_source(data, temp, data->num_temp_alarms) < 0)
2265*c3963bc0SZev Weiss 		return 0;				/* alarm */
2266*c3963bc0SZev Weiss 
2267*c3963bc0SZev Weiss 	if (nr == 3 && find_temp_source(data, temp, data->num_temp_beeps) < 0)
2268*c3963bc0SZev Weiss 		return 0;				/* beep */
2269*c3963bc0SZev Weiss 
2270*c3963bc0SZev Weiss 	if (nr == 4 && !data->reg_temp[1][temp])	/* max */
2271*c3963bc0SZev Weiss 		return 0;
2272*c3963bc0SZev Weiss 
2273*c3963bc0SZev Weiss 	if (nr == 5 && !data->reg_temp[2][temp])	/* max_hyst */
2274*c3963bc0SZev Weiss 		return 0;
2275*c3963bc0SZev Weiss 
2276*c3963bc0SZev Weiss 	if (nr == 6 && !data->reg_temp[3][temp])	/* crit */
2277*c3963bc0SZev Weiss 		return 0;
2278*c3963bc0SZev Weiss 
2279*c3963bc0SZev Weiss 	if (nr == 7 && !data->reg_temp[4][temp])	/* lcrit */
2280*c3963bc0SZev Weiss 		return 0;
2281*c3963bc0SZev Weiss 
2282*c3963bc0SZev Weiss 	/* offset and type only apply to fixed sensors */
2283*c3963bc0SZev Weiss 	if (nr > 7 && !(data->have_temp_fixed & BIT(temp)))
2284*c3963bc0SZev Weiss 		return 0;
2285*c3963bc0SZev Weiss 
2286*c3963bc0SZev Weiss 	return nct6775_attr_mode(data, attr);
2287*c3963bc0SZev Weiss }
2288*c3963bc0SZev Weiss 
2289*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(temp_input, "temp%d_input", 0444, show_temp, NULL, 0, 0);
2290*c3963bc0SZev Weiss SENSOR_TEMPLATE(temp_label, "temp%d_label", 0444, show_temp_label, NULL, 0);
2291*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(temp_max, "temp%d_max", 0644, show_temp, store_temp, 0, 1);
2292*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(temp_max_hyst, "temp%d_max_hyst", 0644, show_temp, store_temp, 0, 2);
2293*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(temp_crit, "temp%d_crit", 0644, show_temp, store_temp, 0, 3);
2294*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(temp_lcrit, "temp%d_lcrit", 0644, show_temp, store_temp, 0, 4);
2295*c3963bc0SZev Weiss SENSOR_TEMPLATE(temp_offset, "temp%d_offset", 0644, show_temp_offset, store_temp_offset, 0);
2296*c3963bc0SZev Weiss SENSOR_TEMPLATE(temp_type, "temp%d_type", 0644, show_temp_type, store_temp_type, 0);
2297*c3963bc0SZev Weiss SENSOR_TEMPLATE(temp_alarm, "temp%d_alarm", 0444, show_temp_alarm, NULL, 0);
2298*c3963bc0SZev Weiss SENSOR_TEMPLATE(temp_beep, "temp%d_beep", 0644, show_temp_beep, store_temp_beep, 0);
2299*c3963bc0SZev Weiss 
2300*c3963bc0SZev Weiss /*
2301*c3963bc0SZev Weiss  * nct6775_temp_is_visible uses the index into the following array
2302*c3963bc0SZev Weiss  * to determine if attributes should be created or not.
2303*c3963bc0SZev Weiss  * Any change in order or content must be matched.
2304*c3963bc0SZev Weiss  */
2305*c3963bc0SZev Weiss static struct sensor_device_template *nct6775_attributes_temp_template[] = {
2306*c3963bc0SZev Weiss 	&sensor_dev_template_temp_input,
2307*c3963bc0SZev Weiss 	&sensor_dev_template_temp_label,
2308*c3963bc0SZev Weiss 	&sensor_dev_template_temp_alarm,	/* 2 */
2309*c3963bc0SZev Weiss 	&sensor_dev_template_temp_beep,		/* 3 */
2310*c3963bc0SZev Weiss 	&sensor_dev_template_temp_max,		/* 4 */
2311*c3963bc0SZev Weiss 	&sensor_dev_template_temp_max_hyst,	/* 5 */
2312*c3963bc0SZev Weiss 	&sensor_dev_template_temp_crit,		/* 6 */
2313*c3963bc0SZev Weiss 	&sensor_dev_template_temp_lcrit,	/* 7 */
2314*c3963bc0SZev Weiss 	&sensor_dev_template_temp_offset,	/* 8 */
2315*c3963bc0SZev Weiss 	&sensor_dev_template_temp_type,		/* 9 */
2316*c3963bc0SZev Weiss 	NULL
2317*c3963bc0SZev Weiss };
2318*c3963bc0SZev Weiss 
2319*c3963bc0SZev Weiss static const struct sensor_template_group nct6775_temp_template_group = {
2320*c3963bc0SZev Weiss 	.templates = nct6775_attributes_temp_template,
2321*c3963bc0SZev Weiss 	.is_visible = nct6775_temp_is_visible,
2322*c3963bc0SZev Weiss 	.base = 1,
2323*c3963bc0SZev Weiss };
2324*c3963bc0SZev Weiss 
2325*c3963bc0SZev Weiss static ssize_t show_tsi_temp(struct device *dev, struct device_attribute *attr, char *buf)
2326*c3963bc0SZev Weiss {
2327*c3963bc0SZev Weiss 	struct nct6775_data *data = nct6775_update_device(dev);
2328*c3963bc0SZev Weiss 	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2329*c3963bc0SZev Weiss 
2330*c3963bc0SZev Weiss 	if (IS_ERR(data))
2331*c3963bc0SZev Weiss 		return PTR_ERR(data);
2332*c3963bc0SZev Weiss 
2333*c3963bc0SZev Weiss 	return sysfs_emit(buf, "%u\n", tsi_temp_from_reg(data->tsi_temp[sattr->index]));
2334*c3963bc0SZev Weiss }
2335*c3963bc0SZev Weiss 
2336*c3963bc0SZev Weiss static ssize_t show_tsi_temp_label(struct device *dev, struct device_attribute *attr, char *buf)
2337*c3963bc0SZev Weiss {
2338*c3963bc0SZev Weiss 	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2339*c3963bc0SZev Weiss 
2340*c3963bc0SZev Weiss 	return sysfs_emit(buf, "TSI%d_TEMP\n", sattr->index);
2341*c3963bc0SZev Weiss }
2342*c3963bc0SZev Weiss 
2343*c3963bc0SZev Weiss SENSOR_TEMPLATE(tsi_temp_input, "temp%d_input", 0444, show_tsi_temp, NULL, 0);
2344*c3963bc0SZev Weiss SENSOR_TEMPLATE(tsi_temp_label, "temp%d_label", 0444, show_tsi_temp_label, NULL, 0);
2345*c3963bc0SZev Weiss 
2346*c3963bc0SZev Weiss static umode_t nct6775_tsi_temp_is_visible(struct kobject *kobj, struct attribute *attr,
2347*c3963bc0SZev Weiss 					       int index)
2348*c3963bc0SZev Weiss {
2349*c3963bc0SZev Weiss 	struct device *dev = kobj_to_dev(kobj);
2350*c3963bc0SZev Weiss 	struct nct6775_data *data = dev_get_drvdata(dev);
2351*c3963bc0SZev Weiss 	int temp = index / 2;
2352*c3963bc0SZev Weiss 
2353*c3963bc0SZev Weiss 	return (data->have_tsi_temp & BIT(temp)) ? nct6775_attr_mode(data, attr) : 0;
2354*c3963bc0SZev Weiss }
2355*c3963bc0SZev Weiss 
2356*c3963bc0SZev Weiss /*
2357*c3963bc0SZev Weiss  * The index calculation in nct6775_tsi_temp_is_visible() must be kept in
2358*c3963bc0SZev Weiss  * sync with the size of this array.
2359*c3963bc0SZev Weiss  */
2360*c3963bc0SZev Weiss static struct sensor_device_template *nct6775_tsi_temp_template[] = {
2361*c3963bc0SZev Weiss 	&sensor_dev_template_tsi_temp_input,
2362*c3963bc0SZev Weiss 	&sensor_dev_template_tsi_temp_label,
2363*c3963bc0SZev Weiss 	NULL
2364*c3963bc0SZev Weiss };
2365*c3963bc0SZev Weiss 
2366*c3963bc0SZev Weiss static ssize_t
2367*c3963bc0SZev Weiss show_pwm_mode(struct device *dev, struct device_attribute *attr, char *buf)
2368*c3963bc0SZev Weiss {
2369*c3963bc0SZev Weiss 	struct nct6775_data *data = nct6775_update_device(dev);
2370*c3963bc0SZev Weiss 	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2371*c3963bc0SZev Weiss 
2372*c3963bc0SZev Weiss 	if (IS_ERR(data))
2373*c3963bc0SZev Weiss 		return PTR_ERR(data);
2374*c3963bc0SZev Weiss 
2375*c3963bc0SZev Weiss 	return sprintf(buf, "%d\n", data->pwm_mode[sattr->index]);
2376*c3963bc0SZev Weiss }
2377*c3963bc0SZev Weiss 
2378*c3963bc0SZev Weiss static ssize_t
2379*c3963bc0SZev Weiss store_pwm_mode(struct device *dev, struct device_attribute *attr,
2380*c3963bc0SZev Weiss 	       const char *buf, size_t count)
2381*c3963bc0SZev Weiss {
2382*c3963bc0SZev Weiss 	struct nct6775_data *data = dev_get_drvdata(dev);
2383*c3963bc0SZev Weiss 	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2384*c3963bc0SZev Weiss 	int nr = sattr->index;
2385*c3963bc0SZev Weiss 	unsigned long val;
2386*c3963bc0SZev Weiss 	int err;
2387*c3963bc0SZev Weiss 	u16 reg;
2388*c3963bc0SZev Weiss 
2389*c3963bc0SZev Weiss 	err = kstrtoul(buf, 10, &val);
2390*c3963bc0SZev Weiss 	if (err < 0)
2391*c3963bc0SZev Weiss 		return err;
2392*c3963bc0SZev Weiss 
2393*c3963bc0SZev Weiss 	if (val > 1)
2394*c3963bc0SZev Weiss 		return -EINVAL;
2395*c3963bc0SZev Weiss 
2396*c3963bc0SZev Weiss 	/* Setting DC mode (0) is not supported for all chips/channels */
2397*c3963bc0SZev Weiss 	if (data->REG_PWM_MODE[nr] == 0) {
2398*c3963bc0SZev Weiss 		if (!val)
2399*c3963bc0SZev Weiss 			return -EINVAL;
2400*c3963bc0SZev Weiss 		return count;
2401*c3963bc0SZev Weiss 	}
2402*c3963bc0SZev Weiss 
2403*c3963bc0SZev Weiss 	mutex_lock(&data->update_lock);
2404*c3963bc0SZev Weiss 	data->pwm_mode[nr] = val;
2405*c3963bc0SZev Weiss 	err = nct6775_read_value(data, data->REG_PWM_MODE[nr], &reg);
2406*c3963bc0SZev Weiss 	if (err)
2407*c3963bc0SZev Weiss 		goto out;
2408*c3963bc0SZev Weiss 	reg &= ~data->PWM_MODE_MASK[nr];
2409*c3963bc0SZev Weiss 	if (!val)
2410*c3963bc0SZev Weiss 		reg |= data->PWM_MODE_MASK[nr];
2411*c3963bc0SZev Weiss 	err = nct6775_write_value(data, data->REG_PWM_MODE[nr], reg);
2412*c3963bc0SZev Weiss out:
2413*c3963bc0SZev Weiss 	mutex_unlock(&data->update_lock);
2414*c3963bc0SZev Weiss 	return err ? : count;
2415*c3963bc0SZev Weiss }
2416*c3963bc0SZev Weiss 
2417*c3963bc0SZev Weiss static ssize_t
2418*c3963bc0SZev Weiss show_pwm(struct device *dev, struct device_attribute *attr, char *buf)
2419*c3963bc0SZev Weiss {
2420*c3963bc0SZev Weiss 	struct nct6775_data *data = nct6775_update_device(dev);
2421*c3963bc0SZev Weiss 	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2422*c3963bc0SZev Weiss 	int nr = sattr->nr;
2423*c3963bc0SZev Weiss 	int index = sattr->index;
2424*c3963bc0SZev Weiss 	int err;
2425*c3963bc0SZev Weiss 	u16 pwm;
2426*c3963bc0SZev Weiss 
2427*c3963bc0SZev Weiss 	if (IS_ERR(data))
2428*c3963bc0SZev Weiss 		return PTR_ERR(data);
2429*c3963bc0SZev Weiss 
2430*c3963bc0SZev Weiss 	/*
2431*c3963bc0SZev Weiss 	 * For automatic fan control modes, show current pwm readings.
2432*c3963bc0SZev Weiss 	 * Otherwise, show the configured value.
2433*c3963bc0SZev Weiss 	 */
2434*c3963bc0SZev Weiss 	if (index == 0 && data->pwm_enable[nr] > manual) {
2435*c3963bc0SZev Weiss 		err = nct6775_read_value(data, data->REG_PWM_READ[nr], &pwm);
2436*c3963bc0SZev Weiss 		if (err)
2437*c3963bc0SZev Weiss 			return err;
2438*c3963bc0SZev Weiss 	} else {
2439*c3963bc0SZev Weiss 		pwm = data->pwm[index][nr];
2440*c3963bc0SZev Weiss 	}
2441*c3963bc0SZev Weiss 
2442*c3963bc0SZev Weiss 	return sprintf(buf, "%d\n", pwm);
2443*c3963bc0SZev Weiss }
2444*c3963bc0SZev Weiss 
2445*c3963bc0SZev Weiss static ssize_t
2446*c3963bc0SZev Weiss store_pwm(struct device *dev, struct device_attribute *attr, const char *buf,
2447*c3963bc0SZev Weiss 	  size_t count)
2448*c3963bc0SZev Weiss {
2449*c3963bc0SZev Weiss 	struct nct6775_data *data = dev_get_drvdata(dev);
2450*c3963bc0SZev Weiss 	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2451*c3963bc0SZev Weiss 	int nr = sattr->nr;
2452*c3963bc0SZev Weiss 	int index = sattr->index;
2453*c3963bc0SZev Weiss 	unsigned long val;
2454*c3963bc0SZev Weiss 	int minval[7] = { 0, 1, 1, data->pwm[2][nr], 0, 0, 0 };
2455*c3963bc0SZev Weiss 	int maxval[7]
2456*c3963bc0SZev Weiss 	  = { 255, 255, data->pwm[3][nr] ? : 255, 255, 255, 255, 255 };
2457*c3963bc0SZev Weiss 	int err;
2458*c3963bc0SZev Weiss 	u16 reg;
2459*c3963bc0SZev Weiss 
2460*c3963bc0SZev Weiss 	err = kstrtoul(buf, 10, &val);
2461*c3963bc0SZev Weiss 	if (err < 0)
2462*c3963bc0SZev Weiss 		return err;
2463*c3963bc0SZev Weiss 	val = clamp_val(val, minval[index], maxval[index]);
2464*c3963bc0SZev Weiss 
2465*c3963bc0SZev Weiss 	mutex_lock(&data->update_lock);
2466*c3963bc0SZev Weiss 	data->pwm[index][nr] = val;
2467*c3963bc0SZev Weiss 	err = nct6775_write_value(data, data->REG_PWM[index][nr], val);
2468*c3963bc0SZev Weiss 	if (err)
2469*c3963bc0SZev Weiss 		goto out;
2470*c3963bc0SZev Weiss 	if (index == 2)	{ /* floor: disable if val == 0 */
2471*c3963bc0SZev Weiss 		err = nct6775_read_value(data, data->REG_TEMP_SEL[nr], &reg);
2472*c3963bc0SZev Weiss 		if (err)
2473*c3963bc0SZev Weiss 			goto out;
2474*c3963bc0SZev Weiss 		reg &= 0x7f;
2475*c3963bc0SZev Weiss 		if (val)
2476*c3963bc0SZev Weiss 			reg |= 0x80;
2477*c3963bc0SZev Weiss 		err = nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg);
2478*c3963bc0SZev Weiss 	}
2479*c3963bc0SZev Weiss out:
2480*c3963bc0SZev Weiss 	mutex_unlock(&data->update_lock);
2481*c3963bc0SZev Weiss 	return err ? : count;
2482*c3963bc0SZev Weiss }
2483*c3963bc0SZev Weiss 
2484*c3963bc0SZev Weiss /* Returns 0 if OK, -EINVAL otherwise */
2485*c3963bc0SZev Weiss static int check_trip_points(struct nct6775_data *data, int nr)
2486*c3963bc0SZev Weiss {
2487*c3963bc0SZev Weiss 	int i;
2488*c3963bc0SZev Weiss 
2489*c3963bc0SZev Weiss 	for (i = 0; i < data->auto_pwm_num - 1; i++) {
2490*c3963bc0SZev Weiss 		if (data->auto_temp[nr][i] > data->auto_temp[nr][i + 1])
2491*c3963bc0SZev Weiss 			return -EINVAL;
2492*c3963bc0SZev Weiss 	}
2493*c3963bc0SZev Weiss 	for (i = 0; i < data->auto_pwm_num - 1; i++) {
2494*c3963bc0SZev Weiss 		if (data->auto_pwm[nr][i] > data->auto_pwm[nr][i + 1])
2495*c3963bc0SZev Weiss 			return -EINVAL;
2496*c3963bc0SZev Weiss 	}
2497*c3963bc0SZev Weiss 	/* validate critical temperature and pwm if enabled (pwm > 0) */
2498*c3963bc0SZev Weiss 	if (data->auto_pwm[nr][data->auto_pwm_num]) {
2499*c3963bc0SZev Weiss 		if (data->auto_temp[nr][data->auto_pwm_num - 1] >
2500*c3963bc0SZev Weiss 				data->auto_temp[nr][data->auto_pwm_num] ||
2501*c3963bc0SZev Weiss 		    data->auto_pwm[nr][data->auto_pwm_num - 1] >
2502*c3963bc0SZev Weiss 				data->auto_pwm[nr][data->auto_pwm_num])
2503*c3963bc0SZev Weiss 			return -EINVAL;
2504*c3963bc0SZev Weiss 	}
2505*c3963bc0SZev Weiss 	return 0;
2506*c3963bc0SZev Weiss }
2507*c3963bc0SZev Weiss 
2508*c3963bc0SZev Weiss static int pwm_update_registers(struct nct6775_data *data, int nr)
2509*c3963bc0SZev Weiss {
2510*c3963bc0SZev Weiss 	u16 reg;
2511*c3963bc0SZev Weiss 	int err;
2512*c3963bc0SZev Weiss 
2513*c3963bc0SZev Weiss 	switch (data->pwm_enable[nr]) {
2514*c3963bc0SZev Weiss 	case off:
2515*c3963bc0SZev Weiss 	case manual:
2516*c3963bc0SZev Weiss 		break;
2517*c3963bc0SZev Weiss 	case speed_cruise:
2518*c3963bc0SZev Weiss 		err = nct6775_read_value(data, data->REG_FAN_MODE[nr], &reg);
2519*c3963bc0SZev Weiss 		if (err)
2520*c3963bc0SZev Weiss 			return err;
2521*c3963bc0SZev Weiss 		reg = (reg & ~data->tolerance_mask) |
2522*c3963bc0SZev Weiss 		  (data->target_speed_tolerance[nr] & data->tolerance_mask);
2523*c3963bc0SZev Weiss 		err = nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2524*c3963bc0SZev Weiss 		if (err)
2525*c3963bc0SZev Weiss 			return err;
2526*c3963bc0SZev Weiss 		err = nct6775_write_value(data, data->REG_TARGET[nr],
2527*c3963bc0SZev Weiss 					  data->target_speed[nr] & 0xff);
2528*c3963bc0SZev Weiss 		if (err)
2529*c3963bc0SZev Weiss 			return err;
2530*c3963bc0SZev Weiss 		if (data->REG_TOLERANCE_H) {
2531*c3963bc0SZev Weiss 			reg = (data->target_speed[nr] >> 8) & 0x0f;
2532*c3963bc0SZev Weiss 			reg |= (data->target_speed_tolerance[nr] & 0x38) << 1;
2533*c3963bc0SZev Weiss 			err = nct6775_write_value(data, data->REG_TOLERANCE_H[nr], reg);
2534*c3963bc0SZev Weiss 			if (err)
2535*c3963bc0SZev Weiss 				return err;
2536*c3963bc0SZev Weiss 		}
2537*c3963bc0SZev Weiss 		break;
2538*c3963bc0SZev Weiss 	case thermal_cruise:
2539*c3963bc0SZev Weiss 		err = nct6775_write_value(data, data->REG_TARGET[nr], data->target_temp[nr]);
2540*c3963bc0SZev Weiss 		if (err)
2541*c3963bc0SZev Weiss 			return err;
2542*c3963bc0SZev Weiss 		fallthrough;
2543*c3963bc0SZev Weiss 	default:
2544*c3963bc0SZev Weiss 		err = nct6775_read_value(data, data->REG_FAN_MODE[nr], &reg);
2545*c3963bc0SZev Weiss 		if (err)
2546*c3963bc0SZev Weiss 			return err;
2547*c3963bc0SZev Weiss 		reg = (reg & ~data->tolerance_mask) |
2548*c3963bc0SZev Weiss 		  data->temp_tolerance[0][nr];
2549*c3963bc0SZev Weiss 		err = nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2550*c3963bc0SZev Weiss 		if (err)
2551*c3963bc0SZev Weiss 			return err;
2552*c3963bc0SZev Weiss 		break;
2553*c3963bc0SZev Weiss 	}
2554*c3963bc0SZev Weiss 
2555*c3963bc0SZev Weiss 	return 0;
2556*c3963bc0SZev Weiss }
2557*c3963bc0SZev Weiss 
2558*c3963bc0SZev Weiss static ssize_t
2559*c3963bc0SZev Weiss show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf)
2560*c3963bc0SZev Weiss {
2561*c3963bc0SZev Weiss 	struct nct6775_data *data = nct6775_update_device(dev);
2562*c3963bc0SZev Weiss 	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2563*c3963bc0SZev Weiss 
2564*c3963bc0SZev Weiss 	if (IS_ERR(data))
2565*c3963bc0SZev Weiss 		return PTR_ERR(data);
2566*c3963bc0SZev Weiss 
2567*c3963bc0SZev Weiss 	return sprintf(buf, "%d\n", data->pwm_enable[sattr->index]);
2568*c3963bc0SZev Weiss }
2569*c3963bc0SZev Weiss 
2570*c3963bc0SZev Weiss static ssize_t
2571*c3963bc0SZev Weiss store_pwm_enable(struct device *dev, struct device_attribute *attr,
2572*c3963bc0SZev Weiss 		 const char *buf, size_t count)
2573*c3963bc0SZev Weiss {
2574*c3963bc0SZev Weiss 	struct nct6775_data *data = dev_get_drvdata(dev);
2575*c3963bc0SZev Weiss 	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2576*c3963bc0SZev Weiss 	int nr = sattr->index;
2577*c3963bc0SZev Weiss 	unsigned long val;
2578*c3963bc0SZev Weiss 	int err;
2579*c3963bc0SZev Weiss 	u16 reg;
2580*c3963bc0SZev Weiss 
2581*c3963bc0SZev Weiss 	err = kstrtoul(buf, 10, &val);
2582*c3963bc0SZev Weiss 	if (err < 0)
2583*c3963bc0SZev Weiss 		return err;
2584*c3963bc0SZev Weiss 
2585*c3963bc0SZev Weiss 	if (val > sf4)
2586*c3963bc0SZev Weiss 		return -EINVAL;
2587*c3963bc0SZev Weiss 
2588*c3963bc0SZev Weiss 	if (val == sf3 && data->kind != nct6775)
2589*c3963bc0SZev Weiss 		return -EINVAL;
2590*c3963bc0SZev Weiss 
2591*c3963bc0SZev Weiss 	if (val == sf4 && check_trip_points(data, nr)) {
2592*c3963bc0SZev Weiss 		dev_err(dev, "Inconsistent trip points, not switching to SmartFan IV mode\n");
2593*c3963bc0SZev Weiss 		dev_err(dev, "Adjust trip points and try again\n");
2594*c3963bc0SZev Weiss 		return -EINVAL;
2595*c3963bc0SZev Weiss 	}
2596*c3963bc0SZev Weiss 
2597*c3963bc0SZev Weiss 	mutex_lock(&data->update_lock);
2598*c3963bc0SZev Weiss 	data->pwm_enable[nr] = val;
2599*c3963bc0SZev Weiss 	if (val == off) {
2600*c3963bc0SZev Weiss 		/*
2601*c3963bc0SZev Weiss 		 * turn off pwm control: select manual mode, set pwm to maximum
2602*c3963bc0SZev Weiss 		 */
2603*c3963bc0SZev Weiss 		data->pwm[0][nr] = 255;
2604*c3963bc0SZev Weiss 		err = nct6775_write_value(data, data->REG_PWM[0][nr], 255);
2605*c3963bc0SZev Weiss 		if (err)
2606*c3963bc0SZev Weiss 			goto out;
2607*c3963bc0SZev Weiss 	}
2608*c3963bc0SZev Weiss 	err = pwm_update_registers(data, nr);
2609*c3963bc0SZev Weiss 	if (err)
2610*c3963bc0SZev Weiss 		goto out;
2611*c3963bc0SZev Weiss 	err = nct6775_read_value(data, data->REG_FAN_MODE[nr], &reg);
2612*c3963bc0SZev Weiss 	if (err)
2613*c3963bc0SZev Weiss 		goto out;
2614*c3963bc0SZev Weiss 	reg &= 0x0f;
2615*c3963bc0SZev Weiss 	reg |= pwm_enable_to_reg(val) << 4;
2616*c3963bc0SZev Weiss 	err = nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2617*c3963bc0SZev Weiss out:
2618*c3963bc0SZev Weiss 	mutex_unlock(&data->update_lock);
2619*c3963bc0SZev Weiss 	return err ? : count;
2620*c3963bc0SZev Weiss }
2621*c3963bc0SZev Weiss 
2622*c3963bc0SZev Weiss static ssize_t
2623*c3963bc0SZev Weiss show_pwm_temp_sel_common(struct nct6775_data *data, char *buf, int src)
2624*c3963bc0SZev Weiss {
2625*c3963bc0SZev Weiss 	int i, sel = 0;
2626*c3963bc0SZev Weiss 
2627*c3963bc0SZev Weiss 	for (i = 0; i < NUM_TEMP; i++) {
2628*c3963bc0SZev Weiss 		if (!(data->have_temp & BIT(i)))
2629*c3963bc0SZev Weiss 			continue;
2630*c3963bc0SZev Weiss 		if (src == data->temp_src[i]) {
2631*c3963bc0SZev Weiss 			sel = i + 1;
2632*c3963bc0SZev Weiss 			break;
2633*c3963bc0SZev Weiss 		}
2634*c3963bc0SZev Weiss 	}
2635*c3963bc0SZev Weiss 
2636*c3963bc0SZev Weiss 	return sprintf(buf, "%d\n", sel);
2637*c3963bc0SZev Weiss }
2638*c3963bc0SZev Weiss 
2639*c3963bc0SZev Weiss static ssize_t
2640*c3963bc0SZev Weiss show_pwm_temp_sel(struct device *dev, struct device_attribute *attr, char *buf)
2641*c3963bc0SZev Weiss {
2642*c3963bc0SZev Weiss 	struct nct6775_data *data = nct6775_update_device(dev);
2643*c3963bc0SZev Weiss 	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2644*c3963bc0SZev Weiss 	int index = sattr->index;
2645*c3963bc0SZev Weiss 
2646*c3963bc0SZev Weiss 	if (IS_ERR(data))
2647*c3963bc0SZev Weiss 		return PTR_ERR(data);
2648*c3963bc0SZev Weiss 
2649*c3963bc0SZev Weiss 	return show_pwm_temp_sel_common(data, buf, data->pwm_temp_sel[index]);
2650*c3963bc0SZev Weiss }
2651*c3963bc0SZev Weiss 
2652*c3963bc0SZev Weiss static ssize_t
2653*c3963bc0SZev Weiss store_pwm_temp_sel(struct device *dev, struct device_attribute *attr,
2654*c3963bc0SZev Weiss 		   const char *buf, size_t count)
2655*c3963bc0SZev Weiss {
2656*c3963bc0SZev Weiss 	struct nct6775_data *data = nct6775_update_device(dev);
2657*c3963bc0SZev Weiss 	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2658*c3963bc0SZev Weiss 	int nr = sattr->index;
2659*c3963bc0SZev Weiss 	unsigned long val;
2660*c3963bc0SZev Weiss 	int err, src;
2661*c3963bc0SZev Weiss 	u16 reg;
2662*c3963bc0SZev Weiss 
2663*c3963bc0SZev Weiss 	if (IS_ERR(data))
2664*c3963bc0SZev Weiss 		return PTR_ERR(data);
2665*c3963bc0SZev Weiss 
2666*c3963bc0SZev Weiss 	err = kstrtoul(buf, 10, &val);
2667*c3963bc0SZev Weiss 	if (err < 0)
2668*c3963bc0SZev Weiss 		return err;
2669*c3963bc0SZev Weiss 	if (val == 0 || val > NUM_TEMP)
2670*c3963bc0SZev Weiss 		return -EINVAL;
2671*c3963bc0SZev Weiss 	if (!(data->have_temp & BIT(val - 1)) || !data->temp_src[val - 1])
2672*c3963bc0SZev Weiss 		return -EINVAL;
2673*c3963bc0SZev Weiss 
2674*c3963bc0SZev Weiss 	mutex_lock(&data->update_lock);
2675*c3963bc0SZev Weiss 	src = data->temp_src[val - 1];
2676*c3963bc0SZev Weiss 	data->pwm_temp_sel[nr] = src;
2677*c3963bc0SZev Weiss 	err = nct6775_read_value(data, data->REG_TEMP_SEL[nr], &reg);
2678*c3963bc0SZev Weiss 	if (err)
2679*c3963bc0SZev Weiss 		goto out;
2680*c3963bc0SZev Weiss 	reg &= 0xe0;
2681*c3963bc0SZev Weiss 	reg |= src;
2682*c3963bc0SZev Weiss 	err = nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg);
2683*c3963bc0SZev Weiss out:
2684*c3963bc0SZev Weiss 	mutex_unlock(&data->update_lock);
2685*c3963bc0SZev Weiss 
2686*c3963bc0SZev Weiss 	return err ? : count;
2687*c3963bc0SZev Weiss }
2688*c3963bc0SZev Weiss 
2689*c3963bc0SZev Weiss static ssize_t
2690*c3963bc0SZev Weiss show_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr,
2691*c3963bc0SZev Weiss 			 char *buf)
2692*c3963bc0SZev Weiss {
2693*c3963bc0SZev Weiss 	struct nct6775_data *data = nct6775_update_device(dev);
2694*c3963bc0SZev Weiss 	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2695*c3963bc0SZev Weiss 	int index = sattr->index;
2696*c3963bc0SZev Weiss 
2697*c3963bc0SZev Weiss 	if (IS_ERR(data))
2698*c3963bc0SZev Weiss 		return PTR_ERR(data);
2699*c3963bc0SZev Weiss 
2700*c3963bc0SZev Weiss 	return show_pwm_temp_sel_common(data, buf,
2701*c3963bc0SZev Weiss 					data->pwm_weight_temp_sel[index]);
2702*c3963bc0SZev Weiss }
2703*c3963bc0SZev Weiss 
2704*c3963bc0SZev Weiss static ssize_t
2705*c3963bc0SZev Weiss store_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr,
2706*c3963bc0SZev Weiss 			  const char *buf, size_t count)
2707*c3963bc0SZev Weiss {
2708*c3963bc0SZev Weiss 	struct nct6775_data *data = nct6775_update_device(dev);
2709*c3963bc0SZev Weiss 	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2710*c3963bc0SZev Weiss 	int nr = sattr->index;
2711*c3963bc0SZev Weiss 	unsigned long val;
2712*c3963bc0SZev Weiss 	int err, src;
2713*c3963bc0SZev Weiss 	u16 reg;
2714*c3963bc0SZev Weiss 
2715*c3963bc0SZev Weiss 	if (IS_ERR(data))
2716*c3963bc0SZev Weiss 		return PTR_ERR(data);
2717*c3963bc0SZev Weiss 
2718*c3963bc0SZev Weiss 	err = kstrtoul(buf, 10, &val);
2719*c3963bc0SZev Weiss 	if (err < 0)
2720*c3963bc0SZev Weiss 		return err;
2721*c3963bc0SZev Weiss 	if (val > NUM_TEMP)
2722*c3963bc0SZev Weiss 		return -EINVAL;
2723*c3963bc0SZev Weiss 	val = array_index_nospec(val, NUM_TEMP + 1);
2724*c3963bc0SZev Weiss 	if (val && (!(data->have_temp & BIT(val - 1)) ||
2725*c3963bc0SZev Weiss 		    !data->temp_src[val - 1]))
2726*c3963bc0SZev Weiss 		return -EINVAL;
2727*c3963bc0SZev Weiss 
2728*c3963bc0SZev Weiss 	mutex_lock(&data->update_lock);
2729*c3963bc0SZev Weiss 	if (val) {
2730*c3963bc0SZev Weiss 		src = data->temp_src[val - 1];
2731*c3963bc0SZev Weiss 		data->pwm_weight_temp_sel[nr] = src;
2732*c3963bc0SZev Weiss 		err = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr], &reg);
2733*c3963bc0SZev Weiss 		if (err)
2734*c3963bc0SZev Weiss 			goto out;
2735*c3963bc0SZev Weiss 		reg &= 0xe0;
2736*c3963bc0SZev Weiss 		reg |= (src | 0x80);
2737*c3963bc0SZev Weiss 		err = nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg);
2738*c3963bc0SZev Weiss 	} else {
2739*c3963bc0SZev Weiss 		data->pwm_weight_temp_sel[nr] = 0;
2740*c3963bc0SZev Weiss 		err = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr], &reg);
2741*c3963bc0SZev Weiss 		if (err)
2742*c3963bc0SZev Weiss 			goto out;
2743*c3963bc0SZev Weiss 		reg &= 0x7f;
2744*c3963bc0SZev Weiss 		err = nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg);
2745*c3963bc0SZev Weiss 	}
2746*c3963bc0SZev Weiss out:
2747*c3963bc0SZev Weiss 	mutex_unlock(&data->update_lock);
2748*c3963bc0SZev Weiss 
2749*c3963bc0SZev Weiss 	return err ? : count;
2750*c3963bc0SZev Weiss }
2751*c3963bc0SZev Weiss 
2752*c3963bc0SZev Weiss static ssize_t
2753*c3963bc0SZev Weiss show_target_temp(struct device *dev, struct device_attribute *attr, char *buf)
2754*c3963bc0SZev Weiss {
2755*c3963bc0SZev Weiss 	struct nct6775_data *data = nct6775_update_device(dev);
2756*c3963bc0SZev Weiss 	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2757*c3963bc0SZev Weiss 
2758*c3963bc0SZev Weiss 	if (IS_ERR(data))
2759*c3963bc0SZev Weiss 		return PTR_ERR(data);
2760*c3963bc0SZev Weiss 
2761*c3963bc0SZev Weiss 	return sprintf(buf, "%d\n", data->target_temp[sattr->index] * 1000);
2762*c3963bc0SZev Weiss }
2763*c3963bc0SZev Weiss 
2764*c3963bc0SZev Weiss static ssize_t
2765*c3963bc0SZev Weiss store_target_temp(struct device *dev, struct device_attribute *attr,
2766*c3963bc0SZev Weiss 		  const char *buf, size_t count)
2767*c3963bc0SZev Weiss {
2768*c3963bc0SZev Weiss 	struct nct6775_data *data = dev_get_drvdata(dev);
2769*c3963bc0SZev Weiss 	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2770*c3963bc0SZev Weiss 	int nr = sattr->index;
2771*c3963bc0SZev Weiss 	unsigned long val;
2772*c3963bc0SZev Weiss 	int err;
2773*c3963bc0SZev Weiss 
2774*c3963bc0SZev Weiss 	err = kstrtoul(buf, 10, &val);
2775*c3963bc0SZev Weiss 	if (err < 0)
2776*c3963bc0SZev Weiss 		return err;
2777*c3963bc0SZev Weiss 
2778*c3963bc0SZev Weiss 	val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0,
2779*c3963bc0SZev Weiss 			data->target_temp_mask);
2780*c3963bc0SZev Weiss 
2781*c3963bc0SZev Weiss 	mutex_lock(&data->update_lock);
2782*c3963bc0SZev Weiss 	data->target_temp[nr] = val;
2783*c3963bc0SZev Weiss 	err = pwm_update_registers(data, nr);
2784*c3963bc0SZev Weiss 	mutex_unlock(&data->update_lock);
2785*c3963bc0SZev Weiss 	return err ? : count;
2786*c3963bc0SZev Weiss }
2787*c3963bc0SZev Weiss 
2788*c3963bc0SZev Weiss static ssize_t
2789*c3963bc0SZev Weiss show_target_speed(struct device *dev, struct device_attribute *attr, char *buf)
2790*c3963bc0SZev Weiss {
2791*c3963bc0SZev Weiss 	struct nct6775_data *data = nct6775_update_device(dev);
2792*c3963bc0SZev Weiss 	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2793*c3963bc0SZev Weiss 	int nr = sattr->index;
2794*c3963bc0SZev Weiss 
2795*c3963bc0SZev Weiss 	if (IS_ERR(data))
2796*c3963bc0SZev Weiss 		return PTR_ERR(data);
2797*c3963bc0SZev Weiss 
2798*c3963bc0SZev Weiss 	return sprintf(buf, "%d\n",
2799*c3963bc0SZev Weiss 		       fan_from_reg16(data->target_speed[nr],
2800*c3963bc0SZev Weiss 				      data->fan_div[nr]));
2801*c3963bc0SZev Weiss }
2802*c3963bc0SZev Weiss 
2803*c3963bc0SZev Weiss static ssize_t
2804*c3963bc0SZev Weiss store_target_speed(struct device *dev, struct device_attribute *attr,
2805*c3963bc0SZev Weiss 		   const char *buf, size_t count)
2806*c3963bc0SZev Weiss {
2807*c3963bc0SZev Weiss 	struct nct6775_data *data = dev_get_drvdata(dev);
2808*c3963bc0SZev Weiss 	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2809*c3963bc0SZev Weiss 	int nr = sattr->index;
2810*c3963bc0SZev Weiss 	unsigned long val;
2811*c3963bc0SZev Weiss 	int err;
2812*c3963bc0SZev Weiss 	u16 speed;
2813*c3963bc0SZev Weiss 
2814*c3963bc0SZev Weiss 	err = kstrtoul(buf, 10, &val);
2815*c3963bc0SZev Weiss 	if (err < 0)
2816*c3963bc0SZev Weiss 		return err;
2817*c3963bc0SZev Weiss 
2818*c3963bc0SZev Weiss 	val = clamp_val(val, 0, 1350000U);
2819*c3963bc0SZev Weiss 	speed = fan_to_reg(val, data->fan_div[nr]);
2820*c3963bc0SZev Weiss 
2821*c3963bc0SZev Weiss 	mutex_lock(&data->update_lock);
2822*c3963bc0SZev Weiss 	data->target_speed[nr] = speed;
2823*c3963bc0SZev Weiss 	err = pwm_update_registers(data, nr);
2824*c3963bc0SZev Weiss 	mutex_unlock(&data->update_lock);
2825*c3963bc0SZev Weiss 	return err ? : count;
2826*c3963bc0SZev Weiss }
2827*c3963bc0SZev Weiss 
2828*c3963bc0SZev Weiss static ssize_t
2829*c3963bc0SZev Weiss show_temp_tolerance(struct device *dev, struct device_attribute *attr,
2830*c3963bc0SZev Weiss 		    char *buf)
2831*c3963bc0SZev Weiss {
2832*c3963bc0SZev Weiss 	struct nct6775_data *data = nct6775_update_device(dev);
2833*c3963bc0SZev Weiss 	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2834*c3963bc0SZev Weiss 	int nr = sattr->nr;
2835*c3963bc0SZev Weiss 	int index = sattr->index;
2836*c3963bc0SZev Weiss 
2837*c3963bc0SZev Weiss 	if (IS_ERR(data))
2838*c3963bc0SZev Weiss 		return PTR_ERR(data);
2839*c3963bc0SZev Weiss 
2840*c3963bc0SZev Weiss 	return sprintf(buf, "%d\n", data->temp_tolerance[index][nr] * 1000);
2841*c3963bc0SZev Weiss }
2842*c3963bc0SZev Weiss 
2843*c3963bc0SZev Weiss static ssize_t
2844*c3963bc0SZev Weiss store_temp_tolerance(struct device *dev, struct device_attribute *attr,
2845*c3963bc0SZev Weiss 		     const char *buf, size_t count)
2846*c3963bc0SZev Weiss {
2847*c3963bc0SZev Weiss 	struct nct6775_data *data = dev_get_drvdata(dev);
2848*c3963bc0SZev Weiss 	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2849*c3963bc0SZev Weiss 	int nr = sattr->nr;
2850*c3963bc0SZev Weiss 	int index = sattr->index;
2851*c3963bc0SZev Weiss 	unsigned long val;
2852*c3963bc0SZev Weiss 	int err;
2853*c3963bc0SZev Weiss 
2854*c3963bc0SZev Weiss 	err = kstrtoul(buf, 10, &val);
2855*c3963bc0SZev Weiss 	if (err < 0)
2856*c3963bc0SZev Weiss 		return err;
2857*c3963bc0SZev Weiss 
2858*c3963bc0SZev Weiss 	/* Limit tolerance as needed */
2859*c3963bc0SZev Weiss 	val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, data->tolerance_mask);
2860*c3963bc0SZev Weiss 
2861*c3963bc0SZev Weiss 	mutex_lock(&data->update_lock);
2862*c3963bc0SZev Weiss 	data->temp_tolerance[index][nr] = val;
2863*c3963bc0SZev Weiss 	if (index)
2864*c3963bc0SZev Weiss 		err = pwm_update_registers(data, nr);
2865*c3963bc0SZev Weiss 	else
2866*c3963bc0SZev Weiss 		err = nct6775_write_value(data, data->REG_CRITICAL_TEMP_TOLERANCE[nr], val);
2867*c3963bc0SZev Weiss 	mutex_unlock(&data->update_lock);
2868*c3963bc0SZev Weiss 	return err ? : count;
2869*c3963bc0SZev Weiss }
2870*c3963bc0SZev Weiss 
2871*c3963bc0SZev Weiss /*
2872*c3963bc0SZev Weiss  * Fan speed tolerance is a tricky beast, since the associated register is
2873*c3963bc0SZev Weiss  * a tick counter, but the value is reported and configured as rpm.
2874*c3963bc0SZev Weiss  * Compute resulting low and high rpm values and report the difference.
2875*c3963bc0SZev Weiss  * A fan speed tolerance only makes sense if a fan target speed has been
2876*c3963bc0SZev Weiss  * configured, so only display values other than 0 if that is the case.
2877*c3963bc0SZev Weiss  */
2878*c3963bc0SZev Weiss static ssize_t
2879*c3963bc0SZev Weiss show_speed_tolerance(struct device *dev, struct device_attribute *attr,
2880*c3963bc0SZev Weiss 		     char *buf)
2881*c3963bc0SZev Weiss {
2882*c3963bc0SZev Weiss 	struct nct6775_data *data = nct6775_update_device(dev);
2883*c3963bc0SZev Weiss 	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2884*c3963bc0SZev Weiss 	int nr = sattr->index;
2885*c3963bc0SZev Weiss 	int target, tolerance = 0;
2886*c3963bc0SZev Weiss 
2887*c3963bc0SZev Weiss 	if (IS_ERR(data))
2888*c3963bc0SZev Weiss 		return PTR_ERR(data);
2889*c3963bc0SZev Weiss 
2890*c3963bc0SZev Weiss 	target = data->target_speed[nr];
2891*c3963bc0SZev Weiss 
2892*c3963bc0SZev Weiss 	if (target) {
2893*c3963bc0SZev Weiss 		int low = target - data->target_speed_tolerance[nr];
2894*c3963bc0SZev Weiss 		int high = target + data->target_speed_tolerance[nr];
2895*c3963bc0SZev Weiss 
2896*c3963bc0SZev Weiss 		if (low <= 0)
2897*c3963bc0SZev Weiss 			low = 1;
2898*c3963bc0SZev Weiss 		if (high > 0xffff)
2899*c3963bc0SZev Weiss 			high = 0xffff;
2900*c3963bc0SZev Weiss 		if (high < low)
2901*c3963bc0SZev Weiss 			high = low;
2902*c3963bc0SZev Weiss 
2903*c3963bc0SZev Weiss 		tolerance = (fan_from_reg16(low, data->fan_div[nr])
2904*c3963bc0SZev Weiss 			     - fan_from_reg16(high, data->fan_div[nr])) / 2;
2905*c3963bc0SZev Weiss 	}
2906*c3963bc0SZev Weiss 
2907*c3963bc0SZev Weiss 	return sprintf(buf, "%d\n", tolerance);
2908*c3963bc0SZev Weiss }
2909*c3963bc0SZev Weiss 
2910*c3963bc0SZev Weiss static ssize_t
2911*c3963bc0SZev Weiss store_speed_tolerance(struct device *dev, struct device_attribute *attr,
2912*c3963bc0SZev Weiss 		      const char *buf, size_t count)
2913*c3963bc0SZev Weiss {
2914*c3963bc0SZev Weiss 	struct nct6775_data *data = dev_get_drvdata(dev);
2915*c3963bc0SZev Weiss 	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2916*c3963bc0SZev Weiss 	int nr = sattr->index;
2917*c3963bc0SZev Weiss 	unsigned long val;
2918*c3963bc0SZev Weiss 	int err;
2919*c3963bc0SZev Weiss 	int low, high;
2920*c3963bc0SZev Weiss 
2921*c3963bc0SZev Weiss 	err = kstrtoul(buf, 10, &val);
2922*c3963bc0SZev Weiss 	if (err < 0)
2923*c3963bc0SZev Weiss 		return err;
2924*c3963bc0SZev Weiss 
2925*c3963bc0SZev Weiss 	high = fan_from_reg16(data->target_speed[nr], data->fan_div[nr]) + val;
2926*c3963bc0SZev Weiss 	low = fan_from_reg16(data->target_speed[nr], data->fan_div[nr]) - val;
2927*c3963bc0SZev Weiss 	if (low <= 0)
2928*c3963bc0SZev Weiss 		low = 1;
2929*c3963bc0SZev Weiss 	if (high < low)
2930*c3963bc0SZev Weiss 		high = low;
2931*c3963bc0SZev Weiss 
2932*c3963bc0SZev Weiss 	val = (fan_to_reg(low, data->fan_div[nr]) -
2933*c3963bc0SZev Weiss 	       fan_to_reg(high, data->fan_div[nr])) / 2;
2934*c3963bc0SZev Weiss 
2935*c3963bc0SZev Weiss 	/* Limit tolerance as needed */
2936*c3963bc0SZev Weiss 	val = clamp_val(val, 0, data->speed_tolerance_limit);
2937*c3963bc0SZev Weiss 
2938*c3963bc0SZev Weiss 	mutex_lock(&data->update_lock);
2939*c3963bc0SZev Weiss 	data->target_speed_tolerance[nr] = val;
2940*c3963bc0SZev Weiss 	err = pwm_update_registers(data, nr);
2941*c3963bc0SZev Weiss 	mutex_unlock(&data->update_lock);
2942*c3963bc0SZev Weiss 	return err ? : count;
2943*c3963bc0SZev Weiss }
2944*c3963bc0SZev Weiss 
2945*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(pwm, "pwm%d", 0644, show_pwm, store_pwm, 0, 0);
2946*c3963bc0SZev Weiss SENSOR_TEMPLATE(pwm_mode, "pwm%d_mode", 0644, show_pwm_mode, store_pwm_mode, 0);
2947*c3963bc0SZev Weiss SENSOR_TEMPLATE(pwm_enable, "pwm%d_enable", 0644, show_pwm_enable, store_pwm_enable, 0);
2948*c3963bc0SZev Weiss SENSOR_TEMPLATE(pwm_temp_sel, "pwm%d_temp_sel", 0644, show_pwm_temp_sel, store_pwm_temp_sel, 0);
2949*c3963bc0SZev Weiss SENSOR_TEMPLATE(pwm_target_temp, "pwm%d_target_temp", 0644, show_target_temp, store_target_temp, 0);
2950*c3963bc0SZev Weiss SENSOR_TEMPLATE(fan_target, "fan%d_target", 0644, show_target_speed, store_target_speed, 0);
2951*c3963bc0SZev Weiss SENSOR_TEMPLATE(fan_tolerance, "fan%d_tolerance", 0644, show_speed_tolerance,
2952*c3963bc0SZev Weiss 		store_speed_tolerance, 0);
2953*c3963bc0SZev Weiss 
2954*c3963bc0SZev Weiss /* Smart Fan registers */
2955*c3963bc0SZev Weiss 
2956*c3963bc0SZev Weiss static ssize_t
2957*c3963bc0SZev Weiss show_weight_temp(struct device *dev, struct device_attribute *attr, char *buf)
2958*c3963bc0SZev Weiss {
2959*c3963bc0SZev Weiss 	struct nct6775_data *data = nct6775_update_device(dev);
2960*c3963bc0SZev Weiss 	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2961*c3963bc0SZev Weiss 	int nr = sattr->nr;
2962*c3963bc0SZev Weiss 	int index = sattr->index;
2963*c3963bc0SZev Weiss 
2964*c3963bc0SZev Weiss 	if (IS_ERR(data))
2965*c3963bc0SZev Weiss 		return PTR_ERR(data);
2966*c3963bc0SZev Weiss 
2967*c3963bc0SZev Weiss 	return sprintf(buf, "%d\n", data->weight_temp[index][nr] * 1000);
2968*c3963bc0SZev Weiss }
2969*c3963bc0SZev Weiss 
2970*c3963bc0SZev Weiss static ssize_t
2971*c3963bc0SZev Weiss store_weight_temp(struct device *dev, struct device_attribute *attr,
2972*c3963bc0SZev Weiss 		  const char *buf, size_t count)
2973*c3963bc0SZev Weiss {
2974*c3963bc0SZev Weiss 	struct nct6775_data *data = dev_get_drvdata(dev);
2975*c3963bc0SZev Weiss 	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2976*c3963bc0SZev Weiss 	int nr = sattr->nr;
2977*c3963bc0SZev Weiss 	int index = sattr->index;
2978*c3963bc0SZev Weiss 	unsigned long val;
2979*c3963bc0SZev Weiss 	int err;
2980*c3963bc0SZev Weiss 
2981*c3963bc0SZev Weiss 	err = kstrtoul(buf, 10, &val);
2982*c3963bc0SZev Weiss 	if (err < 0)
2983*c3963bc0SZev Weiss 		return err;
2984*c3963bc0SZev Weiss 
2985*c3963bc0SZev Weiss 	val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, 255);
2986*c3963bc0SZev Weiss 
2987*c3963bc0SZev Weiss 	mutex_lock(&data->update_lock);
2988*c3963bc0SZev Weiss 	data->weight_temp[index][nr] = val;
2989*c3963bc0SZev Weiss 	err = nct6775_write_value(data, data->REG_WEIGHT_TEMP[index][nr], val);
2990*c3963bc0SZev Weiss 	mutex_unlock(&data->update_lock);
2991*c3963bc0SZev Weiss 	return err ? : count;
2992*c3963bc0SZev Weiss }
2993*c3963bc0SZev Weiss 
2994*c3963bc0SZev Weiss SENSOR_TEMPLATE(pwm_weight_temp_sel, "pwm%d_weight_temp_sel", 0644,
2995*c3963bc0SZev Weiss 		show_pwm_weight_temp_sel, store_pwm_weight_temp_sel, 0);
2996*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(pwm_weight_temp_step, "pwm%d_weight_temp_step",
2997*c3963bc0SZev Weiss 		  0644, show_weight_temp, store_weight_temp, 0, 0);
2998*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(pwm_weight_temp_step_tol, "pwm%d_weight_temp_step_tol",
2999*c3963bc0SZev Weiss 		  0644, show_weight_temp, store_weight_temp, 0, 1);
3000*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(pwm_weight_temp_step_base, "pwm%d_weight_temp_step_base",
3001*c3963bc0SZev Weiss 		  0644, show_weight_temp, store_weight_temp, 0, 2);
3002*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(pwm_weight_duty_step, "pwm%d_weight_duty_step", 0644, show_pwm, store_pwm, 0, 5);
3003*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(pwm_weight_duty_base, "pwm%d_weight_duty_base", 0644, show_pwm, store_pwm, 0, 6);
3004*c3963bc0SZev Weiss 
3005*c3963bc0SZev Weiss static ssize_t
3006*c3963bc0SZev Weiss show_fan_time(struct device *dev, struct device_attribute *attr, char *buf)
3007*c3963bc0SZev Weiss {
3008*c3963bc0SZev Weiss 	struct nct6775_data *data = nct6775_update_device(dev);
3009*c3963bc0SZev Weiss 	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
3010*c3963bc0SZev Weiss 	int nr = sattr->nr;
3011*c3963bc0SZev Weiss 	int index = sattr->index;
3012*c3963bc0SZev Weiss 
3013*c3963bc0SZev Weiss 	if (IS_ERR(data))
3014*c3963bc0SZev Weiss 		return PTR_ERR(data);
3015*c3963bc0SZev Weiss 
3016*c3963bc0SZev Weiss 	return sprintf(buf, "%d\n",
3017*c3963bc0SZev Weiss 		       step_time_from_reg(data->fan_time[index][nr],
3018*c3963bc0SZev Weiss 					  data->pwm_mode[nr]));
3019*c3963bc0SZev Weiss }
3020*c3963bc0SZev Weiss 
3021*c3963bc0SZev Weiss static ssize_t
3022*c3963bc0SZev Weiss store_fan_time(struct device *dev, struct device_attribute *attr,
3023*c3963bc0SZev Weiss 	       const char *buf, size_t count)
3024*c3963bc0SZev Weiss {
3025*c3963bc0SZev Weiss 	struct nct6775_data *data = dev_get_drvdata(dev);
3026*c3963bc0SZev Weiss 	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
3027*c3963bc0SZev Weiss 	int nr = sattr->nr;
3028*c3963bc0SZev Weiss 	int index = sattr->index;
3029*c3963bc0SZev Weiss 	unsigned long val;
3030*c3963bc0SZev Weiss 	int err;
3031*c3963bc0SZev Weiss 
3032*c3963bc0SZev Weiss 	err = kstrtoul(buf, 10, &val);
3033*c3963bc0SZev Weiss 	if (err < 0)
3034*c3963bc0SZev Weiss 		return err;
3035*c3963bc0SZev Weiss 
3036*c3963bc0SZev Weiss 	val = step_time_to_reg(val, data->pwm_mode[nr]);
3037*c3963bc0SZev Weiss 	mutex_lock(&data->update_lock);
3038*c3963bc0SZev Weiss 	data->fan_time[index][nr] = val;
3039*c3963bc0SZev Weiss 	err = nct6775_write_value(data, data->REG_FAN_TIME[index][nr], val);
3040*c3963bc0SZev Weiss 	mutex_unlock(&data->update_lock);
3041*c3963bc0SZev Weiss 	return err ? : count;
3042*c3963bc0SZev Weiss }
3043*c3963bc0SZev Weiss 
3044*c3963bc0SZev Weiss static ssize_t
3045*c3963bc0SZev Weiss show_auto_pwm(struct device *dev, struct device_attribute *attr, char *buf)
3046*c3963bc0SZev Weiss {
3047*c3963bc0SZev Weiss 	struct nct6775_data *data = nct6775_update_device(dev);
3048*c3963bc0SZev Weiss 	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
3049*c3963bc0SZev Weiss 
3050*c3963bc0SZev Weiss 	if (IS_ERR(data))
3051*c3963bc0SZev Weiss 		return PTR_ERR(data);
3052*c3963bc0SZev Weiss 
3053*c3963bc0SZev Weiss 	return sprintf(buf, "%d\n", data->auto_pwm[sattr->nr][sattr->index]);
3054*c3963bc0SZev Weiss }
3055*c3963bc0SZev Weiss 
3056*c3963bc0SZev Weiss static ssize_t
3057*c3963bc0SZev Weiss store_auto_pwm(struct device *dev, struct device_attribute *attr,
3058*c3963bc0SZev Weiss 	       const char *buf, size_t count)
3059*c3963bc0SZev Weiss {
3060*c3963bc0SZev Weiss 	struct nct6775_data *data = dev_get_drvdata(dev);
3061*c3963bc0SZev Weiss 	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
3062*c3963bc0SZev Weiss 	int nr = sattr->nr;
3063*c3963bc0SZev Weiss 	int point = sattr->index;
3064*c3963bc0SZev Weiss 	unsigned long val;
3065*c3963bc0SZev Weiss 	int err;
3066*c3963bc0SZev Weiss 	u16 reg;
3067*c3963bc0SZev Weiss 
3068*c3963bc0SZev Weiss 	err = kstrtoul(buf, 10, &val);
3069*c3963bc0SZev Weiss 	if (err < 0)
3070*c3963bc0SZev Weiss 		return err;
3071*c3963bc0SZev Weiss 	if (val > 255)
3072*c3963bc0SZev Weiss 		return -EINVAL;
3073*c3963bc0SZev Weiss 
3074*c3963bc0SZev Weiss 	if (point == data->auto_pwm_num) {
3075*c3963bc0SZev Weiss 		if (data->kind != nct6775 && !val)
3076*c3963bc0SZev Weiss 			return -EINVAL;
3077*c3963bc0SZev Weiss 		if (data->kind != nct6779 && val)
3078*c3963bc0SZev Weiss 			val = 0xff;
3079*c3963bc0SZev Weiss 	}
3080*c3963bc0SZev Weiss 
3081*c3963bc0SZev Weiss 	mutex_lock(&data->update_lock);
3082*c3963bc0SZev Weiss 	data->auto_pwm[nr][point] = val;
3083*c3963bc0SZev Weiss 	if (point < data->auto_pwm_num) {
3084*c3963bc0SZev Weiss 		err = nct6775_write_value(data, NCT6775_AUTO_PWM(data, nr, point),
3085*c3963bc0SZev Weiss 					  data->auto_pwm[nr][point]);
3086*c3963bc0SZev Weiss 	} else {
3087*c3963bc0SZev Weiss 		switch (data->kind) {
3088*c3963bc0SZev Weiss 		case nct6775:
3089*c3963bc0SZev Weiss 			/* disable if needed (pwm == 0) */
3090*c3963bc0SZev Weiss 			err = nct6775_read_value(data, NCT6775_REG_CRITICAL_ENAB[nr], &reg);
3091*c3963bc0SZev Weiss 			if (err)
3092*c3963bc0SZev Weiss 				break;
3093*c3963bc0SZev Weiss 			if (val)
3094*c3963bc0SZev Weiss 				reg |= 0x02;
3095*c3963bc0SZev Weiss 			else
3096*c3963bc0SZev Weiss 				reg &= ~0x02;
3097*c3963bc0SZev Weiss 			err = nct6775_write_value(data, NCT6775_REG_CRITICAL_ENAB[nr], reg);
3098*c3963bc0SZev Weiss 			break;
3099*c3963bc0SZev Weiss 		case nct6776:
3100*c3963bc0SZev Weiss 			break; /* always enabled, nothing to do */
3101*c3963bc0SZev Weiss 		case nct6106:
3102*c3963bc0SZev Weiss 		case nct6116:
3103*c3963bc0SZev Weiss 		case nct6779:
3104*c3963bc0SZev Weiss 		case nct6791:
3105*c3963bc0SZev Weiss 		case nct6792:
3106*c3963bc0SZev Weiss 		case nct6793:
3107*c3963bc0SZev Weiss 		case nct6795:
3108*c3963bc0SZev Weiss 		case nct6796:
3109*c3963bc0SZev Weiss 		case nct6797:
3110*c3963bc0SZev Weiss 		case nct6798:
3111*c3963bc0SZev Weiss 			err = nct6775_write_value(data, data->REG_CRITICAL_PWM[nr], val);
3112*c3963bc0SZev Weiss 			if (err)
3113*c3963bc0SZev Weiss 				break;
3114*c3963bc0SZev Weiss 			err = nct6775_read_value(data, data->REG_CRITICAL_PWM_ENABLE[nr], &reg);
3115*c3963bc0SZev Weiss 			if (err)
3116*c3963bc0SZev Weiss 				break;
3117*c3963bc0SZev Weiss 			if (val == 255)
3118*c3963bc0SZev Weiss 				reg &= ~data->CRITICAL_PWM_ENABLE_MASK;
3119*c3963bc0SZev Weiss 			else
3120*c3963bc0SZev Weiss 				reg |= data->CRITICAL_PWM_ENABLE_MASK;
3121*c3963bc0SZev Weiss 			err = nct6775_write_value(data, data->REG_CRITICAL_PWM_ENABLE[nr], reg);
3122*c3963bc0SZev Weiss 			break;
3123*c3963bc0SZev Weiss 		}
3124*c3963bc0SZev Weiss 	}
3125*c3963bc0SZev Weiss 	mutex_unlock(&data->update_lock);
3126*c3963bc0SZev Weiss 	return err ? : count;
3127*c3963bc0SZev Weiss }
3128*c3963bc0SZev Weiss 
3129*c3963bc0SZev Weiss static ssize_t
3130*c3963bc0SZev Weiss show_auto_temp(struct device *dev, struct device_attribute *attr, char *buf)
3131*c3963bc0SZev Weiss {
3132*c3963bc0SZev Weiss 	struct nct6775_data *data = nct6775_update_device(dev);
3133*c3963bc0SZev Weiss 	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
3134*c3963bc0SZev Weiss 	int nr = sattr->nr;
3135*c3963bc0SZev Weiss 	int point = sattr->index;
3136*c3963bc0SZev Weiss 
3137*c3963bc0SZev Weiss 	if (IS_ERR(data))
3138*c3963bc0SZev Weiss 		return PTR_ERR(data);
3139*c3963bc0SZev Weiss 
3140*c3963bc0SZev Weiss 	/*
3141*c3963bc0SZev Weiss 	 * We don't know for sure if the temperature is signed or unsigned.
3142*c3963bc0SZev Weiss 	 * Assume it is unsigned.
3143*c3963bc0SZev Weiss 	 */
3144*c3963bc0SZev Weiss 	return sprintf(buf, "%d\n", data->auto_temp[nr][point] * 1000);
3145*c3963bc0SZev Weiss }
3146*c3963bc0SZev Weiss 
3147*c3963bc0SZev Weiss static ssize_t
3148*c3963bc0SZev Weiss store_auto_temp(struct device *dev, struct device_attribute *attr,
3149*c3963bc0SZev Weiss 		const char *buf, size_t count)
3150*c3963bc0SZev Weiss {
3151*c3963bc0SZev Weiss 	struct nct6775_data *data = dev_get_drvdata(dev);
3152*c3963bc0SZev Weiss 	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
3153*c3963bc0SZev Weiss 	int nr = sattr->nr;
3154*c3963bc0SZev Weiss 	int point = sattr->index;
3155*c3963bc0SZev Weiss 	unsigned long val;
3156*c3963bc0SZev Weiss 	int err;
3157*c3963bc0SZev Weiss 
3158*c3963bc0SZev Weiss 	err = kstrtoul(buf, 10, &val);
3159*c3963bc0SZev Weiss 	if (err)
3160*c3963bc0SZev Weiss 		return err;
3161*c3963bc0SZev Weiss 	if (val > 255000)
3162*c3963bc0SZev Weiss 		return -EINVAL;
3163*c3963bc0SZev Weiss 
3164*c3963bc0SZev Weiss 	mutex_lock(&data->update_lock);
3165*c3963bc0SZev Weiss 	data->auto_temp[nr][point] = DIV_ROUND_CLOSEST(val, 1000);
3166*c3963bc0SZev Weiss 	if (point < data->auto_pwm_num) {
3167*c3963bc0SZev Weiss 		err = nct6775_write_value(data, NCT6775_AUTO_TEMP(data, nr, point),
3168*c3963bc0SZev Weiss 					  data->auto_temp[nr][point]);
3169*c3963bc0SZev Weiss 	} else {
3170*c3963bc0SZev Weiss 		err = nct6775_write_value(data, data->REG_CRITICAL_TEMP[nr],
3171*c3963bc0SZev Weiss 					  data->auto_temp[nr][point]);
3172*c3963bc0SZev Weiss 	}
3173*c3963bc0SZev Weiss 	mutex_unlock(&data->update_lock);
3174*c3963bc0SZev Weiss 	return err ? : count;
3175*c3963bc0SZev Weiss }
3176*c3963bc0SZev Weiss 
3177*c3963bc0SZev Weiss static umode_t nct6775_pwm_is_visible(struct kobject *kobj,
3178*c3963bc0SZev Weiss 				      struct attribute *attr, int index)
3179*c3963bc0SZev Weiss {
3180*c3963bc0SZev Weiss 	struct device *dev = kobj_to_dev(kobj);
3181*c3963bc0SZev Weiss 	struct nct6775_data *data = dev_get_drvdata(dev);
3182*c3963bc0SZev Weiss 	int pwm = index / 36;	/* pwm index */
3183*c3963bc0SZev Weiss 	int nr = index % 36;	/* attribute index */
3184*c3963bc0SZev Weiss 
3185*c3963bc0SZev Weiss 	if (!(data->has_pwm & BIT(pwm)))
3186*c3963bc0SZev Weiss 		return 0;
3187*c3963bc0SZev Weiss 
3188*c3963bc0SZev Weiss 	if ((nr >= 14 && nr <= 18) || nr == 21)   /* weight */
3189*c3963bc0SZev Weiss 		if (!data->REG_WEIGHT_TEMP_SEL[pwm])
3190*c3963bc0SZev Weiss 			return 0;
3191*c3963bc0SZev Weiss 	if (nr == 19 && data->REG_PWM[3] == NULL) /* pwm_max */
3192*c3963bc0SZev Weiss 		return 0;
3193*c3963bc0SZev Weiss 	if (nr == 20 && data->REG_PWM[4] == NULL) /* pwm_step */
3194*c3963bc0SZev Weiss 		return 0;
3195*c3963bc0SZev Weiss 	if (nr == 21 && data->REG_PWM[6] == NULL) /* weight_duty_base */
3196*c3963bc0SZev Weiss 		return 0;
3197*c3963bc0SZev Weiss 
3198*c3963bc0SZev Weiss 	if (nr >= 22 && nr <= 35) {		/* auto point */
3199*c3963bc0SZev Weiss 		int api = (nr - 22) / 2;	/* auto point index */
3200*c3963bc0SZev Weiss 
3201*c3963bc0SZev Weiss 		if (api > data->auto_pwm_num)
3202*c3963bc0SZev Weiss 			return 0;
3203*c3963bc0SZev Weiss 	}
3204*c3963bc0SZev Weiss 	return nct6775_attr_mode(data, attr);
3205*c3963bc0SZev Weiss }
3206*c3963bc0SZev Weiss 
3207*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(pwm_stop_time, "pwm%d_stop_time", 0644, show_fan_time, store_fan_time, 0, 0);
3208*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(pwm_step_up_time, "pwm%d_step_up_time", 0644,
3209*c3963bc0SZev Weiss 		  show_fan_time, store_fan_time, 0, 1);
3210*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(pwm_step_down_time, "pwm%d_step_down_time", 0644,
3211*c3963bc0SZev Weiss 		  show_fan_time, store_fan_time, 0, 2);
3212*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(pwm_start, "pwm%d_start", 0644, show_pwm, store_pwm, 0, 1);
3213*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(pwm_floor, "pwm%d_floor", 0644, show_pwm, store_pwm, 0, 2);
3214*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(pwm_temp_tolerance, "pwm%d_temp_tolerance", 0644,
3215*c3963bc0SZev Weiss 		  show_temp_tolerance, store_temp_tolerance, 0, 0);
3216*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(pwm_crit_temp_tolerance, "pwm%d_crit_temp_tolerance",
3217*c3963bc0SZev Weiss 		  0644, show_temp_tolerance, store_temp_tolerance, 0, 1);
3218*c3963bc0SZev Weiss 
3219*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(pwm_max, "pwm%d_max", 0644, show_pwm, store_pwm, 0, 3);
3220*c3963bc0SZev Weiss 
3221*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(pwm_step, "pwm%d_step", 0644, show_pwm, store_pwm, 0, 4);
3222*c3963bc0SZev Weiss 
3223*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(pwm_auto_point1_pwm, "pwm%d_auto_point1_pwm",
3224*c3963bc0SZev Weiss 		  0644, show_auto_pwm, store_auto_pwm, 0, 0);
3225*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(pwm_auto_point1_temp, "pwm%d_auto_point1_temp",
3226*c3963bc0SZev Weiss 		  0644, show_auto_temp, store_auto_temp, 0, 0);
3227*c3963bc0SZev Weiss 
3228*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(pwm_auto_point2_pwm, "pwm%d_auto_point2_pwm",
3229*c3963bc0SZev Weiss 		  0644, show_auto_pwm, store_auto_pwm, 0, 1);
3230*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(pwm_auto_point2_temp, "pwm%d_auto_point2_temp",
3231*c3963bc0SZev Weiss 		  0644, show_auto_temp, store_auto_temp, 0, 1);
3232*c3963bc0SZev Weiss 
3233*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(pwm_auto_point3_pwm, "pwm%d_auto_point3_pwm",
3234*c3963bc0SZev Weiss 		  0644, show_auto_pwm, store_auto_pwm, 0, 2);
3235*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(pwm_auto_point3_temp, "pwm%d_auto_point3_temp",
3236*c3963bc0SZev Weiss 		  0644, show_auto_temp, store_auto_temp, 0, 2);
3237*c3963bc0SZev Weiss 
3238*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(pwm_auto_point4_pwm, "pwm%d_auto_point4_pwm",
3239*c3963bc0SZev Weiss 		  0644, show_auto_pwm, store_auto_pwm, 0, 3);
3240*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(pwm_auto_point4_temp, "pwm%d_auto_point4_temp",
3241*c3963bc0SZev Weiss 		  0644, show_auto_temp, store_auto_temp, 0, 3);
3242*c3963bc0SZev Weiss 
3243*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(pwm_auto_point5_pwm, "pwm%d_auto_point5_pwm",
3244*c3963bc0SZev Weiss 		  0644, show_auto_pwm, store_auto_pwm, 0, 4);
3245*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(pwm_auto_point5_temp, "pwm%d_auto_point5_temp",
3246*c3963bc0SZev Weiss 		  0644, show_auto_temp, store_auto_temp, 0, 4);
3247*c3963bc0SZev Weiss 
3248*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(pwm_auto_point6_pwm, "pwm%d_auto_point6_pwm",
3249*c3963bc0SZev Weiss 		  0644, show_auto_pwm, store_auto_pwm, 0, 5);
3250*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(pwm_auto_point6_temp, "pwm%d_auto_point6_temp",
3251*c3963bc0SZev Weiss 		  0644, show_auto_temp, store_auto_temp, 0, 5);
3252*c3963bc0SZev Weiss 
3253*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(pwm_auto_point7_pwm, "pwm%d_auto_point7_pwm",
3254*c3963bc0SZev Weiss 		  0644, show_auto_pwm, store_auto_pwm, 0, 6);
3255*c3963bc0SZev Weiss SENSOR_TEMPLATE_2(pwm_auto_point7_temp, "pwm%d_auto_point7_temp",
3256*c3963bc0SZev Weiss 		  0644, show_auto_temp, store_auto_temp, 0, 6);
3257*c3963bc0SZev Weiss 
3258*c3963bc0SZev Weiss /*
3259*c3963bc0SZev Weiss  * nct6775_pwm_is_visible uses the index into the following array
3260*c3963bc0SZev Weiss  * to determine if attributes should be created or not.
3261*c3963bc0SZev Weiss  * Any change in order or content must be matched.
3262*c3963bc0SZev Weiss  */
3263*c3963bc0SZev Weiss static struct sensor_device_template *nct6775_attributes_pwm_template[] = {
3264*c3963bc0SZev Weiss 	&sensor_dev_template_pwm,
3265*c3963bc0SZev Weiss 	&sensor_dev_template_pwm_mode,
3266*c3963bc0SZev Weiss 	&sensor_dev_template_pwm_enable,
3267*c3963bc0SZev Weiss 	&sensor_dev_template_pwm_temp_sel,
3268*c3963bc0SZev Weiss 	&sensor_dev_template_pwm_temp_tolerance,
3269*c3963bc0SZev Weiss 	&sensor_dev_template_pwm_crit_temp_tolerance,
3270*c3963bc0SZev Weiss 	&sensor_dev_template_pwm_target_temp,
3271*c3963bc0SZev Weiss 	&sensor_dev_template_fan_target,
3272*c3963bc0SZev Weiss 	&sensor_dev_template_fan_tolerance,
3273*c3963bc0SZev Weiss 	&sensor_dev_template_pwm_stop_time,
3274*c3963bc0SZev Weiss 	&sensor_dev_template_pwm_step_up_time,
3275*c3963bc0SZev Weiss 	&sensor_dev_template_pwm_step_down_time,
3276*c3963bc0SZev Weiss 	&sensor_dev_template_pwm_start,
3277*c3963bc0SZev Weiss 	&sensor_dev_template_pwm_floor,
3278*c3963bc0SZev Weiss 	&sensor_dev_template_pwm_weight_temp_sel,	/* 14 */
3279*c3963bc0SZev Weiss 	&sensor_dev_template_pwm_weight_temp_step,
3280*c3963bc0SZev Weiss 	&sensor_dev_template_pwm_weight_temp_step_tol,
3281*c3963bc0SZev Weiss 	&sensor_dev_template_pwm_weight_temp_step_base,
3282*c3963bc0SZev Weiss 	&sensor_dev_template_pwm_weight_duty_step,	/* 18 */
3283*c3963bc0SZev Weiss 	&sensor_dev_template_pwm_max,			/* 19 */
3284*c3963bc0SZev Weiss 	&sensor_dev_template_pwm_step,			/* 20 */
3285*c3963bc0SZev Weiss 	&sensor_dev_template_pwm_weight_duty_base,	/* 21 */
3286*c3963bc0SZev Weiss 	&sensor_dev_template_pwm_auto_point1_pwm,	/* 22 */
3287*c3963bc0SZev Weiss 	&sensor_dev_template_pwm_auto_point1_temp,
3288*c3963bc0SZev Weiss 	&sensor_dev_template_pwm_auto_point2_pwm,
3289*c3963bc0SZev Weiss 	&sensor_dev_template_pwm_auto_point2_temp,
3290*c3963bc0SZev Weiss 	&sensor_dev_template_pwm_auto_point3_pwm,
3291*c3963bc0SZev Weiss 	&sensor_dev_template_pwm_auto_point3_temp,
3292*c3963bc0SZev Weiss 	&sensor_dev_template_pwm_auto_point4_pwm,
3293*c3963bc0SZev Weiss 	&sensor_dev_template_pwm_auto_point4_temp,
3294*c3963bc0SZev Weiss 	&sensor_dev_template_pwm_auto_point5_pwm,
3295*c3963bc0SZev Weiss 	&sensor_dev_template_pwm_auto_point5_temp,
3296*c3963bc0SZev Weiss 	&sensor_dev_template_pwm_auto_point6_pwm,
3297*c3963bc0SZev Weiss 	&sensor_dev_template_pwm_auto_point6_temp,
3298*c3963bc0SZev Weiss 	&sensor_dev_template_pwm_auto_point7_pwm,
3299*c3963bc0SZev Weiss 	&sensor_dev_template_pwm_auto_point7_temp,	/* 35 */
3300*c3963bc0SZev Weiss 
3301*c3963bc0SZev Weiss 	NULL
3302*c3963bc0SZev Weiss };
3303*c3963bc0SZev Weiss 
3304*c3963bc0SZev Weiss static const struct sensor_template_group nct6775_pwm_template_group = {
3305*c3963bc0SZev Weiss 	.templates = nct6775_attributes_pwm_template,
3306*c3963bc0SZev Weiss 	.is_visible = nct6775_pwm_is_visible,
3307*c3963bc0SZev Weiss 	.base = 1,
3308*c3963bc0SZev Weiss };
3309*c3963bc0SZev Weiss 
3310*c3963bc0SZev Weiss static inline int nct6775_init_device(struct nct6775_data *data)
3311*c3963bc0SZev Weiss {
3312*c3963bc0SZev Weiss 	int i, err;
3313*c3963bc0SZev Weiss 	u16 tmp, diode;
3314*c3963bc0SZev Weiss 
3315*c3963bc0SZev Weiss 	/* Start monitoring if needed */
3316*c3963bc0SZev Weiss 	if (data->REG_CONFIG) {
3317*c3963bc0SZev Weiss 		err = nct6775_read_value(data, data->REG_CONFIG, &tmp);
3318*c3963bc0SZev Weiss 		if (err)
3319*c3963bc0SZev Weiss 			return err;
3320*c3963bc0SZev Weiss 		if (!(tmp & 0x01)) {
3321*c3963bc0SZev Weiss 			err = nct6775_write_value(data, data->REG_CONFIG, tmp | 0x01);
3322*c3963bc0SZev Weiss 			if (err)
3323*c3963bc0SZev Weiss 				return err;
3324*c3963bc0SZev Weiss 		}
3325*c3963bc0SZev Weiss 	}
3326*c3963bc0SZev Weiss 
3327*c3963bc0SZev Weiss 	/* Enable temperature sensors if needed */
3328*c3963bc0SZev Weiss 	for (i = 0; i < NUM_TEMP; i++) {
3329*c3963bc0SZev Weiss 		if (!(data->have_temp & BIT(i)))
3330*c3963bc0SZev Weiss 			continue;
3331*c3963bc0SZev Weiss 		if (!data->reg_temp_config[i])
3332*c3963bc0SZev Weiss 			continue;
3333*c3963bc0SZev Weiss 		err = nct6775_read_value(data, data->reg_temp_config[i], &tmp);
3334*c3963bc0SZev Weiss 		if (err)
3335*c3963bc0SZev Weiss 			return err;
3336*c3963bc0SZev Weiss 		if (tmp & 0x01) {
3337*c3963bc0SZev Weiss 			err = nct6775_write_value(data, data->reg_temp_config[i], tmp & 0xfe);
3338*c3963bc0SZev Weiss 			if (err)
3339*c3963bc0SZev Weiss 				return err;
3340*c3963bc0SZev Weiss 		}
3341*c3963bc0SZev Weiss 	}
3342*c3963bc0SZev Weiss 
3343*c3963bc0SZev Weiss 	/* Enable VBAT monitoring if needed */
3344*c3963bc0SZev Weiss 	err = nct6775_read_value(data, data->REG_VBAT, &tmp);
3345*c3963bc0SZev Weiss 	if (err)
3346*c3963bc0SZev Weiss 		return err;
3347*c3963bc0SZev Weiss 	if (!(tmp & 0x01)) {
3348*c3963bc0SZev Weiss 		err = nct6775_write_value(data, data->REG_VBAT, tmp | 0x01);
3349*c3963bc0SZev Weiss 		if (err)
3350*c3963bc0SZev Weiss 			return err;
3351*c3963bc0SZev Weiss 	}
3352*c3963bc0SZev Weiss 
3353*c3963bc0SZev Weiss 	err = nct6775_read_value(data, data->REG_DIODE, &diode);
3354*c3963bc0SZev Weiss 	if (err)
3355*c3963bc0SZev Weiss 		return err;
3356*c3963bc0SZev Weiss 
3357*c3963bc0SZev Weiss 	for (i = 0; i < data->temp_fixed_num; i++) {
3358*c3963bc0SZev Weiss 		if (!(data->have_temp_fixed & BIT(i)))
3359*c3963bc0SZev Weiss 			continue;
3360*c3963bc0SZev Weiss 		if ((tmp & (data->DIODE_MASK << i)))	/* diode */
3361*c3963bc0SZev Weiss 			data->temp_type[i]
3362*c3963bc0SZev Weiss 			  = 3 - ((diode >> i) & data->DIODE_MASK);
3363*c3963bc0SZev Weiss 		else				/* thermistor */
3364*c3963bc0SZev Weiss 			data->temp_type[i] = 4;
3365*c3963bc0SZev Weiss 	}
3366*c3963bc0SZev Weiss 
3367*c3963bc0SZev Weiss 	return 0;
3368*c3963bc0SZev Weiss }
3369*c3963bc0SZev Weiss 
3370*c3963bc0SZev Weiss static int add_temp_sensors(struct nct6775_data *data, const u16 *regp,
3371*c3963bc0SZev Weiss 			    int *available, int *mask)
3372*c3963bc0SZev Weiss {
3373*c3963bc0SZev Weiss 	int i, err;
3374*c3963bc0SZev Weiss 	u16 src;
3375*c3963bc0SZev Weiss 
3376*c3963bc0SZev Weiss 	for (i = 0; i < data->pwm_num && *available; i++) {
3377*c3963bc0SZev Weiss 		int index;
3378*c3963bc0SZev Weiss 
3379*c3963bc0SZev Weiss 		if (!regp[i])
3380*c3963bc0SZev Weiss 			continue;
3381*c3963bc0SZev Weiss 		err = nct6775_read_value(data, regp[i], &src);
3382*c3963bc0SZev Weiss 		if (err)
3383*c3963bc0SZev Weiss 			return err;
3384*c3963bc0SZev Weiss 		src &= 0x1f;
3385*c3963bc0SZev Weiss 		if (!src || (*mask & BIT(src)))
3386*c3963bc0SZev Weiss 			continue;
3387*c3963bc0SZev Weiss 		if (!(data->temp_mask & BIT(src)))
3388*c3963bc0SZev Weiss 			continue;
3389*c3963bc0SZev Weiss 
3390*c3963bc0SZev Weiss 		index = __ffs(*available);
3391*c3963bc0SZev Weiss 		err = nct6775_write_value(data, data->REG_TEMP_SOURCE[index], src);
3392*c3963bc0SZev Weiss 		if (err)
3393*c3963bc0SZev Weiss 			return err;
3394*c3963bc0SZev Weiss 		*available &= ~BIT(index);
3395*c3963bc0SZev Weiss 		*mask |= BIT(src);
3396*c3963bc0SZev Weiss 	}
3397*c3963bc0SZev Weiss 
3398*c3963bc0SZev Weiss 	return 0;
3399*c3963bc0SZev Weiss }
3400*c3963bc0SZev Weiss 
3401*c3963bc0SZev Weiss int nct6775_probe(struct device *dev, struct nct6775_data *data,
3402*c3963bc0SZev Weiss 		  const struct regmap_config *regmapcfg)
3403*c3963bc0SZev Weiss {
3404*c3963bc0SZev Weiss 	int i, s, err = 0;
3405*c3963bc0SZev Weiss 	int mask, available;
3406*c3963bc0SZev Weiss 	u16 src;
3407*c3963bc0SZev Weiss 	const u16 *reg_temp, *reg_temp_over, *reg_temp_hyst, *reg_temp_config;
3408*c3963bc0SZev Weiss 	const u16 *reg_temp_mon, *reg_temp_alternate, *reg_temp_crit;
3409*c3963bc0SZev Weiss 	const u16 *reg_temp_crit_l = NULL, *reg_temp_crit_h = NULL;
3410*c3963bc0SZev Weiss 	int num_reg_temp, num_reg_temp_mon, num_reg_tsi_temp;
3411*c3963bc0SZev Weiss 	struct device *hwmon_dev;
3412*c3963bc0SZev Weiss 	struct sensor_template_group tsi_temp_tg;
3413*c3963bc0SZev Weiss 
3414*c3963bc0SZev Weiss 	data->regmap = devm_regmap_init(dev, NULL, data, regmapcfg);
3415*c3963bc0SZev Weiss 	if (IS_ERR(data->regmap))
3416*c3963bc0SZev Weiss 		return PTR_ERR(data->regmap);
3417*c3963bc0SZev Weiss 
3418*c3963bc0SZev Weiss 	mutex_init(&data->update_lock);
3419*c3963bc0SZev Weiss 	data->name = nct6775_device_names[data->kind];
3420*c3963bc0SZev Weiss 	data->bank = 0xff;		/* Force initial bank selection */
3421*c3963bc0SZev Weiss 
3422*c3963bc0SZev Weiss 	switch (data->kind) {
3423*c3963bc0SZev Weiss 	case nct6106:
3424*c3963bc0SZev Weiss 		data->in_num = 9;
3425*c3963bc0SZev Weiss 		data->pwm_num = 3;
3426*c3963bc0SZev Weiss 		data->auto_pwm_num = 4;
3427*c3963bc0SZev Weiss 		data->temp_fixed_num = 3;
3428*c3963bc0SZev Weiss 		data->num_temp_alarms = 6;
3429*c3963bc0SZev Weiss 		data->num_temp_beeps = 6;
3430*c3963bc0SZev Weiss 
3431*c3963bc0SZev Weiss 		data->fan_from_reg = fan_from_reg13;
3432*c3963bc0SZev Weiss 		data->fan_from_reg_min = fan_from_reg13;
3433*c3963bc0SZev Weiss 
3434*c3963bc0SZev Weiss 		data->temp_label = nct6776_temp_label;
3435*c3963bc0SZev Weiss 		data->temp_mask = NCT6776_TEMP_MASK;
3436*c3963bc0SZev Weiss 		data->virt_temp_mask = NCT6776_VIRT_TEMP_MASK;
3437*c3963bc0SZev Weiss 
3438*c3963bc0SZev Weiss 		data->REG_VBAT = NCT6106_REG_VBAT;
3439*c3963bc0SZev Weiss 		data->REG_DIODE = NCT6106_REG_DIODE;
3440*c3963bc0SZev Weiss 		data->DIODE_MASK = NCT6106_DIODE_MASK;
3441*c3963bc0SZev Weiss 		data->REG_VIN = NCT6106_REG_IN;
3442*c3963bc0SZev Weiss 		data->REG_IN_MINMAX[0] = NCT6106_REG_IN_MIN;
3443*c3963bc0SZev Weiss 		data->REG_IN_MINMAX[1] = NCT6106_REG_IN_MAX;
3444*c3963bc0SZev Weiss 		data->REG_TARGET = NCT6106_REG_TARGET;
3445*c3963bc0SZev Weiss 		data->REG_FAN = NCT6106_REG_FAN;
3446*c3963bc0SZev Weiss 		data->REG_FAN_MODE = NCT6106_REG_FAN_MODE;
3447*c3963bc0SZev Weiss 		data->REG_FAN_MIN = NCT6106_REG_FAN_MIN;
3448*c3963bc0SZev Weiss 		data->REG_FAN_PULSES = NCT6106_REG_FAN_PULSES;
3449*c3963bc0SZev Weiss 		data->FAN_PULSE_SHIFT = NCT6106_FAN_PULSE_SHIFT;
3450*c3963bc0SZev Weiss 		data->REG_FAN_TIME[0] = NCT6106_REG_FAN_STOP_TIME;
3451*c3963bc0SZev Weiss 		data->REG_FAN_TIME[1] = NCT6106_REG_FAN_STEP_UP_TIME;
3452*c3963bc0SZev Weiss 		data->REG_FAN_TIME[2] = NCT6106_REG_FAN_STEP_DOWN_TIME;
3453*c3963bc0SZev Weiss 		data->REG_TOLERANCE_H = NCT6106_REG_TOLERANCE_H;
3454*c3963bc0SZev Weiss 		data->REG_PWM[0] = NCT6116_REG_PWM;
3455*c3963bc0SZev Weiss 		data->REG_PWM[1] = NCT6106_REG_FAN_START_OUTPUT;
3456*c3963bc0SZev Weiss 		data->REG_PWM[2] = NCT6106_REG_FAN_STOP_OUTPUT;
3457*c3963bc0SZev Weiss 		data->REG_PWM[5] = NCT6106_REG_WEIGHT_DUTY_STEP;
3458*c3963bc0SZev Weiss 		data->REG_PWM[6] = NCT6106_REG_WEIGHT_DUTY_BASE;
3459*c3963bc0SZev Weiss 		data->REG_PWM_READ = NCT6106_REG_PWM_READ;
3460*c3963bc0SZev Weiss 		data->REG_PWM_MODE = NCT6106_REG_PWM_MODE;
3461*c3963bc0SZev Weiss 		data->PWM_MODE_MASK = NCT6106_PWM_MODE_MASK;
3462*c3963bc0SZev Weiss 		data->REG_AUTO_TEMP = NCT6106_REG_AUTO_TEMP;
3463*c3963bc0SZev Weiss 		data->REG_AUTO_PWM = NCT6106_REG_AUTO_PWM;
3464*c3963bc0SZev Weiss 		data->REG_CRITICAL_TEMP = NCT6106_REG_CRITICAL_TEMP;
3465*c3963bc0SZev Weiss 		data->REG_CRITICAL_TEMP_TOLERANCE
3466*c3963bc0SZev Weiss 		  = NCT6106_REG_CRITICAL_TEMP_TOLERANCE;
3467*c3963bc0SZev Weiss 		data->REG_CRITICAL_PWM_ENABLE = NCT6106_REG_CRITICAL_PWM_ENABLE;
3468*c3963bc0SZev Weiss 		data->CRITICAL_PWM_ENABLE_MASK
3469*c3963bc0SZev Weiss 		  = NCT6106_CRITICAL_PWM_ENABLE_MASK;
3470*c3963bc0SZev Weiss 		data->REG_CRITICAL_PWM = NCT6106_REG_CRITICAL_PWM;
3471*c3963bc0SZev Weiss 		data->REG_TEMP_OFFSET = NCT6106_REG_TEMP_OFFSET;
3472*c3963bc0SZev Weiss 		data->REG_TEMP_SOURCE = NCT6106_REG_TEMP_SOURCE;
3473*c3963bc0SZev Weiss 		data->REG_TEMP_SEL = NCT6116_REG_TEMP_SEL;
3474*c3963bc0SZev Weiss 		data->REG_WEIGHT_TEMP_SEL = NCT6106_REG_WEIGHT_TEMP_SEL;
3475*c3963bc0SZev Weiss 		data->REG_WEIGHT_TEMP[0] = NCT6106_REG_WEIGHT_TEMP_STEP;
3476*c3963bc0SZev Weiss 		data->REG_WEIGHT_TEMP[1] = NCT6106_REG_WEIGHT_TEMP_STEP_TOL;
3477*c3963bc0SZev Weiss 		data->REG_WEIGHT_TEMP[2] = NCT6106_REG_WEIGHT_TEMP_BASE;
3478*c3963bc0SZev Weiss 		data->REG_ALARM = NCT6106_REG_ALARM;
3479*c3963bc0SZev Weiss 		data->ALARM_BITS = NCT6106_ALARM_BITS;
3480*c3963bc0SZev Weiss 		data->REG_BEEP = NCT6106_REG_BEEP;
3481*c3963bc0SZev Weiss 		data->BEEP_BITS = NCT6106_BEEP_BITS;
3482*c3963bc0SZev Weiss 		data->REG_TSI_TEMP = NCT6106_REG_TSI_TEMP;
3483*c3963bc0SZev Weiss 
3484*c3963bc0SZev Weiss 		reg_temp = NCT6106_REG_TEMP;
3485*c3963bc0SZev Weiss 		reg_temp_mon = NCT6106_REG_TEMP_MON;
3486*c3963bc0SZev Weiss 		num_reg_temp = ARRAY_SIZE(NCT6106_REG_TEMP);
3487*c3963bc0SZev Weiss 		num_reg_temp_mon = ARRAY_SIZE(NCT6106_REG_TEMP_MON);
3488*c3963bc0SZev Weiss 		num_reg_tsi_temp = ARRAY_SIZE(NCT6106_REG_TSI_TEMP);
3489*c3963bc0SZev Weiss 		reg_temp_over = NCT6106_REG_TEMP_OVER;
3490*c3963bc0SZev Weiss 		reg_temp_hyst = NCT6106_REG_TEMP_HYST;
3491*c3963bc0SZev Weiss 		reg_temp_config = NCT6106_REG_TEMP_CONFIG;
3492*c3963bc0SZev Weiss 		reg_temp_alternate = NCT6106_REG_TEMP_ALTERNATE;
3493*c3963bc0SZev Weiss 		reg_temp_crit = NCT6106_REG_TEMP_CRIT;
3494*c3963bc0SZev Weiss 		reg_temp_crit_l = NCT6106_REG_TEMP_CRIT_L;
3495*c3963bc0SZev Weiss 		reg_temp_crit_h = NCT6106_REG_TEMP_CRIT_H;
3496*c3963bc0SZev Weiss 
3497*c3963bc0SZev Weiss 		break;
3498*c3963bc0SZev Weiss 	case nct6116:
3499*c3963bc0SZev Weiss 		data->in_num = 9;
3500*c3963bc0SZev Weiss 		data->pwm_num = 3;
3501*c3963bc0SZev Weiss 		data->auto_pwm_num = 4;
3502*c3963bc0SZev Weiss 		data->temp_fixed_num = 3;
3503*c3963bc0SZev Weiss 		data->num_temp_alarms = 3;
3504*c3963bc0SZev Weiss 		data->num_temp_beeps = 3;
3505*c3963bc0SZev Weiss 
3506*c3963bc0SZev Weiss 		data->fan_from_reg = fan_from_reg13;
3507*c3963bc0SZev Weiss 		data->fan_from_reg_min = fan_from_reg13;
3508*c3963bc0SZev Weiss 
3509*c3963bc0SZev Weiss 		data->temp_label = nct6776_temp_label;
3510*c3963bc0SZev Weiss 		data->temp_mask = NCT6776_TEMP_MASK;
3511*c3963bc0SZev Weiss 		data->virt_temp_mask = NCT6776_VIRT_TEMP_MASK;
3512*c3963bc0SZev Weiss 
3513*c3963bc0SZev Weiss 		data->REG_VBAT = NCT6106_REG_VBAT;
3514*c3963bc0SZev Weiss 		data->REG_DIODE = NCT6106_REG_DIODE;
3515*c3963bc0SZev Weiss 		data->DIODE_MASK = NCT6106_DIODE_MASK;
3516*c3963bc0SZev Weiss 		data->REG_VIN = NCT6106_REG_IN;
3517*c3963bc0SZev Weiss 		data->REG_IN_MINMAX[0] = NCT6106_REG_IN_MIN;
3518*c3963bc0SZev Weiss 		data->REG_IN_MINMAX[1] = NCT6106_REG_IN_MAX;
3519*c3963bc0SZev Weiss 		data->REG_TARGET = NCT6116_REG_TARGET;
3520*c3963bc0SZev Weiss 		data->REG_FAN = NCT6116_REG_FAN;
3521*c3963bc0SZev Weiss 		data->REG_FAN_MODE = NCT6116_REG_FAN_MODE;
3522*c3963bc0SZev Weiss 		data->REG_FAN_MIN = NCT6116_REG_FAN_MIN;
3523*c3963bc0SZev Weiss 		data->REG_FAN_PULSES = NCT6116_REG_FAN_PULSES;
3524*c3963bc0SZev Weiss 		data->FAN_PULSE_SHIFT = NCT6116_FAN_PULSE_SHIFT;
3525*c3963bc0SZev Weiss 		data->REG_FAN_TIME[0] = NCT6116_REG_FAN_STOP_TIME;
3526*c3963bc0SZev Weiss 		data->REG_FAN_TIME[1] = NCT6116_REG_FAN_STEP_UP_TIME;
3527*c3963bc0SZev Weiss 		data->REG_FAN_TIME[2] = NCT6116_REG_FAN_STEP_DOWN_TIME;
3528*c3963bc0SZev Weiss 		data->REG_TOLERANCE_H = NCT6116_REG_TOLERANCE_H;
3529*c3963bc0SZev Weiss 		data->REG_PWM[0] = NCT6116_REG_PWM;
3530*c3963bc0SZev Weiss 		data->REG_PWM[1] = NCT6116_REG_FAN_START_OUTPUT;
3531*c3963bc0SZev Weiss 		data->REG_PWM[2] = NCT6116_REG_FAN_STOP_OUTPUT;
3532*c3963bc0SZev Weiss 		data->REG_PWM[5] = NCT6106_REG_WEIGHT_DUTY_STEP;
3533*c3963bc0SZev Weiss 		data->REG_PWM[6] = NCT6106_REG_WEIGHT_DUTY_BASE;
3534*c3963bc0SZev Weiss 		data->REG_PWM_READ = NCT6106_REG_PWM_READ;
3535*c3963bc0SZev Weiss 		data->REG_PWM_MODE = NCT6106_REG_PWM_MODE;
3536*c3963bc0SZev Weiss 		data->PWM_MODE_MASK = NCT6106_PWM_MODE_MASK;
3537*c3963bc0SZev Weiss 		data->REG_AUTO_TEMP = NCT6116_REG_AUTO_TEMP;
3538*c3963bc0SZev Weiss 		data->REG_AUTO_PWM = NCT6116_REG_AUTO_PWM;
3539*c3963bc0SZev Weiss 		data->REG_CRITICAL_TEMP = NCT6116_REG_CRITICAL_TEMP;
3540*c3963bc0SZev Weiss 		data->REG_CRITICAL_TEMP_TOLERANCE
3541*c3963bc0SZev Weiss 		  = NCT6116_REG_CRITICAL_TEMP_TOLERANCE;
3542*c3963bc0SZev Weiss 		data->REG_CRITICAL_PWM_ENABLE = NCT6116_REG_CRITICAL_PWM_ENABLE;
3543*c3963bc0SZev Weiss 		data->CRITICAL_PWM_ENABLE_MASK
3544*c3963bc0SZev Weiss 		  = NCT6106_CRITICAL_PWM_ENABLE_MASK;
3545*c3963bc0SZev Weiss 		data->REG_CRITICAL_PWM = NCT6116_REG_CRITICAL_PWM;
3546*c3963bc0SZev Weiss 		data->REG_TEMP_OFFSET = NCT6106_REG_TEMP_OFFSET;
3547*c3963bc0SZev Weiss 		data->REG_TEMP_SOURCE = NCT6116_REG_TEMP_SOURCE;
3548*c3963bc0SZev Weiss 		data->REG_TEMP_SEL = NCT6116_REG_TEMP_SEL;
3549*c3963bc0SZev Weiss 		data->REG_WEIGHT_TEMP_SEL = NCT6106_REG_WEIGHT_TEMP_SEL;
3550*c3963bc0SZev Weiss 		data->REG_WEIGHT_TEMP[0] = NCT6106_REG_WEIGHT_TEMP_STEP;
3551*c3963bc0SZev Weiss 		data->REG_WEIGHT_TEMP[1] = NCT6106_REG_WEIGHT_TEMP_STEP_TOL;
3552*c3963bc0SZev Weiss 		data->REG_WEIGHT_TEMP[2] = NCT6106_REG_WEIGHT_TEMP_BASE;
3553*c3963bc0SZev Weiss 		data->REG_ALARM = NCT6106_REG_ALARM;
3554*c3963bc0SZev Weiss 		data->ALARM_BITS = NCT6116_ALARM_BITS;
3555*c3963bc0SZev Weiss 		data->REG_BEEP = NCT6106_REG_BEEP;
3556*c3963bc0SZev Weiss 		data->BEEP_BITS = NCT6116_BEEP_BITS;
3557*c3963bc0SZev Weiss 		data->REG_TSI_TEMP = NCT6116_REG_TSI_TEMP;
3558*c3963bc0SZev Weiss 
3559*c3963bc0SZev Weiss 		reg_temp = NCT6106_REG_TEMP;
3560*c3963bc0SZev Weiss 		reg_temp_mon = NCT6106_REG_TEMP_MON;
3561*c3963bc0SZev Weiss 		num_reg_temp = ARRAY_SIZE(NCT6106_REG_TEMP);
3562*c3963bc0SZev Weiss 		num_reg_temp_mon = ARRAY_SIZE(NCT6106_REG_TEMP_MON);
3563*c3963bc0SZev Weiss 		num_reg_tsi_temp = ARRAY_SIZE(NCT6116_REG_TSI_TEMP);
3564*c3963bc0SZev Weiss 		reg_temp_over = NCT6106_REG_TEMP_OVER;
3565*c3963bc0SZev Weiss 		reg_temp_hyst = NCT6106_REG_TEMP_HYST;
3566*c3963bc0SZev Weiss 		reg_temp_config = NCT6106_REG_TEMP_CONFIG;
3567*c3963bc0SZev Weiss 		reg_temp_alternate = NCT6106_REG_TEMP_ALTERNATE;
3568*c3963bc0SZev Weiss 		reg_temp_crit = NCT6106_REG_TEMP_CRIT;
3569*c3963bc0SZev Weiss 		reg_temp_crit_l = NCT6106_REG_TEMP_CRIT_L;
3570*c3963bc0SZev Weiss 		reg_temp_crit_h = NCT6106_REG_TEMP_CRIT_H;
3571*c3963bc0SZev Weiss 
3572*c3963bc0SZev Weiss 		break;
3573*c3963bc0SZev Weiss 	case nct6775:
3574*c3963bc0SZev Weiss 		data->in_num = 9;
3575*c3963bc0SZev Weiss 		data->pwm_num = 3;
3576*c3963bc0SZev Weiss 		data->auto_pwm_num = 6;
3577*c3963bc0SZev Weiss 		data->has_fan_div = true;
3578*c3963bc0SZev Weiss 		data->temp_fixed_num = 3;
3579*c3963bc0SZev Weiss 		data->num_temp_alarms = 3;
3580*c3963bc0SZev Weiss 		data->num_temp_beeps = 3;
3581*c3963bc0SZev Weiss 
3582*c3963bc0SZev Weiss 		data->ALARM_BITS = NCT6775_ALARM_BITS;
3583*c3963bc0SZev Weiss 		data->BEEP_BITS = NCT6775_BEEP_BITS;
3584*c3963bc0SZev Weiss 
3585*c3963bc0SZev Weiss 		data->fan_from_reg = fan_from_reg16;
3586*c3963bc0SZev Weiss 		data->fan_from_reg_min = fan_from_reg8;
3587*c3963bc0SZev Weiss 		data->target_temp_mask = 0x7f;
3588*c3963bc0SZev Weiss 		data->tolerance_mask = 0x0f;
3589*c3963bc0SZev Weiss 		data->speed_tolerance_limit = 15;
3590*c3963bc0SZev Weiss 
3591*c3963bc0SZev Weiss 		data->temp_label = nct6775_temp_label;
3592*c3963bc0SZev Weiss 		data->temp_mask = NCT6775_TEMP_MASK;
3593*c3963bc0SZev Weiss 		data->virt_temp_mask = NCT6775_VIRT_TEMP_MASK;
3594*c3963bc0SZev Weiss 
3595*c3963bc0SZev Weiss 		data->REG_CONFIG = NCT6775_REG_CONFIG;
3596*c3963bc0SZev Weiss 		data->REG_VBAT = NCT6775_REG_VBAT;
3597*c3963bc0SZev Weiss 		data->REG_DIODE = NCT6775_REG_DIODE;
3598*c3963bc0SZev Weiss 		data->DIODE_MASK = NCT6775_DIODE_MASK;
3599*c3963bc0SZev Weiss 		data->REG_VIN = NCT6775_REG_IN;
3600*c3963bc0SZev Weiss 		data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3601*c3963bc0SZev Weiss 		data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
3602*c3963bc0SZev Weiss 		data->REG_TARGET = NCT6775_REG_TARGET;
3603*c3963bc0SZev Weiss 		data->REG_FAN = NCT6775_REG_FAN;
3604*c3963bc0SZev Weiss 		data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
3605*c3963bc0SZev Weiss 		data->REG_FAN_MIN = NCT6775_REG_FAN_MIN;
3606*c3963bc0SZev Weiss 		data->REG_FAN_PULSES = NCT6775_REG_FAN_PULSES;
3607*c3963bc0SZev Weiss 		data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
3608*c3963bc0SZev Weiss 		data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3609*c3963bc0SZev Weiss 		data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3610*c3963bc0SZev Weiss 		data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
3611*c3963bc0SZev Weiss 		data->REG_PWM[0] = NCT6775_REG_PWM;
3612*c3963bc0SZev Weiss 		data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3613*c3963bc0SZev Weiss 		data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
3614*c3963bc0SZev Weiss 		data->REG_PWM[3] = NCT6775_REG_FAN_MAX_OUTPUT;
3615*c3963bc0SZev Weiss 		data->REG_PWM[4] = NCT6775_REG_FAN_STEP_OUTPUT;
3616*c3963bc0SZev Weiss 		data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
3617*c3963bc0SZev Weiss 		data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3618*c3963bc0SZev Weiss 		data->REG_PWM_MODE = NCT6775_REG_PWM_MODE;
3619*c3963bc0SZev Weiss 		data->PWM_MODE_MASK = NCT6775_PWM_MODE_MASK;
3620*c3963bc0SZev Weiss 		data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3621*c3963bc0SZev Weiss 		data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3622*c3963bc0SZev Weiss 		data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3623*c3963bc0SZev Weiss 		data->REG_CRITICAL_TEMP_TOLERANCE
3624*c3963bc0SZev Weiss 		  = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
3625*c3963bc0SZev Weiss 		data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET;
3626*c3963bc0SZev Weiss 		data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
3627*c3963bc0SZev Weiss 		data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
3628*c3963bc0SZev Weiss 		data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3629*c3963bc0SZev Weiss 		data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3630*c3963bc0SZev Weiss 		data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3631*c3963bc0SZev Weiss 		data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
3632*c3963bc0SZev Weiss 		data->REG_ALARM = NCT6775_REG_ALARM;
3633*c3963bc0SZev Weiss 		data->REG_BEEP = NCT6775_REG_BEEP;
3634*c3963bc0SZev Weiss 		data->REG_TSI_TEMP = NCT6775_REG_TSI_TEMP;
3635*c3963bc0SZev Weiss 
3636*c3963bc0SZev Weiss 		reg_temp = NCT6775_REG_TEMP;
3637*c3963bc0SZev Weiss 		reg_temp_mon = NCT6775_REG_TEMP_MON;
3638*c3963bc0SZev Weiss 		num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
3639*c3963bc0SZev Weiss 		num_reg_temp_mon = ARRAY_SIZE(NCT6775_REG_TEMP_MON);
3640*c3963bc0SZev Weiss 		num_reg_tsi_temp = ARRAY_SIZE(NCT6775_REG_TSI_TEMP);
3641*c3963bc0SZev Weiss 		reg_temp_over = NCT6775_REG_TEMP_OVER;
3642*c3963bc0SZev Weiss 		reg_temp_hyst = NCT6775_REG_TEMP_HYST;
3643*c3963bc0SZev Weiss 		reg_temp_config = NCT6775_REG_TEMP_CONFIG;
3644*c3963bc0SZev Weiss 		reg_temp_alternate = NCT6775_REG_TEMP_ALTERNATE;
3645*c3963bc0SZev Weiss 		reg_temp_crit = NCT6775_REG_TEMP_CRIT;
3646*c3963bc0SZev Weiss 
3647*c3963bc0SZev Weiss 		break;
3648*c3963bc0SZev Weiss 	case nct6776:
3649*c3963bc0SZev Weiss 		data->in_num = 9;
3650*c3963bc0SZev Weiss 		data->pwm_num = 3;
3651*c3963bc0SZev Weiss 		data->auto_pwm_num = 4;
3652*c3963bc0SZev Weiss 		data->has_fan_div = false;
3653*c3963bc0SZev Weiss 		data->temp_fixed_num = 3;
3654*c3963bc0SZev Weiss 		data->num_temp_alarms = 3;
3655*c3963bc0SZev Weiss 		data->num_temp_beeps = 6;
3656*c3963bc0SZev Weiss 
3657*c3963bc0SZev Weiss 		data->ALARM_BITS = NCT6776_ALARM_BITS;
3658*c3963bc0SZev Weiss 		data->BEEP_BITS = NCT6776_BEEP_BITS;
3659*c3963bc0SZev Weiss 
3660*c3963bc0SZev Weiss 		data->fan_from_reg = fan_from_reg13;
3661*c3963bc0SZev Weiss 		data->fan_from_reg_min = fan_from_reg13;
3662*c3963bc0SZev Weiss 		data->target_temp_mask = 0xff;
3663*c3963bc0SZev Weiss 		data->tolerance_mask = 0x07;
3664*c3963bc0SZev Weiss 		data->speed_tolerance_limit = 63;
3665*c3963bc0SZev Weiss 
3666*c3963bc0SZev Weiss 		data->temp_label = nct6776_temp_label;
3667*c3963bc0SZev Weiss 		data->temp_mask = NCT6776_TEMP_MASK;
3668*c3963bc0SZev Weiss 		data->virt_temp_mask = NCT6776_VIRT_TEMP_MASK;
3669*c3963bc0SZev Weiss 
3670*c3963bc0SZev Weiss 		data->REG_CONFIG = NCT6775_REG_CONFIG;
3671*c3963bc0SZev Weiss 		data->REG_VBAT = NCT6775_REG_VBAT;
3672*c3963bc0SZev Weiss 		data->REG_DIODE = NCT6775_REG_DIODE;
3673*c3963bc0SZev Weiss 		data->DIODE_MASK = NCT6775_DIODE_MASK;
3674*c3963bc0SZev Weiss 		data->REG_VIN = NCT6775_REG_IN;
3675*c3963bc0SZev Weiss 		data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3676*c3963bc0SZev Weiss 		data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
3677*c3963bc0SZev Weiss 		data->REG_TARGET = NCT6775_REG_TARGET;
3678*c3963bc0SZev Weiss 		data->REG_FAN = NCT6775_REG_FAN;
3679*c3963bc0SZev Weiss 		data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
3680*c3963bc0SZev Weiss 		data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
3681*c3963bc0SZev Weiss 		data->REG_FAN_PULSES = NCT6776_REG_FAN_PULSES;
3682*c3963bc0SZev Weiss 		data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
3683*c3963bc0SZev Weiss 		data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3684*c3963bc0SZev Weiss 		data->REG_FAN_TIME[1] = NCT6776_REG_FAN_STEP_UP_TIME;
3685*c3963bc0SZev Weiss 		data->REG_FAN_TIME[2] = NCT6776_REG_FAN_STEP_DOWN_TIME;
3686*c3963bc0SZev Weiss 		data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
3687*c3963bc0SZev Weiss 		data->REG_PWM[0] = NCT6775_REG_PWM;
3688*c3963bc0SZev Weiss 		data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3689*c3963bc0SZev Weiss 		data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
3690*c3963bc0SZev Weiss 		data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
3691*c3963bc0SZev Weiss 		data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
3692*c3963bc0SZev Weiss 		data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3693*c3963bc0SZev Weiss 		data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3694*c3963bc0SZev Weiss 		data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
3695*c3963bc0SZev Weiss 		data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3696*c3963bc0SZev Weiss 		data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3697*c3963bc0SZev Weiss 		data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3698*c3963bc0SZev Weiss 		data->REG_CRITICAL_TEMP_TOLERANCE
3699*c3963bc0SZev Weiss 		  = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
3700*c3963bc0SZev Weiss 		data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET;
3701*c3963bc0SZev Weiss 		data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
3702*c3963bc0SZev Weiss 		data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
3703*c3963bc0SZev Weiss 		data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3704*c3963bc0SZev Weiss 		data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3705*c3963bc0SZev Weiss 		data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3706*c3963bc0SZev Weiss 		data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
3707*c3963bc0SZev Weiss 		data->REG_ALARM = NCT6775_REG_ALARM;
3708*c3963bc0SZev Weiss 		data->REG_BEEP = NCT6776_REG_BEEP;
3709*c3963bc0SZev Weiss 		data->REG_TSI_TEMP = NCT6776_REG_TSI_TEMP;
3710*c3963bc0SZev Weiss 
3711*c3963bc0SZev Weiss 		reg_temp = NCT6775_REG_TEMP;
3712*c3963bc0SZev Weiss 		reg_temp_mon = NCT6775_REG_TEMP_MON;
3713*c3963bc0SZev Weiss 		num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
3714*c3963bc0SZev Weiss 		num_reg_temp_mon = ARRAY_SIZE(NCT6775_REG_TEMP_MON);
3715*c3963bc0SZev Weiss 		num_reg_tsi_temp = ARRAY_SIZE(NCT6776_REG_TSI_TEMP);
3716*c3963bc0SZev Weiss 		reg_temp_over = NCT6775_REG_TEMP_OVER;
3717*c3963bc0SZev Weiss 		reg_temp_hyst = NCT6775_REG_TEMP_HYST;
3718*c3963bc0SZev Weiss 		reg_temp_config = NCT6776_REG_TEMP_CONFIG;
3719*c3963bc0SZev Weiss 		reg_temp_alternate = NCT6776_REG_TEMP_ALTERNATE;
3720*c3963bc0SZev Weiss 		reg_temp_crit = NCT6776_REG_TEMP_CRIT;
3721*c3963bc0SZev Weiss 
3722*c3963bc0SZev Weiss 		break;
3723*c3963bc0SZev Weiss 	case nct6779:
3724*c3963bc0SZev Weiss 		data->in_num = 15;
3725*c3963bc0SZev Weiss 		data->pwm_num = 5;
3726*c3963bc0SZev Weiss 		data->auto_pwm_num = 4;
3727*c3963bc0SZev Weiss 		data->has_fan_div = false;
3728*c3963bc0SZev Weiss 		data->temp_fixed_num = 6;
3729*c3963bc0SZev Weiss 		data->num_temp_alarms = 2;
3730*c3963bc0SZev Weiss 		data->num_temp_beeps = 2;
3731*c3963bc0SZev Weiss 
3732*c3963bc0SZev Weiss 		data->ALARM_BITS = NCT6779_ALARM_BITS;
3733*c3963bc0SZev Weiss 		data->BEEP_BITS = NCT6779_BEEP_BITS;
3734*c3963bc0SZev Weiss 
3735*c3963bc0SZev Weiss 		data->fan_from_reg = fan_from_reg_rpm;
3736*c3963bc0SZev Weiss 		data->fan_from_reg_min = fan_from_reg13;
3737*c3963bc0SZev Weiss 		data->target_temp_mask = 0xff;
3738*c3963bc0SZev Weiss 		data->tolerance_mask = 0x07;
3739*c3963bc0SZev Weiss 		data->speed_tolerance_limit = 63;
3740*c3963bc0SZev Weiss 
3741*c3963bc0SZev Weiss 		data->temp_label = nct6779_temp_label;
3742*c3963bc0SZev Weiss 		data->temp_mask = NCT6779_TEMP_MASK;
3743*c3963bc0SZev Weiss 		data->virt_temp_mask = NCT6779_VIRT_TEMP_MASK;
3744*c3963bc0SZev Weiss 
3745*c3963bc0SZev Weiss 		data->REG_CONFIG = NCT6775_REG_CONFIG;
3746*c3963bc0SZev Weiss 		data->REG_VBAT = NCT6775_REG_VBAT;
3747*c3963bc0SZev Weiss 		data->REG_DIODE = NCT6775_REG_DIODE;
3748*c3963bc0SZev Weiss 		data->DIODE_MASK = NCT6775_DIODE_MASK;
3749*c3963bc0SZev Weiss 		data->REG_VIN = NCT6779_REG_IN;
3750*c3963bc0SZev Weiss 		data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3751*c3963bc0SZev Weiss 		data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
3752*c3963bc0SZev Weiss 		data->REG_TARGET = NCT6775_REG_TARGET;
3753*c3963bc0SZev Weiss 		data->REG_FAN = NCT6779_REG_FAN;
3754*c3963bc0SZev Weiss 		data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
3755*c3963bc0SZev Weiss 		data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
3756*c3963bc0SZev Weiss 		data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES;
3757*c3963bc0SZev Weiss 		data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
3758*c3963bc0SZev Weiss 		data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3759*c3963bc0SZev Weiss 		data->REG_FAN_TIME[1] = NCT6776_REG_FAN_STEP_UP_TIME;
3760*c3963bc0SZev Weiss 		data->REG_FAN_TIME[2] = NCT6776_REG_FAN_STEP_DOWN_TIME;
3761*c3963bc0SZev Weiss 		data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
3762*c3963bc0SZev Weiss 		data->REG_PWM[0] = NCT6775_REG_PWM;
3763*c3963bc0SZev Weiss 		data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3764*c3963bc0SZev Weiss 		data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
3765*c3963bc0SZev Weiss 		data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
3766*c3963bc0SZev Weiss 		data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
3767*c3963bc0SZev Weiss 		data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3768*c3963bc0SZev Weiss 		data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3769*c3963bc0SZev Weiss 		data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
3770*c3963bc0SZev Weiss 		data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3771*c3963bc0SZev Weiss 		data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3772*c3963bc0SZev Weiss 		data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3773*c3963bc0SZev Weiss 		data->REG_CRITICAL_TEMP_TOLERANCE
3774*c3963bc0SZev Weiss 		  = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
3775*c3963bc0SZev Weiss 		data->REG_CRITICAL_PWM_ENABLE = NCT6779_REG_CRITICAL_PWM_ENABLE;
3776*c3963bc0SZev Weiss 		data->CRITICAL_PWM_ENABLE_MASK
3777*c3963bc0SZev Weiss 		  = NCT6779_CRITICAL_PWM_ENABLE_MASK;
3778*c3963bc0SZev Weiss 		data->REG_CRITICAL_PWM = NCT6779_REG_CRITICAL_PWM;
3779*c3963bc0SZev Weiss 		data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET;
3780*c3963bc0SZev Weiss 		data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
3781*c3963bc0SZev Weiss 		data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
3782*c3963bc0SZev Weiss 		data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3783*c3963bc0SZev Weiss 		data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3784*c3963bc0SZev Weiss 		data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3785*c3963bc0SZev Weiss 		data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
3786*c3963bc0SZev Weiss 		data->REG_ALARM = NCT6779_REG_ALARM;
3787*c3963bc0SZev Weiss 		data->REG_BEEP = NCT6776_REG_BEEP;
3788*c3963bc0SZev Weiss 		data->REG_TSI_TEMP = NCT6776_REG_TSI_TEMP;
3789*c3963bc0SZev Weiss 
3790*c3963bc0SZev Weiss 		reg_temp = NCT6779_REG_TEMP;
3791*c3963bc0SZev Weiss 		reg_temp_mon = NCT6779_REG_TEMP_MON;
3792*c3963bc0SZev Weiss 		num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
3793*c3963bc0SZev Weiss 		num_reg_temp_mon = ARRAY_SIZE(NCT6779_REG_TEMP_MON);
3794*c3963bc0SZev Weiss 		num_reg_tsi_temp = ARRAY_SIZE(NCT6776_REG_TSI_TEMP);
3795*c3963bc0SZev Weiss 		reg_temp_over = NCT6779_REG_TEMP_OVER;
3796*c3963bc0SZev Weiss 		reg_temp_hyst = NCT6779_REG_TEMP_HYST;
3797*c3963bc0SZev Weiss 		reg_temp_config = NCT6779_REG_TEMP_CONFIG;
3798*c3963bc0SZev Weiss 		reg_temp_alternate = NCT6779_REG_TEMP_ALTERNATE;
3799*c3963bc0SZev Weiss 		reg_temp_crit = NCT6779_REG_TEMP_CRIT;
3800*c3963bc0SZev Weiss 
3801*c3963bc0SZev Weiss 		break;
3802*c3963bc0SZev Weiss 	case nct6791:
3803*c3963bc0SZev Weiss 	case nct6792:
3804*c3963bc0SZev Weiss 	case nct6793:
3805*c3963bc0SZev Weiss 	case nct6795:
3806*c3963bc0SZev Weiss 	case nct6796:
3807*c3963bc0SZev Weiss 	case nct6797:
3808*c3963bc0SZev Weiss 	case nct6798:
3809*c3963bc0SZev Weiss 		data->in_num = 15;
3810*c3963bc0SZev Weiss 		data->pwm_num = (data->kind == nct6796 ||
3811*c3963bc0SZev Weiss 				 data->kind == nct6797 ||
3812*c3963bc0SZev Weiss 				 data->kind == nct6798) ? 7 : 6;
3813*c3963bc0SZev Weiss 		data->auto_pwm_num = 4;
3814*c3963bc0SZev Weiss 		data->has_fan_div = false;
3815*c3963bc0SZev Weiss 		data->temp_fixed_num = 6;
3816*c3963bc0SZev Weiss 		data->num_temp_alarms = 2;
3817*c3963bc0SZev Weiss 		data->num_temp_beeps = 2;
3818*c3963bc0SZev Weiss 
3819*c3963bc0SZev Weiss 		data->ALARM_BITS = NCT6791_ALARM_BITS;
3820*c3963bc0SZev Weiss 		data->BEEP_BITS = NCT6779_BEEP_BITS;
3821*c3963bc0SZev Weiss 
3822*c3963bc0SZev Weiss 		data->fan_from_reg = fan_from_reg_rpm;
3823*c3963bc0SZev Weiss 		data->fan_from_reg_min = fan_from_reg13;
3824*c3963bc0SZev Weiss 		data->target_temp_mask = 0xff;
3825*c3963bc0SZev Weiss 		data->tolerance_mask = 0x07;
3826*c3963bc0SZev Weiss 		data->speed_tolerance_limit = 63;
3827*c3963bc0SZev Weiss 
3828*c3963bc0SZev Weiss 		switch (data->kind) {
3829*c3963bc0SZev Weiss 		default:
3830*c3963bc0SZev Weiss 		case nct6791:
3831*c3963bc0SZev Weiss 			data->temp_label = nct6779_temp_label;
3832*c3963bc0SZev Weiss 			data->temp_mask = NCT6791_TEMP_MASK;
3833*c3963bc0SZev Weiss 			data->virt_temp_mask = NCT6791_VIRT_TEMP_MASK;
3834*c3963bc0SZev Weiss 			break;
3835*c3963bc0SZev Weiss 		case nct6792:
3836*c3963bc0SZev Weiss 			data->temp_label = nct6792_temp_label;
3837*c3963bc0SZev Weiss 			data->temp_mask = NCT6792_TEMP_MASK;
3838*c3963bc0SZev Weiss 			data->virt_temp_mask = NCT6792_VIRT_TEMP_MASK;
3839*c3963bc0SZev Weiss 			break;
3840*c3963bc0SZev Weiss 		case nct6793:
3841*c3963bc0SZev Weiss 			data->temp_label = nct6793_temp_label;
3842*c3963bc0SZev Weiss 			data->temp_mask = NCT6793_TEMP_MASK;
3843*c3963bc0SZev Weiss 			data->virt_temp_mask = NCT6793_VIRT_TEMP_MASK;
3844*c3963bc0SZev Weiss 			break;
3845*c3963bc0SZev Weiss 		case nct6795:
3846*c3963bc0SZev Weiss 		case nct6797:
3847*c3963bc0SZev Weiss 			data->temp_label = nct6795_temp_label;
3848*c3963bc0SZev Weiss 			data->temp_mask = NCT6795_TEMP_MASK;
3849*c3963bc0SZev Weiss 			data->virt_temp_mask = NCT6795_VIRT_TEMP_MASK;
3850*c3963bc0SZev Weiss 			break;
3851*c3963bc0SZev Weiss 		case nct6796:
3852*c3963bc0SZev Weiss 			data->temp_label = nct6796_temp_label;
3853*c3963bc0SZev Weiss 			data->temp_mask = NCT6796_TEMP_MASK;
3854*c3963bc0SZev Weiss 			data->virt_temp_mask = NCT6796_VIRT_TEMP_MASK;
3855*c3963bc0SZev Weiss 			break;
3856*c3963bc0SZev Weiss 		case nct6798:
3857*c3963bc0SZev Weiss 			data->temp_label = nct6798_temp_label;
3858*c3963bc0SZev Weiss 			data->temp_mask = NCT6798_TEMP_MASK;
3859*c3963bc0SZev Weiss 			data->virt_temp_mask = NCT6798_VIRT_TEMP_MASK;
3860*c3963bc0SZev Weiss 			break;
3861*c3963bc0SZev Weiss 		}
3862*c3963bc0SZev Weiss 
3863*c3963bc0SZev Weiss 		data->REG_CONFIG = NCT6775_REG_CONFIG;
3864*c3963bc0SZev Weiss 		data->REG_VBAT = NCT6775_REG_VBAT;
3865*c3963bc0SZev Weiss 		data->REG_DIODE = NCT6775_REG_DIODE;
3866*c3963bc0SZev Weiss 		data->DIODE_MASK = NCT6775_DIODE_MASK;
3867*c3963bc0SZev Weiss 		data->REG_VIN = NCT6779_REG_IN;
3868*c3963bc0SZev Weiss 		data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3869*c3963bc0SZev Weiss 		data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
3870*c3963bc0SZev Weiss 		data->REG_TARGET = NCT6775_REG_TARGET;
3871*c3963bc0SZev Weiss 		data->REG_FAN = NCT6779_REG_FAN;
3872*c3963bc0SZev Weiss 		data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
3873*c3963bc0SZev Weiss 		data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
3874*c3963bc0SZev Weiss 		data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES;
3875*c3963bc0SZev Weiss 		data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
3876*c3963bc0SZev Weiss 		data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3877*c3963bc0SZev Weiss 		data->REG_FAN_TIME[1] = NCT6776_REG_FAN_STEP_UP_TIME;
3878*c3963bc0SZev Weiss 		data->REG_FAN_TIME[2] = NCT6776_REG_FAN_STEP_DOWN_TIME;
3879*c3963bc0SZev Weiss 		data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
3880*c3963bc0SZev Weiss 		data->REG_PWM[0] = NCT6775_REG_PWM;
3881*c3963bc0SZev Weiss 		data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3882*c3963bc0SZev Weiss 		data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
3883*c3963bc0SZev Weiss 		data->REG_PWM[5] = NCT6791_REG_WEIGHT_DUTY_STEP;
3884*c3963bc0SZev Weiss 		data->REG_PWM[6] = NCT6791_REG_WEIGHT_DUTY_BASE;
3885*c3963bc0SZev Weiss 		data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3886*c3963bc0SZev Weiss 		data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3887*c3963bc0SZev Weiss 		data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
3888*c3963bc0SZev Weiss 		data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3889*c3963bc0SZev Weiss 		data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3890*c3963bc0SZev Weiss 		data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3891*c3963bc0SZev Weiss 		data->REG_CRITICAL_TEMP_TOLERANCE
3892*c3963bc0SZev Weiss 		  = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
3893*c3963bc0SZev Weiss 		data->REG_CRITICAL_PWM_ENABLE = NCT6779_REG_CRITICAL_PWM_ENABLE;
3894*c3963bc0SZev Weiss 		data->CRITICAL_PWM_ENABLE_MASK
3895*c3963bc0SZev Weiss 		  = NCT6779_CRITICAL_PWM_ENABLE_MASK;
3896*c3963bc0SZev Weiss 		data->REG_CRITICAL_PWM = NCT6779_REG_CRITICAL_PWM;
3897*c3963bc0SZev Weiss 		data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET;
3898*c3963bc0SZev Weiss 		data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
3899*c3963bc0SZev Weiss 		data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
3900*c3963bc0SZev Weiss 		data->REG_WEIGHT_TEMP_SEL = NCT6791_REG_WEIGHT_TEMP_SEL;
3901*c3963bc0SZev Weiss 		data->REG_WEIGHT_TEMP[0] = NCT6791_REG_WEIGHT_TEMP_STEP;
3902*c3963bc0SZev Weiss 		data->REG_WEIGHT_TEMP[1] = NCT6791_REG_WEIGHT_TEMP_STEP_TOL;
3903*c3963bc0SZev Weiss 		data->REG_WEIGHT_TEMP[2] = NCT6791_REG_WEIGHT_TEMP_BASE;
3904*c3963bc0SZev Weiss 		data->REG_ALARM = NCT6791_REG_ALARM;
3905*c3963bc0SZev Weiss 		if (data->kind == nct6791)
3906*c3963bc0SZev Weiss 			data->REG_BEEP = NCT6776_REG_BEEP;
3907*c3963bc0SZev Weiss 		else
3908*c3963bc0SZev Weiss 			data->REG_BEEP = NCT6792_REG_BEEP;
3909*c3963bc0SZev Weiss 		switch (data->kind) {
3910*c3963bc0SZev Weiss 		case nct6791:
3911*c3963bc0SZev Weiss 		case nct6792:
3912*c3963bc0SZev Weiss 		case nct6793:
3913*c3963bc0SZev Weiss 			data->REG_TSI_TEMP = NCT6776_REG_TSI_TEMP;
3914*c3963bc0SZev Weiss 			num_reg_tsi_temp = ARRAY_SIZE(NCT6776_REG_TSI_TEMP);
3915*c3963bc0SZev Weiss 			break;
3916*c3963bc0SZev Weiss 		case nct6795:
3917*c3963bc0SZev Weiss 		case nct6796:
3918*c3963bc0SZev Weiss 		case nct6797:
3919*c3963bc0SZev Weiss 		case nct6798:
3920*c3963bc0SZev Weiss 			data->REG_TSI_TEMP = NCT6796_REG_TSI_TEMP;
3921*c3963bc0SZev Weiss 			num_reg_tsi_temp = ARRAY_SIZE(NCT6796_REG_TSI_TEMP);
3922*c3963bc0SZev Weiss 			break;
3923*c3963bc0SZev Weiss 		default:
3924*c3963bc0SZev Weiss 			num_reg_tsi_temp = 0;
3925*c3963bc0SZev Weiss 			break;
3926*c3963bc0SZev Weiss 		}
3927*c3963bc0SZev Weiss 
3928*c3963bc0SZev Weiss 		reg_temp = NCT6779_REG_TEMP;
3929*c3963bc0SZev Weiss 		num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
3930*c3963bc0SZev Weiss 		if (data->kind == nct6791) {
3931*c3963bc0SZev Weiss 			reg_temp_mon = NCT6779_REG_TEMP_MON;
3932*c3963bc0SZev Weiss 			num_reg_temp_mon = ARRAY_SIZE(NCT6779_REG_TEMP_MON);
3933*c3963bc0SZev Weiss 		} else {
3934*c3963bc0SZev Weiss 			reg_temp_mon = NCT6792_REG_TEMP_MON;
3935*c3963bc0SZev Weiss 			num_reg_temp_mon = ARRAY_SIZE(NCT6792_REG_TEMP_MON);
3936*c3963bc0SZev Weiss 		}
3937*c3963bc0SZev Weiss 		reg_temp_over = NCT6779_REG_TEMP_OVER;
3938*c3963bc0SZev Weiss 		reg_temp_hyst = NCT6779_REG_TEMP_HYST;
3939*c3963bc0SZev Weiss 		reg_temp_config = NCT6779_REG_TEMP_CONFIG;
3940*c3963bc0SZev Weiss 		reg_temp_alternate = NCT6779_REG_TEMP_ALTERNATE;
3941*c3963bc0SZev Weiss 		reg_temp_crit = NCT6779_REG_TEMP_CRIT;
3942*c3963bc0SZev Weiss 
3943*c3963bc0SZev Weiss 		break;
3944*c3963bc0SZev Weiss 	default:
3945*c3963bc0SZev Weiss 		return -ENODEV;
3946*c3963bc0SZev Weiss 	}
3947*c3963bc0SZev Weiss 	data->have_in = BIT(data->in_num) - 1;
3948*c3963bc0SZev Weiss 	data->have_temp = 0;
3949*c3963bc0SZev Weiss 
3950*c3963bc0SZev Weiss 	/*
3951*c3963bc0SZev Weiss 	 * On some boards, not all available temperature sources are monitored,
3952*c3963bc0SZev Weiss 	 * even though some of the monitoring registers are unused.
3953*c3963bc0SZev Weiss 	 * Get list of unused monitoring registers, then detect if any fan
3954*c3963bc0SZev Weiss 	 * controls are configured to use unmonitored temperature sources.
3955*c3963bc0SZev Weiss 	 * If so, assign the unmonitored temperature sources to available
3956*c3963bc0SZev Weiss 	 * monitoring registers.
3957*c3963bc0SZev Weiss 	 */
3958*c3963bc0SZev Weiss 	mask = 0;
3959*c3963bc0SZev Weiss 	available = 0;
3960*c3963bc0SZev Weiss 	for (i = 0; i < num_reg_temp; i++) {
3961*c3963bc0SZev Weiss 		if (reg_temp[i] == 0)
3962*c3963bc0SZev Weiss 			continue;
3963*c3963bc0SZev Weiss 
3964*c3963bc0SZev Weiss 		err = nct6775_read_value(data, data->REG_TEMP_SOURCE[i], &src);
3965*c3963bc0SZev Weiss 		if (err)
3966*c3963bc0SZev Weiss 			return err;
3967*c3963bc0SZev Weiss 		src &= 0x1f;
3968*c3963bc0SZev Weiss 		if (!src || (mask & BIT(src)))
3969*c3963bc0SZev Weiss 			available |= BIT(i);
3970*c3963bc0SZev Weiss 
3971*c3963bc0SZev Weiss 		mask |= BIT(src);
3972*c3963bc0SZev Weiss 	}
3973*c3963bc0SZev Weiss 
3974*c3963bc0SZev Weiss 	/*
3975*c3963bc0SZev Weiss 	 * Now find unmonitored temperature registers and enable monitoring
3976*c3963bc0SZev Weiss 	 * if additional monitoring registers are available.
3977*c3963bc0SZev Weiss 	 */
3978*c3963bc0SZev Weiss 	err = add_temp_sensors(data, data->REG_TEMP_SEL, &available, &mask);
3979*c3963bc0SZev Weiss 	if (err)
3980*c3963bc0SZev Weiss 		return err;
3981*c3963bc0SZev Weiss 	err = add_temp_sensors(data, data->REG_WEIGHT_TEMP_SEL, &available, &mask);
3982*c3963bc0SZev Weiss 	if (err)
3983*c3963bc0SZev Weiss 		return err;
3984*c3963bc0SZev Weiss 
3985*c3963bc0SZev Weiss 	mask = 0;
3986*c3963bc0SZev Weiss 	s = NUM_TEMP_FIXED;	/* First dynamic temperature attribute */
3987*c3963bc0SZev Weiss 	for (i = 0; i < num_reg_temp; i++) {
3988*c3963bc0SZev Weiss 		if (reg_temp[i] == 0)
3989*c3963bc0SZev Weiss 			continue;
3990*c3963bc0SZev Weiss 
3991*c3963bc0SZev Weiss 		err = nct6775_read_value(data, data->REG_TEMP_SOURCE[i], &src);
3992*c3963bc0SZev Weiss 		if (err)
3993*c3963bc0SZev Weiss 			return err;
3994*c3963bc0SZev Weiss 		src &= 0x1f;
3995*c3963bc0SZev Weiss 		if (!src || (mask & BIT(src)))
3996*c3963bc0SZev Weiss 			continue;
3997*c3963bc0SZev Weiss 
3998*c3963bc0SZev Weiss 		if (!(data->temp_mask & BIT(src))) {
3999*c3963bc0SZev Weiss 			dev_info(dev,
4000*c3963bc0SZev Weiss 				 "Invalid temperature source %d at index %d, source register 0x%x, temp register 0x%x\n",
4001*c3963bc0SZev Weiss 				 src, i, data->REG_TEMP_SOURCE[i], reg_temp[i]);
4002*c3963bc0SZev Weiss 			continue;
4003*c3963bc0SZev Weiss 		}
4004*c3963bc0SZev Weiss 
4005*c3963bc0SZev Weiss 		mask |= BIT(src);
4006*c3963bc0SZev Weiss 
4007*c3963bc0SZev Weiss 		/* Use fixed index for SYSTIN(1), CPUTIN(2), AUXTIN(3) */
4008*c3963bc0SZev Weiss 		if (src <= data->temp_fixed_num) {
4009*c3963bc0SZev Weiss 			data->have_temp |= BIT(src - 1);
4010*c3963bc0SZev Weiss 			data->have_temp_fixed |= BIT(src - 1);
4011*c3963bc0SZev Weiss 			data->reg_temp[0][src - 1] = reg_temp[i];
4012*c3963bc0SZev Weiss 			data->reg_temp[1][src - 1] = reg_temp_over[i];
4013*c3963bc0SZev Weiss 			data->reg_temp[2][src - 1] = reg_temp_hyst[i];
4014*c3963bc0SZev Weiss 			if (reg_temp_crit_h && reg_temp_crit_h[i])
4015*c3963bc0SZev Weiss 				data->reg_temp[3][src - 1] = reg_temp_crit_h[i];
4016*c3963bc0SZev Weiss 			else if (reg_temp_crit[src - 1])
4017*c3963bc0SZev Weiss 				data->reg_temp[3][src - 1]
4018*c3963bc0SZev Weiss 				  = reg_temp_crit[src - 1];
4019*c3963bc0SZev Weiss 			if (reg_temp_crit_l && reg_temp_crit_l[i])
4020*c3963bc0SZev Weiss 				data->reg_temp[4][src - 1] = reg_temp_crit_l[i];
4021*c3963bc0SZev Weiss 			data->reg_temp_config[src - 1] = reg_temp_config[i];
4022*c3963bc0SZev Weiss 			data->temp_src[src - 1] = src;
4023*c3963bc0SZev Weiss 			continue;
4024*c3963bc0SZev Weiss 		}
4025*c3963bc0SZev Weiss 
4026*c3963bc0SZev Weiss 		if (s >= NUM_TEMP)
4027*c3963bc0SZev Weiss 			continue;
4028*c3963bc0SZev Weiss 
4029*c3963bc0SZev Weiss 		/* Use dynamic index for other sources */
4030*c3963bc0SZev Weiss 		data->have_temp |= BIT(s);
4031*c3963bc0SZev Weiss 		data->reg_temp[0][s] = reg_temp[i];
4032*c3963bc0SZev Weiss 		data->reg_temp[1][s] = reg_temp_over[i];
4033*c3963bc0SZev Weiss 		data->reg_temp[2][s] = reg_temp_hyst[i];
4034*c3963bc0SZev Weiss 		data->reg_temp_config[s] = reg_temp_config[i];
4035*c3963bc0SZev Weiss 		if (reg_temp_crit_h && reg_temp_crit_h[i])
4036*c3963bc0SZev Weiss 			data->reg_temp[3][s] = reg_temp_crit_h[i];
4037*c3963bc0SZev Weiss 		else if (reg_temp_crit[src - 1])
4038*c3963bc0SZev Weiss 			data->reg_temp[3][s] = reg_temp_crit[src - 1];
4039*c3963bc0SZev Weiss 		if (reg_temp_crit_l && reg_temp_crit_l[i])
4040*c3963bc0SZev Weiss 			data->reg_temp[4][s] = reg_temp_crit_l[i];
4041*c3963bc0SZev Weiss 
4042*c3963bc0SZev Weiss 		data->temp_src[s] = src;
4043*c3963bc0SZev Weiss 		s++;
4044*c3963bc0SZev Weiss 	}
4045*c3963bc0SZev Weiss 
4046*c3963bc0SZev Weiss 	/*
4047*c3963bc0SZev Weiss 	 * Repeat with temperatures used for fan control.
4048*c3963bc0SZev Weiss 	 * This set of registers does not support limits.
4049*c3963bc0SZev Weiss 	 */
4050*c3963bc0SZev Weiss 	for (i = 0; i < num_reg_temp_mon; i++) {
4051*c3963bc0SZev Weiss 		if (reg_temp_mon[i] == 0)
4052*c3963bc0SZev Weiss 			continue;
4053*c3963bc0SZev Weiss 
4054*c3963bc0SZev Weiss 		err = nct6775_read_value(data, data->REG_TEMP_SEL[i], &src);
4055*c3963bc0SZev Weiss 		if (err)
4056*c3963bc0SZev Weiss 			return err;
4057*c3963bc0SZev Weiss 		src &= 0x1f;
4058*c3963bc0SZev Weiss 		if (!src)
4059*c3963bc0SZev Weiss 			continue;
4060*c3963bc0SZev Weiss 
4061*c3963bc0SZev Weiss 		if (!(data->temp_mask & BIT(src))) {
4062*c3963bc0SZev Weiss 			dev_info(dev,
4063*c3963bc0SZev Weiss 				 "Invalid temperature source %d at index %d, source register 0x%x, temp register 0x%x\n",
4064*c3963bc0SZev Weiss 				 src, i, data->REG_TEMP_SEL[i],
4065*c3963bc0SZev Weiss 				 reg_temp_mon[i]);
4066*c3963bc0SZev Weiss 			continue;
4067*c3963bc0SZev Weiss 		}
4068*c3963bc0SZev Weiss 
4069*c3963bc0SZev Weiss 		/*
4070*c3963bc0SZev Weiss 		 * For virtual temperature sources, the 'virtual' temperature
4071*c3963bc0SZev Weiss 		 * for each fan reflects a different temperature, and there
4072*c3963bc0SZev Weiss 		 * are no duplicates.
4073*c3963bc0SZev Weiss 		 */
4074*c3963bc0SZev Weiss 		if (!(data->virt_temp_mask & BIT(src))) {
4075*c3963bc0SZev Weiss 			if (mask & BIT(src))
4076*c3963bc0SZev Weiss 				continue;
4077*c3963bc0SZev Weiss 			mask |= BIT(src);
4078*c3963bc0SZev Weiss 		}
4079*c3963bc0SZev Weiss 
4080*c3963bc0SZev Weiss 		/* Use fixed index for SYSTIN(1), CPUTIN(2), AUXTIN(3) */
4081*c3963bc0SZev Weiss 		if (src <= data->temp_fixed_num) {
4082*c3963bc0SZev Weiss 			if (data->have_temp & BIT(src - 1))
4083*c3963bc0SZev Weiss 				continue;
4084*c3963bc0SZev Weiss 			data->have_temp |= BIT(src - 1);
4085*c3963bc0SZev Weiss 			data->have_temp_fixed |= BIT(src - 1);
4086*c3963bc0SZev Weiss 			data->reg_temp[0][src - 1] = reg_temp_mon[i];
4087*c3963bc0SZev Weiss 			data->temp_src[src - 1] = src;
4088*c3963bc0SZev Weiss 			continue;
4089*c3963bc0SZev Weiss 		}
4090*c3963bc0SZev Weiss 
4091*c3963bc0SZev Weiss 		if (s >= NUM_TEMP)
4092*c3963bc0SZev Weiss 			continue;
4093*c3963bc0SZev Weiss 
4094*c3963bc0SZev Weiss 		/* Use dynamic index for other sources */
4095*c3963bc0SZev Weiss 		data->have_temp |= BIT(s);
4096*c3963bc0SZev Weiss 		data->reg_temp[0][s] = reg_temp_mon[i];
4097*c3963bc0SZev Weiss 		data->temp_src[s] = src;
4098*c3963bc0SZev Weiss 		s++;
4099*c3963bc0SZev Weiss 	}
4100*c3963bc0SZev Weiss 
4101*c3963bc0SZev Weiss #ifdef USE_ALTERNATE
4102*c3963bc0SZev Weiss 	/*
4103*c3963bc0SZev Weiss 	 * Go through the list of alternate temp registers and enable
4104*c3963bc0SZev Weiss 	 * if possible.
4105*c3963bc0SZev Weiss 	 * The temperature is already monitored if the respective bit in <mask>
4106*c3963bc0SZev Weiss 	 * is set.
4107*c3963bc0SZev Weiss 	 */
4108*c3963bc0SZev Weiss 	for (i = 0; i < 31; i++) {
4109*c3963bc0SZev Weiss 		if (!(data->temp_mask & BIT(i + 1)))
4110*c3963bc0SZev Weiss 			continue;
4111*c3963bc0SZev Weiss 		if (!reg_temp_alternate[i])
4112*c3963bc0SZev Weiss 			continue;
4113*c3963bc0SZev Weiss 		if (mask & BIT(i + 1))
4114*c3963bc0SZev Weiss 			continue;
4115*c3963bc0SZev Weiss 		if (i < data->temp_fixed_num) {
4116*c3963bc0SZev Weiss 			if (data->have_temp & BIT(i))
4117*c3963bc0SZev Weiss 				continue;
4118*c3963bc0SZev Weiss 			data->have_temp |= BIT(i);
4119*c3963bc0SZev Weiss 			data->have_temp_fixed |= BIT(i);
4120*c3963bc0SZev Weiss 			data->reg_temp[0][i] = reg_temp_alternate[i];
4121*c3963bc0SZev Weiss 			if (i < num_reg_temp) {
4122*c3963bc0SZev Weiss 				data->reg_temp[1][i] = reg_temp_over[i];
4123*c3963bc0SZev Weiss 				data->reg_temp[2][i] = reg_temp_hyst[i];
4124*c3963bc0SZev Weiss 			}
4125*c3963bc0SZev Weiss 			data->temp_src[i] = i + 1;
4126*c3963bc0SZev Weiss 			continue;
4127*c3963bc0SZev Weiss 		}
4128*c3963bc0SZev Weiss 
4129*c3963bc0SZev Weiss 		if (s >= NUM_TEMP)	/* Abort if no more space */
4130*c3963bc0SZev Weiss 			break;
4131*c3963bc0SZev Weiss 
4132*c3963bc0SZev Weiss 		data->have_temp |= BIT(s);
4133*c3963bc0SZev Weiss 		data->reg_temp[0][s] = reg_temp_alternate[i];
4134*c3963bc0SZev Weiss 		data->temp_src[s] = i + 1;
4135*c3963bc0SZev Weiss 		s++;
4136*c3963bc0SZev Weiss 	}
4137*c3963bc0SZev Weiss #endif /* USE_ALTERNATE */
4138*c3963bc0SZev Weiss 
4139*c3963bc0SZev Weiss 	/* Check which TSIx_TEMP registers are active */
4140*c3963bc0SZev Weiss 	for (i = 0; i < num_reg_tsi_temp; i++) {
4141*c3963bc0SZev Weiss 		u16 tmp;
4142*c3963bc0SZev Weiss 
4143*c3963bc0SZev Weiss 		err = nct6775_read_value(data, data->REG_TSI_TEMP[i], &tmp);
4144*c3963bc0SZev Weiss 		if (err)
4145*c3963bc0SZev Weiss 			return err;
4146*c3963bc0SZev Weiss 		if (tmp)
4147*c3963bc0SZev Weiss 			data->have_tsi_temp |= BIT(i);
4148*c3963bc0SZev Weiss 	}
4149*c3963bc0SZev Weiss 
4150*c3963bc0SZev Weiss 	/* Initialize the chip */
4151*c3963bc0SZev Weiss 	err = nct6775_init_device(data);
4152*c3963bc0SZev Weiss 	if (err)
4153*c3963bc0SZev Weiss 		return err;
4154*c3963bc0SZev Weiss 
4155*c3963bc0SZev Weiss 	if (data->driver_init) {
4156*c3963bc0SZev Weiss 		err = data->driver_init(data);
4157*c3963bc0SZev Weiss 		if (err)
4158*c3963bc0SZev Weiss 			return err;
4159*c3963bc0SZev Weiss 	}
4160*c3963bc0SZev Weiss 
4161*c3963bc0SZev Weiss 	/* Read fan clock dividers immediately */
4162*c3963bc0SZev Weiss 	err = nct6775_init_fan_common(dev, data);
4163*c3963bc0SZev Weiss 	if (err)
4164*c3963bc0SZev Weiss 		return err;
4165*c3963bc0SZev Weiss 
4166*c3963bc0SZev Weiss 	/* Register sysfs hooks */
4167*c3963bc0SZev Weiss 	err = nct6775_add_template_attr_group(dev, data, &nct6775_pwm_template_group,
4168*c3963bc0SZev Weiss 					      data->pwm_num);
4169*c3963bc0SZev Weiss 	if (err)
4170*c3963bc0SZev Weiss 		return err;
4171*c3963bc0SZev Weiss 
4172*c3963bc0SZev Weiss 	err = nct6775_add_template_attr_group(dev, data, &nct6775_in_template_group,
4173*c3963bc0SZev Weiss 					      fls(data->have_in));
4174*c3963bc0SZev Weiss 	if (err)
4175*c3963bc0SZev Weiss 		return err;
4176*c3963bc0SZev Weiss 
4177*c3963bc0SZev Weiss 	err = nct6775_add_template_attr_group(dev, data, &nct6775_fan_template_group,
4178*c3963bc0SZev Weiss 					      fls(data->has_fan));
4179*c3963bc0SZev Weiss 	if (err)
4180*c3963bc0SZev Weiss 		return err;
4181*c3963bc0SZev Weiss 
4182*c3963bc0SZev Weiss 	err = nct6775_add_template_attr_group(dev, data, &nct6775_temp_template_group,
4183*c3963bc0SZev Weiss 					      fls(data->have_temp));
4184*c3963bc0SZev Weiss 	if (err)
4185*c3963bc0SZev Weiss 		return err;
4186*c3963bc0SZev Weiss 
4187*c3963bc0SZev Weiss 	if (data->have_tsi_temp) {
4188*c3963bc0SZev Weiss 		tsi_temp_tg.templates = nct6775_tsi_temp_template;
4189*c3963bc0SZev Weiss 		tsi_temp_tg.is_visible = nct6775_tsi_temp_is_visible;
4190*c3963bc0SZev Weiss 		tsi_temp_tg.base = fls(data->have_temp) + 1;
4191*c3963bc0SZev Weiss 		err = nct6775_add_template_attr_group(dev, data, &tsi_temp_tg,
4192*c3963bc0SZev Weiss 						      fls(data->have_tsi_temp));
4193*c3963bc0SZev Weiss 		if (err)
4194*c3963bc0SZev Weiss 			return err;
4195*c3963bc0SZev Weiss 	}
4196*c3963bc0SZev Weiss 
4197*c3963bc0SZev Weiss 	hwmon_dev = devm_hwmon_device_register_with_groups(dev, data->name,
4198*c3963bc0SZev Weiss 							   data, data->groups);
4199*c3963bc0SZev Weiss 	return PTR_ERR_OR_ZERO(hwmon_dev);
4200*c3963bc0SZev Weiss }
4201*c3963bc0SZev Weiss EXPORT_SYMBOL_GPL(nct6775_probe);
4202*c3963bc0SZev Weiss 
4203*c3963bc0SZev Weiss MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
4204*c3963bc0SZev Weiss MODULE_DESCRIPTION("Core driver for NCT6775F and compatible chips");
4205*c3963bc0SZev Weiss MODULE_LICENSE("GPL");
4206