blob: 1560f2359f6a4432dfcb1e858d2098be81276e86 [file] [log] [blame]
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001/*
2 * nct6775 - Driver for the hardware monitoring functionality of
3 * Nuvoton NCT677x Super-I/O chips
4 *
5 * Copyright (C) 2012 Guenter Roeck <linux@roeck-us.net>
6 *
7 * Derived from w83627ehf driver
8 * Copyright (C) 2005-2012 Jean Delvare <khali@linux-fr.org>
9 * Copyright (C) 2006 Yuan Mu (Winbond),
10 * Rudolf Marek <r.marek@assembler.cz>
11 * David Hubbard <david.c.hubbard@gmail.com>
12 * Daniel J Blueman <daniel.blueman@gmail.com>
13 * Copyright (C) 2010 Sheng-Yuan Huang (Nuvoton) (PS00)
14 *
15 * Shamelessly ripped from the w83627hf driver
16 * Copyright (C) 2003 Mark Studebaker
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31 *
32 *
33 * Supports the following chips:
34 *
35 * Chip #vin #fan #pwm #temp chip IDs man ID
Guenter Roeck6c009502012-07-01 08:23:15 -070036 * nct6106d 9 3 3 6+3 0xc450 0xc1 0x5ca3
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070037 * nct6775f 9 4 3 6+3 0xb470 0xc1 0x5ca3
38 * nct6776f 9 5 3 6+3 0xc330 0xc1 0x5ca3
39 * nct6779d 15 5 5 2+6 0xc560 0xc1 0x5ca3
40 *
41 * #temp lists the number of monitored temperature sources (first value) plus
42 * the number of directly connectable temperature sensors (second value).
43 */
44
45#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
46
47#include <linux/module.h>
48#include <linux/init.h>
49#include <linux/slab.h>
50#include <linux/jiffies.h>
51#include <linux/platform_device.h>
52#include <linux/hwmon.h>
53#include <linux/hwmon-sysfs.h>
54#include <linux/hwmon-vid.h>
55#include <linux/err.h>
56#include <linux/mutex.h>
57#include <linux/acpi.h>
58#include <linux/io.h>
59#include "lm75.h"
60
Guenter Roeckaa136e52012-12-04 03:26:05 -080061#define USE_ALTERNATE
62
Guenter Roeck6c009502012-07-01 08:23:15 -070063enum kinds { nct6106, nct6775, nct6776, nct6779 };
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070064
65/* used to set data->name = nct6775_device_names[data->sio_kind] */
66static const char * const nct6775_device_names[] = {
Guenter Roeck6c009502012-07-01 08:23:15 -070067 "nct6106",
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070068 "nct6775",
69 "nct6776",
70 "nct6779",
71};
72
73static unsigned short force_id;
74module_param(force_id, ushort, 0);
75MODULE_PARM_DESC(force_id, "Override the detected device ID");
76
Guenter Roeck47ece962012-12-04 07:59:32 -080077static unsigned short fan_debounce;
78module_param(fan_debounce, ushort, 0);
79MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal");
80
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070081#define DRVNAME "nct6775"
82
83/*
84 * Super-I/O constants and functions
85 */
86
Guenter Roecka6bd5872012-12-04 03:13:34 -080087#define NCT6775_LD_ACPI 0x0a
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070088#define NCT6775_LD_HWM 0x0b
89#define NCT6775_LD_VID 0x0d
90
91#define SIO_REG_LDSEL 0x07 /* Logical device select */
92#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
93#define SIO_REG_ENABLE 0x30 /* Logical device enable */
94#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
95
Guenter Roeck6c009502012-07-01 08:23:15 -070096#define SIO_NCT6106_ID 0xc450
Guenter Roeck9de2e2e2012-05-20 19:29:48 -070097#define SIO_NCT6775_ID 0xb470
98#define SIO_NCT6776_ID 0xc330
99#define SIO_NCT6779_ID 0xc560
100#define SIO_ID_MASK 0xFFF0
101
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800102enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 };
103
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700104static inline void
105superio_outb(int ioreg, int reg, int val)
106{
107 outb(reg, ioreg);
108 outb(val, ioreg + 1);
109}
110
111static inline int
112superio_inb(int ioreg, int reg)
113{
114 outb(reg, ioreg);
115 return inb(ioreg + 1);
116}
117
118static inline void
119superio_select(int ioreg, int ld)
120{
121 outb(SIO_REG_LDSEL, ioreg);
122 outb(ld, ioreg + 1);
123}
124
125static inline int
126superio_enter(int ioreg)
127{
128 /*
129 * Try to reserve <ioreg> and <ioreg + 1> for exclusive access.
130 */
131 if (!request_muxed_region(ioreg, 2, DRVNAME))
132 return -EBUSY;
133
134 outb(0x87, ioreg);
135 outb(0x87, ioreg);
136
137 return 0;
138}
139
140static inline void
141superio_exit(int ioreg)
142{
143 outb(0xaa, ioreg);
144 outb(0x02, ioreg);
145 outb(0x02, ioreg + 1);
146 release_region(ioreg, 2);
147}
148
149/*
150 * ISA constants
151 */
152
153#define IOREGION_ALIGNMENT (~7)
154#define IOREGION_OFFSET 5
155#define IOREGION_LENGTH 2
156#define ADDR_REG_OFFSET 0
157#define DATA_REG_OFFSET 1
158
159#define NCT6775_REG_BANK 0x4E
160#define NCT6775_REG_CONFIG 0x40
161
162/*
163 * Not currently used:
164 * REG_MAN_ID has the value 0x5ca3 for all supported chips.
165 * REG_CHIP_ID == 0x88/0xa1/0xc1 depending on chip model.
166 * REG_MAN_ID is at port 0x4f
167 * REG_CHIP_ID is at port 0x58
168 */
169
Guenter Roeckaa136e52012-12-04 03:26:05 -0800170#define NUM_TEMP 10 /* Max number of temp attribute sets w/ limits*/
171#define NUM_TEMP_FIXED 6 /* Max number of fixed temp attribute sets */
172
Guenter Roeck6c009502012-07-01 08:23:15 -0700173#define NUM_REG_ALARM 7 /* Max number of alarm registers */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700174
175/* Common and NCT6775 specific data */
176
177/* Voltage min/max registers for nr=7..14 are in bank 5 */
178
179static const u16 NCT6775_REG_IN_MAX[] = {
180 0x2b, 0x2d, 0x2f, 0x31, 0x33, 0x35, 0x37, 0x554, 0x556, 0x558, 0x55a,
181 0x55c, 0x55e, 0x560, 0x562 };
182static const u16 NCT6775_REG_IN_MIN[] = {
183 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x555, 0x557, 0x559, 0x55b,
184 0x55d, 0x55f, 0x561, 0x563 };
185static const u16 NCT6775_REG_IN[] = {
186 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x550, 0x551, 0x552
187};
188
189#define NCT6775_REG_VBAT 0x5D
Guenter Roeckaa136e52012-12-04 03:26:05 -0800190#define NCT6775_REG_DIODE 0x5E
Guenter Roeck6c009502012-07-01 08:23:15 -0700191#define NCT6775_DIODE_MASK 0x02
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700192
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800193#define NCT6775_REG_FANDIV1 0x506
194#define NCT6775_REG_FANDIV2 0x507
195
Guenter Roeck47ece962012-12-04 07:59:32 -0800196#define NCT6775_REG_CR_FAN_DEBOUNCE 0xf0
197
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700198static const u16 NCT6775_REG_ALARM[NUM_REG_ALARM] = { 0x459, 0x45A, 0x45B };
199
200/* 0..15 voltages, 16..23 fans, 24..31 temperatures */
201
202static const s8 NCT6775_ALARM_BITS[] = {
203 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
204 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */
205 -1, /* unused */
Guenter Roeck41fa9a92013-06-23 13:04:04 -0700206 6, 7, 11, -1, -1, /* fan1..fan5 */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700207 -1, -1, -1, /* unused */
208 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
209 12, -1 }; /* intrusion0, intrusion1 */
210
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800211#define FAN_ALARM_BASE 16
Guenter Roeckaa136e52012-12-04 03:26:05 -0800212#define TEMP_ALARM_BASE 24
Guenter Roecka6bd5872012-12-04 03:13:34 -0800213#define INTRUSION_ALARM_BASE 30
214
215static const u8 NCT6775_REG_CR_CASEOPEN_CLR[] = { 0xe6, 0xee };
216static const u8 NCT6775_CR_CASEOPEN_CLR_MASK[] = { 0x20, 0x01 };
217
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800218/* DC or PWM output fan configuration */
219static const u8 NCT6775_REG_PWM_MODE[] = { 0x04, 0x04, 0x12 };
220static const u8 NCT6775_PWM_MODE_MASK[] = { 0x01, 0x02, 0x01 };
221
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800222/* Advanced Fan control, some values are common for all fans */
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800223
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800224static const u16 NCT6775_REG_TARGET[] = { 0x101, 0x201, 0x301, 0x801, 0x901 };
225static const u16 NCT6775_REG_FAN_MODE[] = { 0x102, 0x202, 0x302, 0x802, 0x902 };
226static const u16 NCT6775_REG_FAN_STEP_DOWN_TIME[] = {
227 0x103, 0x203, 0x303, 0x803, 0x903 };
228static const u16 NCT6775_REG_FAN_STEP_UP_TIME[] = {
229 0x104, 0x204, 0x304, 0x804, 0x904 };
230static const u16 NCT6775_REG_FAN_STOP_OUTPUT[] = {
231 0x105, 0x205, 0x305, 0x805, 0x905 };
232static const u16 NCT6775_REG_FAN_START_OUTPUT[]
233 = { 0x106, 0x206, 0x306, 0x806, 0x906 };
234static const u16 NCT6775_REG_FAN_MAX_OUTPUT[] = { 0x10a, 0x20a, 0x30a };
235static const u16 NCT6775_REG_FAN_STEP_OUTPUT[] = { 0x10b, 0x20b, 0x30b };
236
237static const u16 NCT6775_REG_FAN_STOP_TIME[] = {
238 0x107, 0x207, 0x307, 0x807, 0x907 };
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800239static const u16 NCT6775_REG_PWM[] = { 0x109, 0x209, 0x309, 0x809, 0x909 };
240static const u16 NCT6775_REG_PWM_READ[] = { 0x01, 0x03, 0x11, 0x13, 0x15 };
241
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800242static const u16 NCT6775_REG_FAN[] = { 0x630, 0x632, 0x634, 0x636, 0x638 };
243static const u16 NCT6775_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d };
Guenter Roeck5c25d952012-12-11 07:29:06 -0800244static const u16 NCT6775_REG_FAN_PULSES[] = { 0x641, 0x642, 0x643, 0x644, 0 };
Guenter Roeck6c009502012-07-01 08:23:15 -0700245static const u16 NCT6775_FAN_PULSE_SHIFT[] = { 0, 0, 0, 0, 0 };
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800246
Guenter Roeckaa136e52012-12-04 03:26:05 -0800247static const u16 NCT6775_REG_TEMP[] = {
248 0x27, 0x150, 0x250, 0x62b, 0x62c, 0x62d };
249
250static const u16 NCT6775_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
251 0, 0x152, 0x252, 0x628, 0x629, 0x62A };
252static const u16 NCT6775_REG_TEMP_HYST[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
253 0x3a, 0x153, 0x253, 0x673, 0x678, 0x67D };
254static const u16 NCT6775_REG_TEMP_OVER[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
255 0x39, 0x155, 0x255, 0x672, 0x677, 0x67C };
256
257static const u16 NCT6775_REG_TEMP_SOURCE[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
258 0x621, 0x622, 0x623, 0x624, 0x625, 0x626 };
259
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800260static const u16 NCT6775_REG_TEMP_SEL[] = {
261 0x100, 0x200, 0x300, 0x800, 0x900 };
262
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800263static const u16 NCT6775_REG_WEIGHT_TEMP_SEL[] = {
264 0x139, 0x239, 0x339, 0x839, 0x939 };
265static const u16 NCT6775_REG_WEIGHT_TEMP_STEP[] = {
266 0x13a, 0x23a, 0x33a, 0x83a, 0x93a };
267static const u16 NCT6775_REG_WEIGHT_TEMP_STEP_TOL[] = {
268 0x13b, 0x23b, 0x33b, 0x83b, 0x93b };
269static const u16 NCT6775_REG_WEIGHT_DUTY_STEP[] = {
270 0x13c, 0x23c, 0x33c, 0x83c, 0x93c };
271static const u16 NCT6775_REG_WEIGHT_TEMP_BASE[] = {
272 0x13d, 0x23d, 0x33d, 0x83d, 0x93d };
273
Guenter Roeckaa136e52012-12-04 03:26:05 -0800274static const u16 NCT6775_REG_TEMP_OFFSET[] = { 0x454, 0x455, 0x456 };
275
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800276static const u16 NCT6775_REG_AUTO_TEMP[] = {
277 0x121, 0x221, 0x321, 0x821, 0x921 };
278static const u16 NCT6775_REG_AUTO_PWM[] = {
279 0x127, 0x227, 0x327, 0x827, 0x927 };
280
281#define NCT6775_AUTO_TEMP(data, nr, p) ((data)->REG_AUTO_TEMP[nr] + (p))
282#define NCT6775_AUTO_PWM(data, nr, p) ((data)->REG_AUTO_PWM[nr] + (p))
283
284static const u16 NCT6775_REG_CRITICAL_ENAB[] = { 0x134, 0x234, 0x334 };
285
286static const u16 NCT6775_REG_CRITICAL_TEMP[] = {
287 0x135, 0x235, 0x335, 0x835, 0x935 };
288static const u16 NCT6775_REG_CRITICAL_TEMP_TOLERANCE[] = {
289 0x138, 0x238, 0x338, 0x838, 0x938 };
290
Guenter Roeckaa136e52012-12-04 03:26:05 -0800291static const char *const nct6775_temp_label[] = {
292 "",
293 "SYSTIN",
294 "CPUTIN",
295 "AUXTIN",
296 "AMD SB-TSI",
297 "PECI Agent 0",
298 "PECI Agent 1",
299 "PECI Agent 2",
300 "PECI Agent 3",
301 "PECI Agent 4",
302 "PECI Agent 5",
303 "PECI Agent 6",
304 "PECI Agent 7",
305 "PCH_CHIP_CPU_MAX_TEMP",
306 "PCH_CHIP_TEMP",
307 "PCH_CPU_TEMP",
308 "PCH_MCH_TEMP",
309 "PCH_DIM0_TEMP",
310 "PCH_DIM1_TEMP",
311 "PCH_DIM2_TEMP",
312 "PCH_DIM3_TEMP"
313};
314
315static const u16 NCT6775_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6775_temp_label) - 1]
316 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x661, 0x662, 0x664 };
317
318static const u16 NCT6775_REG_TEMP_CRIT[ARRAY_SIZE(nct6775_temp_label) - 1]
319 = { 0, 0, 0, 0, 0xa00, 0xa01, 0xa02, 0xa03, 0xa04, 0xa05, 0xa06,
320 0xa07 };
321
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700322/* NCT6776 specific data */
323
324static const s8 NCT6776_ALARM_BITS[] = {
325 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
326 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */
327 -1, /* unused */
328 6, 7, 11, 10, 23, /* fan1..fan5 */
329 -1, -1, -1, /* unused */
330 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
331 12, 9 }; /* intrusion0, intrusion1 */
332
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800333static const u16 NCT6776_REG_TOLERANCE_H[] = {
334 0x10c, 0x20c, 0x30c, 0x80c, 0x90c };
335
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800336static const u8 NCT6776_REG_PWM_MODE[] = { 0x04, 0, 0 };
337static const u8 NCT6776_PWM_MODE_MASK[] = { 0x01, 0, 0 };
338
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800339static const u16 NCT6776_REG_FAN_MIN[] = { 0x63a, 0x63c, 0x63e, 0x640, 0x642 };
Guenter Roeck5c25d952012-12-11 07:29:06 -0800340static const u16 NCT6776_REG_FAN_PULSES[] = { 0x644, 0x645, 0x646, 0, 0 };
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800341
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800342static const u16 NCT6776_REG_WEIGHT_DUTY_BASE[] = {
343 0x13e, 0x23e, 0x33e, 0x83e, 0x93e };
344
Guenter Roeckaa136e52012-12-04 03:26:05 -0800345static const u16 NCT6776_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6775_REG_TEMP)] = {
346 0x18, 0x152, 0x252, 0x628, 0x629, 0x62A };
347
348static const char *const nct6776_temp_label[] = {
349 "",
350 "SYSTIN",
351 "CPUTIN",
352 "AUXTIN",
353 "SMBUSMASTER 0",
354 "SMBUSMASTER 1",
355 "SMBUSMASTER 2",
356 "SMBUSMASTER 3",
357 "SMBUSMASTER 4",
358 "SMBUSMASTER 5",
359 "SMBUSMASTER 6",
360 "SMBUSMASTER 7",
361 "PECI Agent 0",
362 "PECI Agent 1",
363 "PCH_CHIP_CPU_MAX_TEMP",
364 "PCH_CHIP_TEMP",
365 "PCH_CPU_TEMP",
366 "PCH_MCH_TEMP",
367 "PCH_DIM0_TEMP",
368 "PCH_DIM1_TEMP",
369 "PCH_DIM2_TEMP",
370 "PCH_DIM3_TEMP",
371 "BYTE_TEMP"
372};
373
374static const u16 NCT6776_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6776_temp_label) - 1]
375 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x401, 0x402, 0x404 };
376
377static const u16 NCT6776_REG_TEMP_CRIT[ARRAY_SIZE(nct6776_temp_label) - 1]
378 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a };
379
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700380/* NCT6779 specific data */
381
382static const u16 NCT6779_REG_IN[] = {
383 0x480, 0x481, 0x482, 0x483, 0x484, 0x485, 0x486, 0x487,
384 0x488, 0x489, 0x48a, 0x48b, 0x48c, 0x48d, 0x48e };
385
386static const u16 NCT6779_REG_ALARM[NUM_REG_ALARM] = {
387 0x459, 0x45A, 0x45B, 0x568 };
388
389static const s8 NCT6779_ALARM_BITS[] = {
390 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */
391 17, 24, 25, 26, 27, 28, 29, /* in8..in14 */
392 -1, /* unused */
393 6, 7, 11, 10, 23, /* fan1..fan5 */
394 -1, -1, -1, /* unused */
395 4, 5, 13, -1, -1, -1, /* temp1..temp6 */
396 12, 9 }; /* intrusion0, intrusion1 */
397
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800398static const u16 NCT6779_REG_FAN[] = { 0x4b0, 0x4b2, 0x4b4, 0x4b6, 0x4b8 };
Guenter Roeck5c25d952012-12-11 07:29:06 -0800399static const u16 NCT6779_REG_FAN_PULSES[] = {
400 0x644, 0x645, 0x646, 0x647, 0x648 };
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800401
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800402static const u16 NCT6779_REG_CRITICAL_PWM_ENABLE[] = {
403 0x136, 0x236, 0x336, 0x836, 0x936 };
Guenter Roeck6c009502012-07-01 08:23:15 -0700404#define NCT6779_CRITICAL_PWM_ENABLE_MASK 0x01
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800405static const u16 NCT6779_REG_CRITICAL_PWM[] = {
406 0x137, 0x237, 0x337, 0x837, 0x937 };
407
Guenter Roeckaa136e52012-12-04 03:26:05 -0800408static const u16 NCT6779_REG_TEMP[] = { 0x27, 0x150 };
409static const u16 NCT6779_REG_TEMP_CONFIG[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
410 0x18, 0x152 };
411static const u16 NCT6779_REG_TEMP_HYST[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
412 0x3a, 0x153 };
413static const u16 NCT6779_REG_TEMP_OVER[ARRAY_SIZE(NCT6779_REG_TEMP)] = {
414 0x39, 0x155 };
415
416static const u16 NCT6779_REG_TEMP_OFFSET[] = {
417 0x454, 0x455, 0x456, 0x44a, 0x44b, 0x44c };
418
419static const char *const nct6779_temp_label[] = {
420 "",
421 "SYSTIN",
422 "CPUTIN",
423 "AUXTIN0",
424 "AUXTIN1",
425 "AUXTIN2",
426 "AUXTIN3",
427 "",
428 "SMBUSMASTER 0",
429 "SMBUSMASTER 1",
430 "SMBUSMASTER 2",
431 "SMBUSMASTER 3",
432 "SMBUSMASTER 4",
433 "SMBUSMASTER 5",
434 "SMBUSMASTER 6",
435 "SMBUSMASTER 7",
436 "PECI Agent 0",
437 "PECI Agent 1",
438 "PCH_CHIP_CPU_MAX_TEMP",
439 "PCH_CHIP_TEMP",
440 "PCH_CPU_TEMP",
441 "PCH_MCH_TEMP",
442 "PCH_DIM0_TEMP",
443 "PCH_DIM1_TEMP",
444 "PCH_DIM2_TEMP",
445 "PCH_DIM3_TEMP",
446 "BYTE_TEMP"
447};
448
449static const u16 NCT6779_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6779_temp_label) - 1]
450 = { 0x490, 0x491, 0x492, 0x493, 0x494, 0x495, 0, 0,
451 0, 0, 0, 0, 0, 0, 0, 0,
452 0, 0x400, 0x401, 0x402, 0x404, 0x405, 0x406, 0x407,
453 0x408, 0 };
454
455static const u16 NCT6779_REG_TEMP_CRIT[ARRAY_SIZE(nct6779_temp_label) - 1]
456 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a };
457
Guenter Roeck6c009502012-07-01 08:23:15 -0700458/* NCT6102D/NCT6106D specific data */
459
460#define NCT6106_REG_VBAT 0x318
461#define NCT6106_REG_DIODE 0x319
462#define NCT6106_DIODE_MASK 0x01
463
464static const u16 NCT6106_REG_IN_MAX[] = {
465 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9e, 0xa0, 0xa2 };
466static const u16 NCT6106_REG_IN_MIN[] = {
467 0x91, 0x93, 0x95, 0x97, 0x99, 0x9b, 0x9f, 0xa1, 0xa3 };
468static const u16 NCT6106_REG_IN[] = {
469 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x07, 0x08, 0x09 };
470
471static const u16 NCT6106_REG_TEMP[] = { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15 };
472static const u16 NCT6106_REG_TEMP_HYST[] = {
473 0xc3, 0xc7, 0xcb, 0xcf, 0xd3, 0xd7 };
474static const u16 NCT6106_REG_TEMP_OVER[] = {
Guenter Roeckb7a61352013-04-02 22:14:06 -0700475 0xc2, 0xc6, 0xca, 0xce, 0xd2, 0xd6 };
476static const u16 NCT6106_REG_TEMP_CRIT_L[] = {
477 0xc0, 0xc4, 0xc8, 0xcc, 0xd0, 0xd4 };
478static const u16 NCT6106_REG_TEMP_CRIT_H[] = {
479 0xc1, 0xc5, 0xc9, 0xcf, 0xd1, 0xd5 };
Guenter Roeck6c009502012-07-01 08:23:15 -0700480static const u16 NCT6106_REG_TEMP_OFFSET[] = { 0x311, 0x312, 0x313 };
481static const u16 NCT6106_REG_TEMP_CONFIG[] = {
482 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc };
483
484static const u16 NCT6106_REG_FAN[] = { 0x20, 0x22, 0x24 };
485static const u16 NCT6106_REG_FAN_MIN[] = { 0xe0, 0xe2, 0xe4 };
486static const u16 NCT6106_REG_FAN_PULSES[] = { 0xf6, 0xf6, 0xf6, 0, 0 };
487static const u16 NCT6106_FAN_PULSE_SHIFT[] = { 0, 2, 4, 0, 0 };
488
489static const u8 NCT6106_REG_PWM_MODE[] = { 0xf3, 0xf3, 0xf3 };
490static const u8 NCT6106_PWM_MODE_MASK[] = { 0x01, 0x02, 0x04 };
491static const u16 NCT6106_REG_PWM[] = { 0x119, 0x129, 0x139 };
492static const u16 NCT6106_REG_PWM_READ[] = { 0x4a, 0x4b, 0x4c };
493static const u16 NCT6106_REG_FAN_MODE[] = { 0x113, 0x123, 0x133 };
494static const u16 NCT6106_REG_TEMP_SEL[] = { 0x110, 0x120, 0x130 };
495static const u16 NCT6106_REG_TEMP_SOURCE[] = {
496 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5 };
497
498static const u16 NCT6106_REG_CRITICAL_TEMP[] = { 0x11a, 0x12a, 0x13a };
499static const u16 NCT6106_REG_CRITICAL_TEMP_TOLERANCE[] = {
500 0x11b, 0x12b, 0x13b };
501
502static const u16 NCT6106_REG_CRITICAL_PWM_ENABLE[] = { 0x11c, 0x12c, 0x13c };
503#define NCT6106_CRITICAL_PWM_ENABLE_MASK 0x10
504static const u16 NCT6106_REG_CRITICAL_PWM[] = { 0x11d, 0x12d, 0x13d };
505
506static const u16 NCT6106_REG_FAN_STEP_UP_TIME[] = { 0x114, 0x124, 0x134 };
507static const u16 NCT6106_REG_FAN_STEP_DOWN_TIME[] = { 0x115, 0x125, 0x135 };
508static const u16 NCT6106_REG_FAN_STOP_OUTPUT[] = { 0x116, 0x126, 0x136 };
509static const u16 NCT6106_REG_FAN_START_OUTPUT[] = { 0x117, 0x127, 0x137 };
510static const u16 NCT6106_REG_FAN_STOP_TIME[] = { 0x118, 0x128, 0x138 };
511static const u16 NCT6106_REG_TOLERANCE_H[] = { 0x112, 0x122, 0x132 };
512
513static const u16 NCT6106_REG_TARGET[] = { 0x111, 0x121, 0x131 };
514
515static const u16 NCT6106_REG_WEIGHT_TEMP_SEL[] = { 0x168, 0x178, 0x188 };
516static const u16 NCT6106_REG_WEIGHT_TEMP_STEP[] = { 0x169, 0x179, 0x189 };
517static const u16 NCT6106_REG_WEIGHT_TEMP_STEP_TOL[] = { 0x16a, 0x17a, 0x18a };
518static const u16 NCT6106_REG_WEIGHT_DUTY_STEP[] = { 0x16b, 0x17b, 0x17c };
519static const u16 NCT6106_REG_WEIGHT_TEMP_BASE[] = { 0x16c, 0x17c, 0x18c };
520static const u16 NCT6106_REG_WEIGHT_DUTY_BASE[] = { 0x16d, 0x17d, 0x18d };
521
522static const u16 NCT6106_REG_AUTO_TEMP[] = { 0x160, 0x170, 0x180 };
523static const u16 NCT6106_REG_AUTO_PWM[] = { 0x164, 0x174, 0x184 };
524
525static const u16 NCT6106_REG_ALARM[NUM_REG_ALARM] = {
526 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d };
527
528static const s8 NCT6106_ALARM_BITS[] = {
529 0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */
530 9, -1, -1, -1, -1, -1, -1, /* in8..in14 */
531 -1, /* unused */
532 32, 33, 34, -1, -1, /* fan1..fan5 */
533 -1, -1, -1, /* unused */
534 16, 17, 18, 19, 20, 21, /* temp1..temp6 */
535 48, -1 /* intrusion0, intrusion1 */
536};
537
538static const u16 NCT6106_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6776_temp_label) - 1]
539 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x51, 0x52, 0x54 };
540
541static const u16 NCT6106_REG_TEMP_CRIT[ARRAY_SIZE(nct6776_temp_label) - 1]
542 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x204, 0x205 };
543
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800544static enum pwm_enable reg_to_pwm_enable(int pwm, int mode)
545{
546 if (mode == 0 && pwm == 255)
547 return off;
548 return mode + 1;
549}
550
551static int pwm_enable_to_reg(enum pwm_enable mode)
552{
553 if (mode == off)
554 return 0;
555 return mode - 1;
556}
557
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700558/*
559 * Conversions
560 */
561
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800562/* 1 is DC mode, output in ms */
563static unsigned int step_time_from_reg(u8 reg, u8 mode)
564{
565 return mode ? 400 * reg : 100 * reg;
566}
567
568static u8 step_time_to_reg(unsigned int msec, u8 mode)
569{
570 return clamp_val((mode ? (msec + 200) / 400 :
571 (msec + 50) / 100), 1, 255);
572}
573
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800574static unsigned int fan_from_reg8(u16 reg, unsigned int divreg)
575{
576 if (reg == 0 || reg == 255)
577 return 0;
578 return 1350000U / (reg << divreg);
579}
580
581static unsigned int fan_from_reg13(u16 reg, unsigned int divreg)
582{
583 if ((reg & 0xff1f) == 0xff1f)
584 return 0;
585
586 reg = (reg & 0x1f) | ((reg & 0xff00) >> 3);
587
588 if (reg == 0)
589 return 0;
590
591 return 1350000U / reg;
592}
593
594static unsigned int fan_from_reg16(u16 reg, unsigned int divreg)
595{
596 if (reg == 0 || reg == 0xffff)
597 return 0;
598
599 /*
600 * Even though the registers are 16 bit wide, the fan divisor
601 * still applies.
602 */
603 return 1350000U / (reg << divreg);
604}
605
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800606static u16 fan_to_reg(u32 fan, unsigned int divreg)
607{
608 if (!fan)
609 return 0;
610
611 return (1350000U / fan) >> divreg;
612}
613
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800614static inline unsigned int
615div_from_reg(u8 reg)
616{
617 return 1 << reg;
618}
619
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700620/*
621 * Some of the voltage inputs have internal scaling, the tables below
622 * contain 8 (the ADC LSB in mV) * scaling factor * 100
623 */
624static const u16 scale_in[15] = {
625 800, 800, 1600, 1600, 800, 800, 800, 1600, 1600, 800, 800, 800, 800,
626 800, 800
627};
628
629static inline long in_from_reg(u8 reg, u8 nr)
630{
631 return DIV_ROUND_CLOSEST(reg * scale_in[nr], 100);
632}
633
634static inline u8 in_to_reg(u32 val, u8 nr)
635{
636 return clamp_val(DIV_ROUND_CLOSEST(val * 100, scale_in[nr]), 0, 255);
637}
638
639/*
640 * Data structures and manipulation thereof
641 */
642
643struct nct6775_data {
644 int addr; /* IO base of hw monitor block */
645 enum kinds kind;
646 const char *name;
647
648 struct device *hwmon_dev;
Guenter Roeckf73cf632013-03-18 09:22:50 -0700649 struct attribute_group *group_in;
650 struct attribute_group *group_fan;
651 struct attribute_group *group_temp;
652 struct attribute_group *group_pwm;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700653
Guenter Roeckb7a61352013-04-02 22:14:06 -0700654 u16 reg_temp[5][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
655 * 3=temp_crit, 4=temp_lcrit
Guenter Roeckaa136e52012-12-04 03:26:05 -0800656 */
657 u8 temp_src[NUM_TEMP];
658 u16 reg_temp_config[NUM_TEMP];
659 const char * const *temp_label;
660 int temp_label_num;
661
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700662 u16 REG_CONFIG;
663 u16 REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -0800664 u16 REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -0700665 u8 DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700666
667 const s8 *ALARM_BITS;
668
669 const u16 *REG_VIN;
670 const u16 *REG_IN_MINMAX[2];
671
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800672 const u16 *REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800673 const u16 *REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800674 const u16 *REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800675 const u16 *REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -0800676 const u16 *REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -0700677 const u16 *FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800678 const u16 *REG_FAN_TIME[3];
679
680 const u16 *REG_TOLERANCE_H;
Guenter Roeckaa136e52012-12-04 03:26:05 -0800681
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800682 const u8 *REG_PWM_MODE;
683 const u8 *PWM_MODE_MASK;
684
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800685 const u16 *REG_PWM[7]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor,
686 * [3]=pwm_max, [4]=pwm_step,
687 * [5]=weight_duty_step, [6]=weight_duty_base
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800688 */
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800689 const u16 *REG_PWM_READ;
690
Guenter Roeck6c009502012-07-01 08:23:15 -0700691 const u16 *REG_CRITICAL_PWM_ENABLE;
692 u8 CRITICAL_PWM_ENABLE_MASK;
693 const u16 *REG_CRITICAL_PWM;
694
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800695 const u16 *REG_AUTO_TEMP;
696 const u16 *REG_AUTO_PWM;
697
698 const u16 *REG_CRITICAL_TEMP;
699 const u16 *REG_CRITICAL_TEMP_TOLERANCE;
700
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800701 const u16 *REG_TEMP_SOURCE; /* temp register sources */
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800702 const u16 *REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800703 const u16 *REG_WEIGHT_TEMP_SEL;
704 const u16 *REG_WEIGHT_TEMP[3]; /* 0=base, 1=tolerance, 2=step */
705
Guenter Roeckaa136e52012-12-04 03:26:05 -0800706 const u16 *REG_TEMP_OFFSET;
707
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700708 const u16 *REG_ALARM;
709
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800710 unsigned int (*fan_from_reg)(u16 reg, unsigned int divreg);
711 unsigned int (*fan_from_reg_min)(u16 reg, unsigned int divreg);
712
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700713 struct mutex update_lock;
714 bool valid; /* true if following fields are valid */
715 unsigned long last_updated; /* In jiffies */
716
717 /* Register values */
718 u8 bank; /* current register bank */
719 u8 in_num; /* number of in inputs we have */
720 u8 in[15][3]; /* [0]=in, [1]=in_max, [2]=in_min */
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800721 unsigned int rpm[5];
722 u16 fan_min[5];
Guenter Roeck5c25d952012-12-11 07:29:06 -0800723 u8 fan_pulses[5];
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800724 u8 fan_div[5];
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800725 u8 has_pwm;
Guenter Roeck1c65dc32012-12-04 07:56:24 -0800726 u8 has_fan; /* some fan inputs can be disabled */
727 u8 has_fan_min; /* some fans don't have min register */
728 bool has_fan_div;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700729
Guenter Roeck6c009502012-07-01 08:23:15 -0700730 u8 num_temp_alarms; /* 2, 3, or 6 */
Guenter Roeckaa136e52012-12-04 03:26:05 -0800731 u8 temp_fixed_num; /* 3 or 6 */
732 u8 temp_type[NUM_TEMP_FIXED];
733 s8 temp_offset[NUM_TEMP_FIXED];
734 s16 temp[4][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
735 * 3=temp_crit */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700736 u64 alarms;
737
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800738 u8 pwm_num; /* number of pwm */
739 u8 pwm_mode[5]; /* 1->DC variable voltage, 0->PWM variable duty cycle */
740 enum pwm_enable pwm_enable[5];
741 /* 0->off
742 * 1->manual
743 * 2->thermal cruise mode (also called SmartFan I)
744 * 3->fan speed cruise mode
745 * 4->SmartFan III
746 * 5->enhanced variable thermal cruise (SmartFan IV)
747 */
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800748 u8 pwm[7][5]; /* [0]=pwm, [1]=pwm_start, [2]=pwm_floor,
749 * [3]=pwm_max, [4]=pwm_step,
750 * [5]=weight_duty_step, [6]=weight_duty_base
Guenter Roeckcdcaece2012-12-04 09:04:52 -0800751 */
752
753 u8 target_temp[5];
754 u8 target_temp_mask;
755 u32 target_speed[5];
756 u32 target_speed_tolerance[5];
757 u8 speed_tolerance_limit;
758
759 u8 temp_tolerance[2][5];
760 u8 tolerance_mask;
761
762 u8 fan_time[3][5]; /* 0 = stop_time, 1 = step_up, 2 = step_down */
763
764 /* Automatic fan speed control registers */
765 int auto_pwm_num;
766 u8 auto_pwm[5][7];
767 u8 auto_temp[5][7];
768 u8 pwm_temp_sel[5];
Guenter Roeckbbd8dec2012-12-04 09:08:29 -0800769 u8 pwm_weight_temp_sel[5];
770 u8 weight_temp[3][5]; /* 0->temp_step, 1->temp_step_tol,
771 * 2->temp_base
772 */
Guenter Roeck77eb5b32012-12-04 08:30:54 -0800773
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700774 u8 vid;
775 u8 vrm;
776
Guenter Roeckf73cf632013-03-18 09:22:50 -0700777 bool have_vid;
778
Guenter Roeckaa136e52012-12-04 03:26:05 -0800779 u16 have_temp;
780 u16 have_temp_fixed;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700781 u16 have_in;
Guenter Roeck84d19d92012-12-04 08:01:39 -0800782#ifdef CONFIG_PM
783 /* Remember extra register values over suspend/resume */
784 u8 vbat;
785 u8 fandiv1;
786 u8 fandiv2;
787#endif
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700788};
789
790struct nct6775_sio_data {
791 int sioreg;
792 enum kinds kind;
793};
794
Guenter Roeckf73cf632013-03-18 09:22:50 -0700795struct sensor_device_template {
796 struct device_attribute dev_attr;
797 union {
798 struct {
799 u8 nr;
800 u8 index;
801 } s;
802 int index;
803 } u;
804 bool s2; /* true if both index and nr are used */
805};
806
807struct sensor_device_attr_u {
808 union {
809 struct sensor_device_attribute a1;
810 struct sensor_device_attribute_2 a2;
811 } u;
812 char name[32];
813};
814
815#define __TEMPLATE_ATTR(_template, _mode, _show, _store) { \
816 .attr = {.name = _template, .mode = _mode }, \
817 .show = _show, \
818 .store = _store, \
819}
820
821#define SENSOR_DEVICE_TEMPLATE(_template, _mode, _show, _store, _index) \
822 { .dev_attr = __TEMPLATE_ATTR(_template, _mode, _show, _store), \
823 .u.index = _index, \
824 .s2 = false }
825
826#define SENSOR_DEVICE_TEMPLATE_2(_template, _mode, _show, _store, \
827 _nr, _index) \
828 { .dev_attr = __TEMPLATE_ATTR(_template, _mode, _show, _store), \
829 .u.s.index = _index, \
830 .u.s.nr = _nr, \
831 .s2 = true }
832
833#define SENSOR_TEMPLATE(_name, _template, _mode, _show, _store, _index) \
834static struct sensor_device_template sensor_dev_template_##_name \
835 = SENSOR_DEVICE_TEMPLATE(_template, _mode, _show, _store, \
836 _index)
837
838#define SENSOR_TEMPLATE_2(_name, _template, _mode, _show, _store, \
839 _nr, _index) \
840static struct sensor_device_template sensor_dev_template_##_name \
841 = SENSOR_DEVICE_TEMPLATE_2(_template, _mode, _show, _store, \
842 _nr, _index)
843
844struct sensor_template_group {
845 struct sensor_device_template **templates;
846 umode_t (*is_visible)(struct kobject *, struct attribute *, int);
847 int base;
848};
849
850static struct attribute_group *
851nct6775_create_attr_group(struct device *dev, struct sensor_template_group *tg,
852 int repeat)
853{
854 struct attribute_group *group;
855 struct sensor_device_attr_u *su;
856 struct sensor_device_attribute *a;
857 struct sensor_device_attribute_2 *a2;
858 struct attribute **attrs;
859 struct sensor_device_template **t;
860 int err, i, j, count;
861
862 if (repeat <= 0)
863 return ERR_PTR(-EINVAL);
864
865 t = tg->templates;
866 for (count = 0; *t; t++, count++)
867 ;
868
869 if (count == 0)
870 return ERR_PTR(-EINVAL);
871
872 group = devm_kzalloc(dev, sizeof(*group), GFP_KERNEL);
873 if (group == NULL)
874 return ERR_PTR(-ENOMEM);
875
876 attrs = devm_kzalloc(dev, sizeof(*attrs) * (repeat * count + 1),
877 GFP_KERNEL);
878 if (attrs == NULL)
879 return ERR_PTR(-ENOMEM);
880
881 su = devm_kzalloc(dev, sizeof(*su) * repeat * count,
882 GFP_KERNEL);
883 if (su == NULL)
884 return ERR_PTR(-ENOMEM);
885
886 group->attrs = attrs;
887 group->is_visible = tg->is_visible;
888
889 for (i = 0; i < repeat; i++) {
890 t = tg->templates;
891 for (j = 0; *t != NULL; j++) {
892 snprintf(su->name, sizeof(su->name),
893 (*t)->dev_attr.attr.name, tg->base + i);
894 if ((*t)->s2) {
895 a2 = &su->u.a2;
896 a2->dev_attr.attr.name = su->name;
897 a2->nr = (*t)->u.s.nr + i;
898 a2->index = (*t)->u.s.index;
899 a2->dev_attr.attr.mode =
900 (*t)->dev_attr.attr.mode;
901 a2->dev_attr.show = (*t)->dev_attr.show;
902 a2->dev_attr.store = (*t)->dev_attr.store;
903 *attrs = &a2->dev_attr.attr;
904 } else {
905 a = &su->u.a1;
906 a->dev_attr.attr.name = su->name;
907 a->index = (*t)->u.index + i;
908 a->dev_attr.attr.mode =
909 (*t)->dev_attr.attr.mode;
910 a->dev_attr.show = (*t)->dev_attr.show;
911 a->dev_attr.store = (*t)->dev_attr.store;
912 *attrs = &a->dev_attr.attr;
913 }
914 attrs++;
915 su++;
916 t++;
917 }
918 }
919
920 err = sysfs_create_group(&dev->kobj, group);
921 if (err)
922 return ERR_PTR(-ENOMEM);
923
924 return group;
925}
926
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700927static bool is_word_sized(struct nct6775_data *data, u16 reg)
928{
929 switch (data->kind) {
Guenter Roeck6c009502012-07-01 08:23:15 -0700930 case nct6106:
931 return reg == 0x20 || reg == 0x22 || reg == 0x24 ||
932 reg == 0xe0 || reg == 0xe2 || reg == 0xe4 ||
933 reg == 0x111 || reg == 0x121 || reg == 0x131;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700934 case nct6775:
935 return (((reg & 0xff00) == 0x100 ||
936 (reg & 0xff00) == 0x200) &&
937 ((reg & 0x00ff) == 0x50 ||
938 (reg & 0x00ff) == 0x53 ||
939 (reg & 0x00ff) == 0x55)) ||
940 (reg & 0xfff0) == 0x630 ||
941 reg == 0x640 || reg == 0x642 ||
942 reg == 0x662 ||
943 ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) ||
944 reg == 0x73 || reg == 0x75 || reg == 0x77;
945 case nct6776:
946 return (((reg & 0xff00) == 0x100 ||
947 (reg & 0xff00) == 0x200) &&
948 ((reg & 0x00ff) == 0x50 ||
949 (reg & 0x00ff) == 0x53 ||
950 (reg & 0x00ff) == 0x55)) ||
951 (reg & 0xfff0) == 0x630 ||
952 reg == 0x402 ||
953 reg == 0x640 || reg == 0x642 ||
954 ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) ||
955 reg == 0x73 || reg == 0x75 || reg == 0x77;
956 case nct6779:
957 return reg == 0x150 || reg == 0x153 || reg == 0x155 ||
958 ((reg & 0xfff0) == 0x4b0 && (reg & 0x000f) < 0x09) ||
959 reg == 0x402 ||
960 reg == 0x63a || reg == 0x63c || reg == 0x63e ||
961 reg == 0x640 || reg == 0x642 ||
962 reg == 0x73 || reg == 0x75 || reg == 0x77 || reg == 0x79 ||
963 reg == 0x7b;
964 }
965 return false;
966}
967
968/*
969 * On older chips, only registers 0x50-0x5f are banked.
970 * On more recent chips, all registers are banked.
971 * Assume that is the case and set the bank number for each access.
972 * Cache the bank number so it only needs to be set if it changes.
973 */
974static inline void nct6775_set_bank(struct nct6775_data *data, u16 reg)
975{
976 u8 bank = reg >> 8;
977 if (data->bank != bank) {
978 outb_p(NCT6775_REG_BANK, data->addr + ADDR_REG_OFFSET);
979 outb_p(bank, data->addr + DATA_REG_OFFSET);
980 data->bank = bank;
981 }
982}
983
984static u16 nct6775_read_value(struct nct6775_data *data, u16 reg)
985{
986 int res, word_sized = is_word_sized(data, reg);
987
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700988 nct6775_set_bank(data, reg);
989 outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);
990 res = inb_p(data->addr + DATA_REG_OFFSET);
991 if (word_sized) {
992 outb_p((reg & 0xff) + 1,
993 data->addr + ADDR_REG_OFFSET);
994 res = (res << 8) + inb_p(data->addr + DATA_REG_OFFSET);
995 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -0700996 return res;
997}
998
999static int nct6775_write_value(struct nct6775_data *data, u16 reg, u16 value)
1000{
1001 int word_sized = is_word_sized(data, reg);
1002
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001003 nct6775_set_bank(data, reg);
1004 outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);
1005 if (word_sized) {
1006 outb_p(value >> 8, data->addr + DATA_REG_OFFSET);
1007 outb_p((reg & 0xff) + 1,
1008 data->addr + ADDR_REG_OFFSET);
1009 }
1010 outb_p(value & 0xff, data->addr + DATA_REG_OFFSET);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001011 return 0;
1012}
1013
Guenter Roeckaa136e52012-12-04 03:26:05 -08001014/* We left-align 8-bit temperature values to make the code simpler */
1015static u16 nct6775_read_temp(struct nct6775_data *data, u16 reg)
1016{
1017 u16 res;
1018
1019 res = nct6775_read_value(data, reg);
1020 if (!is_word_sized(data, reg))
1021 res <<= 8;
1022
1023 return res;
1024}
1025
1026static int nct6775_write_temp(struct nct6775_data *data, u16 reg, u16 value)
1027{
1028 if (!is_word_sized(data, reg))
1029 value >>= 8;
1030 return nct6775_write_value(data, reg, value);
1031}
1032
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001033/* This function assumes that the caller holds data->update_lock */
1034static void nct6775_write_fan_div(struct nct6775_data *data, int nr)
1035{
1036 u8 reg;
1037
1038 switch (nr) {
1039 case 0:
1040 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x70)
1041 | (data->fan_div[0] & 0x7);
1042 nct6775_write_value(data, NCT6775_REG_FANDIV1, reg);
1043 break;
1044 case 1:
1045 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x7)
1046 | ((data->fan_div[1] << 4) & 0x70);
1047 nct6775_write_value(data, NCT6775_REG_FANDIV1, reg);
1048 break;
1049 case 2:
1050 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x70)
1051 | (data->fan_div[2] & 0x7);
1052 nct6775_write_value(data, NCT6775_REG_FANDIV2, reg);
1053 break;
1054 case 3:
1055 reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x7)
1056 | ((data->fan_div[3] << 4) & 0x70);
1057 nct6775_write_value(data, NCT6775_REG_FANDIV2, reg);
1058 break;
1059 }
1060}
1061
1062static void nct6775_write_fan_div_common(struct nct6775_data *data, int nr)
1063{
1064 if (data->kind == nct6775)
1065 nct6775_write_fan_div(data, nr);
1066}
1067
1068static void nct6775_update_fan_div(struct nct6775_data *data)
1069{
1070 u8 i;
1071
1072 i = nct6775_read_value(data, NCT6775_REG_FANDIV1);
1073 data->fan_div[0] = i & 0x7;
1074 data->fan_div[1] = (i & 0x70) >> 4;
1075 i = nct6775_read_value(data, NCT6775_REG_FANDIV2);
1076 data->fan_div[2] = i & 0x7;
Guenter Roeck6445e662013-04-21 09:13:28 -07001077 if (data->has_fan & (1 << 3))
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001078 data->fan_div[3] = (i & 0x70) >> 4;
1079}
1080
1081static void nct6775_update_fan_div_common(struct nct6775_data *data)
1082{
1083 if (data->kind == nct6775)
1084 nct6775_update_fan_div(data);
1085}
1086
1087static void nct6775_init_fan_div(struct nct6775_data *data)
1088{
1089 int i;
1090
1091 nct6775_update_fan_div_common(data);
1092 /*
1093 * For all fans, start with highest divider value if the divider
1094 * register is not initialized. This ensures that we get a
1095 * reading from the fan count register, even if it is not optimal.
1096 * We'll compute a better divider later on.
1097 */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001098 for (i = 0; i < ARRAY_SIZE(data->fan_div); i++) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001099 if (!(data->has_fan & (1 << i)))
1100 continue;
1101 if (data->fan_div[i] == 0) {
1102 data->fan_div[i] = 7;
1103 nct6775_write_fan_div_common(data, i);
1104 }
1105 }
1106}
1107
1108static void nct6775_init_fan_common(struct device *dev,
1109 struct nct6775_data *data)
1110{
1111 int i;
1112 u8 reg;
1113
1114 if (data->has_fan_div)
1115 nct6775_init_fan_div(data);
1116
1117 /*
1118 * If fan_min is not set (0), set it to 0xff to disable it. This
1119 * prevents the unnecessary warning when fanX_min is reported as 0.
1120 */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001121 for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001122 if (data->has_fan_min & (1 << i)) {
1123 reg = nct6775_read_value(data, data->REG_FAN_MIN[i]);
1124 if (!reg)
1125 nct6775_write_value(data, data->REG_FAN_MIN[i],
1126 data->has_fan_div ? 0xff
1127 : 0xff1f);
1128 }
1129 }
1130}
1131
1132static void nct6775_select_fan_div(struct device *dev,
1133 struct nct6775_data *data, int nr, u16 reg)
1134{
1135 u8 fan_div = data->fan_div[nr];
1136 u16 fan_min;
1137
1138 if (!data->has_fan_div)
1139 return;
1140
1141 /*
1142 * If we failed to measure the fan speed, or the reported value is not
1143 * in the optimal range, and the clock divider can be modified,
1144 * let's try that for next time.
1145 */
1146 if (reg == 0x00 && fan_div < 0x07)
1147 fan_div++;
1148 else if (reg != 0x00 && reg < 0x30 && fan_div > 0)
1149 fan_div--;
1150
1151 if (fan_div != data->fan_div[nr]) {
1152 dev_dbg(dev, "Modifying fan%d clock divider from %u to %u\n",
1153 nr + 1, div_from_reg(data->fan_div[nr]),
1154 div_from_reg(fan_div));
1155
1156 /* Preserve min limit if possible */
1157 if (data->has_fan_min & (1 << nr)) {
1158 fan_min = data->fan_min[nr];
1159 if (fan_div > data->fan_div[nr]) {
1160 if (fan_min != 255 && fan_min > 1)
1161 fan_min >>= 1;
1162 } else {
1163 if (fan_min != 255) {
1164 fan_min <<= 1;
1165 if (fan_min > 254)
1166 fan_min = 254;
1167 }
1168 }
1169 if (fan_min != data->fan_min[nr]) {
1170 data->fan_min[nr] = fan_min;
1171 nct6775_write_value(data, data->REG_FAN_MIN[nr],
1172 fan_min);
1173 }
1174 }
1175 data->fan_div[nr] = fan_div;
1176 nct6775_write_fan_div_common(data, nr);
1177 }
1178}
1179
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001180static void nct6775_update_pwm(struct device *dev)
1181{
1182 struct nct6775_data *data = dev_get_drvdata(dev);
1183 int i, j;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001184 int fanmodecfg, reg;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001185 bool duty_is_dc;
1186
1187 for (i = 0; i < data->pwm_num; i++) {
1188 if (!(data->has_pwm & (1 << i)))
1189 continue;
1190
1191 duty_is_dc = data->REG_PWM_MODE[i] &&
1192 (nct6775_read_value(data, data->REG_PWM_MODE[i])
1193 & data->PWM_MODE_MASK[i]);
1194 data->pwm_mode[i] = duty_is_dc;
1195
1196 fanmodecfg = nct6775_read_value(data, data->REG_FAN_MODE[i]);
1197 for (j = 0; j < ARRAY_SIZE(data->REG_PWM); j++) {
1198 if (data->REG_PWM[j] && data->REG_PWM[j][i]) {
1199 data->pwm[j][i]
1200 = nct6775_read_value(data,
1201 data->REG_PWM[j][i]);
1202 }
1203 }
1204
1205 data->pwm_enable[i] = reg_to_pwm_enable(data->pwm[0][i],
1206 (fanmodecfg >> 4) & 7);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001207
1208 if (!data->temp_tolerance[0][i] ||
1209 data->pwm_enable[i] != speed_cruise)
1210 data->temp_tolerance[0][i] = fanmodecfg & 0x0f;
1211 if (!data->target_speed_tolerance[i] ||
1212 data->pwm_enable[i] == speed_cruise) {
1213 u8 t = fanmodecfg & 0x0f;
1214 if (data->REG_TOLERANCE_H) {
1215 t |= (nct6775_read_value(data,
1216 data->REG_TOLERANCE_H[i]) & 0x70) >> 1;
1217 }
1218 data->target_speed_tolerance[i] = t;
1219 }
1220
1221 data->temp_tolerance[1][i] =
1222 nct6775_read_value(data,
1223 data->REG_CRITICAL_TEMP_TOLERANCE[i]);
1224
1225 reg = nct6775_read_value(data, data->REG_TEMP_SEL[i]);
1226 data->pwm_temp_sel[i] = reg & 0x1f;
1227 /* If fan can stop, report floor as 0 */
1228 if (reg & 0x80)
1229 data->pwm[2][i] = 0;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08001230
1231 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[i]);
1232 data->pwm_weight_temp_sel[i] = reg & 0x1f;
1233 /* If weight is disabled, report weight source as 0 */
1234 if (j == 1 && !(reg & 0x80))
1235 data->pwm_weight_temp_sel[i] = 0;
1236
1237 /* Weight temp data */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001238 for (j = 0; j < ARRAY_SIZE(data->weight_temp); j++) {
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08001239 data->weight_temp[j][i]
1240 = nct6775_read_value(data,
1241 data->REG_WEIGHT_TEMP[j][i]);
1242 }
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001243 }
1244}
1245
1246static void nct6775_update_pwm_limits(struct device *dev)
1247{
1248 struct nct6775_data *data = dev_get_drvdata(dev);
1249 int i, j;
1250 u8 reg;
1251 u16 reg_t;
1252
1253 for (i = 0; i < data->pwm_num; i++) {
1254 if (!(data->has_pwm & (1 << i)))
1255 continue;
1256
Guenter Roeckc409fd42013-04-09 05:04:00 -07001257 for (j = 0; j < ARRAY_SIZE(data->fan_time); j++) {
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001258 data->fan_time[j][i] =
1259 nct6775_read_value(data, data->REG_FAN_TIME[j][i]);
1260 }
1261
1262 reg_t = nct6775_read_value(data, data->REG_TARGET[i]);
1263 /* Update only in matching mode or if never updated */
1264 if (!data->target_temp[i] ||
1265 data->pwm_enable[i] == thermal_cruise)
1266 data->target_temp[i] = reg_t & data->target_temp_mask;
1267 if (!data->target_speed[i] ||
1268 data->pwm_enable[i] == speed_cruise) {
1269 if (data->REG_TOLERANCE_H) {
1270 reg_t |= (nct6775_read_value(data,
1271 data->REG_TOLERANCE_H[i]) & 0x0f) << 8;
1272 }
1273 data->target_speed[i] = reg_t;
1274 }
1275
1276 for (j = 0; j < data->auto_pwm_num; j++) {
1277 data->auto_pwm[i][j] =
1278 nct6775_read_value(data,
1279 NCT6775_AUTO_PWM(data, i, j));
1280 data->auto_temp[i][j] =
1281 nct6775_read_value(data,
1282 NCT6775_AUTO_TEMP(data, i, j));
1283 }
1284
1285 /* critical auto_pwm temperature data */
1286 data->auto_temp[i][data->auto_pwm_num] =
1287 nct6775_read_value(data, data->REG_CRITICAL_TEMP[i]);
1288
1289 switch (data->kind) {
1290 case nct6775:
1291 reg = nct6775_read_value(data,
1292 NCT6775_REG_CRITICAL_ENAB[i]);
1293 data->auto_pwm[i][data->auto_pwm_num] =
1294 (reg & 0x02) ? 0xff : 0x00;
1295 break;
1296 case nct6776:
1297 data->auto_pwm[i][data->auto_pwm_num] = 0xff;
1298 break;
Guenter Roeck6c009502012-07-01 08:23:15 -07001299 case nct6106:
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001300 case nct6779:
1301 reg = nct6775_read_value(data,
Guenter Roeck6c009502012-07-01 08:23:15 -07001302 data->REG_CRITICAL_PWM_ENABLE[i]);
1303 if (reg & data->CRITICAL_PWM_ENABLE_MASK)
1304 reg = nct6775_read_value(data,
1305 data->REG_CRITICAL_PWM[i]);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001306 else
Guenter Roeck6c009502012-07-01 08:23:15 -07001307 reg = 0xff;
1308 data->auto_pwm[i][data->auto_pwm_num] = reg;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001309 break;
1310 }
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001311 }
1312}
1313
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001314static struct nct6775_data *nct6775_update_device(struct device *dev)
1315{
1316 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeckaa136e52012-12-04 03:26:05 -08001317 int i, j;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001318
1319 mutex_lock(&data->update_lock);
1320
Guenter Roeck6445e662013-04-21 09:13:28 -07001321 if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001322 || !data->valid) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001323 /* Fan clock dividers */
1324 nct6775_update_fan_div_common(data);
1325
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001326 /* Measured voltages and limits */
1327 for (i = 0; i < data->in_num; i++) {
1328 if (!(data->have_in & (1 << i)))
1329 continue;
1330
1331 data->in[i][0] = nct6775_read_value(data,
1332 data->REG_VIN[i]);
1333 data->in[i][1] = nct6775_read_value(data,
1334 data->REG_IN_MINMAX[0][i]);
1335 data->in[i][2] = nct6775_read_value(data,
1336 data->REG_IN_MINMAX[1][i]);
1337 }
1338
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001339 /* Measured fan speeds and limits */
Guenter Roeckc409fd42013-04-09 05:04:00 -07001340 for (i = 0; i < ARRAY_SIZE(data->rpm); i++) {
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001341 u16 reg;
1342
1343 if (!(data->has_fan & (1 << i)))
1344 continue;
1345
1346 reg = nct6775_read_value(data, data->REG_FAN[i]);
1347 data->rpm[i] = data->fan_from_reg(reg,
1348 data->fan_div[i]);
1349
1350 if (data->has_fan_min & (1 << i))
1351 data->fan_min[i] = nct6775_read_value(data,
1352 data->REG_FAN_MIN[i]);
Guenter Roeck5c25d952012-12-11 07:29:06 -08001353 data->fan_pulses[i] =
Guenter Roeck6c009502012-07-01 08:23:15 -07001354 (nct6775_read_value(data, data->REG_FAN_PULSES[i])
1355 >> data->FAN_PULSE_SHIFT[i]) & 0x03;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001356
1357 nct6775_select_fan_div(dev, data, i, reg);
1358 }
1359
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001360 nct6775_update_pwm(dev);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08001361 nct6775_update_pwm_limits(dev);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001362
Guenter Roeckaa136e52012-12-04 03:26:05 -08001363 /* Measured temperatures and limits */
1364 for (i = 0; i < NUM_TEMP; i++) {
1365 if (!(data->have_temp & (1 << i)))
1366 continue;
Guenter Roeckc409fd42013-04-09 05:04:00 -07001367 for (j = 0; j < ARRAY_SIZE(data->reg_temp); j++) {
Guenter Roeckaa136e52012-12-04 03:26:05 -08001368 if (data->reg_temp[j][i])
1369 data->temp[j][i]
1370 = nct6775_read_temp(data,
1371 data->reg_temp[j][i]);
1372 }
1373 if (!(data->have_temp_fixed & (1 << i)))
1374 continue;
1375 data->temp_offset[i]
1376 = nct6775_read_value(data, data->REG_TEMP_OFFSET[i]);
1377 }
1378
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001379 data->alarms = 0;
1380 for (i = 0; i < NUM_REG_ALARM; i++) {
1381 u8 alarm;
1382 if (!data->REG_ALARM[i])
1383 continue;
1384 alarm = nct6775_read_value(data, data->REG_ALARM[i]);
1385 data->alarms |= ((u64)alarm) << (i << 3);
1386 }
1387
1388 data->last_updated = jiffies;
1389 data->valid = true;
1390 }
1391
1392 mutex_unlock(&data->update_lock);
1393 return data;
1394}
1395
1396/*
1397 * Sysfs callback functions
1398 */
1399static ssize_t
1400show_in_reg(struct device *dev, struct device_attribute *attr, char *buf)
1401{
1402 struct nct6775_data *data = nct6775_update_device(dev);
1403 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1404 int nr = sattr->nr;
1405 int index = sattr->index;
1406 return sprintf(buf, "%ld\n", in_from_reg(data->in[nr][index], nr));
1407}
1408
1409static ssize_t
1410store_in_reg(struct device *dev, struct device_attribute *attr, const char *buf,
1411 size_t count)
1412{
1413 struct nct6775_data *data = dev_get_drvdata(dev);
1414 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1415 int nr = sattr->nr;
1416 int index = sattr->index;
1417 unsigned long val;
1418 int err = kstrtoul(buf, 10, &val);
1419 if (err < 0)
1420 return err;
1421 mutex_lock(&data->update_lock);
1422 data->in[nr][index] = in_to_reg(val, nr);
Guenter Roeck6445e662013-04-21 09:13:28 -07001423 nct6775_write_value(data, data->REG_IN_MINMAX[index - 1][nr],
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001424 data->in[nr][index]);
1425 mutex_unlock(&data->update_lock);
1426 return count;
1427}
1428
1429static ssize_t
1430show_alarm(struct device *dev, struct device_attribute *attr, char *buf)
1431{
1432 struct nct6775_data *data = nct6775_update_device(dev);
1433 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1434 int nr = data->ALARM_BITS[sattr->index];
1435 return sprintf(buf, "%u\n",
1436 (unsigned int)((data->alarms >> nr) & 0x01));
1437}
1438
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07001439static int find_temp_source(struct nct6775_data *data, int index, int count)
1440{
1441 int source = data->temp_src[index];
1442 int nr;
1443
1444 for (nr = 0; nr < count; nr++) {
1445 int src;
1446
1447 src = nct6775_read_value(data,
1448 data->REG_TEMP_SOURCE[nr]) & 0x1f;
1449 if (src == source)
1450 return nr;
1451 }
1452 return -1;
1453}
1454
1455static ssize_t
1456show_temp_alarm(struct device *dev, struct device_attribute *attr, char *buf)
1457{
1458 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1459 struct nct6775_data *data = nct6775_update_device(dev);
1460 unsigned int alarm = 0;
1461 int nr;
1462
1463 /*
1464 * For temperatures, there is no fixed mapping from registers to alarm
1465 * bits. Alarm bits are determined by the temperature source mapping.
1466 */
1467 nr = find_temp_source(data, sattr->index, data->num_temp_alarms);
1468 if (nr >= 0) {
1469 int bit = data->ALARM_BITS[nr + TEMP_ALARM_BASE];
1470 alarm = (data->alarms >> bit) & 0x01;
1471 }
1472 return sprintf(buf, "%u\n", alarm);
1473}
1474
Guenter Roeckf73cf632013-03-18 09:22:50 -07001475static umode_t nct6775_in_is_visible(struct kobject *kobj,
1476 struct attribute *attr, int index)
1477{
1478 struct device *dev = container_of(kobj, struct device, kobj);
1479 struct nct6775_data *data = dev_get_drvdata(dev);
1480 int in = index / 4; /* voltage index */
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001481
Guenter Roeckf73cf632013-03-18 09:22:50 -07001482 if (!(data->have_in & (1 << in)))
1483 return 0;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001484
Guenter Roeckf73cf632013-03-18 09:22:50 -07001485 return attr->mode;
1486}
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001487
Guenter Roeckf73cf632013-03-18 09:22:50 -07001488SENSOR_TEMPLATE_2(in_input, "in%d_input", S_IRUGO, show_in_reg, NULL, 0, 0);
1489SENSOR_TEMPLATE(in_alarm, "in%d_alarm", S_IRUGO, show_alarm, NULL, 0);
1490SENSOR_TEMPLATE_2(in_min, "in%d_min", S_IWUSR | S_IRUGO, show_in_reg,
1491 store_in_reg, 0, 1);
1492SENSOR_TEMPLATE_2(in_max, "in%d_max", S_IWUSR | S_IRUGO, show_in_reg,
1493 store_in_reg, 0, 2);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001494
Guenter Roeckf73cf632013-03-18 09:22:50 -07001495/*
1496 * nct6775_in_is_visible uses the index into the following array
1497 * to determine if attributes should be created or not.
1498 * Any change in order or content must be matched.
1499 */
1500static struct sensor_device_template *nct6775_attributes_in_template[] = {
1501 &sensor_dev_template_in_input,
1502 &sensor_dev_template_in_alarm,
1503 &sensor_dev_template_in_min,
1504 &sensor_dev_template_in_max,
1505 NULL
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001506};
1507
Guenter Roeckf73cf632013-03-18 09:22:50 -07001508static struct sensor_template_group nct6775_in_template_group = {
1509 .templates = nct6775_attributes_in_template,
1510 .is_visible = nct6775_in_is_visible,
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07001511};
1512
1513static ssize_t
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001514show_fan(struct device *dev, struct device_attribute *attr, char *buf)
1515{
1516 struct nct6775_data *data = nct6775_update_device(dev);
1517 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1518 int nr = sattr->index;
1519 return sprintf(buf, "%d\n", data->rpm[nr]);
1520}
1521
1522static ssize_t
1523show_fan_min(struct device *dev, struct device_attribute *attr, char *buf)
1524{
1525 struct nct6775_data *data = nct6775_update_device(dev);
1526 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1527 int nr = sattr->index;
1528 return sprintf(buf, "%d\n",
1529 data->fan_from_reg_min(data->fan_min[nr],
1530 data->fan_div[nr]));
1531}
1532
1533static ssize_t
1534show_fan_div(struct device *dev, struct device_attribute *attr, char *buf)
1535{
1536 struct nct6775_data *data = nct6775_update_device(dev);
1537 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1538 int nr = sattr->index;
1539 return sprintf(buf, "%u\n", div_from_reg(data->fan_div[nr]));
1540}
1541
1542static ssize_t
1543store_fan_min(struct device *dev, struct device_attribute *attr,
1544 const char *buf, size_t count)
1545{
1546 struct nct6775_data *data = dev_get_drvdata(dev);
1547 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1548 int nr = sattr->index;
1549 unsigned long val;
1550 int err;
1551 unsigned int reg;
1552 u8 new_div;
1553
1554 err = kstrtoul(buf, 10, &val);
1555 if (err < 0)
1556 return err;
1557
1558 mutex_lock(&data->update_lock);
1559 if (!data->has_fan_div) {
1560 /* NCT6776F or NCT6779D; we know this is a 13 bit register */
1561 if (!val) {
1562 val = 0xff1f;
1563 } else {
1564 if (val > 1350000U)
1565 val = 135000U;
1566 val = 1350000U / val;
1567 val = (val & 0x1f) | ((val << 3) & 0xff00);
1568 }
1569 data->fan_min[nr] = val;
1570 goto write_min; /* Leave fan divider alone */
1571 }
1572 if (!val) {
1573 /* No min limit, alarm disabled */
1574 data->fan_min[nr] = 255;
1575 new_div = data->fan_div[nr]; /* No change */
1576 dev_info(dev, "fan%u low limit and alarm disabled\n", nr + 1);
1577 goto write_div;
1578 }
1579 reg = 1350000U / val;
1580 if (reg >= 128 * 255) {
1581 /*
1582 * Speed below this value cannot possibly be represented,
1583 * even with the highest divider (128)
1584 */
1585 data->fan_min[nr] = 254;
1586 new_div = 7; /* 128 == (1 << 7) */
1587 dev_warn(dev,
1588 "fan%u low limit %lu below minimum %u, set to minimum\n",
1589 nr + 1, val, data->fan_from_reg_min(254, 7));
1590 } else if (!reg) {
1591 /*
1592 * Speed above this value cannot possibly be represented,
1593 * even with the lowest divider (1)
1594 */
1595 data->fan_min[nr] = 1;
1596 new_div = 0; /* 1 == (1 << 0) */
1597 dev_warn(dev,
1598 "fan%u low limit %lu above maximum %u, set to maximum\n",
1599 nr + 1, val, data->fan_from_reg_min(1, 0));
1600 } else {
1601 /*
1602 * Automatically pick the best divider, i.e. the one such
1603 * that the min limit will correspond to a register value
1604 * in the 96..192 range
1605 */
1606 new_div = 0;
1607 while (reg > 192 && new_div < 7) {
1608 reg >>= 1;
1609 new_div++;
1610 }
1611 data->fan_min[nr] = reg;
1612 }
1613
1614write_div:
1615 /*
1616 * Write both the fan clock divider (if it changed) and the new
1617 * fan min (unconditionally)
1618 */
1619 if (new_div != data->fan_div[nr]) {
1620 dev_dbg(dev, "fan%u clock divider changed from %u to %u\n",
1621 nr + 1, div_from_reg(data->fan_div[nr]),
1622 div_from_reg(new_div));
1623 data->fan_div[nr] = new_div;
1624 nct6775_write_fan_div_common(data, nr);
1625 /* Give the chip time to sample a new speed value */
1626 data->last_updated = jiffies;
1627 }
1628
1629write_min:
1630 nct6775_write_value(data, data->REG_FAN_MIN[nr], data->fan_min[nr]);
1631 mutex_unlock(&data->update_lock);
1632
1633 return count;
1634}
1635
Guenter Roeck5c25d952012-12-11 07:29:06 -08001636static ssize_t
1637show_fan_pulses(struct device *dev, struct device_attribute *attr, char *buf)
1638{
1639 struct nct6775_data *data = nct6775_update_device(dev);
1640 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1641 int p = data->fan_pulses[sattr->index];
1642
1643 return sprintf(buf, "%d\n", p ? : 4);
1644}
1645
1646static ssize_t
1647store_fan_pulses(struct device *dev, struct device_attribute *attr,
1648 const char *buf, size_t count)
1649{
1650 struct nct6775_data *data = dev_get_drvdata(dev);
1651 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1652 int nr = sattr->index;
1653 unsigned long val;
1654 int err;
Guenter Roeck6c009502012-07-01 08:23:15 -07001655 u8 reg;
Guenter Roeck5c25d952012-12-11 07:29:06 -08001656
1657 err = kstrtoul(buf, 10, &val);
1658 if (err < 0)
1659 return err;
1660
1661 if (val > 4)
1662 return -EINVAL;
1663
1664 mutex_lock(&data->update_lock);
1665 data->fan_pulses[nr] = val & 3;
Guenter Roeck6c009502012-07-01 08:23:15 -07001666 reg = nct6775_read_value(data, data->REG_FAN_PULSES[nr]);
1667 reg &= ~(0x03 << data->FAN_PULSE_SHIFT[nr]);
1668 reg |= (val & 3) << data->FAN_PULSE_SHIFT[nr];
1669 nct6775_write_value(data, data->REG_FAN_PULSES[nr], reg);
Guenter Roeck5c25d952012-12-11 07:29:06 -08001670 mutex_unlock(&data->update_lock);
1671
1672 return count;
1673}
1674
Guenter Roeckf73cf632013-03-18 09:22:50 -07001675static umode_t nct6775_fan_is_visible(struct kobject *kobj,
1676 struct attribute *attr, int index)
1677{
1678 struct device *dev = container_of(kobj, struct device, kobj);
1679 struct nct6775_data *data = dev_get_drvdata(dev);
1680 int fan = index / 5; /* fan index */
1681 int nr = index % 5; /* attribute index */
1682
1683 if (!(data->has_fan & (1 << fan)))
1684 return 0;
1685
1686 if (nr == 1 && data->ALARM_BITS[FAN_ALARM_BASE + fan] == -1)
1687 return 0;
1688 if (nr == 3 && !(data->has_fan_min & (1 << fan)))
1689 return 0;
1690 if (nr == 4 && data->kind != nct6775)
1691 return 0;
1692
1693 return attr->mode;
1694}
1695
1696SENSOR_TEMPLATE(fan_input, "fan%d_input", S_IRUGO, show_fan, NULL, 0);
1697SENSOR_TEMPLATE(fan_alarm, "fan%d_alarm", S_IRUGO, show_alarm, NULL,
1698 FAN_ALARM_BASE);
1699SENSOR_TEMPLATE(fan_pulses, "fan%d_pulses", S_IWUSR | S_IRUGO, show_fan_pulses,
1700 store_fan_pulses, 0);
1701SENSOR_TEMPLATE(fan_min, "fan%d_min", S_IWUSR | S_IRUGO, show_fan_min,
1702 store_fan_min, 0);
1703SENSOR_TEMPLATE(fan_div, "fan%d_div", S_IRUGO, show_fan_div, NULL, 0);
1704
1705/*
1706 * nct6775_fan_is_visible uses the index into the following array
1707 * to determine if attributes should be created or not.
1708 * Any change in order or content must be matched.
1709 */
1710static struct sensor_device_template *nct6775_attributes_fan_template[] = {
1711 &sensor_dev_template_fan_input,
1712 &sensor_dev_template_fan_alarm, /* 1 */
1713 &sensor_dev_template_fan_pulses,
1714 &sensor_dev_template_fan_min, /* 3 */
1715 &sensor_dev_template_fan_div, /* 4 */
1716 NULL
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001717};
1718
Guenter Roeckf73cf632013-03-18 09:22:50 -07001719static struct sensor_template_group nct6775_fan_template_group = {
1720 .templates = nct6775_attributes_fan_template,
1721 .is_visible = nct6775_fan_is_visible,
1722 .base = 1,
Guenter Roeck1c65dc32012-12-04 07:56:24 -08001723};
1724
1725static ssize_t
Guenter Roeckaa136e52012-12-04 03:26:05 -08001726show_temp_label(struct device *dev, struct device_attribute *attr, char *buf)
1727{
1728 struct nct6775_data *data = nct6775_update_device(dev);
1729 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1730 int nr = sattr->index;
1731 return sprintf(buf, "%s\n", data->temp_label[data->temp_src[nr]]);
1732}
1733
1734static ssize_t
1735show_temp(struct device *dev, struct device_attribute *attr, char *buf)
1736{
1737 struct nct6775_data *data = nct6775_update_device(dev);
1738 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1739 int nr = sattr->nr;
1740 int index = sattr->index;
1741
1742 return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->temp[index][nr]));
1743}
1744
1745static ssize_t
1746store_temp(struct device *dev, struct device_attribute *attr, const char *buf,
1747 size_t count)
1748{
1749 struct nct6775_data *data = dev_get_drvdata(dev);
1750 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1751 int nr = sattr->nr;
1752 int index = sattr->index;
1753 int err;
1754 long val;
1755
1756 err = kstrtol(buf, 10, &val);
1757 if (err < 0)
1758 return err;
1759
1760 mutex_lock(&data->update_lock);
1761 data->temp[index][nr] = LM75_TEMP_TO_REG(val);
1762 nct6775_write_temp(data, data->reg_temp[index][nr],
1763 data->temp[index][nr]);
1764 mutex_unlock(&data->update_lock);
1765 return count;
1766}
1767
1768static ssize_t
1769show_temp_offset(struct device *dev, struct device_attribute *attr, char *buf)
1770{
1771 struct nct6775_data *data = nct6775_update_device(dev);
1772 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1773
1774 return sprintf(buf, "%d\n", data->temp_offset[sattr->index] * 1000);
1775}
1776
1777static ssize_t
1778store_temp_offset(struct device *dev, struct device_attribute *attr,
1779 const char *buf, size_t count)
1780{
1781 struct nct6775_data *data = dev_get_drvdata(dev);
1782 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1783 int nr = sattr->index;
1784 long val;
1785 int err;
1786
1787 err = kstrtol(buf, 10, &val);
1788 if (err < 0)
1789 return err;
1790
1791 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -128, 127);
1792
1793 mutex_lock(&data->update_lock);
1794 data->temp_offset[nr] = val;
1795 nct6775_write_value(data, data->REG_TEMP_OFFSET[nr], val);
1796 mutex_unlock(&data->update_lock);
1797
1798 return count;
1799}
1800
1801static ssize_t
1802show_temp_type(struct device *dev, struct device_attribute *attr, char *buf)
1803{
1804 struct nct6775_data *data = nct6775_update_device(dev);
1805 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1806 int nr = sattr->index;
1807 return sprintf(buf, "%d\n", (int)data->temp_type[nr]);
1808}
1809
1810static ssize_t
1811store_temp_type(struct device *dev, struct device_attribute *attr,
1812 const char *buf, size_t count)
1813{
1814 struct nct6775_data *data = nct6775_update_device(dev);
1815 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1816 int nr = sattr->index;
1817 unsigned long val;
1818 int err;
Guenter Roeck6c009502012-07-01 08:23:15 -07001819 u8 vbat, diode, vbit, dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08001820
1821 err = kstrtoul(buf, 10, &val);
1822 if (err < 0)
1823 return err;
1824
1825 if (val != 1 && val != 3 && val != 4)
1826 return -EINVAL;
1827
1828 mutex_lock(&data->update_lock);
1829
1830 data->temp_type[nr] = val;
Guenter Roeck6c009502012-07-01 08:23:15 -07001831 vbit = 0x02 << nr;
1832 dbit = data->DIODE_MASK << nr;
1833 vbat = nct6775_read_value(data, data->REG_VBAT) & ~vbit;
1834 diode = nct6775_read_value(data, data->REG_DIODE) & ~dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08001835 switch (val) {
1836 case 1: /* CPU diode (diode, current mode) */
Guenter Roeck6c009502012-07-01 08:23:15 -07001837 vbat |= vbit;
1838 diode |= dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08001839 break;
1840 case 3: /* diode, voltage mode */
Guenter Roeck6c009502012-07-01 08:23:15 -07001841 vbat |= dbit;
Guenter Roeckaa136e52012-12-04 03:26:05 -08001842 break;
1843 case 4: /* thermistor */
1844 break;
1845 }
1846 nct6775_write_value(data, data->REG_VBAT, vbat);
1847 nct6775_write_value(data, data->REG_DIODE, diode);
1848
1849 mutex_unlock(&data->update_lock);
1850 return count;
1851}
1852
Guenter Roeckf73cf632013-03-18 09:22:50 -07001853static umode_t nct6775_temp_is_visible(struct kobject *kobj,
1854 struct attribute *attr, int index)
1855{
1856 struct device *dev = container_of(kobj, struct device, kobj);
1857 struct nct6775_data *data = dev_get_drvdata(dev);
Guenter Roeckb7a61352013-04-02 22:14:06 -07001858 int temp = index / 9; /* temp index */
1859 int nr = index % 9; /* attribute index */
Guenter Roeckf73cf632013-03-18 09:22:50 -07001860
1861 if (!(data->have_temp & (1 << temp)))
1862 return 0;
1863
1864 if (nr == 2 && find_temp_source(data, temp, data->num_temp_alarms) < 0)
1865 return 0; /* alarm */
1866
1867 if (nr == 3 && !data->reg_temp[1][temp]) /* max */
1868 return 0;
1869
1870 if (nr == 4 && !data->reg_temp[2][temp]) /* max_hyst */
1871 return 0;
1872
1873 if (nr == 5 && !data->reg_temp[3][temp]) /* crit */
1874 return 0;
1875
Guenter Roeckb7a61352013-04-02 22:14:06 -07001876 if (nr == 6 && !data->reg_temp[4][temp]) /* lcrit */
1877 return 0;
1878
1879 /* offset and type only apply to fixed sensors */
1880 if (nr > 6 && !(data->have_temp_fixed & (1 << temp)))
Guenter Roeckf73cf632013-03-18 09:22:50 -07001881 return 0;
1882
1883 return attr->mode;
1884}
1885
1886SENSOR_TEMPLATE_2(temp_input, "temp%d_input", S_IRUGO, show_temp, NULL, 0, 0);
1887SENSOR_TEMPLATE(temp_label, "temp%d_label", S_IRUGO, show_temp_label, NULL, 0);
1888SENSOR_TEMPLATE_2(temp_max, "temp%d_max", S_IRUGO | S_IWUSR, show_temp,
1889 store_temp, 0, 1);
1890SENSOR_TEMPLATE_2(temp_max_hyst, "temp%d_max_hyst", S_IRUGO | S_IWUSR,
1891 show_temp, store_temp, 0, 2);
1892SENSOR_TEMPLATE_2(temp_crit, "temp%d_crit", S_IRUGO | S_IWUSR, show_temp,
1893 store_temp, 0, 3);
Guenter Roeckb7a61352013-04-02 22:14:06 -07001894SENSOR_TEMPLATE_2(temp_lcrit, "temp%d_lcrit", S_IRUGO | S_IWUSR, show_temp,
1895 store_temp, 0, 4);
Guenter Roeckf73cf632013-03-18 09:22:50 -07001896SENSOR_TEMPLATE(temp_offset, "temp%d_offset", S_IRUGO | S_IWUSR,
1897 show_temp_offset, store_temp_offset, 0);
1898SENSOR_TEMPLATE(temp_type, "temp%d_type", S_IRUGO | S_IWUSR, show_temp_type,
1899 store_temp_type, 0);
1900SENSOR_TEMPLATE(temp_alarm, "temp%d_alarm", S_IRUGO, show_temp_alarm, NULL, 0);
1901
1902/*
1903 * nct6775_temp_is_visible uses the index into the following array
1904 * to determine if attributes should be created or not.
1905 * Any change in order or content must be matched.
1906 */
1907static struct sensor_device_template *nct6775_attributes_temp_template[] = {
1908 &sensor_dev_template_temp_input,
1909 &sensor_dev_template_temp_label,
1910 &sensor_dev_template_temp_alarm, /* 2 */
1911 &sensor_dev_template_temp_max, /* 3 */
1912 &sensor_dev_template_temp_max_hyst, /* 4 */
1913 &sensor_dev_template_temp_crit, /* 5 */
Guenter Roeckb7a61352013-04-02 22:14:06 -07001914 &sensor_dev_template_temp_lcrit, /* 6 */
1915 &sensor_dev_template_temp_offset, /* 7 */
1916 &sensor_dev_template_temp_type, /* 8 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07001917 NULL
Guenter Roeckaa136e52012-12-04 03:26:05 -08001918};
1919
Guenter Roeckf73cf632013-03-18 09:22:50 -07001920static struct sensor_template_group nct6775_temp_template_group = {
1921 .templates = nct6775_attributes_temp_template,
1922 .is_visible = nct6775_temp_is_visible,
1923 .base = 1,
Guenter Roeckaa136e52012-12-04 03:26:05 -08001924};
1925
Guenter Roeckaa136e52012-12-04 03:26:05 -08001926static ssize_t
Guenter Roeck77eb5b32012-12-04 08:30:54 -08001927show_pwm_mode(struct device *dev, struct device_attribute *attr, char *buf)
1928{
1929 struct nct6775_data *data = nct6775_update_device(dev);
1930 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1931
1932 return sprintf(buf, "%d\n", !data->pwm_mode[sattr->index]);
1933}
1934
1935static ssize_t
1936store_pwm_mode(struct device *dev, struct device_attribute *attr,
1937 const char *buf, size_t count)
1938{
1939 struct nct6775_data *data = dev_get_drvdata(dev);
1940 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
1941 int nr = sattr->index;
1942 unsigned long val;
1943 int err;
1944 u8 reg;
1945
1946 err = kstrtoul(buf, 10, &val);
1947 if (err < 0)
1948 return err;
1949
1950 if (val > 1)
1951 return -EINVAL;
1952
1953 /* Setting DC mode is not supported for all chips/channels */
1954 if (data->REG_PWM_MODE[nr] == 0) {
1955 if (val)
1956 return -EINVAL;
1957 return count;
1958 }
1959
1960 mutex_lock(&data->update_lock);
1961 data->pwm_mode[nr] = val;
1962 reg = nct6775_read_value(data, data->REG_PWM_MODE[nr]);
1963 reg &= ~data->PWM_MODE_MASK[nr];
1964 if (val)
1965 reg |= data->PWM_MODE_MASK[nr];
1966 nct6775_write_value(data, data->REG_PWM_MODE[nr], reg);
1967 mutex_unlock(&data->update_lock);
1968 return count;
1969}
1970
1971static ssize_t
1972show_pwm(struct device *dev, struct device_attribute *attr, char *buf)
1973{
1974 struct nct6775_data *data = nct6775_update_device(dev);
1975 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1976 int nr = sattr->nr;
1977 int index = sattr->index;
1978 int pwm;
1979
1980 /*
1981 * For automatic fan control modes, show current pwm readings.
1982 * Otherwise, show the configured value.
1983 */
1984 if (index == 0 && data->pwm_enable[nr] > manual)
1985 pwm = nct6775_read_value(data, data->REG_PWM_READ[nr]);
1986 else
1987 pwm = data->pwm[index][nr];
1988
1989 return sprintf(buf, "%d\n", pwm);
1990}
1991
1992static ssize_t
1993store_pwm(struct device *dev, struct device_attribute *attr, const char *buf,
1994 size_t count)
1995{
1996 struct nct6775_data *data = dev_get_drvdata(dev);
1997 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
1998 int nr = sattr->nr;
1999 int index = sattr->index;
2000 unsigned long val;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002001 int minval[7] = { 0, 1, 1, data->pwm[2][nr], 0, 0, 0 };
2002 int maxval[7]
2003 = { 255, 255, data->pwm[3][nr] ? : 255, 255, 255, 255, 255 };
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002004 int err;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002005 u8 reg;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002006
2007 err = kstrtoul(buf, 10, &val);
2008 if (err < 0)
2009 return err;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002010 val = clamp_val(val, minval[index], maxval[index]);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002011
2012 mutex_lock(&data->update_lock);
2013 data->pwm[index][nr] = val;
2014 nct6775_write_value(data, data->REG_PWM[index][nr], val);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002015 if (index == 2) { /* floor: disable if val == 0 */
2016 reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]);
2017 reg &= 0x7f;
2018 if (val)
2019 reg |= 0x80;
2020 nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg);
2021 }
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002022 mutex_unlock(&data->update_lock);
2023 return count;
2024}
2025
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002026/* Returns 0 if OK, -EINVAL otherwise */
2027static int check_trip_points(struct nct6775_data *data, int nr)
2028{
2029 int i;
2030
2031 for (i = 0; i < data->auto_pwm_num - 1; i++) {
2032 if (data->auto_temp[nr][i] > data->auto_temp[nr][i + 1])
2033 return -EINVAL;
2034 }
2035 for (i = 0; i < data->auto_pwm_num - 1; i++) {
2036 if (data->auto_pwm[nr][i] > data->auto_pwm[nr][i + 1])
2037 return -EINVAL;
2038 }
2039 /* validate critical temperature and pwm if enabled (pwm > 0) */
2040 if (data->auto_pwm[nr][data->auto_pwm_num]) {
2041 if (data->auto_temp[nr][data->auto_pwm_num - 1] >
2042 data->auto_temp[nr][data->auto_pwm_num] ||
2043 data->auto_pwm[nr][data->auto_pwm_num - 1] >
2044 data->auto_pwm[nr][data->auto_pwm_num])
2045 return -EINVAL;
2046 }
2047 return 0;
2048}
2049
2050static void pwm_update_registers(struct nct6775_data *data, int nr)
2051{
2052 u8 reg;
2053
2054 switch (data->pwm_enable[nr]) {
2055 case off:
2056 case manual:
2057 break;
2058 case speed_cruise:
2059 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2060 reg = (reg & ~data->tolerance_mask) |
2061 (data->target_speed_tolerance[nr] & data->tolerance_mask);
2062 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2063 nct6775_write_value(data, data->REG_TARGET[nr],
2064 data->target_speed[nr] & 0xff);
2065 if (data->REG_TOLERANCE_H) {
2066 reg = (data->target_speed[nr] >> 8) & 0x0f;
2067 reg |= (data->target_speed_tolerance[nr] & 0x38) << 1;
2068 nct6775_write_value(data,
2069 data->REG_TOLERANCE_H[nr],
2070 reg);
2071 }
2072 break;
2073 case thermal_cruise:
2074 nct6775_write_value(data, data->REG_TARGET[nr],
2075 data->target_temp[nr]);
2076 /* intentional */
2077 default:
2078 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2079 reg = (reg & ~data->tolerance_mask) |
2080 data->temp_tolerance[0][nr];
2081 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2082 break;
2083 }
2084}
2085
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002086static ssize_t
2087show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf)
2088{
2089 struct nct6775_data *data = nct6775_update_device(dev);
2090 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2091
2092 return sprintf(buf, "%d\n", data->pwm_enable[sattr->index]);
2093}
2094
2095static ssize_t
2096store_pwm_enable(struct device *dev, struct device_attribute *attr,
2097 const char *buf, size_t count)
2098{
2099 struct nct6775_data *data = dev_get_drvdata(dev);
2100 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2101 int nr = sattr->index;
2102 unsigned long val;
2103 int err;
2104 u16 reg;
2105
2106 err = kstrtoul(buf, 10, &val);
2107 if (err < 0)
2108 return err;
2109
2110 if (val > sf4)
2111 return -EINVAL;
2112
2113 if (val == sf3 && data->kind != nct6775)
2114 return -EINVAL;
2115
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002116 if (val == sf4 && check_trip_points(data, nr)) {
2117 dev_err(dev, "Inconsistent trip points, not switching to SmartFan IV mode\n");
2118 dev_err(dev, "Adjust trip points and try again\n");
2119 return -EINVAL;
2120 }
2121
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002122 mutex_lock(&data->update_lock);
2123 data->pwm_enable[nr] = val;
2124 if (val == off) {
2125 /*
2126 * turn off pwm control: select manual mode, set pwm to maximum
2127 */
2128 data->pwm[0][nr] = 255;
2129 nct6775_write_value(data, data->REG_PWM[0][nr], 255);
2130 }
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002131 pwm_update_registers(data, nr);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002132 reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
2133 reg &= 0x0f;
2134 reg |= pwm_enable_to_reg(val) << 4;
2135 nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
2136 mutex_unlock(&data->update_lock);
2137 return count;
2138}
2139
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002140static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002141show_pwm_temp_sel_common(struct nct6775_data *data, char *buf, int src)
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002142{
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002143 int i, sel = 0;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002144
2145 for (i = 0; i < NUM_TEMP; i++) {
2146 if (!(data->have_temp & (1 << i)))
2147 continue;
2148 if (src == data->temp_src[i]) {
2149 sel = i + 1;
2150 break;
2151 }
2152 }
2153
2154 return sprintf(buf, "%d\n", sel);
2155}
2156
2157static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002158show_pwm_temp_sel(struct device *dev, struct device_attribute *attr, char *buf)
2159{
2160 struct nct6775_data *data = nct6775_update_device(dev);
2161 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2162 int index = sattr->index;
2163
2164 return show_pwm_temp_sel_common(data, buf, data->pwm_temp_sel[index]);
2165}
2166
2167static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002168store_pwm_temp_sel(struct device *dev, struct device_attribute *attr,
2169 const char *buf, size_t count)
2170{
2171 struct nct6775_data *data = nct6775_update_device(dev);
2172 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2173 int nr = sattr->index;
2174 unsigned long val;
2175 int err, reg, src;
2176
2177 err = kstrtoul(buf, 10, &val);
2178 if (err < 0)
2179 return err;
2180 if (val == 0 || val > NUM_TEMP)
2181 return -EINVAL;
2182 if (!(data->have_temp & (1 << (val - 1))) || !data->temp_src[val - 1])
2183 return -EINVAL;
2184
2185 mutex_lock(&data->update_lock);
2186 src = data->temp_src[val - 1];
2187 data->pwm_temp_sel[nr] = src;
2188 reg = nct6775_read_value(data, data->REG_TEMP_SEL[nr]);
2189 reg &= 0xe0;
2190 reg |= src;
2191 nct6775_write_value(data, data->REG_TEMP_SEL[nr], reg);
2192 mutex_unlock(&data->update_lock);
2193
2194 return count;
2195}
2196
2197static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002198show_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr,
2199 char *buf)
2200{
2201 struct nct6775_data *data = nct6775_update_device(dev);
2202 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2203 int index = sattr->index;
2204
2205 return show_pwm_temp_sel_common(data, buf,
2206 data->pwm_weight_temp_sel[index]);
2207}
2208
2209static ssize_t
2210store_pwm_weight_temp_sel(struct device *dev, struct device_attribute *attr,
2211 const char *buf, size_t count)
2212{
2213 struct nct6775_data *data = nct6775_update_device(dev);
2214 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2215 int nr = sattr->index;
2216 unsigned long val;
2217 int err, reg, src;
2218
2219 err = kstrtoul(buf, 10, &val);
2220 if (err < 0)
2221 return err;
2222 if (val > NUM_TEMP)
2223 return -EINVAL;
2224 if (val && (!(data->have_temp & (1 << (val - 1))) ||
2225 !data->temp_src[val - 1]))
2226 return -EINVAL;
2227
2228 mutex_lock(&data->update_lock);
2229 if (val) {
2230 src = data->temp_src[val - 1];
2231 data->pwm_weight_temp_sel[nr] = src;
2232 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]);
2233 reg &= 0xe0;
2234 reg |= (src | 0x80);
2235 nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg);
2236 } else {
2237 data->pwm_weight_temp_sel[nr] = 0;
2238 reg = nct6775_read_value(data, data->REG_WEIGHT_TEMP_SEL[nr]);
2239 reg &= 0x7f;
2240 nct6775_write_value(data, data->REG_WEIGHT_TEMP_SEL[nr], reg);
2241 }
2242 mutex_unlock(&data->update_lock);
2243
2244 return count;
2245}
2246
2247static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002248show_target_temp(struct device *dev, struct device_attribute *attr, char *buf)
2249{
2250 struct nct6775_data *data = nct6775_update_device(dev);
2251 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2252
2253 return sprintf(buf, "%d\n", data->target_temp[sattr->index] * 1000);
2254}
2255
2256static ssize_t
2257store_target_temp(struct device *dev, struct device_attribute *attr,
2258 const char *buf, size_t count)
2259{
2260 struct nct6775_data *data = dev_get_drvdata(dev);
2261 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2262 int nr = sattr->index;
2263 unsigned long val;
2264 int err;
2265
2266 err = kstrtoul(buf, 10, &val);
2267 if (err < 0)
2268 return err;
2269
2270 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0,
2271 data->target_temp_mask);
2272
2273 mutex_lock(&data->update_lock);
2274 data->target_temp[nr] = val;
2275 pwm_update_registers(data, nr);
2276 mutex_unlock(&data->update_lock);
2277 return count;
2278}
2279
2280static ssize_t
2281show_target_speed(struct device *dev, struct device_attribute *attr, char *buf)
2282{
2283 struct nct6775_data *data = nct6775_update_device(dev);
2284 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2285 int nr = sattr->index;
2286
2287 return sprintf(buf, "%d\n",
2288 fan_from_reg16(data->target_speed[nr],
2289 data->fan_div[nr]));
2290}
2291
2292static ssize_t
2293store_target_speed(struct device *dev, struct device_attribute *attr,
2294 const char *buf, size_t count)
2295{
2296 struct nct6775_data *data = dev_get_drvdata(dev);
2297 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2298 int nr = sattr->index;
2299 unsigned long val;
2300 int err;
2301 u16 speed;
2302
2303 err = kstrtoul(buf, 10, &val);
2304 if (err < 0)
2305 return err;
2306
2307 val = clamp_val(val, 0, 1350000U);
2308 speed = fan_to_reg(val, data->fan_div[nr]);
2309
2310 mutex_lock(&data->update_lock);
2311 data->target_speed[nr] = speed;
2312 pwm_update_registers(data, nr);
2313 mutex_unlock(&data->update_lock);
2314 return count;
2315}
2316
2317static ssize_t
2318show_temp_tolerance(struct device *dev, struct device_attribute *attr,
2319 char *buf)
2320{
2321 struct nct6775_data *data = nct6775_update_device(dev);
2322 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2323 int nr = sattr->nr;
2324 int index = sattr->index;
2325
2326 return sprintf(buf, "%d\n", data->temp_tolerance[index][nr] * 1000);
2327}
2328
2329static ssize_t
2330store_temp_tolerance(struct device *dev, struct device_attribute *attr,
2331 const char *buf, size_t count)
2332{
2333 struct nct6775_data *data = dev_get_drvdata(dev);
2334 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2335 int nr = sattr->nr;
2336 int index = sattr->index;
2337 unsigned long val;
2338 int err;
2339
2340 err = kstrtoul(buf, 10, &val);
2341 if (err < 0)
2342 return err;
2343
2344 /* Limit tolerance as needed */
2345 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, data->tolerance_mask);
2346
2347 mutex_lock(&data->update_lock);
2348 data->temp_tolerance[index][nr] = val;
2349 if (index)
2350 pwm_update_registers(data, nr);
2351 else
2352 nct6775_write_value(data,
2353 data->REG_CRITICAL_TEMP_TOLERANCE[nr],
2354 val);
2355 mutex_unlock(&data->update_lock);
2356 return count;
2357}
2358
2359/*
2360 * Fan speed tolerance is a tricky beast, since the associated register is
2361 * a tick counter, but the value is reported and configured as rpm.
2362 * Compute resulting low and high rpm values and report the difference.
2363 */
2364static ssize_t
2365show_speed_tolerance(struct device *dev, struct device_attribute *attr,
2366 char *buf)
2367{
2368 struct nct6775_data *data = nct6775_update_device(dev);
2369 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2370 int nr = sattr->index;
2371 int low = data->target_speed[nr] - data->target_speed_tolerance[nr];
2372 int high = data->target_speed[nr] + data->target_speed_tolerance[nr];
2373 int tolerance;
2374
2375 if (low <= 0)
2376 low = 1;
2377 if (high > 0xffff)
2378 high = 0xffff;
2379 if (high < low)
2380 high = low;
2381
2382 tolerance = (fan_from_reg16(low, data->fan_div[nr])
2383 - fan_from_reg16(high, data->fan_div[nr])) / 2;
2384
2385 return sprintf(buf, "%d\n", tolerance);
2386}
2387
2388static ssize_t
2389store_speed_tolerance(struct device *dev, struct device_attribute *attr,
2390 const char *buf, size_t count)
2391{
2392 struct nct6775_data *data = dev_get_drvdata(dev);
2393 struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
2394 int nr = sattr->index;
2395 unsigned long val;
2396 int err;
2397 int low, high;
2398
2399 err = kstrtoul(buf, 10, &val);
2400 if (err < 0)
2401 return err;
2402
2403 high = fan_from_reg16(data->target_speed[nr],
2404 data->fan_div[nr]) + val;
2405 low = fan_from_reg16(data->target_speed[nr],
2406 data->fan_div[nr]) - val;
2407 if (low <= 0)
2408 low = 1;
2409 if (high < low)
2410 high = low;
2411
2412 val = (fan_to_reg(low, data->fan_div[nr]) -
2413 fan_to_reg(high, data->fan_div[nr])) / 2;
2414
2415 /* Limit tolerance as needed */
2416 val = clamp_val(val, 0, data->speed_tolerance_limit);
2417
2418 mutex_lock(&data->update_lock);
2419 data->target_speed_tolerance[nr] = val;
2420 pwm_update_registers(data, nr);
2421 mutex_unlock(&data->update_lock);
2422 return count;
2423}
2424
Guenter Roeckf73cf632013-03-18 09:22:50 -07002425SENSOR_TEMPLATE_2(pwm, "pwm%d", S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 0);
2426SENSOR_TEMPLATE(pwm_mode, "pwm%d_mode", S_IWUSR | S_IRUGO, show_pwm_mode,
2427 store_pwm_mode, 0);
2428SENSOR_TEMPLATE(pwm_enable, "pwm%d_enable", S_IWUSR | S_IRUGO, show_pwm_enable,
2429 store_pwm_enable, 0);
2430SENSOR_TEMPLATE(pwm_temp_sel, "pwm%d_temp_sel", S_IWUSR | S_IRUGO,
2431 show_pwm_temp_sel, store_pwm_temp_sel, 0);
2432SENSOR_TEMPLATE(pwm_target_temp, "pwm%d_target_temp", S_IWUSR | S_IRUGO,
2433 show_target_temp, store_target_temp, 0);
2434SENSOR_TEMPLATE(fan_target, "fan%d_target", S_IWUSR | S_IRUGO,
2435 show_target_speed, store_target_speed, 0);
2436SENSOR_TEMPLATE(fan_tolerance, "fan%d_tolerance", S_IWUSR | S_IRUGO,
2437 show_speed_tolerance, store_speed_tolerance, 0);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002438
2439/* Smart Fan registers */
2440
2441static ssize_t
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002442show_weight_temp(struct device *dev, struct device_attribute *attr, char *buf)
2443{
2444 struct nct6775_data *data = nct6775_update_device(dev);
2445 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2446 int nr = sattr->nr;
2447 int index = sattr->index;
2448
2449 return sprintf(buf, "%d\n", data->weight_temp[index][nr] * 1000);
2450}
2451
2452static ssize_t
2453store_weight_temp(struct device *dev, struct device_attribute *attr,
2454 const char *buf, size_t count)
2455{
2456 struct nct6775_data *data = dev_get_drvdata(dev);
2457 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2458 int nr = sattr->nr;
2459 int index = sattr->index;
2460 unsigned long val;
2461 int err;
2462
2463 err = kstrtoul(buf, 10, &val);
2464 if (err < 0)
2465 return err;
2466
2467 val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, 255);
2468
2469 mutex_lock(&data->update_lock);
2470 data->weight_temp[index][nr] = val;
2471 nct6775_write_value(data, data->REG_WEIGHT_TEMP[index][nr], val);
2472 mutex_unlock(&data->update_lock);
2473 return count;
2474}
2475
Guenter Roeckf73cf632013-03-18 09:22:50 -07002476SENSOR_TEMPLATE(pwm_weight_temp_sel, "pwm%d_weight_temp_sel", S_IWUSR | S_IRUGO,
2477 show_pwm_weight_temp_sel, store_pwm_weight_temp_sel, 0);
2478SENSOR_TEMPLATE_2(pwm_weight_temp_step, "pwm%d_weight_temp_step",
2479 S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 0);
2480SENSOR_TEMPLATE_2(pwm_weight_temp_step_tol, "pwm%d_weight_temp_step_tol",
2481 S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 1);
2482SENSOR_TEMPLATE_2(pwm_weight_temp_step_base, "pwm%d_weight_temp_step_base",
2483 S_IWUSR | S_IRUGO, show_weight_temp, store_weight_temp, 0, 2);
2484SENSOR_TEMPLATE_2(pwm_weight_duty_step, "pwm%d_weight_duty_step",
2485 S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 5);
2486SENSOR_TEMPLATE_2(pwm_weight_duty_base, "pwm%d_weight_duty_base",
2487 S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 6);
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08002488
2489static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002490show_fan_time(struct device *dev, struct device_attribute *attr, char *buf)
2491{
2492 struct nct6775_data *data = nct6775_update_device(dev);
2493 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2494 int nr = sattr->nr;
2495 int index = sattr->index;
2496
2497 return sprintf(buf, "%d\n",
2498 step_time_from_reg(data->fan_time[index][nr],
2499 data->pwm_mode[nr]));
2500}
2501
2502static ssize_t
2503store_fan_time(struct device *dev, struct device_attribute *attr,
2504 const char *buf, size_t count)
2505{
2506 struct nct6775_data *data = dev_get_drvdata(dev);
2507 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2508 int nr = sattr->nr;
2509 int index = sattr->index;
2510 unsigned long val;
2511 int err;
2512
2513 err = kstrtoul(buf, 10, &val);
2514 if (err < 0)
2515 return err;
2516
2517 val = step_time_to_reg(val, data->pwm_mode[nr]);
2518 mutex_lock(&data->update_lock);
2519 data->fan_time[index][nr] = val;
2520 nct6775_write_value(data, data->REG_FAN_TIME[index][nr], val);
2521 mutex_unlock(&data->update_lock);
2522 return count;
2523}
2524
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002525static ssize_t
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07002526show_name(struct device *dev, struct device_attribute *attr, char *buf)
2527{
2528 struct nct6775_data *data = dev_get_drvdata(dev);
2529
2530 return sprintf(buf, "%s\n", data->name);
2531}
2532
2533static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
2534
2535static ssize_t
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002536show_auto_pwm(struct device *dev, struct device_attribute *attr, char *buf)
2537{
2538 struct nct6775_data *data = nct6775_update_device(dev);
2539 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2540
2541 return sprintf(buf, "%d\n", data->auto_pwm[sattr->nr][sattr->index]);
2542}
2543
2544static ssize_t
2545store_auto_pwm(struct device *dev, struct device_attribute *attr,
2546 const char *buf, size_t count)
2547{
2548 struct nct6775_data *data = dev_get_drvdata(dev);
2549 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2550 int nr = sattr->nr;
2551 int point = sattr->index;
2552 unsigned long val;
2553 int err;
2554 u8 reg;
2555
2556 err = kstrtoul(buf, 10, &val);
2557 if (err < 0)
2558 return err;
2559 if (val > 255)
2560 return -EINVAL;
2561
2562 if (point == data->auto_pwm_num) {
2563 if (data->kind != nct6775 && !val)
2564 return -EINVAL;
2565 if (data->kind != nct6779 && val)
2566 val = 0xff;
2567 }
2568
2569 mutex_lock(&data->update_lock);
2570 data->auto_pwm[nr][point] = val;
2571 if (point < data->auto_pwm_num) {
2572 nct6775_write_value(data,
2573 NCT6775_AUTO_PWM(data, nr, point),
2574 data->auto_pwm[nr][point]);
2575 } else {
2576 switch (data->kind) {
2577 case nct6775:
2578 /* disable if needed (pwm == 0) */
2579 reg = nct6775_read_value(data,
2580 NCT6775_REG_CRITICAL_ENAB[nr]);
2581 if (val)
2582 reg |= 0x02;
2583 else
2584 reg &= ~0x02;
2585 nct6775_write_value(data, NCT6775_REG_CRITICAL_ENAB[nr],
2586 reg);
2587 break;
2588 case nct6776:
2589 break; /* always enabled, nothing to do */
Guenter Roeck6c009502012-07-01 08:23:15 -07002590 case nct6106:
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002591 case nct6779:
Guenter Roeck6c009502012-07-01 08:23:15 -07002592 nct6775_write_value(data, data->REG_CRITICAL_PWM[nr],
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002593 val);
2594 reg = nct6775_read_value(data,
Guenter Roeck6c009502012-07-01 08:23:15 -07002595 data->REG_CRITICAL_PWM_ENABLE[nr]);
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002596 if (val == 255)
Guenter Roeck6c009502012-07-01 08:23:15 -07002597 reg &= ~data->CRITICAL_PWM_ENABLE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002598 else
Guenter Roeck6c009502012-07-01 08:23:15 -07002599 reg |= data->CRITICAL_PWM_ENABLE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002600 nct6775_write_value(data,
Guenter Roeck6c009502012-07-01 08:23:15 -07002601 data->REG_CRITICAL_PWM_ENABLE[nr],
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002602 reg);
2603 break;
2604 }
2605 }
2606 mutex_unlock(&data->update_lock);
2607 return count;
2608}
2609
2610static ssize_t
2611show_auto_temp(struct device *dev, struct device_attribute *attr, char *buf)
2612{
2613 struct nct6775_data *data = nct6775_update_device(dev);
2614 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2615 int nr = sattr->nr;
2616 int point = sattr->index;
2617
2618 /*
2619 * We don't know for sure if the temperature is signed or unsigned.
2620 * Assume it is unsigned.
2621 */
2622 return sprintf(buf, "%d\n", data->auto_temp[nr][point] * 1000);
2623}
2624
2625static ssize_t
2626store_auto_temp(struct device *dev, struct device_attribute *attr,
2627 const char *buf, size_t count)
2628{
2629 struct nct6775_data *data = dev_get_drvdata(dev);
2630 struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
2631 int nr = sattr->nr;
2632 int point = sattr->index;
2633 unsigned long val;
2634 int err;
2635
2636 err = kstrtoul(buf, 10, &val);
2637 if (err)
2638 return err;
2639 if (val > 255000)
2640 return -EINVAL;
2641
2642 mutex_lock(&data->update_lock);
2643 data->auto_temp[nr][point] = DIV_ROUND_CLOSEST(val, 1000);
2644 if (point < data->auto_pwm_num) {
2645 nct6775_write_value(data,
2646 NCT6775_AUTO_TEMP(data, nr, point),
2647 data->auto_temp[nr][point]);
2648 } else {
2649 nct6775_write_value(data, data->REG_CRITICAL_TEMP[nr],
2650 data->auto_temp[nr][point]);
2651 }
2652 mutex_unlock(&data->update_lock);
2653 return count;
2654}
2655
Guenter Roeckf73cf632013-03-18 09:22:50 -07002656static umode_t nct6775_pwm_is_visible(struct kobject *kobj,
2657 struct attribute *attr, int index)
2658{
2659 struct device *dev = container_of(kobj, struct device, kobj);
2660 struct nct6775_data *data = dev_get_drvdata(dev);
2661 int pwm = index / 36; /* pwm index */
2662 int nr = index % 36; /* attribute index */
2663
2664 if (!(data->has_pwm & (1 << pwm)))
2665 return 0;
2666
2667 if (nr == 19 && data->REG_PWM[3] == NULL) /* pwm_max */
2668 return 0;
2669 if (nr == 20 && data->REG_PWM[4] == NULL) /* pwm_step */
2670 return 0;
2671 if (nr == 21 && data->REG_PWM[6] == NULL) /* weight_duty_base */
2672 return 0;
2673
2674 if (nr >= 22 && nr <= 35) { /* auto point */
2675 int api = (nr - 22) / 2; /* auto point index */
2676
2677 if (api > data->auto_pwm_num)
2678 return 0;
2679 }
2680 return attr->mode;
2681}
2682
2683SENSOR_TEMPLATE_2(pwm_stop_time, "pwm%d_stop_time", S_IWUSR | S_IRUGO,
2684 show_fan_time, store_fan_time, 0, 0);
2685SENSOR_TEMPLATE_2(pwm_step_up_time, "pwm%d_step_up_time", S_IWUSR | S_IRUGO,
2686 show_fan_time, store_fan_time, 0, 1);
2687SENSOR_TEMPLATE_2(pwm_step_down_time, "pwm%d_step_down_time", S_IWUSR | S_IRUGO,
2688 show_fan_time, store_fan_time, 0, 2);
2689SENSOR_TEMPLATE_2(pwm_start, "pwm%d_start", S_IWUSR | S_IRUGO, show_pwm,
2690 store_pwm, 0, 1);
2691SENSOR_TEMPLATE_2(pwm_floor, "pwm%d_floor", S_IWUSR | S_IRUGO, show_pwm,
2692 store_pwm, 0, 2);
2693SENSOR_TEMPLATE_2(pwm_temp_tolerance, "pwm%d_temp_tolerance", S_IWUSR | S_IRUGO,
2694 show_temp_tolerance, store_temp_tolerance, 0, 0);
2695SENSOR_TEMPLATE_2(pwm_crit_temp_tolerance, "pwm%d_crit_temp_tolerance",
2696 S_IWUSR | S_IRUGO, show_temp_tolerance, store_temp_tolerance,
2697 0, 1);
2698
2699SENSOR_TEMPLATE_2(pwm_max, "pwm%d_max", S_IWUSR | S_IRUGO, show_pwm, store_pwm,
2700 0, 3);
2701
2702SENSOR_TEMPLATE_2(pwm_step, "pwm%d_step", S_IWUSR | S_IRUGO, show_pwm,
2703 store_pwm, 0, 4);
2704
2705SENSOR_TEMPLATE_2(pwm_auto_point1_pwm, "pwm%d_auto_point1_pwm",
2706 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 0);
2707SENSOR_TEMPLATE_2(pwm_auto_point1_temp, "pwm%d_auto_point1_temp",
2708 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 0);
2709
2710SENSOR_TEMPLATE_2(pwm_auto_point2_pwm, "pwm%d_auto_point2_pwm",
2711 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 1);
2712SENSOR_TEMPLATE_2(pwm_auto_point2_temp, "pwm%d_auto_point2_temp",
2713 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 1);
2714
2715SENSOR_TEMPLATE_2(pwm_auto_point3_pwm, "pwm%d_auto_point3_pwm",
2716 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 2);
2717SENSOR_TEMPLATE_2(pwm_auto_point3_temp, "pwm%d_auto_point3_temp",
2718 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 2);
2719
2720SENSOR_TEMPLATE_2(pwm_auto_point4_pwm, "pwm%d_auto_point4_pwm",
2721 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 3);
2722SENSOR_TEMPLATE_2(pwm_auto_point4_temp, "pwm%d_auto_point4_temp",
2723 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 3);
2724
2725SENSOR_TEMPLATE_2(pwm_auto_point5_pwm, "pwm%d_auto_point5_pwm",
2726 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 4);
2727SENSOR_TEMPLATE_2(pwm_auto_point5_temp, "pwm%d_auto_point5_temp",
2728 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 4);
2729
2730SENSOR_TEMPLATE_2(pwm_auto_point6_pwm, "pwm%d_auto_point6_pwm",
2731 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 5);
2732SENSOR_TEMPLATE_2(pwm_auto_point6_temp, "pwm%d_auto_point6_temp",
2733 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 5);
2734
2735SENSOR_TEMPLATE_2(pwm_auto_point7_pwm, "pwm%d_auto_point7_pwm",
2736 S_IWUSR | S_IRUGO, show_auto_pwm, store_auto_pwm, 0, 6);
2737SENSOR_TEMPLATE_2(pwm_auto_point7_temp, "pwm%d_auto_point7_temp",
2738 S_IWUSR | S_IRUGO, show_auto_temp, store_auto_temp, 0, 6);
2739
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002740/*
Guenter Roeckf73cf632013-03-18 09:22:50 -07002741 * nct6775_pwm_is_visible uses the index into the following array
2742 * to determine if attributes should be created or not.
2743 * Any change in order or content must be matched.
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002744 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07002745static struct sensor_device_template *nct6775_attributes_pwm_template[] = {
2746 &sensor_dev_template_pwm,
2747 &sensor_dev_template_pwm_mode,
2748 &sensor_dev_template_pwm_enable,
2749 &sensor_dev_template_pwm_temp_sel,
2750 &sensor_dev_template_pwm_temp_tolerance,
2751 &sensor_dev_template_pwm_crit_temp_tolerance,
2752 &sensor_dev_template_pwm_target_temp,
2753 &sensor_dev_template_fan_target,
2754 &sensor_dev_template_fan_tolerance,
2755 &sensor_dev_template_pwm_stop_time,
2756 &sensor_dev_template_pwm_step_up_time,
2757 &sensor_dev_template_pwm_step_down_time,
2758 &sensor_dev_template_pwm_start,
2759 &sensor_dev_template_pwm_floor,
2760 &sensor_dev_template_pwm_weight_temp_sel,
2761 &sensor_dev_template_pwm_weight_temp_step,
2762 &sensor_dev_template_pwm_weight_temp_step_tol,
2763 &sensor_dev_template_pwm_weight_temp_step_base,
2764 &sensor_dev_template_pwm_weight_duty_step,
2765 &sensor_dev_template_pwm_max, /* 19 */
2766 &sensor_dev_template_pwm_step, /* 20 */
2767 &sensor_dev_template_pwm_weight_duty_base, /* 21 */
2768 &sensor_dev_template_pwm_auto_point1_pwm, /* 22 */
2769 &sensor_dev_template_pwm_auto_point1_temp,
2770 &sensor_dev_template_pwm_auto_point2_pwm,
2771 &sensor_dev_template_pwm_auto_point2_temp,
2772 &sensor_dev_template_pwm_auto_point3_pwm,
2773 &sensor_dev_template_pwm_auto_point3_temp,
2774 &sensor_dev_template_pwm_auto_point4_pwm,
2775 &sensor_dev_template_pwm_auto_point4_temp,
2776 &sensor_dev_template_pwm_auto_point5_pwm,
2777 &sensor_dev_template_pwm_auto_point5_temp,
2778 &sensor_dev_template_pwm_auto_point6_pwm,
2779 &sensor_dev_template_pwm_auto_point6_temp,
2780 &sensor_dev_template_pwm_auto_point7_pwm,
2781 &sensor_dev_template_pwm_auto_point7_temp, /* 35 */
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002782
Guenter Roeckf73cf632013-03-18 09:22:50 -07002783 NULL
2784};
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002785
Guenter Roeckf73cf632013-03-18 09:22:50 -07002786static struct sensor_template_group nct6775_pwm_template_group = {
2787 .templates = nct6775_attributes_pwm_template,
2788 .is_visible = nct6775_pwm_is_visible,
2789 .base = 1,
Guenter Roeckcdcaece2012-12-04 09:04:52 -08002790};
2791
2792static ssize_t
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07002793show_vid(struct device *dev, struct device_attribute *attr, char *buf)
2794{
2795 struct nct6775_data *data = dev_get_drvdata(dev);
2796 return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
2797}
2798
2799static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
2800
Guenter Roecka6bd5872012-12-04 03:13:34 -08002801/* Case open detection */
2802
2803static ssize_t
2804clear_caseopen(struct device *dev, struct device_attribute *attr,
2805 const char *buf, size_t count)
2806{
2807 struct nct6775_data *data = dev_get_drvdata(dev);
2808 struct nct6775_sio_data *sio_data = dev->platform_data;
2809 int nr = to_sensor_dev_attr(attr)->index - INTRUSION_ALARM_BASE;
2810 unsigned long val;
2811 u8 reg;
2812 int ret;
2813
2814 if (kstrtoul(buf, 10, &val) || val != 0)
2815 return -EINVAL;
2816
2817 mutex_lock(&data->update_lock);
2818
2819 /*
2820 * Use CR registers to clear caseopen status.
2821 * The CR registers are the same for all chips, and not all chips
2822 * support clearing the caseopen status through "regular" registers.
2823 */
2824 ret = superio_enter(sio_data->sioreg);
2825 if (ret) {
2826 count = ret;
2827 goto error;
2828 }
2829
2830 superio_select(sio_data->sioreg, NCT6775_LD_ACPI);
2831 reg = superio_inb(sio_data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr]);
2832 reg |= NCT6775_CR_CASEOPEN_CLR_MASK[nr];
2833 superio_outb(sio_data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
2834 reg &= ~NCT6775_CR_CASEOPEN_CLR_MASK[nr];
2835 superio_outb(sio_data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
2836 superio_exit(sio_data->sioreg);
2837
2838 data->valid = false; /* Force cache refresh */
2839error:
2840 mutex_unlock(&data->update_lock);
2841 return count;
2842}
2843
Guenter Roeckf73cf632013-03-18 09:22:50 -07002844static SENSOR_DEVICE_ATTR(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm,
2845 clear_caseopen, INTRUSION_ALARM_BASE);
2846static SENSOR_DEVICE_ATTR(intrusion1_alarm, S_IWUSR | S_IRUGO, show_alarm,
2847 clear_caseopen, INTRUSION_ALARM_BASE + 1);
2848
2849static umode_t nct6775_other_is_visible(struct kobject *kobj,
2850 struct attribute *attr, int index)
2851{
2852 struct device *dev = container_of(kobj, struct device, kobj);
2853 struct nct6775_data *data = dev_get_drvdata(dev);
2854
2855 if (index == 1 && !data->have_vid)
2856 return 0;
2857
2858 if (index == 2 || index == 3) {
2859 if (data->ALARM_BITS[INTRUSION_ALARM_BASE + index - 2] < 0)
2860 return 0;
2861 }
2862
2863 return attr->mode;
2864}
2865
2866/*
2867 * nct6775_other_is_visible uses the index into the following array
2868 * to determine if attributes should be created or not.
2869 * Any change in order or content must be matched.
2870 */
2871static struct attribute *nct6775_attributes_other[] = {
2872 &dev_attr_name.attr,
2873 &dev_attr_cpu0_vid.attr, /* 1 */
2874 &sensor_dev_attr_intrusion0_alarm.dev_attr.attr, /* 2 */
2875 &sensor_dev_attr_intrusion1_alarm.dev_attr.attr, /* 3 */
2876
2877 NULL
2878};
2879
2880static const struct attribute_group nct6775_group_other = {
2881 .attrs = nct6775_attributes_other,
2882 .is_visible = nct6775_other_is_visible,
Guenter Roecka6bd5872012-12-04 03:13:34 -08002883};
2884
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07002885/*
2886 * Driver and device management
2887 */
2888
2889static void nct6775_device_remove_files(struct device *dev)
2890{
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07002891 struct nct6775_data *data = dev_get_drvdata(dev);
2892
Guenter Roeckf73cf632013-03-18 09:22:50 -07002893 if (data->group_pwm)
2894 sysfs_remove_group(&dev->kobj, data->group_pwm);
2895 if (data->group_in)
2896 sysfs_remove_group(&dev->kobj, data->group_in);
2897 if (data->group_fan)
2898 sysfs_remove_group(&dev->kobj, data->group_fan);
2899 if (data->group_temp)
2900 sysfs_remove_group(&dev->kobj, data->group_temp);
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002901
Guenter Roeckf73cf632013-03-18 09:22:50 -07002902 sysfs_remove_group(&dev->kobj, &nct6775_group_other);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07002903}
2904
2905/* Get the monitoring functions started */
2906static inline void nct6775_init_device(struct nct6775_data *data)
2907{
Guenter Roeckaa136e52012-12-04 03:26:05 -08002908 int i;
2909 u8 tmp, diode;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07002910
2911 /* Start monitoring if needed */
2912 if (data->REG_CONFIG) {
2913 tmp = nct6775_read_value(data, data->REG_CONFIG);
2914 if (!(tmp & 0x01))
2915 nct6775_write_value(data, data->REG_CONFIG, tmp | 0x01);
2916 }
2917
Guenter Roeckaa136e52012-12-04 03:26:05 -08002918 /* Enable temperature sensors if needed */
2919 for (i = 0; i < NUM_TEMP; i++) {
2920 if (!(data->have_temp & (1 << i)))
2921 continue;
2922 if (!data->reg_temp_config[i])
2923 continue;
2924 tmp = nct6775_read_value(data, data->reg_temp_config[i]);
2925 if (tmp & 0x01)
2926 nct6775_write_value(data, data->reg_temp_config[i],
2927 tmp & 0xfe);
2928 }
2929
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07002930 /* Enable VBAT monitoring if needed */
2931 tmp = nct6775_read_value(data, data->REG_VBAT);
2932 if (!(tmp & 0x01))
2933 nct6775_write_value(data, data->REG_VBAT, tmp | 0x01);
Guenter Roeckaa136e52012-12-04 03:26:05 -08002934
2935 diode = nct6775_read_value(data, data->REG_DIODE);
2936
2937 for (i = 0; i < data->temp_fixed_num; i++) {
2938 if (!(data->have_temp_fixed & (1 << i)))
2939 continue;
Guenter Roeck6c009502012-07-01 08:23:15 -07002940 if ((tmp & (data->DIODE_MASK << i))) /* diode */
2941 data->temp_type[i]
2942 = 3 - ((diode >> i) & data->DIODE_MASK);
Guenter Roeckaa136e52012-12-04 03:26:05 -08002943 else /* thermistor */
2944 data->temp_type[i] = 4;
2945 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07002946}
2947
Guenter Roeckf73cf632013-03-18 09:22:50 -07002948static void
Guenter Roeck1c65dc32012-12-04 07:56:24 -08002949nct6775_check_fan_inputs(const struct nct6775_sio_data *sio_data,
2950 struct nct6775_data *data)
2951{
2952 int regval;
2953 bool fan3pin, fan3min, fan4pin, fan4min, fan5pin;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002954 bool pwm3pin, pwm4pin, pwm5pin;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08002955
2956 /* fan4 and fan5 share some pins with the GPIO and serial flash */
2957 if (data->kind == nct6775) {
2958 regval = superio_inb(sio_data->sioreg, 0x2c);
2959
2960 fan3pin = regval & (1 << 6);
2961 fan3min = fan3pin;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002962 pwm3pin = regval & (1 << 7);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08002963
2964 /* On NCT6775, fan4 shares pins with the fdc interface */
2965 fan4pin = !(superio_inb(sio_data->sioreg, 0x2A) & 0x80);
2966 fan4min = 0;
2967 fan5pin = 0;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002968 pwm4pin = 0;
2969 pwm5pin = 0;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08002970 } else if (data->kind == nct6776) {
2971 bool gpok = superio_inb(sio_data->sioreg, 0x27) & 0x80;
2972
2973 superio_select(sio_data->sioreg, NCT6775_LD_HWM);
2974 regval = superio_inb(sio_data->sioreg, SIO_REG_ENABLE);
2975
2976 if (regval & 0x80)
2977 fan3pin = gpok;
2978 else
2979 fan3pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x40);
2980
2981 if (regval & 0x40)
2982 fan4pin = gpok;
2983 else
2984 fan4pin = superio_inb(sio_data->sioreg, 0x1C) & 0x01;
2985
2986 if (regval & 0x20)
2987 fan5pin = gpok;
2988 else
2989 fan5pin = superio_inb(sio_data->sioreg, 0x1C) & 0x02;
2990
2991 fan4min = fan4pin;
2992 fan3min = fan3pin;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08002993 pwm3pin = fan3pin;
2994 pwm4pin = 0;
2995 pwm5pin = 0;
Guenter Roeck6c009502012-07-01 08:23:15 -07002996 } else if (data->kind == nct6106) {
2997 regval = superio_inb(sio_data->sioreg, 0x24);
2998 fan3pin = !(regval & 0x80);
2999 pwm3pin = regval & 0x08;
3000 fan3min = fan3pin;
3001
3002 fan4pin = false;
3003 fan4min = false;
3004 fan5pin = false;
3005 pwm4pin = false;
3006 pwm5pin = false;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003007 } else { /* NCT6779D */
3008 regval = superio_inb(sio_data->sioreg, 0x1c);
3009
3010 fan3pin = !(regval & (1 << 5));
3011 fan4pin = !(regval & (1 << 6));
3012 fan5pin = !(regval & (1 << 7));
3013
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003014 pwm3pin = !(regval & (1 << 0));
3015 pwm4pin = !(regval & (1 << 1));
3016 pwm5pin = !(regval & (1 << 2));
3017
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003018 fan3min = fan3pin;
3019 fan4min = fan4pin;
3020 }
3021
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003022 data->has_fan = data->has_fan_min = 0x03; /* fan1 and fan2 */
3023 data->has_fan |= fan3pin << 2;
3024 data->has_fan_min |= fan3min << 2;
3025
3026 data->has_fan |= (fan4pin << 3) | (fan5pin << 4);
3027 data->has_fan_min |= (fan4min << 3) | (fan5pin << 4);
3028
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003029 data->has_pwm = 0x03 | (pwm3pin << 2) | (pwm4pin << 3) | (pwm5pin << 4);
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003030}
3031
Guenter Roeck8e9285b2012-12-04 08:03:37 -08003032static void add_temp_sensors(struct nct6775_data *data, const u16 *regp,
3033 int *available, int *mask)
3034{
3035 int i;
3036 u8 src;
3037
3038 for (i = 0; i < data->pwm_num && *available; i++) {
3039 int index;
3040
3041 if (!regp[i])
3042 continue;
3043 src = nct6775_read_value(data, regp[i]);
3044 src &= 0x1f;
3045 if (!src || (*mask & (1 << src)))
3046 continue;
3047 if (src >= data->temp_label_num ||
3048 !strlen(data->temp_label[src]))
3049 continue;
3050
3051 index = __ffs(*available);
3052 nct6775_write_value(data, data->REG_TEMP_SOURCE[index], src);
3053 *available &= ~(1 << index);
3054 *mask |= 1 << src;
3055 }
3056}
3057
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003058static int nct6775_probe(struct platform_device *pdev)
3059{
3060 struct device *dev = &pdev->dev;
3061 struct nct6775_sio_data *sio_data = dev->platform_data;
3062 struct nct6775_data *data;
3063 struct resource *res;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003064 int i, s, err = 0;
3065 int src, mask, available;
3066 const u16 *reg_temp, *reg_temp_over, *reg_temp_hyst, *reg_temp_config;
3067 const u16 *reg_temp_alternate, *reg_temp_crit;
Guenter Roeckb7a61352013-04-02 22:14:06 -07003068 const u16 *reg_temp_crit_l = NULL, *reg_temp_crit_h = NULL;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003069 int num_reg_temp;
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003070 u8 cr2a;
Guenter Roeckf73cf632013-03-18 09:22:50 -07003071 struct attribute_group *group;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003072
3073 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
3074 if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH,
3075 DRVNAME))
3076 return -EBUSY;
3077
3078 data = devm_kzalloc(&pdev->dev, sizeof(struct nct6775_data),
3079 GFP_KERNEL);
3080 if (!data)
3081 return -ENOMEM;
3082
3083 data->kind = sio_data->kind;
3084 data->addr = res->start;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003085 mutex_init(&data->update_lock);
3086 data->name = nct6775_device_names[data->kind];
3087 data->bank = 0xff; /* Force initial bank selection */
3088 platform_set_drvdata(pdev, data);
3089
3090 switch (data->kind) {
Guenter Roeck6c009502012-07-01 08:23:15 -07003091 case nct6106:
3092 data->in_num = 9;
3093 data->pwm_num = 3;
3094 data->auto_pwm_num = 4;
3095 data->temp_fixed_num = 3;
3096 data->num_temp_alarms = 6;
3097
3098 data->fan_from_reg = fan_from_reg13;
3099 data->fan_from_reg_min = fan_from_reg13;
3100
3101 data->temp_label = nct6776_temp_label;
3102 data->temp_label_num = ARRAY_SIZE(nct6776_temp_label);
3103
3104 data->REG_VBAT = NCT6106_REG_VBAT;
3105 data->REG_DIODE = NCT6106_REG_DIODE;
3106 data->DIODE_MASK = NCT6106_DIODE_MASK;
3107 data->REG_VIN = NCT6106_REG_IN;
3108 data->REG_IN_MINMAX[0] = NCT6106_REG_IN_MIN;
3109 data->REG_IN_MINMAX[1] = NCT6106_REG_IN_MAX;
3110 data->REG_TARGET = NCT6106_REG_TARGET;
3111 data->REG_FAN = NCT6106_REG_FAN;
3112 data->REG_FAN_MODE = NCT6106_REG_FAN_MODE;
3113 data->REG_FAN_MIN = NCT6106_REG_FAN_MIN;
3114 data->REG_FAN_PULSES = NCT6106_REG_FAN_PULSES;
3115 data->FAN_PULSE_SHIFT = NCT6106_FAN_PULSE_SHIFT;
3116 data->REG_FAN_TIME[0] = NCT6106_REG_FAN_STOP_TIME;
3117 data->REG_FAN_TIME[1] = NCT6106_REG_FAN_STEP_UP_TIME;
3118 data->REG_FAN_TIME[2] = NCT6106_REG_FAN_STEP_DOWN_TIME;
3119 data->REG_PWM[0] = NCT6106_REG_PWM;
3120 data->REG_PWM[1] = NCT6106_REG_FAN_START_OUTPUT;
3121 data->REG_PWM[2] = NCT6106_REG_FAN_STOP_OUTPUT;
3122 data->REG_PWM[5] = NCT6106_REG_WEIGHT_DUTY_STEP;
3123 data->REG_PWM[6] = NCT6106_REG_WEIGHT_DUTY_BASE;
3124 data->REG_PWM_READ = NCT6106_REG_PWM_READ;
3125 data->REG_PWM_MODE = NCT6106_REG_PWM_MODE;
3126 data->PWM_MODE_MASK = NCT6106_PWM_MODE_MASK;
3127 data->REG_AUTO_TEMP = NCT6106_REG_AUTO_TEMP;
3128 data->REG_AUTO_PWM = NCT6106_REG_AUTO_PWM;
3129 data->REG_CRITICAL_TEMP = NCT6106_REG_CRITICAL_TEMP;
3130 data->REG_CRITICAL_TEMP_TOLERANCE
3131 = NCT6106_REG_CRITICAL_TEMP_TOLERANCE;
3132 data->REG_CRITICAL_PWM_ENABLE = NCT6106_REG_CRITICAL_PWM_ENABLE;
3133 data->CRITICAL_PWM_ENABLE_MASK
3134 = NCT6106_CRITICAL_PWM_ENABLE_MASK;
3135 data->REG_CRITICAL_PWM = NCT6106_REG_CRITICAL_PWM;
3136 data->REG_TEMP_OFFSET = NCT6106_REG_TEMP_OFFSET;
3137 data->REG_TEMP_SOURCE = NCT6106_REG_TEMP_SOURCE;
3138 data->REG_TEMP_SEL = NCT6106_REG_TEMP_SEL;
3139 data->REG_WEIGHT_TEMP_SEL = NCT6106_REG_WEIGHT_TEMP_SEL;
3140 data->REG_WEIGHT_TEMP[0] = NCT6106_REG_WEIGHT_TEMP_STEP;
3141 data->REG_WEIGHT_TEMP[1] = NCT6106_REG_WEIGHT_TEMP_STEP_TOL;
3142 data->REG_WEIGHT_TEMP[2] = NCT6106_REG_WEIGHT_TEMP_BASE;
3143 data->REG_ALARM = NCT6106_REG_ALARM;
3144 data->ALARM_BITS = NCT6106_ALARM_BITS;
3145
3146 reg_temp = NCT6106_REG_TEMP;
3147 num_reg_temp = ARRAY_SIZE(NCT6106_REG_TEMP);
3148 reg_temp_over = NCT6106_REG_TEMP_OVER;
3149 reg_temp_hyst = NCT6106_REG_TEMP_HYST;
3150 reg_temp_config = NCT6106_REG_TEMP_CONFIG;
3151 reg_temp_alternate = NCT6106_REG_TEMP_ALTERNATE;
3152 reg_temp_crit = NCT6106_REG_TEMP_CRIT;
Guenter Roeckb7a61352013-04-02 22:14:06 -07003153 reg_temp_crit_l = NCT6106_REG_TEMP_CRIT_L;
3154 reg_temp_crit_h = NCT6106_REG_TEMP_CRIT_H;
Guenter Roeck6c009502012-07-01 08:23:15 -07003155
3156 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003157 case nct6775:
3158 data->in_num = 9;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003159 data->pwm_num = 3;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003160 data->auto_pwm_num = 6;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003161 data->has_fan_div = true;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003162 data->temp_fixed_num = 3;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07003163 data->num_temp_alarms = 3;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003164
3165 data->ALARM_BITS = NCT6775_ALARM_BITS;
3166
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003167 data->fan_from_reg = fan_from_reg16;
3168 data->fan_from_reg_min = fan_from_reg8;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003169 data->target_temp_mask = 0x7f;
3170 data->tolerance_mask = 0x0f;
3171 data->speed_tolerance_limit = 15;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003172
Guenter Roeckaa136e52012-12-04 03:26:05 -08003173 data->temp_label = nct6775_temp_label;
3174 data->temp_label_num = ARRAY_SIZE(nct6775_temp_label);
3175
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003176 data->REG_CONFIG = NCT6775_REG_CONFIG;
3177 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003178 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003179 data->DIODE_MASK = NCT6775_DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003180 data->REG_VIN = NCT6775_REG_IN;
3181 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3182 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003183 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003184 data->REG_FAN = NCT6775_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003185 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003186 data->REG_FAN_MIN = NCT6775_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003187 data->REG_FAN_PULSES = NCT6775_REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -07003188 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003189 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3190 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3191 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003192 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003193 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3194 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
3195 data->REG_PWM[3] = NCT6775_REG_FAN_MAX_OUTPUT;
3196 data->REG_PWM[4] = NCT6775_REG_FAN_STEP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003197 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003198 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3199 data->REG_PWM_MODE = NCT6775_REG_PWM_MODE;
3200 data->PWM_MODE_MASK = NCT6775_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003201 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3202 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3203 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3204 data->REG_CRITICAL_TEMP_TOLERANCE
3205 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003206 data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET;
3207 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003208 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003209 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3210 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3211 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3212 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003213 data->REG_ALARM = NCT6775_REG_ALARM;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003214
3215 reg_temp = NCT6775_REG_TEMP;
3216 num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
3217 reg_temp_over = NCT6775_REG_TEMP_OVER;
3218 reg_temp_hyst = NCT6775_REG_TEMP_HYST;
3219 reg_temp_config = NCT6775_REG_TEMP_CONFIG;
3220 reg_temp_alternate = NCT6775_REG_TEMP_ALTERNATE;
3221 reg_temp_crit = NCT6775_REG_TEMP_CRIT;
3222
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003223 break;
3224 case nct6776:
3225 data->in_num = 9;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003226 data->pwm_num = 3;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003227 data->auto_pwm_num = 4;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003228 data->has_fan_div = false;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003229 data->temp_fixed_num = 3;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07003230 data->num_temp_alarms = 3;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003231
3232 data->ALARM_BITS = NCT6776_ALARM_BITS;
3233
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003234 data->fan_from_reg = fan_from_reg13;
3235 data->fan_from_reg_min = fan_from_reg13;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003236 data->target_temp_mask = 0xff;
3237 data->tolerance_mask = 0x07;
3238 data->speed_tolerance_limit = 63;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003239
Guenter Roeckaa136e52012-12-04 03:26:05 -08003240 data->temp_label = nct6776_temp_label;
3241 data->temp_label_num = ARRAY_SIZE(nct6776_temp_label);
3242
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003243 data->REG_CONFIG = NCT6775_REG_CONFIG;
3244 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003245 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003246 data->DIODE_MASK = NCT6775_DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003247 data->REG_VIN = NCT6775_REG_IN;
3248 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3249 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003250 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003251 data->REG_FAN = NCT6775_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003252 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003253 data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003254 data->REG_FAN_PULSES = NCT6776_REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -07003255 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003256 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3257 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3258 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
3259 data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003260 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003261 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3262 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003263 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
3264 data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003265 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3266 data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3267 data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003268 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3269 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3270 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3271 data->REG_CRITICAL_TEMP_TOLERANCE
3272 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003273 data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET;
3274 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003275 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003276 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3277 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3278 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3279 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003280 data->REG_ALARM = NCT6775_REG_ALARM;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003281
3282 reg_temp = NCT6775_REG_TEMP;
3283 num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
3284 reg_temp_over = NCT6775_REG_TEMP_OVER;
3285 reg_temp_hyst = NCT6775_REG_TEMP_HYST;
3286 reg_temp_config = NCT6776_REG_TEMP_CONFIG;
3287 reg_temp_alternate = NCT6776_REG_TEMP_ALTERNATE;
3288 reg_temp_crit = NCT6776_REG_TEMP_CRIT;
3289
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003290 break;
3291 case nct6779:
3292 data->in_num = 15;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003293 data->pwm_num = 5;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003294 data->auto_pwm_num = 4;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003295 data->has_fan_div = false;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003296 data->temp_fixed_num = 6;
Guenter Roeckb1d2bff2013-06-22 16:15:31 -07003297 data->num_temp_alarms = 2;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003298
3299 data->ALARM_BITS = NCT6779_ALARM_BITS;
3300
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003301 data->fan_from_reg = fan_from_reg13;
3302 data->fan_from_reg_min = fan_from_reg13;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003303 data->target_temp_mask = 0xff;
3304 data->tolerance_mask = 0x07;
3305 data->speed_tolerance_limit = 63;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003306
Guenter Roeckaa136e52012-12-04 03:26:05 -08003307 data->temp_label = nct6779_temp_label;
3308 data->temp_label_num = ARRAY_SIZE(nct6779_temp_label);
3309
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003310 data->REG_CONFIG = NCT6775_REG_CONFIG;
3311 data->REG_VBAT = NCT6775_REG_VBAT;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003312 data->REG_DIODE = NCT6775_REG_DIODE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003313 data->DIODE_MASK = NCT6775_DIODE_MASK;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003314 data->REG_VIN = NCT6779_REG_IN;
3315 data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
3316 data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003317 data->REG_TARGET = NCT6775_REG_TARGET;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003318 data->REG_FAN = NCT6779_REG_FAN;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003319 data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003320 data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
Guenter Roeck5c25d952012-12-11 07:29:06 -08003321 data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES;
Guenter Roeck6c009502012-07-01 08:23:15 -07003322 data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003323 data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
3324 data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
3325 data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
3326 data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003327 data->REG_PWM[0] = NCT6775_REG_PWM;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003328 data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
3329 data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003330 data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
3331 data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003332 data->REG_PWM_READ = NCT6775_REG_PWM_READ;
3333 data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
3334 data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003335 data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
3336 data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
3337 data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
3338 data->REG_CRITICAL_TEMP_TOLERANCE
3339 = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
Guenter Roeck6c009502012-07-01 08:23:15 -07003340 data->REG_CRITICAL_PWM_ENABLE = NCT6779_REG_CRITICAL_PWM_ENABLE;
3341 data->CRITICAL_PWM_ENABLE_MASK
3342 = NCT6779_CRITICAL_PWM_ENABLE_MASK;
3343 data->REG_CRITICAL_PWM = NCT6779_REG_CRITICAL_PWM;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003344 data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET;
3345 data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003346 data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL;
Guenter Roeckbbd8dec2012-12-04 09:08:29 -08003347 data->REG_WEIGHT_TEMP_SEL = NCT6775_REG_WEIGHT_TEMP_SEL;
3348 data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
3349 data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
3350 data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003351 data->REG_ALARM = NCT6779_REG_ALARM;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003352
3353 reg_temp = NCT6779_REG_TEMP;
3354 num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
3355 reg_temp_over = NCT6779_REG_TEMP_OVER;
3356 reg_temp_hyst = NCT6779_REG_TEMP_HYST;
3357 reg_temp_config = NCT6779_REG_TEMP_CONFIG;
3358 reg_temp_alternate = NCT6779_REG_TEMP_ALTERNATE;
3359 reg_temp_crit = NCT6779_REG_TEMP_CRIT;
3360
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003361 break;
3362 default:
3363 return -ENODEV;
3364 }
3365 data->have_in = (1 << data->in_num) - 1;
Guenter Roeckaa136e52012-12-04 03:26:05 -08003366 data->have_temp = 0;
3367
3368 /*
3369 * On some boards, not all available temperature sources are monitored,
3370 * even though some of the monitoring registers are unused.
3371 * Get list of unused monitoring registers, then detect if any fan
3372 * controls are configured to use unmonitored temperature sources.
3373 * If so, assign the unmonitored temperature sources to available
3374 * monitoring registers.
3375 */
3376 mask = 0;
3377 available = 0;
3378 for (i = 0; i < num_reg_temp; i++) {
3379 if (reg_temp[i] == 0)
3380 continue;
3381
3382 src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f;
3383 if (!src || (mask & (1 << src)))
3384 available |= 1 << i;
3385
3386 mask |= 1 << src;
3387 }
3388
Guenter Roeck8e9285b2012-12-04 08:03:37 -08003389 /*
3390 * Now find unmonitored temperature registers and enable monitoring
3391 * if additional monitoring registers are available.
3392 */
3393 add_temp_sensors(data, data->REG_TEMP_SEL, &available, &mask);
3394 add_temp_sensors(data, data->REG_WEIGHT_TEMP_SEL, &available, &mask);
3395
Guenter Roeckaa136e52012-12-04 03:26:05 -08003396 mask = 0;
3397 s = NUM_TEMP_FIXED; /* First dynamic temperature attribute */
3398 for (i = 0; i < num_reg_temp; i++) {
3399 if (reg_temp[i] == 0)
3400 continue;
3401
3402 src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f;
3403 if (!src || (mask & (1 << src)))
3404 continue;
3405
3406 if (src >= data->temp_label_num ||
3407 !strlen(data->temp_label[src])) {
3408 dev_info(dev,
3409 "Invalid temperature source %d at index %d, source register 0x%x, temp register 0x%x\n",
3410 src, i, data->REG_TEMP_SOURCE[i], reg_temp[i]);
3411 continue;
3412 }
3413
3414 mask |= 1 << src;
3415
3416 /* Use fixed index for SYSTIN(1), CPUTIN(2), AUXTIN(3) */
3417 if (src <= data->temp_fixed_num) {
3418 data->have_temp |= 1 << (src - 1);
3419 data->have_temp_fixed |= 1 << (src - 1);
3420 data->reg_temp[0][src - 1] = reg_temp[i];
3421 data->reg_temp[1][src - 1] = reg_temp_over[i];
3422 data->reg_temp[2][src - 1] = reg_temp_hyst[i];
Guenter Roeckb7a61352013-04-02 22:14:06 -07003423 if (reg_temp_crit_h && reg_temp_crit_h[i])
3424 data->reg_temp[3][src - 1] = reg_temp_crit_h[i];
3425 else if (reg_temp_crit[src - 1])
3426 data->reg_temp[3][src - 1]
3427 = reg_temp_crit[src - 1];
3428 if (reg_temp_crit_l && reg_temp_crit_l[i])
3429 data->reg_temp[4][src - 1] = reg_temp_crit_l[i];
Guenter Roeckaa136e52012-12-04 03:26:05 -08003430 data->reg_temp_config[src - 1] = reg_temp_config[i];
3431 data->temp_src[src - 1] = src;
3432 continue;
3433 }
3434
3435 if (s >= NUM_TEMP)
3436 continue;
3437
3438 /* Use dynamic index for other sources */
3439 data->have_temp |= 1 << s;
3440 data->reg_temp[0][s] = reg_temp[i];
3441 data->reg_temp[1][s] = reg_temp_over[i];
3442 data->reg_temp[2][s] = reg_temp_hyst[i];
3443 data->reg_temp_config[s] = reg_temp_config[i];
Guenter Roeckb7a61352013-04-02 22:14:06 -07003444 if (reg_temp_crit_h && reg_temp_crit_h[i])
3445 data->reg_temp[3][s] = reg_temp_crit_h[i];
3446 else if (reg_temp_crit[src - 1])
Guenter Roeckaa136e52012-12-04 03:26:05 -08003447 data->reg_temp[3][s] = reg_temp_crit[src - 1];
Guenter Roeckb7a61352013-04-02 22:14:06 -07003448 if (reg_temp_crit_l && reg_temp_crit_l[i])
3449 data->reg_temp[4][s] = reg_temp_crit_l[i];
Guenter Roeckaa136e52012-12-04 03:26:05 -08003450
3451 data->temp_src[s] = src;
3452 s++;
3453 }
3454
3455#ifdef USE_ALTERNATE
3456 /*
3457 * Go through the list of alternate temp registers and enable
3458 * if possible.
3459 * The temperature is already monitored if the respective bit in <mask>
3460 * is set.
3461 */
3462 for (i = 0; i < data->temp_label_num - 1; i++) {
3463 if (!reg_temp_alternate[i])
3464 continue;
3465 if (mask & (1 << (i + 1)))
3466 continue;
3467 if (i < data->temp_fixed_num) {
3468 if (data->have_temp & (1 << i))
3469 continue;
3470 data->have_temp |= 1 << i;
3471 data->have_temp_fixed |= 1 << i;
3472 data->reg_temp[0][i] = reg_temp_alternate[i];
Guenter Roeck169c05c2013-05-09 10:40:01 -07003473 if (i < num_reg_temp) {
3474 data->reg_temp[1][i] = reg_temp_over[i];
3475 data->reg_temp[2][i] = reg_temp_hyst[i];
3476 }
Guenter Roeckaa136e52012-12-04 03:26:05 -08003477 data->temp_src[i] = i + 1;
3478 continue;
3479 }
3480
3481 if (s >= NUM_TEMP) /* Abort if no more space */
3482 break;
3483
3484 data->have_temp |= 1 << s;
3485 data->reg_temp[0][s] = reg_temp_alternate[i];
3486 data->temp_src[s] = i + 1;
3487 s++;
3488 }
3489#endif /* USE_ALTERNATE */
3490
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003491 /* Initialize the chip */
3492 nct6775_init_device(data);
3493
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003494 err = superio_enter(sio_data->sioreg);
3495 if (err)
3496 return err;
3497
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003498 cr2a = superio_inb(sio_data->sioreg, 0x2a);
3499 switch (data->kind) {
3500 case nct6775:
Guenter Roeckf73cf632013-03-18 09:22:50 -07003501 data->have_vid = (cr2a & 0x40);
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003502 break;
3503 case nct6776:
Guenter Roeckf73cf632013-03-18 09:22:50 -07003504 data->have_vid = (cr2a & 0x60) == 0x40;
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003505 break;
Guenter Roeck6c009502012-07-01 08:23:15 -07003506 case nct6106:
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003507 case nct6779:
3508 break;
3509 }
3510
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003511 /*
3512 * Read VID value
3513 * We can get the VID input values directly at logical device D 0xe3.
3514 */
Guenter Roeckf73cf632013-03-18 09:22:50 -07003515 if (data->have_vid) {
Guenter Roeck0fc1f8f2013-02-26 09:43:50 -08003516 superio_select(sio_data->sioreg, NCT6775_LD_VID);
3517 data->vid = superio_inb(sio_data->sioreg, 0xe3);
3518 data->vrm = vid_which_vrm();
3519 }
Guenter Roeck47ece962012-12-04 07:59:32 -08003520
3521 if (fan_debounce) {
3522 u8 tmp;
3523
3524 superio_select(sio_data->sioreg, NCT6775_LD_HWM);
3525 tmp = superio_inb(sio_data->sioreg,
3526 NCT6775_REG_CR_FAN_DEBOUNCE);
3527 switch (data->kind) {
Guenter Roeck6c009502012-07-01 08:23:15 -07003528 case nct6106:
3529 tmp |= 0xe0;
3530 break;
Guenter Roeck47ece962012-12-04 07:59:32 -08003531 case nct6775:
3532 tmp |= 0x1e;
3533 break;
3534 case nct6776:
3535 case nct6779:
3536 tmp |= 0x3e;
3537 break;
3538 }
3539 superio_outb(sio_data->sioreg, NCT6775_REG_CR_FAN_DEBOUNCE,
3540 tmp);
3541 dev_info(&pdev->dev, "Enabled fan debounce for chip %s\n",
3542 data->name);
3543 }
3544
Guenter Roeckf73cf632013-03-18 09:22:50 -07003545 nct6775_check_fan_inputs(sio_data, data);
3546
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003547 superio_exit(sio_data->sioreg);
3548
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003549 /* Read fan clock dividers immediately */
3550 nct6775_init_fan_common(dev, data);
3551
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003552 /* Register sysfs hooks */
Guenter Roeckf73cf632013-03-18 09:22:50 -07003553 group = nct6775_create_attr_group(dev, &nct6775_pwm_template_group,
3554 data->pwm_num);
3555 if (IS_ERR(group)) {
3556 err = PTR_ERR(group);
3557 goto exit_remove;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003558 }
Guenter Roeckf73cf632013-03-18 09:22:50 -07003559 data->group_pwm = group;
Guenter Roeckcdcaece2012-12-04 09:04:52 -08003560
Guenter Roeckf73cf632013-03-18 09:22:50 -07003561 group = nct6775_create_attr_group(dev, &nct6775_in_template_group,
3562 fls(data->have_in));
3563 if (IS_ERR(group)) {
3564 err = PTR_ERR(group);
3565 goto exit_remove;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003566 }
Guenter Roeckf73cf632013-03-18 09:22:50 -07003567 data->group_in = group;
Guenter Roeck77eb5b32012-12-04 08:30:54 -08003568
Guenter Roeckf73cf632013-03-18 09:22:50 -07003569 group = nct6775_create_attr_group(dev, &nct6775_fan_template_group,
3570 fls(data->has_fan));
3571 if (IS_ERR(group)) {
3572 err = PTR_ERR(group);
3573 goto exit_remove;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003574 }
Guenter Roeckf73cf632013-03-18 09:22:50 -07003575 data->group_fan = group;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003576
Guenter Roeckf73cf632013-03-18 09:22:50 -07003577 group = nct6775_create_attr_group(dev, &nct6775_temp_template_group,
3578 fls(data->have_temp));
3579 if (IS_ERR(group)) {
3580 err = PTR_ERR(group);
3581 goto exit_remove;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003582 }
Guenter Roeckf73cf632013-03-18 09:22:50 -07003583 data->group_temp = group;
Guenter Roeck1c65dc32012-12-04 07:56:24 -08003584
Guenter Roeckf73cf632013-03-18 09:22:50 -07003585 err = sysfs_create_group(&dev->kobj, &nct6775_group_other);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003586 if (err)
3587 goto exit_remove;
3588
3589 data->hwmon_dev = hwmon_device_register(dev);
3590 if (IS_ERR(data->hwmon_dev)) {
3591 err = PTR_ERR(data->hwmon_dev);
3592 goto exit_remove;
3593 }
3594
3595 return 0;
3596
3597exit_remove:
3598 nct6775_device_remove_files(dev);
3599 return err;
3600}
3601
3602static int nct6775_remove(struct platform_device *pdev)
3603{
3604 struct nct6775_data *data = platform_get_drvdata(pdev);
3605
3606 hwmon_device_unregister(data->hwmon_dev);
3607 nct6775_device_remove_files(&pdev->dev);
3608
3609 return 0;
3610}
3611
Guenter Roeck84d19d92012-12-04 08:01:39 -08003612#ifdef CONFIG_PM
3613static int nct6775_suspend(struct device *dev)
3614{
3615 struct nct6775_data *data = nct6775_update_device(dev);
3616 struct nct6775_sio_data *sio_data = dev->platform_data;
3617
3618 mutex_lock(&data->update_lock);
3619 data->vbat = nct6775_read_value(data, data->REG_VBAT);
3620 if (sio_data->kind == nct6775) {
3621 data->fandiv1 = nct6775_read_value(data, NCT6775_REG_FANDIV1);
3622 data->fandiv2 = nct6775_read_value(data, NCT6775_REG_FANDIV2);
3623 }
3624 mutex_unlock(&data->update_lock);
3625
3626 return 0;
3627}
3628
3629static int nct6775_resume(struct device *dev)
3630{
3631 struct nct6775_data *data = dev_get_drvdata(dev);
3632 struct nct6775_sio_data *sio_data = dev->platform_data;
3633 int i, j;
3634
3635 mutex_lock(&data->update_lock);
3636 data->bank = 0xff; /* Force initial bank selection */
3637
3638 /* Restore limits */
3639 for (i = 0; i < data->in_num; i++) {
3640 if (!(data->have_in & (1 << i)))
3641 continue;
3642
3643 nct6775_write_value(data, data->REG_IN_MINMAX[0][i],
3644 data->in[i][1]);
3645 nct6775_write_value(data, data->REG_IN_MINMAX[1][i],
3646 data->in[i][2]);
3647 }
3648
Guenter Roeckc409fd42013-04-09 05:04:00 -07003649 for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) {
Guenter Roeck84d19d92012-12-04 08:01:39 -08003650 if (!(data->has_fan_min & (1 << i)))
3651 continue;
3652
3653 nct6775_write_value(data, data->REG_FAN_MIN[i],
3654 data->fan_min[i]);
3655 }
3656
3657 for (i = 0; i < NUM_TEMP; i++) {
3658 if (!(data->have_temp & (1 << i)))
3659 continue;
3660
Guenter Roeckc409fd42013-04-09 05:04:00 -07003661 for (j = 1; j < ARRAY_SIZE(data->reg_temp); j++)
Guenter Roeck84d19d92012-12-04 08:01:39 -08003662 if (data->reg_temp[j][i])
3663 nct6775_write_temp(data, data->reg_temp[j][i],
3664 data->temp[j][i]);
3665 }
3666
3667 /* Restore other settings */
3668 nct6775_write_value(data, data->REG_VBAT, data->vbat);
3669 if (sio_data->kind == nct6775) {
3670 nct6775_write_value(data, NCT6775_REG_FANDIV1, data->fandiv1);
3671 nct6775_write_value(data, NCT6775_REG_FANDIV2, data->fandiv2);
3672 }
3673
3674 /* Force re-reading all values */
3675 data->valid = false;
3676 mutex_unlock(&data->update_lock);
3677
3678 return 0;
3679}
3680
3681static const struct dev_pm_ops nct6775_dev_pm_ops = {
3682 .suspend = nct6775_suspend,
3683 .resume = nct6775_resume,
3684};
3685
3686#define NCT6775_DEV_PM_OPS (&nct6775_dev_pm_ops)
3687#else
3688#define NCT6775_DEV_PM_OPS NULL
3689#endif /* CONFIG_PM */
3690
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003691static struct platform_driver nct6775_driver = {
3692 .driver = {
3693 .owner = THIS_MODULE,
3694 .name = DRVNAME,
Guenter Roeck84d19d92012-12-04 08:01:39 -08003695 .pm = NCT6775_DEV_PM_OPS,
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003696 },
3697 .probe = nct6775_probe,
3698 .remove = nct6775_remove,
3699};
3700
Guenter Roeck6d4b3622013-04-21 09:08:11 -07003701static const char * const nct6775_sio_names[] __initconst = {
Guenter Roeck6c009502012-07-01 08:23:15 -07003702 "NCT6106D",
Guenter Roeck2c7fd302013-04-02 08:53:19 -07003703 "NCT6775F",
3704 "NCT6776D/F",
3705 "NCT6779D",
3706};
3707
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003708/* nct6775_find() looks for a '627 in the Super-I/O config space */
Guenter Roeck698a7c22013-04-05 07:35:25 -07003709static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003710{
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003711 u16 val;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003712 int err;
Guenter Roeck698a7c22013-04-05 07:35:25 -07003713 int addr;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003714
3715 err = superio_enter(sioaddr);
3716 if (err)
3717 return err;
3718
3719 if (force_id)
3720 val = force_id;
3721 else
3722 val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8)
3723 | superio_inb(sioaddr, SIO_REG_DEVID + 1);
3724 switch (val & SIO_ID_MASK) {
Guenter Roeck6c009502012-07-01 08:23:15 -07003725 case SIO_NCT6106_ID:
3726 sio_data->kind = nct6106;
3727 break;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003728 case SIO_NCT6775_ID:
3729 sio_data->kind = nct6775;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003730 break;
3731 case SIO_NCT6776_ID:
3732 sio_data->kind = nct6776;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003733 break;
3734 case SIO_NCT6779_ID:
3735 sio_data->kind = nct6779;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003736 break;
3737 default:
3738 if (val != 0xffff)
3739 pr_debug("unsupported chip ID: 0x%04x\n", val);
3740 superio_exit(sioaddr);
3741 return -ENODEV;
3742 }
3743
3744 /* We have a known chip, find the HWM I/O address */
3745 superio_select(sioaddr, NCT6775_LD_HWM);
3746 val = (superio_inb(sioaddr, SIO_REG_ADDR) << 8)
3747 | superio_inb(sioaddr, SIO_REG_ADDR + 1);
Guenter Roeck698a7c22013-04-05 07:35:25 -07003748 addr = val & IOREGION_ALIGNMENT;
3749 if (addr == 0) {
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003750 pr_err("Refusing to enable a Super-I/O device with a base I/O port 0\n");
3751 superio_exit(sioaddr);
3752 return -ENODEV;
3753 }
3754
3755 /* Activate logical device if needed */
3756 val = superio_inb(sioaddr, SIO_REG_ENABLE);
3757 if (!(val & 0x01)) {
3758 pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n");
3759 superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
3760 }
3761
3762 superio_exit(sioaddr);
Guenter Roeck698a7c22013-04-05 07:35:25 -07003763 pr_info("Found %s or compatible chip at %#x:%#x\n",
3764 nct6775_sio_names[sio_data->kind], sioaddr, addr);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003765 sio_data->sioreg = sioaddr;
3766
Guenter Roeck698a7c22013-04-05 07:35:25 -07003767 return addr;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003768}
3769
3770/*
3771 * when Super-I/O functions move to a separate file, the Super-I/O
3772 * bus will manage the lifetime of the device and this module will only keep
3773 * track of the nct6775 driver. But since we platform_device_alloc(), we
3774 * must keep track of the device
3775 */
Guenter Roeck698a7c22013-04-05 07:35:25 -07003776static struct platform_device *pdev[2];
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003777
3778static int __init sensors_nct6775_init(void)
3779{
Guenter Roeck698a7c22013-04-05 07:35:25 -07003780 int i, err;
3781 bool found = false;
3782 int address;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003783 struct resource res;
3784 struct nct6775_sio_data sio_data;
Guenter Roeck698a7c22013-04-05 07:35:25 -07003785 int sioaddr[2] = { 0x2e, 0x4e };
3786
3787 err = platform_driver_register(&nct6775_driver);
3788 if (err)
3789 return err;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003790
3791 /*
3792 * initialize sio_data->kind and sio_data->sioreg.
3793 *
3794 * when Super-I/O functions move to a separate file, the Super-I/O
3795 * driver will probe 0x2e and 0x4e and auto-detect the presence of a
3796 * nct6775 hardware monitor, and call probe()
3797 */
Guenter Roeck698a7c22013-04-05 07:35:25 -07003798 for (i = 0; i < ARRAY_SIZE(pdev); i++) {
3799 address = nct6775_find(sioaddr[i], &sio_data);
3800 if (address <= 0)
3801 continue;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003802
Guenter Roeck698a7c22013-04-05 07:35:25 -07003803 found = true;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003804
Guenter Roeck698a7c22013-04-05 07:35:25 -07003805 pdev[i] = platform_device_alloc(DRVNAME, address);
3806 if (!pdev[i]) {
3807 err = -ENOMEM;
3808 goto exit_device_put;
3809 }
3810
3811 err = platform_device_add_data(pdev[i], &sio_data,
3812 sizeof(struct nct6775_sio_data));
3813 if (err)
3814 goto exit_device_put;
3815
3816 memset(&res, 0, sizeof(res));
3817 res.name = DRVNAME;
3818 res.start = address + IOREGION_OFFSET;
3819 res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1;
3820 res.flags = IORESOURCE_IO;
3821
3822 err = acpi_check_resource_conflict(&res);
3823 if (err) {
3824 platform_device_put(pdev[i]);
3825 pdev[i] = NULL;
3826 continue;
3827 }
3828
3829 err = platform_device_add_resources(pdev[i], &res, 1);
3830 if (err)
3831 goto exit_device_put;
3832
3833 /* platform_device_add calls probe() */
3834 err = platform_device_add(pdev[i]);
3835 if (err)
3836 goto exit_device_put;
3837 }
3838 if (!found) {
3839 err = -ENODEV;
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003840 goto exit_unregister;
3841 }
3842
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003843 return 0;
3844
3845exit_device_put:
Guenter Roeck698a7c22013-04-05 07:35:25 -07003846 for (i = 0; i < ARRAY_SIZE(pdev); i++) {
3847 if (pdev[i])
3848 platform_device_put(pdev[i]);
3849 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003850exit_unregister:
3851 platform_driver_unregister(&nct6775_driver);
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003852 return err;
3853}
3854
3855static void __exit sensors_nct6775_exit(void)
3856{
Guenter Roeck698a7c22013-04-05 07:35:25 -07003857 int i;
3858
3859 for (i = 0; i < ARRAY_SIZE(pdev); i++) {
3860 if (pdev[i])
3861 platform_device_unregister(pdev[i]);
3862 }
Guenter Roeck9de2e2e2012-05-20 19:29:48 -07003863 platform_driver_unregister(&nct6775_driver);
3864}
3865
3866MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
3867MODULE_DESCRIPTION("NCT6775F/NCT6776F/NCT6779D driver");
3868MODULE_LICENSE("GPL");
3869
3870module_init(sensors_nct6775_init);
3871module_exit(sensors_nct6775_exit);